PostgreSQL Source Code  git master
reloptions.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * reloptions.c
4  * Core support for relation options (pg_class.reloptions)
5  *
6  * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  * src/backend/access/common/reloptions.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 
16 #include "postgres.h"
17 
18 #include <float.h>
19 
20 #include "access/gist_private.h"
21 #include "access/hash.h"
22 #include "access/htup_details.h"
23 #include "access/nbtree.h"
24 #include "access/reloptions.h"
25 #include "access/spgist.h"
26 #include "access/tuptoaster.h"
27 #include "catalog/pg_type.h"
28 #include "commands/defrem.h"
29 #include "commands/tablespace.h"
30 #include "commands/view.h"
31 #include "nodes/makefuncs.h"
32 #include "postmaster/postmaster.h"
33 #include "utils/array.h"
34 #include "utils/attoptcache.h"
35 #include "utils/builtins.h"
36 #include "utils/guc.h"
37 #include "utils/memutils.h"
38 #include "utils/rel.h"
39 
40 /*
41  * Contents of pg_class.reloptions
42  *
43  * To add an option:
44  *
45  * (i) decide on a type (integer, real, bool, string), name, default value,
46  * upper and lower bounds (if applicable); for strings, consider a validation
47  * routine.
48  * (ii) add a record below (or use add_<type>_reloption).
49  * (iii) add it to the appropriate options struct (perhaps StdRdOptions)
50  * (iv) add it to the appropriate handling routine (perhaps
51  * default_reloptions)
52  * (v) make sure the lock level is set correctly for that operation
53  * (vi) don't forget to document the option
54  *
55  * The default choice for any new option should be AccessExclusiveLock.
56  * In some cases the lock level can be reduced from there, but the lock
57  * level chosen should always conflict with itself to ensure that multiple
58  * changes aren't lost when we attempt concurrent changes.
59  * The choice of lock level depends completely upon how that parameter
60  * is used within the server, not upon how and when you'd like to change it.
61  * Safety first. Existing choices are documented here, and elsewhere in
62  * backend code where the parameters are used.
63  *
64  * In general, anything that affects the results obtained from a SELECT must be
65  * protected by AccessExclusiveLock.
66  *
67  * Autovacuum related parameters can be set at ShareUpdateExclusiveLock
68  * since they are only used by the AV procs and don't change anything
69  * currently executing.
70  *
71  * Fillfactor can be set because it applies only to subsequent changes made to
72  * data blocks, as documented in hio.c
73  *
74  * n_distinct options can be set at ShareUpdateExclusiveLock because they
75  * are only used during ANALYZE, which uses a ShareUpdateExclusiveLock,
76  * so the ANALYZE will not be affected by in-flight changes. Changing those
77  * values has no effect until the next ANALYZE, so no need for stronger lock.
78  *
79  * Planner-related parameters can be set with ShareUpdateExclusiveLock because
80  * they only affect planning and not the correctness of the execution. Plans
81  * cannot be changed in mid-flight, so changes here could not easily result in
82  * new improved plans in any case. So we allow existing queries to continue
83  * and existing plans to survive, a small price to pay for allowing better
84  * plans to be introduced concurrently without interfering with users.
85  *
86  * Setting parallel_workers is safe, since it acts the same as
87  * max_parallel_workers_per_gather which is a USERSET parameter that doesn't
88  * affect existing plans or queries.
89  *
90  * vacuum_truncate can be set at ShareUpdateExclusiveLock because it
91  * is only used during VACUUM, which uses a ShareUpdateExclusiveLock,
92  * so the VACUUM will not be affected by in-flight changes. Changing its
93  * value has no effect until the next VACUUM, so no need for stronger lock.
94  */
95 
97 {
98  {
99  {
100  "autosummarize",
101  "Enables automatic summarization on this BRIN index",
104  },
105  false
106  },
107  {
108  {
109  "autovacuum_enabled",
110  "Enables autovacuum in this relation",
113  },
114  true
115  },
116  {
117  {
118  "user_catalog_table",
119  "Declare a table as an additional catalog table, e.g. for the purpose of logical replication",
122  },
123  false
124  },
125  {
126  {
127  "fastupdate",
128  "Enables \"fast update\" feature for this GIN index",
131  },
132  true
133  },
134  {
135  {
136  "security_barrier",
137  "View acts as a row security barrier",
140  },
141  false
142  },
143  {
144  {
145  "vacuum_index_cleanup",
146  "Enables index vacuuming and index cleanup",
149  },
150  true
151  },
152  {
153  {
154  "vacuum_truncate",
155  "Enables vacuum to truncate empty pages at the end of this table",
158  },
159  true
160  },
161  /* list terminator */
162  {{NULL}}
163 };
164 
166 {
167  {
168  {
169  "fillfactor",
170  "Packs table pages only to this percentage",
172  ShareUpdateExclusiveLock /* since it applies only to later
173  * inserts */
174  },
176  },
177  {
178  {
179  "fillfactor",
180  "Packs btree index pages only to this percentage",
182  ShareUpdateExclusiveLock /* since it applies only to later
183  * inserts */
184  },
186  },
187  {
188  {
189  "fillfactor",
190  "Packs hash index pages only to this percentage",
192  ShareUpdateExclusiveLock /* since it applies only to later
193  * inserts */
194  },
196  },
197  {
198  {
199  "fillfactor",
200  "Packs gist index pages only to this percentage",
202  ShareUpdateExclusiveLock /* since it applies only to later
203  * inserts */
204  },
206  },
207  {
208  {
209  "fillfactor",
210  "Packs spgist index pages only to this percentage",
212  ShareUpdateExclusiveLock /* since it applies only to later
213  * inserts */
214  },
216  },
217  {
218  {
219  "autovacuum_vacuum_threshold",
220  "Minimum number of tuple updates or deletes prior to vacuum",
223  },
224  -1, 0, INT_MAX
225  },
226  {
227  {
228  "autovacuum_analyze_threshold",
229  "Minimum number of tuple inserts, updates or deletes prior to analyze",
232  },
233  -1, 0, INT_MAX
234  },
235  {
236  {
237  "autovacuum_vacuum_cost_limit",
238  "Vacuum cost amount available before napping, for autovacuum",
241  },
242  -1, 1, 10000
243  },
244  {
245  {
246  "autovacuum_freeze_min_age",
247  "Minimum age at which VACUUM should freeze a table row, for autovacuum",
250  },
251  -1, 0, 1000000000
252  },
253  {
254  {
255  "autovacuum_multixact_freeze_min_age",
256  "Minimum multixact age at which VACUUM should freeze a row multixact's, for autovacuum",
259  },
260  -1, 0, 1000000000
261  },
262  {
263  {
264  "autovacuum_freeze_max_age",
265  "Age at which to autovacuum a table to prevent transaction ID wraparound",
268  },
269  -1, 100000, 2000000000
270  },
271  {
272  {
273  "autovacuum_multixact_freeze_max_age",
274  "Multixact age at which to autovacuum a table to prevent multixact wraparound",
277  },
278  -1, 10000, 2000000000
279  },
280  {
281  {
282  "autovacuum_freeze_table_age",
283  "Age at which VACUUM should perform a full table sweep to freeze row versions",
286  }, -1, 0, 2000000000
287  },
288  {
289  {
290  "autovacuum_multixact_freeze_table_age",
291  "Age of multixact at which VACUUM should perform a full table sweep to freeze row versions",
294  }, -1, 0, 2000000000
295  },
296  {
297  {
298  "log_autovacuum_min_duration",
299  "Sets the minimum execution time above which autovacuum actions will be logged",
302  },
303  -1, -1, INT_MAX
304  },
305  {
306  {
307  "toast_tuple_target",
308  "Sets the target tuple length at which external columns will be toasted",
311  },
313  },
314  {
315  {
316  "pages_per_range",
317  "Number of pages that each page range covers in a BRIN index",
320  }, 128, 1, 131072
321  },
322  {
323  {
324  "gin_pending_list_limit",
325  "Maximum size of the pending list for this GIN index, in kilobytes.",
328  },
329  -1, 64, MAX_KILOBYTES
330  },
331  {
332  {
333  "effective_io_concurrency",
334  "Number of simultaneous requests that can be handled efficiently by the disk subsystem.",
337  },
338 #ifdef USE_PREFETCH
339  -1, 0, MAX_IO_CONCURRENCY
340 #else
341  0, 0, 0
342 #endif
343  },
344  {
345  {
346  "parallel_workers",
347  "Number of parallel processes that can be used per executor node for this relation.",
350  },
351  -1, 0, 1024
352  },
353 
354  /* list terminator */
355  {{NULL}}
356 };
357 
359 {
360  {
361  {
362  "autovacuum_vacuum_cost_delay",
363  "Vacuum cost delay in milliseconds, for autovacuum",
366  },
367  -1, 0.0, 100.0
368  },
369  {
370  {
371  "autovacuum_vacuum_scale_factor",
372  "Number of tuple updates or deletes prior to vacuum as a fraction of reltuples",
375  },
376  -1, 0.0, 100.0
377  },
378  {
379  {
380  "autovacuum_analyze_scale_factor",
381  "Number of tuple inserts, updates or deletes prior to analyze as a fraction of reltuples",
384  },
385  -1, 0.0, 100.0
386  },
387  {
388  {
389  "seq_page_cost",
390  "Sets the planner's estimate of the cost of a sequentially fetched disk page.",
393  },
394  -1, 0.0, DBL_MAX
395  },
396  {
397  {
398  "random_page_cost",
399  "Sets the planner's estimate of the cost of a nonsequentially fetched disk page.",
402  },
403  -1, 0.0, DBL_MAX
404  },
405  {
406  {
407  "n_distinct",
408  "Sets the planner's estimate of the number of distinct values appearing in a column (excluding child relations).",
411  },
412  0, -1.0, DBL_MAX
413  },
414  {
415  {
416  "n_distinct_inherited",
417  "Sets the planner's estimate of the number of distinct values appearing in a column (including child relations).",
420  },
421  0, -1.0, DBL_MAX
422  },
423  {
424  {
425  "vacuum_cleanup_index_scale_factor",
426  "Number of tuple inserts prior to index cleanup as a fraction of reltuples.",
429  },
430  -1, 0.0, 1e10
431  },
432  /* list terminator */
433  {{NULL}}
434 };
435 
437 {
438  {
439  {
440  "buffering",
441  "Enables buffering build for this GiST index",
444  },
445  4,
446  false,
448  "auto"
449  },
450  {
451  {
452  "check_option",
453  "View has WITH CHECK OPTION defined (local or cascaded).",
456  },
457  0,
458  true,
460  NULL
461  },
462  /* list terminator */
463  {{NULL}}
464 };
465 
466 static relopt_gen **relOpts = NULL;
468 
469 static int num_custom_options = 0;
470 static relopt_gen **custom_options = NULL;
471 static bool need_initialization = true;
472 
473 static void initialize_reloptions(void);
474 static void parse_one_reloption(relopt_value *option, char *text_str,
475  int text_len, bool validate);
476 
477 /*
478  * initialize_reloptions
479  * initialization routine, must be called before parsing
480  *
481  * Initialize the relOpts array and fill each variable's type and name length.
482  */
483 static void
485 {
486  int i;
487  int j;
488 
489  j = 0;
490  for (i = 0; boolRelOpts[i].gen.name; i++)
491  {
492  Assert(DoLockModesConflict(boolRelOpts[i].gen.lockmode,
493  boolRelOpts[i].gen.lockmode));
494  j++;
495  }
496  for (i = 0; intRelOpts[i].gen.name; i++)
497  {
498  Assert(DoLockModesConflict(intRelOpts[i].gen.lockmode,
499  intRelOpts[i].gen.lockmode));
500  j++;
501  }
502  for (i = 0; realRelOpts[i].gen.name; i++)
503  {
504  Assert(DoLockModesConflict(realRelOpts[i].gen.lockmode,
505  realRelOpts[i].gen.lockmode));
506  j++;
507  }
508  for (i = 0; stringRelOpts[i].gen.name; i++)
509  {
510  Assert(DoLockModesConflict(stringRelOpts[i].gen.lockmode,
511  stringRelOpts[i].gen.lockmode));
512  j++;
513  }
514  j += num_custom_options;
515 
516  if (relOpts)
517  pfree(relOpts);
519  (j + 1) * sizeof(relopt_gen *));
520 
521  j = 0;
522  for (i = 0; boolRelOpts[i].gen.name; i++)
523  {
524  relOpts[j] = &boolRelOpts[i].gen;
525  relOpts[j]->type = RELOPT_TYPE_BOOL;
526  relOpts[j]->namelen = strlen(relOpts[j]->name);
527  j++;
528  }
529 
530  for (i = 0; intRelOpts[i].gen.name; i++)
531  {
532  relOpts[j] = &intRelOpts[i].gen;
533  relOpts[j]->type = RELOPT_TYPE_INT;
534  relOpts[j]->namelen = strlen(relOpts[j]->name);
535  j++;
536  }
537 
538  for (i = 0; realRelOpts[i].gen.name; i++)
539  {
540  relOpts[j] = &realRelOpts[i].gen;
541  relOpts[j]->type = RELOPT_TYPE_REAL;
542  relOpts[j]->namelen = strlen(relOpts[j]->name);
543  j++;
544  }
545 
546  for (i = 0; stringRelOpts[i].gen.name; i++)
547  {
548  relOpts[j] = &stringRelOpts[i].gen;
549  relOpts[j]->type = RELOPT_TYPE_STRING;
550  relOpts[j]->namelen = strlen(relOpts[j]->name);
551  j++;
552  }
553 
554  for (i = 0; i < num_custom_options; i++)
555  {
556  relOpts[j] = custom_options[i];
557  j++;
558  }
559 
560  /* add a list terminator */
561  relOpts[j] = NULL;
562 
563  /* flag the work is complete */
564  need_initialization = false;
565 }
566 
567 /*
568  * add_reloption_kind
569  * Create a new relopt_kind value, to be used in custom reloptions by
570  * user-defined AMs.
571  */
574 {
575  /* don't hand out the last bit so that the enum's behavior is portable */
577  ereport(ERROR,
578  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
579  errmsg("user-defined relation parameter types limit exceeded")));
580  last_assigned_kind <<= 1;
582 }
583 
584 /*
585  * add_reloption
586  * Add an already-created custom reloption to the list, and recompute the
587  * main parser table.
588  */
589 static void
591 {
592  static int max_custom_options = 0;
593 
594  if (num_custom_options >= max_custom_options)
595  {
596  MemoryContext oldcxt;
597 
599 
600  if (max_custom_options == 0)
601  {
602  max_custom_options = 8;
603  custom_options = palloc(max_custom_options * sizeof(relopt_gen *));
604  }
605  else
606  {
607  max_custom_options *= 2;
608  custom_options = repalloc(custom_options,
609  max_custom_options * sizeof(relopt_gen *));
610  }
611  MemoryContextSwitchTo(oldcxt);
612  }
613  custom_options[num_custom_options++] = newoption;
614 
615  need_initialization = true;
616 }
617 
618 /*
619  * allocate_reloption
620  * Allocate a new reloption and initialize the type-agnostic fields
621  * (for types other than string)
622  */
623 static relopt_gen *
624 allocate_reloption(bits32 kinds, int type, const char *name, const char *desc)
625 {
626  MemoryContext oldcxt;
627  size_t size;
628  relopt_gen *newoption;
629 
631 
632  switch (type)
633  {
634  case RELOPT_TYPE_BOOL:
635  size = sizeof(relopt_bool);
636  break;
637  case RELOPT_TYPE_INT:
638  size = sizeof(relopt_int);
639  break;
640  case RELOPT_TYPE_REAL:
641  size = sizeof(relopt_real);
642  break;
643  case RELOPT_TYPE_STRING:
644  size = sizeof(relopt_string);
645  break;
646  default:
647  elog(ERROR, "unsupported reloption type %d", type);
648  return NULL; /* keep compiler quiet */
649  }
650 
651  newoption = palloc(size);
652 
653  newoption->name = pstrdup(name);
654  if (desc)
655  newoption->desc = pstrdup(desc);
656  else
657  newoption->desc = NULL;
658  newoption->kinds = kinds;
659  newoption->namelen = strlen(name);
660  newoption->type = type;
661 
662  MemoryContextSwitchTo(oldcxt);
663 
664  return newoption;
665 }
666 
667 /*
668  * add_bool_reloption
669  * Add a new boolean reloption
670  */
671 void
672 add_bool_reloption(bits32 kinds, const char *name, const char *desc, bool default_val)
673 {
674  relopt_bool *newoption;
675 
676  newoption = (relopt_bool *) allocate_reloption(kinds, RELOPT_TYPE_BOOL,
677  name, desc);
678  newoption->default_val = default_val;
679 
680  add_reloption((relopt_gen *) newoption);
681 }
682 
683 /*
684  * add_int_reloption
685  * Add a new integer reloption
686  */
687 void
688 add_int_reloption(bits32 kinds, const char *name, const char *desc, int default_val,
689  int min_val, int max_val)
690 {
691  relopt_int *newoption;
692 
693  newoption = (relopt_int *) allocate_reloption(kinds, RELOPT_TYPE_INT,
694  name, desc);
695  newoption->default_val = default_val;
696  newoption->min = min_val;
697  newoption->max = max_val;
698 
699  add_reloption((relopt_gen *) newoption);
700 }
701 
702 /*
703  * add_real_reloption
704  * Add a new float reloption
705  */
706 void
707 add_real_reloption(bits32 kinds, const char *name, const char *desc, double default_val,
708  double min_val, double max_val)
709 {
710  relopt_real *newoption;
711 
712  newoption = (relopt_real *) allocate_reloption(kinds, RELOPT_TYPE_REAL,
713  name, desc);
714  newoption->default_val = default_val;
715  newoption->min = min_val;
716  newoption->max = max_val;
717 
718  add_reloption((relopt_gen *) newoption);
719 }
720 
721 /*
722  * add_string_reloption
723  * Add a new string reloption
724  *
725  * "validator" is an optional function pointer that can be used to test the
726  * validity of the values. It must elog(ERROR) when the argument string is
727  * not acceptable for the variable. Note that the default value must pass
728  * the validation.
729  */
730 void
731 add_string_reloption(bits32 kinds, const char *name, const char *desc, const char *default_val,
732  validate_string_relopt validator)
733 {
734  relopt_string *newoption;
735 
736  /* make sure the validator/default combination is sane */
737  if (validator)
738  (validator) (default_val);
739 
740  newoption = (relopt_string *) allocate_reloption(kinds, RELOPT_TYPE_STRING,
741  name, desc);
742  newoption->validate_cb = validator;
743  if (default_val)
744  {
746  default_val);
747  newoption->default_len = strlen(default_val);
748  newoption->default_isnull = false;
749  }
750  else
751  {
752  newoption->default_val = "";
753  newoption->default_len = 0;
754  newoption->default_isnull = true;
755  }
756 
757  add_reloption((relopt_gen *) newoption);
758 }
759 
760 /*
761  * Transform a relation options list (list of DefElem) into the text array
762  * format that is kept in pg_class.reloptions, including only those options
763  * that are in the passed namespace. The output values do not include the
764  * namespace.
765  *
766  * This is used for three cases: CREATE TABLE/INDEX, ALTER TABLE SET, and
767  * ALTER TABLE RESET. In the ALTER cases, oldOptions is the existing
768  * reloptions value (possibly NULL), and we replace or remove entries
769  * as needed.
770  *
771  * If acceptOidsOff is true, then we allow oids = false, but throw error when
772  * on. This is solely needed for backwards compatibility.
773  *
774  * Note that this is not responsible for determining whether the options
775  * are valid, but it does check that namespaces for all the options given are
776  * listed in validnsps. The NULL namespace is always valid and need not be
777  * explicitly listed. Passing a NULL pointer means that only the NULL
778  * namespace is valid.
779  *
780  * Both oldOptions and the result are text arrays (or NULL for "default"),
781  * but we declare them as Datums to avoid including array.h in reloptions.h.
782  */
783 Datum
784 transformRelOptions(Datum oldOptions, List *defList, const char *namspace,
785  char *validnsps[], bool acceptOidsOff, bool isReset)
786 {
787  Datum result;
788  ArrayBuildState *astate;
789  ListCell *cell;
790 
791  /* no change if empty list */
792  if (defList == NIL)
793  return oldOptions;
794 
795  /* We build new array using accumArrayResult */
796  astate = NULL;
797 
798  /* Copy any oldOptions that aren't to be replaced */
799  if (PointerIsValid(DatumGetPointer(oldOptions)))
800  {
801  ArrayType *array = DatumGetArrayTypeP(oldOptions);
802  Datum *oldoptions;
803  int noldoptions;
804  int i;
805 
806  deconstruct_array(array, TEXTOID, -1, false, 'i',
807  &oldoptions, NULL, &noldoptions);
808 
809  for (i = 0; i < noldoptions; i++)
810  {
811  char *text_str = VARDATA(oldoptions[i]);
812  int text_len = VARSIZE(oldoptions[i]) - VARHDRSZ;
813 
814  /* Search for a match in defList */
815  foreach(cell, defList)
816  {
817  DefElem *def = (DefElem *) lfirst(cell);
818  int kw_len;
819 
820  /* ignore if not in the same namespace */
821  if (namspace == NULL)
822  {
823  if (def->defnamespace != NULL)
824  continue;
825  }
826  else if (def->defnamespace == NULL)
827  continue;
828  else if (strcmp(def->defnamespace, namspace) != 0)
829  continue;
830 
831  kw_len = strlen(def->defname);
832  if (text_len > kw_len && text_str[kw_len] == '=' &&
833  strncmp(text_str, def->defname, kw_len) == 0)
834  break;
835  }
836  if (!cell)
837  {
838  /* No match, so keep old option */
839  astate = accumArrayResult(astate, oldoptions[i],
840  false, TEXTOID,
842  }
843  }
844  }
845 
846  /*
847  * If CREATE/SET, add new options to array; if RESET, just check that the
848  * user didn't say RESET (option=val). (Must do this because the grammar
849  * doesn't enforce it.)
850  */
851  foreach(cell, defList)
852  {
853  DefElem *def = (DefElem *) lfirst(cell);
854 
855  if (isReset)
856  {
857  if (def->arg != NULL)
858  ereport(ERROR,
859  (errcode(ERRCODE_SYNTAX_ERROR),
860  errmsg("RESET must not include values for parameters")));
861  }
862  else
863  {
864  text *t;
865  const char *value;
866  Size len;
867 
868  /*
869  * Error out if the namespace is not valid. A NULL namespace is
870  * always valid.
871  */
872  if (def->defnamespace != NULL)
873  {
874  bool valid = false;
875  int i;
876 
877  if (validnsps)
878  {
879  for (i = 0; validnsps[i]; i++)
880  {
881  if (strcmp(def->defnamespace, validnsps[i]) == 0)
882  {
883  valid = true;
884  break;
885  }
886  }
887  }
888 
889  if (!valid)
890  ereport(ERROR,
891  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
892  errmsg("unrecognized parameter namespace \"%s\"",
893  def->defnamespace)));
894  }
895 
896  /* ignore if not in the same namespace */
897  if (namspace == NULL)
898  {
899  if (def->defnamespace != NULL)
900  continue;
901  }
902  else if (def->defnamespace == NULL)
903  continue;
904  else if (strcmp(def->defnamespace, namspace) != 0)
905  continue;
906 
907  /*
908  * Flatten the DefElem into a text string like "name=arg". If we
909  * have just "name", assume "name=true" is meant. Note: the
910  * namespace is not output.
911  */
912  if (def->arg != NULL)
913  value = defGetString(def);
914  else
915  value = "true";
916 
917  /*
918  * This is not a great place for this test, but there's no other
919  * convenient place to filter the option out. As WITH (oids =
920  * false) will be removed someday, this seems like an acceptable
921  * amount of ugly.
922  */
923  if (acceptOidsOff && def->defnamespace == NULL &&
924  strcmp(def->defname, "oids") == 0)
925  {
926  if (defGetBoolean(def))
927  ereport(ERROR,
928  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
929  errmsg("tables declared WITH OIDS are not supported")));
930  /* skip over option, reloptions machinery doesn't know it */
931  continue;
932  }
933 
934  len = VARHDRSZ + strlen(def->defname) + 1 + strlen(value);
935  /* +1 leaves room for sprintf's trailing null */
936  t = (text *) palloc(len + 1);
937  SET_VARSIZE(t, len);
938  sprintf(VARDATA(t), "%s=%s", def->defname, value);
939 
940  astate = accumArrayResult(astate, PointerGetDatum(t),
941  false, TEXTOID,
943  }
944  }
945 
946  if (astate)
947  result = makeArrayResult(astate, CurrentMemoryContext);
948  else
949  result = (Datum) 0;
950 
951  return result;
952 }
953 
954 
955 /*
956  * Convert the text-array format of reloptions into a List of DefElem.
957  * This is the inverse of transformRelOptions().
958  */
959 List *
961 {
962  List *result = NIL;
963  ArrayType *array;
964  Datum *optiondatums;
965  int noptions;
966  int i;
967 
968  /* Nothing to do if no options */
969  if (!PointerIsValid(DatumGetPointer(options)))
970  return result;
971 
972  array = DatumGetArrayTypeP(options);
973 
974  deconstruct_array(array, TEXTOID, -1, false, 'i',
975  &optiondatums, NULL, &noptions);
976 
977  for (i = 0; i < noptions; i++)
978  {
979  char *s;
980  char *p;
981  Node *val = NULL;
982 
983  s = TextDatumGetCString(optiondatums[i]);
984  p = strchr(s, '=');
985  if (p)
986  {
987  *p++ = '\0';
988  val = (Node *) makeString(pstrdup(p));
989  }
990  result = lappend(result, makeDefElem(pstrdup(s), val, -1));
991  }
992 
993  return result;
994 }
995 
996 /*
997  * Extract and parse reloptions from a pg_class tuple.
998  *
999  * This is a low-level routine, expected to be used by relcache code and
1000  * callers that do not have a table's relcache entry (e.g. autovacuum). For
1001  * other uses, consider grabbing the rd_options pointer from the relcache entry
1002  * instead.
1003  *
1004  * tupdesc is pg_class' tuple descriptor. amoptions is a pointer to the index
1005  * AM's options parser function in the case of a tuple corresponding to an
1006  * index, or NULL otherwise.
1007  */
1008 bytea *
1010  amoptions_function amoptions)
1011 {
1012  bytea *options;
1013  bool isnull;
1014  Datum datum;
1015  Form_pg_class classForm;
1016 
1017  datum = fastgetattr(tuple,
1018  Anum_pg_class_reloptions,
1019  tupdesc,
1020  &isnull);
1021  if (isnull)
1022  return NULL;
1023 
1024  classForm = (Form_pg_class) GETSTRUCT(tuple);
1025 
1026  /* Parse into appropriate format; don't error out here */
1027  switch (classForm->relkind)
1028  {
1029  case RELKIND_RELATION:
1030  case RELKIND_TOASTVALUE:
1031  case RELKIND_MATVIEW:
1032  case RELKIND_PARTITIONED_TABLE:
1033  options = heap_reloptions(classForm->relkind, datum, false);
1034  break;
1035  case RELKIND_VIEW:
1036  options = view_reloptions(datum, false);
1037  break;
1038  case RELKIND_INDEX:
1039  case RELKIND_PARTITIONED_INDEX:
1040  options = index_reloptions(amoptions, datum, false);
1041  break;
1042  case RELKIND_FOREIGN_TABLE:
1043  options = NULL;
1044  break;
1045  default:
1046  Assert(false); /* can't get here */
1047  options = NULL; /* keep compiler quiet */
1048  break;
1049  }
1050 
1051  return options;
1052 }
1053 
1054 /*
1055  * Interpret reloptions that are given in text-array format.
1056  *
1057  * options is a reloption text array as constructed by transformRelOptions.
1058  * kind specifies the family of options to be processed.
1059  *
1060  * The return value is a relopt_value * array on which the options actually
1061  * set in the options array are marked with isset=true. The length of this
1062  * array is returned in *numrelopts. Options not set are also present in the
1063  * array; this is so that the caller can easily locate the default values.
1064  *
1065  * If there are no options of the given kind, numrelopts is set to 0 and NULL
1066  * is returned (unless options are illegally supplied despite none being
1067  * defined, in which case an error occurs).
1068  *
1069  * Note: values of type int, bool and real are allocated as part of the
1070  * returned array. Values of type string are allocated separately and must
1071  * be freed by the caller.
1072  */
1073 relopt_value *
1075  int *numrelopts)
1076 {
1077  relopt_value *reloptions = NULL;
1078  int numoptions = 0;
1079  int i;
1080  int j;
1081 
1082  if (need_initialization)
1084 
1085  /* Build a list of expected options, based on kind */
1086 
1087  for (i = 0; relOpts[i]; i++)
1088  if (relOpts[i]->kinds & kind)
1089  numoptions++;
1090 
1091  if (numoptions > 0)
1092  {
1093  reloptions = palloc(numoptions * sizeof(relopt_value));
1094 
1095  for (i = 0, j = 0; relOpts[i]; i++)
1096  {
1097  if (relOpts[i]->kinds & kind)
1098  {
1099  reloptions[j].gen = relOpts[i];
1100  reloptions[j].isset = false;
1101  j++;
1102  }
1103  }
1104  }
1105 
1106  /* Done if no options */
1107  if (PointerIsValid(DatumGetPointer(options)))
1108  {
1109  ArrayType *array = DatumGetArrayTypeP(options);
1110  Datum *optiondatums;
1111  int noptions;
1112 
1113  deconstruct_array(array, TEXTOID, -1, false, 'i',
1114  &optiondatums, NULL, &noptions);
1115 
1116  for (i = 0; i < noptions; i++)
1117  {
1118  char *text_str = VARDATA(optiondatums[i]);
1119  int text_len = VARSIZE(optiondatums[i]) - VARHDRSZ;
1120  int j;
1121 
1122  /* Search for a match in reloptions */
1123  for (j = 0; j < numoptions; j++)
1124  {
1125  int kw_len = reloptions[j].gen->namelen;
1126 
1127  if (text_len > kw_len && text_str[kw_len] == '=' &&
1128  strncmp(text_str, reloptions[j].gen->name, kw_len) == 0)
1129  {
1130  parse_one_reloption(&reloptions[j], text_str, text_len,
1131  validate);
1132  break;
1133  }
1134  }
1135 
1136  if (j >= numoptions && validate)
1137  {
1138  char *s;
1139  char *p;
1140 
1141  s = TextDatumGetCString(optiondatums[i]);
1142  p = strchr(s, '=');
1143  if (p)
1144  *p = '\0';
1145  ereport(ERROR,
1146  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1147  errmsg("unrecognized parameter \"%s\"", s)));
1148  }
1149  }
1150 
1151  /* It's worth avoiding memory leaks in this function */
1152  pfree(optiondatums);
1153  if (((void *) array) != DatumGetPointer(options))
1154  pfree(array);
1155  }
1156 
1157  *numrelopts = numoptions;
1158  return reloptions;
1159 }
1160 
1161 /*
1162  * Subroutine for parseRelOptions, to parse and validate a single option's
1163  * value
1164  */
1165 static void
1166 parse_one_reloption(relopt_value *option, char *text_str, int text_len,
1167  bool validate)
1168 {
1169  char *value;
1170  int value_len;
1171  bool parsed;
1172  bool nofree = false;
1173 
1174  if (option->isset && validate)
1175  ereport(ERROR,
1176  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1177  errmsg("parameter \"%s\" specified more than once",
1178  option->gen->name)));
1179 
1180  value_len = text_len - option->gen->namelen - 1;
1181  value = (char *) palloc(value_len + 1);
1182  memcpy(value, text_str + option->gen->namelen + 1, value_len);
1183  value[value_len] = '\0';
1184 
1185  switch (option->gen->type)
1186  {
1187  case RELOPT_TYPE_BOOL:
1188  {
1189  parsed = parse_bool(value, &option->values.bool_val);
1190  if (validate && !parsed)
1191  ereport(ERROR,
1192  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1193  errmsg("invalid value for boolean option \"%s\": %s",
1194  option->gen->name, value)));
1195  }
1196  break;
1197  case RELOPT_TYPE_INT:
1198  {
1199  relopt_int *optint = (relopt_int *) option->gen;
1200 
1201  parsed = parse_int(value, &option->values.int_val, 0, NULL);
1202  if (validate && !parsed)
1203  ereport(ERROR,
1204  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1205  errmsg("invalid value for integer option \"%s\": %s",
1206  option->gen->name, value)));
1207  if (validate && (option->values.int_val < optint->min ||
1208  option->values.int_val > optint->max))
1209  ereport(ERROR,
1210  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1211  errmsg("value %s out of bounds for option \"%s\"",
1212  value, option->gen->name),
1213  errdetail("Valid values are between \"%d\" and \"%d\".",
1214  optint->min, optint->max)));
1215  }
1216  break;
1217  case RELOPT_TYPE_REAL:
1218  {
1219  relopt_real *optreal = (relopt_real *) option->gen;
1220 
1221  parsed = parse_real(value, &option->values.real_val, 0, NULL);
1222  if (validate && !parsed)
1223  ereport(ERROR,
1224  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1225  errmsg("invalid value for floating point option \"%s\": %s",
1226  option->gen->name, value)));
1227  if (validate && (option->values.real_val < optreal->min ||
1228  option->values.real_val > optreal->max))
1229  ereport(ERROR,
1230  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1231  errmsg("value %s out of bounds for option \"%s\"",
1232  value, option->gen->name),
1233  errdetail("Valid values are between \"%f\" and \"%f\".",
1234  optreal->min, optreal->max)));
1235  }
1236  break;
1237  case RELOPT_TYPE_STRING:
1238  {
1239  relopt_string *optstring = (relopt_string *) option->gen;
1240 
1241  option->values.string_val = value;
1242  nofree = true;
1243  if (validate && optstring->validate_cb)
1244  (optstring->validate_cb) (value);
1245  parsed = true;
1246  }
1247  break;
1248  default:
1249  elog(ERROR, "unsupported reloption type %d", option->gen->type);
1250  parsed = true; /* quiet compiler */
1251  break;
1252  }
1253 
1254  if (parsed)
1255  option->isset = true;
1256  if (!nofree)
1257  pfree(value);
1258 }
1259 
1260 /*
1261  * Given the result from parseRelOptions, allocate a struct that's of the
1262  * specified base size plus any extra space that's needed for string variables.
1263  *
1264  * "base" should be sizeof(struct) of the reloptions struct (StdRdOptions or
1265  * equivalent).
1266  */
1267 void *
1269 {
1270  Size size = base;
1271  int i;
1272 
1273  for (i = 0; i < numoptions; i++)
1274  if (options[i].gen->type == RELOPT_TYPE_STRING)
1275  size += GET_STRING_RELOPTION_LEN(options[i]) + 1;
1276 
1277  return palloc0(size);
1278 }
1279 
1280 /*
1281  * Given the result of parseRelOptions and a parsing table, fill in the
1282  * struct (previously allocated with allocateReloptStruct) with the parsed
1283  * values.
1284  *
1285  * rdopts is the pointer to the allocated struct to be filled.
1286  * basesize is the sizeof(struct) that was passed to allocateReloptStruct.
1287  * options, of length numoptions, is parseRelOptions' output.
1288  * elems, of length numelems, is the table describing the allowed options.
1289  * When validate is true, it is expected that all options appear in elems.
1290  */
1291 void
1292 fillRelOptions(void *rdopts, Size basesize,
1293  relopt_value *options, int numoptions,
1294  bool validate,
1295  const relopt_parse_elt *elems, int numelems)
1296 {
1297  int i;
1298  int offset = basesize;
1299 
1300  for (i = 0; i < numoptions; i++)
1301  {
1302  int j;
1303  bool found = false;
1304 
1305  for (j = 0; j < numelems; j++)
1306  {
1307  if (strcmp(options[i].gen->name, elems[j].optname) == 0)
1308  {
1309  relopt_string *optstring;
1310  char *itempos = ((char *) rdopts) + elems[j].offset;
1311  char *string_val;
1312 
1313  switch (options[i].gen->type)
1314  {
1315  case RELOPT_TYPE_BOOL:
1316  *(bool *) itempos = options[i].isset ?
1317  options[i].values.bool_val :
1318  ((relopt_bool *) options[i].gen)->default_val;
1319  break;
1320  case RELOPT_TYPE_INT:
1321  *(int *) itempos = options[i].isset ?
1322  options[i].values.int_val :
1323  ((relopt_int *) options[i].gen)->default_val;
1324  break;
1325  case RELOPT_TYPE_REAL:
1326  *(double *) itempos = options[i].isset ?
1327  options[i].values.real_val :
1328  ((relopt_real *) options[i].gen)->default_val;
1329  break;
1330  case RELOPT_TYPE_STRING:
1331  optstring = (relopt_string *) options[i].gen;
1332  if (options[i].isset)
1333  string_val = options[i].values.string_val;
1334  else if (!optstring->default_isnull)
1335  string_val = optstring->default_val;
1336  else
1337  string_val = NULL;
1338 
1339  if (string_val == NULL)
1340  *(int *) itempos = 0;
1341  else
1342  {
1343  strcpy((char *) rdopts + offset, string_val);
1344  *(int *) itempos = offset;
1345  offset += strlen(string_val) + 1;
1346  }
1347  break;
1348  default:
1349  elog(ERROR, "unsupported reloption type %d",
1350  options[i].gen->type);
1351  break;
1352  }
1353  found = true;
1354  break;
1355  }
1356  }
1357  if (validate && !found)
1358  elog(ERROR, "reloption \"%s\" not found in parse table",
1359  options[i].gen->name);
1360  }
1361  SET_VARSIZE(rdopts, offset);
1362 }
1363 
1364 
1365 /*
1366  * Option parser for anything that uses StdRdOptions.
1367  */
1368 bytea *
1369 default_reloptions(Datum reloptions, bool validate, relopt_kind kind)
1370 {
1372  StdRdOptions *rdopts;
1373  int numoptions;
1374  static const relopt_parse_elt tab[] = {
1375  {"fillfactor", RELOPT_TYPE_INT, offsetof(StdRdOptions, fillfactor)},
1376  {"autovacuum_enabled", RELOPT_TYPE_BOOL,
1377  offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, enabled)},
1378  {"autovacuum_vacuum_threshold", RELOPT_TYPE_INT,
1379  offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_threshold)},
1380  {"autovacuum_analyze_threshold", RELOPT_TYPE_INT,
1381  offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, analyze_threshold)},
1382  {"autovacuum_vacuum_cost_limit", RELOPT_TYPE_INT,
1383  offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_cost_limit)},
1384  {"autovacuum_freeze_min_age", RELOPT_TYPE_INT,
1385  offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, freeze_min_age)},
1386  {"autovacuum_freeze_max_age", RELOPT_TYPE_INT,
1387  offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, freeze_max_age)},
1388  {"autovacuum_freeze_table_age", RELOPT_TYPE_INT,
1389  offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, freeze_table_age)},
1390  {"autovacuum_multixact_freeze_min_age", RELOPT_TYPE_INT,
1391  offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, multixact_freeze_min_age)},
1392  {"autovacuum_multixact_freeze_max_age", RELOPT_TYPE_INT,
1393  offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, multixact_freeze_max_age)},
1394  {"autovacuum_multixact_freeze_table_age", RELOPT_TYPE_INT,
1395  offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, multixact_freeze_table_age)},
1396  {"log_autovacuum_min_duration", RELOPT_TYPE_INT,
1397  offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, log_min_duration)},
1398  {"toast_tuple_target", RELOPT_TYPE_INT,
1399  offsetof(StdRdOptions, toast_tuple_target)},
1400  {"autovacuum_vacuum_cost_delay", RELOPT_TYPE_REAL,
1401  offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_cost_delay)},
1402  {"autovacuum_vacuum_scale_factor", RELOPT_TYPE_REAL,
1403  offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_scale_factor)},
1404  {"autovacuum_analyze_scale_factor", RELOPT_TYPE_REAL,
1405  offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, analyze_scale_factor)},
1406  {"user_catalog_table", RELOPT_TYPE_BOOL,
1407  offsetof(StdRdOptions, user_catalog_table)},
1408  {"parallel_workers", RELOPT_TYPE_INT,
1409  offsetof(StdRdOptions, parallel_workers)},
1410  {"vacuum_cleanup_index_scale_factor", RELOPT_TYPE_REAL,
1412  {"vacuum_index_cleanup", RELOPT_TYPE_BOOL,
1413  offsetof(StdRdOptions, vacuum_index_cleanup)},
1414  {"vacuum_truncate", RELOPT_TYPE_BOOL,
1415  offsetof(StdRdOptions, vacuum_truncate)}
1416  };
1417 
1418  options = parseRelOptions(reloptions, validate, kind, &numoptions);
1419 
1420  /* if none set, we're done */
1421  if (numoptions == 0)
1422  return NULL;
1423 
1424  rdopts = allocateReloptStruct(sizeof(StdRdOptions), options, numoptions);
1425 
1426  fillRelOptions((void *) rdopts, sizeof(StdRdOptions), options, numoptions,
1427  validate, tab, lengthof(tab));
1428 
1429  pfree(options);
1430 
1431  return (bytea *) rdopts;
1432 }
1433 
1434 /*
1435  * Option parser for views
1436  */
1437 bytea *
1438 view_reloptions(Datum reloptions, bool validate)
1439 {
1441  ViewOptions *vopts;
1442  int numoptions;
1443  static const relopt_parse_elt tab[] = {
1444  {"security_barrier", RELOPT_TYPE_BOOL,
1445  offsetof(ViewOptions, security_barrier)},
1446  {"check_option", RELOPT_TYPE_STRING,
1447  offsetof(ViewOptions, check_option_offset)}
1448  };
1449 
1450  options = parseRelOptions(reloptions, validate, RELOPT_KIND_VIEW, &numoptions);
1451 
1452  /* if none set, we're done */
1453  if (numoptions == 0)
1454  return NULL;
1455 
1456  vopts = allocateReloptStruct(sizeof(ViewOptions), options, numoptions);
1457 
1458  fillRelOptions((void *) vopts, sizeof(ViewOptions), options, numoptions,
1459  validate, tab, lengthof(tab));
1460 
1461  pfree(options);
1462 
1463  return (bytea *) vopts;
1464 }
1465 
1466 /*
1467  * Parse options for heaps, views and toast tables.
1468  */
1469 bytea *
1470 heap_reloptions(char relkind, Datum reloptions, bool validate)
1471 {
1472  StdRdOptions *rdopts;
1473 
1474  switch (relkind)
1475  {
1476  case RELKIND_TOASTVALUE:
1477  rdopts = (StdRdOptions *)
1478  default_reloptions(reloptions, validate, RELOPT_KIND_TOAST);
1479  if (rdopts != NULL)
1480  {
1481  /* adjust default-only parameters for TOAST relations */
1482  rdopts->fillfactor = 100;
1483  rdopts->autovacuum.analyze_threshold = -1;
1484  rdopts->autovacuum.analyze_scale_factor = -1;
1485  }
1486  return (bytea *) rdopts;
1487  case RELKIND_RELATION:
1488  case RELKIND_MATVIEW:
1489  return default_reloptions(reloptions, validate, RELOPT_KIND_HEAP);
1490  case RELKIND_PARTITIONED_TABLE:
1491  return default_reloptions(reloptions, validate,
1493  default:
1494  /* other relkinds are not supported */
1495  return NULL;
1496  }
1497 }
1498 
1499 
1500 /*
1501  * Parse options for indexes.
1502  *
1503  * amoptions index AM's option parser function
1504  * reloptions options as text[] datum
1505  * validate error flag
1506  */
1507 bytea *
1508 index_reloptions(amoptions_function amoptions, Datum reloptions, bool validate)
1509 {
1510  Assert(amoptions != NULL);
1511 
1512  /* Assume function is strict */
1513  if (!PointerIsValid(DatumGetPointer(reloptions)))
1514  return NULL;
1515 
1516  return amoptions(reloptions, validate);
1517 }
1518 
1519 /*
1520  * Option parser for attribute reloptions
1521  */
1522 bytea *
1523 attribute_reloptions(Datum reloptions, bool validate)
1524 {
1526  AttributeOpts *aopts;
1527  int numoptions;
1528  static const relopt_parse_elt tab[] = {
1529  {"n_distinct", RELOPT_TYPE_REAL, offsetof(AttributeOpts, n_distinct)},
1530  {"n_distinct_inherited", RELOPT_TYPE_REAL, offsetof(AttributeOpts, n_distinct_inherited)}
1531  };
1532 
1533  options = parseRelOptions(reloptions, validate, RELOPT_KIND_ATTRIBUTE,
1534  &numoptions);
1535 
1536  /* if none set, we're done */
1537  if (numoptions == 0)
1538  return NULL;
1539 
1540  aopts = allocateReloptStruct(sizeof(AttributeOpts), options, numoptions);
1541 
1542  fillRelOptions((void *) aopts, sizeof(AttributeOpts), options, numoptions,
1543  validate, tab, lengthof(tab));
1544 
1545  pfree(options);
1546 
1547  return (bytea *) aopts;
1548 }
1549 
1550 /*
1551  * Option parser for tablespace reloptions
1552  */
1553 bytea *
1554 tablespace_reloptions(Datum reloptions, bool validate)
1555 {
1557  TableSpaceOpts *tsopts;
1558  int numoptions;
1559  static const relopt_parse_elt tab[] = {
1560  {"random_page_cost", RELOPT_TYPE_REAL, offsetof(TableSpaceOpts, random_page_cost)},
1561  {"seq_page_cost", RELOPT_TYPE_REAL, offsetof(TableSpaceOpts, seq_page_cost)},
1562  {"effective_io_concurrency", RELOPT_TYPE_INT, offsetof(TableSpaceOpts, effective_io_concurrency)}
1563  };
1564 
1565  options = parseRelOptions(reloptions, validate, RELOPT_KIND_TABLESPACE,
1566  &numoptions);
1567 
1568  /* if none set, we're done */
1569  if (numoptions == 0)
1570  return NULL;
1571 
1572  tsopts = allocateReloptStruct(sizeof(TableSpaceOpts), options, numoptions);
1573 
1574  fillRelOptions((void *) tsopts, sizeof(TableSpaceOpts), options, numoptions,
1575  validate, tab, lengthof(tab));
1576 
1577  pfree(options);
1578 
1579  return (bytea *) tsopts;
1580 }
1581 
1582 /*
1583  * Determine the required LOCKMODE from an option list.
1584  *
1585  * Called from AlterTableGetLockLevel(), see that function
1586  * for a longer explanation of how this works.
1587  */
1588 LOCKMODE
1590 {
1591  LOCKMODE lockmode = NoLock;
1592  ListCell *cell;
1593 
1594  if (defList == NIL)
1595  return AccessExclusiveLock;
1596 
1597  if (need_initialization)
1599 
1600  foreach(cell, defList)
1601  {
1602  DefElem *def = (DefElem *) lfirst(cell);
1603  int i;
1604 
1605  for (i = 0; relOpts[i]; i++)
1606  {
1607  if (strncmp(relOpts[i]->name,
1608  def->defname,
1609  relOpts[i]->namelen + 1) == 0)
1610  {
1611  if (lockmode < relOpts[i]->lockmode)
1612  lockmode = relOpts[i]->lockmode;
1613  }
1614  }
1615  }
1616 
1617  return lockmode;
1618 }
Value * makeString(char *str)
Definition: value.c:53
#define HASH_DEFAULT_FILLFACTOR
Definition: hash.h:278
bytea * heap_reloptions(char relkind, Datum reloptions, bool validate)
Definition: reloptions.c:1470
#define NIL
Definition: pg_list.h:65
bool bool_val
Definition: reloptions.h:80
#define MAX_IO_CONCURRENCY
Definition: bufmgr.h:78
static void initialize_reloptions(void)
Definition: reloptions.c:484
#define HASH_MIN_FILLFACTOR
Definition: hash.h:277
static relopt_gen ** custom_options
Definition: reloptions.c:470
char * string_val
Definition: reloptions.h:83
#define VARDATA(PTR)
Definition: postgres.h:302
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
struct relopt_string relopt_string
#define fastgetattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:712
Datum transformRelOptions(Datum oldOptions, List *defList, const char *namspace, char *validnsps[], bool acceptOidsOff, bool isReset)
Definition: reloptions.c:784
#define GET_STRING_RELOPTION_LEN(option)
Definition: reloptions.h:234
const char * desc
Definition: reloptions.h:66
int LOCKMODE
Definition: lockdefs.h:26
#define VARSIZE(PTR)
Definition: postgres.h:303
#define PointerGetDatum(X)
Definition: postgres.h:556
LOCKMODE lockmode
Definition: reloptions.h:68
#define VARHDRSZ
Definition: c.h:555
char * pstrdup(const char *in)
Definition: mcxt.c:1161
static struct @144 value
#define TOAST_TUPLE_TARGET_MAIN
Definition: tuptoaster.h:68
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
char * defnamespace
Definition: parsenodes.h:729
static relopt_bool boolRelOpts[]
Definition: reloptions.c:96
bytea * tablespace_reloptions(Datum reloptions, bool validate)
Definition: reloptions.c:1554
Definition: nodes.h:524
bool default_isnull
Definition: reloptions.h:117
int fillfactor
Definition: rel.h:266
int errcode(int sqlerrcode)
Definition: elog.c:570
double vacuum_cleanup_index_scale_factor
Definition: globals.c:150
bool parse_real(const char *value, double *result, int flags, const char **hintmsg)
Definition: guc.c:6356
bool default_val
Definition: reloptions.h:91
bool parse_bool(const char *value, bool *result)
Definition: bool.c:30
relopt_gen gen
Definition: reloptions.h:115
#define lengthof(array)
Definition: c.h:662
relopt_gen * gen
Definition: reloptions.h:76
struct relopt_bool relopt_bool
DefElem * makeDefElem(char *name, Node *arg, int location)
Definition: makefuncs.c:544
void add_string_reloption(bits32 kinds, const char *name, const char *desc, const char *default_val, validate_string_relopt validator)
Definition: reloptions.c:731
int effective_io_concurrency
Definition: bufmgr.c:113
char relkind
Definition: pg_class.h:81
bytea * attribute_reloptions(Datum reloptions, bool validate)
Definition: reloptions.c:1523
struct relopt_real relopt_real
bytea * view_reloptions(Datum reloptions, bool validate)
Definition: reloptions.c:1438
#define SPGIST_DEFAULT_FILLFACTOR
Definition: spgist.h:24
#define sprintf
Definition: port.h:194
double default_val
Definition: reloptions.h:105
double random_page_cost
Definition: costsize.c:111
bool defGetBoolean(DefElem *def)
Definition: define.c:111
void add_int_reloption(bits32 kinds, const char *name, const char *desc, int default_val, int min_val, int max_val)
Definition: reloptions.c:688
void pfree(void *pointer)
Definition: mcxt.c:1031
#define MAX_KILOBYTES
Definition: guc.h:26
#define ERROR
Definition: elog.h:43
void add_real_reloption(bits32 kinds, const char *name, const char *desc, double default_val, double min_val, double max_val)
Definition: reloptions.c:707
static void parse_one_reloption(relopt_value *option, char *text_str, int text_len, bool validate)
Definition: reloptions.c:1166
static int num_custom_options
Definition: reloptions.c:469
int fillfactor
Definition: pgbench.c:157
char * defGetString(DefElem *def)
Definition: define.c:49
union relopt_value::@47 values
relopt_gen gen
Definition: reloptions.h:90
void * allocateReloptStruct(Size base, relopt_value *options, int numoptions)
Definition: reloptions.c:1268
int analyze_threshold
Definition: rel.h:249
#define NoLock
Definition: lockdefs.h:34
bool DoLockModesConflict(LOCKMODE mode1, LOCKMODE mode2)
Definition: lock.c:556
void gistValidateBufferingOption(const char *value)
Definition: gistbuild.c:244
static relopt_real realRelOpts[]
Definition: reloptions.c:358
int errdetail(const char *fmt,...)
Definition: elog.c:860
int namelen
Definition: reloptions.h:69
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
double real_val
Definition: reloptions.h:82
static relopt_gen * allocate_reloption(bits32 kinds, int type, const char *name, const char *desc)
Definition: reloptions.c:624
#define GIST_DEFAULT_FILLFACTOR
Definition: gist_private.h:461
#define ereport(elevel, rest)
Definition: elog.h:141
Datum makeArrayResult(ArrayBuildState *astate, MemoryContext rcontext)
Definition: arrayfuncs.c:5117
#define BTREE_DEFAULT_FILLFACTOR
Definition: nbtree.h:169
validate_string_relopt validate_cb
Definition: reloptions.h:118
MemoryContext TopMemoryContext
Definition: mcxt.c:44
Node * arg
Definition: parsenodes.h:731
List * lappend(List *list, void *datum)
Definition: list.c:321
#define BTREE_MIN_FILLFACTOR
Definition: nbtree.h:168
void add_bool_reloption(bits32 kinds, const char *name, const char *desc, bool default_val)
Definition: reloptions.c:672
static char ** options
bits32 kinds
Definition: reloptions.h:67
void fillRelOptions(void *rdopts, Size basesize, relopt_value *options, int numoptions, bool validate, const relopt_parse_elt *elems, int numelems)
Definition: reloptions.c:1292
#define TextDatumGetCString(d)
Definition: builtins.h:84
void * palloc0(Size size)
Definition: mcxt.c:955
uintptr_t Datum
Definition: postgres.h:367
relopt_gen gen
Definition: reloptions.h:96
bool parse_int(const char *value, int *result, int flags, const char **hintmsg)
Definition: guc.c:6266
const char * optname
Definition: reloptions.h:125
List * untransformRelOptions(Datum options)
Definition: reloptions.c:960
bytea * extractRelOptions(HeapTuple tuple, TupleDesc tupdesc, amoptions_function amoptions)
Definition: reloptions.c:1009
bytea * index_reloptions(amoptions_function amoptions, Datum reloptions, bool validate)
Definition: reloptions.c:1508
void validateWithCheckOption(const char *value)
Definition: view.c:46
float8 analyze_scale_factor
Definition: rel.h:260
#define ShareUpdateExclusiveLock
Definition: lockdefs.h:39
uint32 bits32
Definition: c.h:367
#define Assert(condition)
Definition: c.h:732
#define lfirst(lc)
Definition: pg_list.h:190
void(* validate_string_relopt)(const char *value)
Definition: reloptions.h:111
#define HEAP_MIN_FILLFACTOR
Definition: rel.h:277
#define TOAST_TUPLE_TARGET
Definition: tuptoaster.h:57
relopt_type type
Definition: reloptions.h:70
#define GIST_MIN_FILLFACTOR
Definition: gist_private.h:460
struct relopt_int relopt_int
size_t Size
Definition: c.h:466
static void add_reloption(relopt_gen *newoption)
Definition: reloptions.c:590
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1044
LOCKMODE AlterTableGetRelOptionsLockLevel(List *defList)
Definition: reloptions.c:1589
relopt_gen gen
Definition: reloptions.h:104
const char * name
Definition: encode.c:521
static relopt_string stringRelOpts[]
Definition: reloptions.c:436
relopt_kind add_reloption_kind(void)
Definition: reloptions.c:573
#define DatumGetPointer(X)
Definition: postgres.h:549
int default_val
Definition: reloptions.h:97
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3461
static Datum values[MAXATTR]
Definition: bootstrap.c:167
FormData_pg_class * Form_pg_class
Definition: pg_class.h:150
ArrayBuildState * accumArrayResult(ArrayBuildState *astate, Datum dvalue, bool disnull, Oid element_type, MemoryContext rcontext)
Definition: arrayfuncs.c:5053
#define AccessExclusiveLock
Definition: lockdefs.h:45
bytea * default_reloptions(Datum reloptions, bool validate, relopt_kind kind)
Definition: reloptions.c:1369
void * palloc(Size size)
Definition: mcxt.c:924
int errmsg(const char *fmt,...)
Definition: elog.c:784
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1148
const char * name
Definition: reloptions.h:64
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:771
relopt_kind
Definition: reloptions.h:38
#define elog(elevel,...)
Definition: elog.h:226
int i
static bool need_initialization
Definition: reloptions.c:471
Definition: c.h:549
char * defname
Definition: parsenodes.h:730
relopt_value * parseRelOptions(Datum options, bool validate, relopt_kind kind, int *numrelopts)
Definition: reloptions.c:1074
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:329
bytea *(* amoptions_function)(Datum reloptions, bool validate)
Definition: amapi.h:103
#define HEAP_DEFAULT_FILLFACTOR
Definition: rel.h:278
static relopt_int intRelOpts[]
Definition: reloptions.c:165
char * default_val
Definition: reloptions.h:119
static relopt_gen ** relOpts
Definition: reloptions.c:466
#define SPGIST_MIN_FILLFACTOR
Definition: spgist.h:23
double max
Definition: reloptions.h:107
double seq_page_cost
Definition: costsize.c:110
static size_t noptions
static bits32 last_assigned_kind
Definition: reloptions.c:467
Definition: pg_list.h:50
#define PointerIsValid(pointer)
Definition: c.h:626
long val
Definition: informix.c:684
double min
Definition: reloptions.h:106
#define offsetof(type, field)
Definition: c.h:655
#define DatumGetArrayTypeP(X)
Definition: array.h:249
AutoVacOpts autovacuum
Definition: rel.h:270