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/heaptoast.h"
23 #include "access/htup_details.h"
24 #include "access/nbtree.h"
25 #include "access/reloptions.h"
26 #include "access/spgist_private.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 
436 /* values from GistOptBufferingMode */
438 {
439  {"auto", GIST_OPTION_BUFFERING_AUTO},
440  {"on", GIST_OPTION_BUFFERING_ON},
441  {"off", GIST_OPTION_BUFFERING_OFF},
442  {(const char *) NULL} /* list terminator */
443 };
444 
445 /* values from ViewOptCheckOption */
447 {
448  /* no value for NOT_SET */
450  {"cascaded", VIEW_OPTION_CHECK_OPTION_CASCADED},
451  {(const char *) NULL} /* list terminator */
452 };
453 
455 {
456  {
457  {
458  "buffering",
459  "Enables buffering build for this GiST index",
462  },
465  gettext_noop("Valid values are \"on\", \"off\", and \"auto\".")
466  },
467  {
468  {
469  "check_option",
470  "View has WITH CHECK OPTION defined (local or cascaded).",
473  },
476  gettext_noop("Valid values are \"local\" and \"cascaded\".")
477  },
478  /* list terminator */
479  {{NULL}}
480 };
481 
483 {
484  /* list terminator */
485  {{NULL}}
486 };
487 
488 static relopt_gen **relOpts = NULL;
490 
491 static int num_custom_options = 0;
492 static relopt_gen **custom_options = NULL;
493 static bool need_initialization = true;
494 
495 static void initialize_reloptions(void);
496 static void parse_one_reloption(relopt_value *option, char *text_str,
497  int text_len, bool validate);
498 
499 /*
500  * Get the length of a string reloption (either default or the user-defined
501  * value). This is used for allocation purposes when building a set of
502  * relation options.
503  */
504 #define GET_STRING_RELOPTION_LEN(option) \
505  ((option).isset ? strlen((option).values.string_val) : \
506  ((relopt_string *) (option).gen)->default_len)
507 
508 /*
509  * initialize_reloptions
510  * initialization routine, must be called before parsing
511  *
512  * Initialize the relOpts array and fill each variable's type and name length.
513  */
514 static void
516 {
517  int i;
518  int j;
519 
520  j = 0;
521  for (i = 0; boolRelOpts[i].gen.name; i++)
522  {
523  Assert(DoLockModesConflict(boolRelOpts[i].gen.lockmode,
524  boolRelOpts[i].gen.lockmode));
525  j++;
526  }
527  for (i = 0; intRelOpts[i].gen.name; i++)
528  {
529  Assert(DoLockModesConflict(intRelOpts[i].gen.lockmode,
530  intRelOpts[i].gen.lockmode));
531  j++;
532  }
533  for (i = 0; realRelOpts[i].gen.name; i++)
534  {
535  Assert(DoLockModesConflict(realRelOpts[i].gen.lockmode,
536  realRelOpts[i].gen.lockmode));
537  j++;
538  }
539  for (i = 0; enumRelOpts[i].gen.name; i++)
540  {
541  Assert(DoLockModesConflict(enumRelOpts[i].gen.lockmode,
542  enumRelOpts[i].gen.lockmode));
543  j++;
544  }
545  for (i = 0; stringRelOpts[i].gen.name; i++)
546  {
547  Assert(DoLockModesConflict(stringRelOpts[i].gen.lockmode,
548  stringRelOpts[i].gen.lockmode));
549  j++;
550  }
551  j += num_custom_options;
552 
553  if (relOpts)
554  pfree(relOpts);
556  (j + 1) * sizeof(relopt_gen *));
557 
558  j = 0;
559  for (i = 0; boolRelOpts[i].gen.name; i++)
560  {
561  relOpts[j] = &boolRelOpts[i].gen;
562  relOpts[j]->type = RELOPT_TYPE_BOOL;
563  relOpts[j]->namelen = strlen(relOpts[j]->name);
564  j++;
565  }
566 
567  for (i = 0; intRelOpts[i].gen.name; i++)
568  {
569  relOpts[j] = &intRelOpts[i].gen;
570  relOpts[j]->type = RELOPT_TYPE_INT;
571  relOpts[j]->namelen = strlen(relOpts[j]->name);
572  j++;
573  }
574 
575  for (i = 0; realRelOpts[i].gen.name; i++)
576  {
577  relOpts[j] = &realRelOpts[i].gen;
578  relOpts[j]->type = RELOPT_TYPE_REAL;
579  relOpts[j]->namelen = strlen(relOpts[j]->name);
580  j++;
581  }
582 
583  for (i = 0; enumRelOpts[i].gen.name; i++)
584  {
585  relOpts[j] = &enumRelOpts[i].gen;
586  relOpts[j]->type = RELOPT_TYPE_ENUM;
587  relOpts[j]->namelen = strlen(relOpts[j]->name);
588  j++;
589  }
590 
591  for (i = 0; stringRelOpts[i].gen.name; i++)
592  {
593  relOpts[j] = &stringRelOpts[i].gen;
594  relOpts[j]->type = RELOPT_TYPE_STRING;
595  relOpts[j]->namelen = strlen(relOpts[j]->name);
596  j++;
597  }
598 
599  for (i = 0; i < num_custom_options; i++)
600  {
601  relOpts[j] = custom_options[i];
602  j++;
603  }
604 
605  /* add a list terminator */
606  relOpts[j] = NULL;
607 
608  /* flag the work is complete */
609  need_initialization = false;
610 }
611 
612 /*
613  * add_reloption_kind
614  * Create a new relopt_kind value, to be used in custom reloptions by
615  * user-defined AMs.
616  */
619 {
620  /* don't hand out the last bit so that the enum's behavior is portable */
622  ereport(ERROR,
623  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
624  errmsg("user-defined relation parameter types limit exceeded")));
625  last_assigned_kind <<= 1;
627 }
628 
629 /*
630  * add_reloption
631  * Add an already-created custom reloption to the list, and recompute the
632  * main parser table.
633  */
634 static void
636 {
637  static int max_custom_options = 0;
638 
639  if (num_custom_options >= max_custom_options)
640  {
641  MemoryContext oldcxt;
642 
644 
645  if (max_custom_options == 0)
646  {
647  max_custom_options = 8;
648  custom_options = palloc(max_custom_options * sizeof(relopt_gen *));
649  }
650  else
651  {
652  max_custom_options *= 2;
653  custom_options = repalloc(custom_options,
654  max_custom_options * sizeof(relopt_gen *));
655  }
656  MemoryContextSwitchTo(oldcxt);
657  }
658  custom_options[num_custom_options++] = newoption;
659 
660  need_initialization = true;
661 }
662 
663 /*
664  * allocate_reloption
665  * Allocate a new reloption and initialize the type-agnostic fields
666  * (for types other than string)
667  */
668 static relopt_gen *
669 allocate_reloption(bits32 kinds, int type, const char *name, const char *desc,
670  LOCKMODE lockmode)
671 {
672  MemoryContext oldcxt;
673  size_t size;
674  relopt_gen *newoption;
675 
677 
678  switch (type)
679  {
680  case RELOPT_TYPE_BOOL:
681  size = sizeof(relopt_bool);
682  break;
683  case RELOPT_TYPE_INT:
684  size = sizeof(relopt_int);
685  break;
686  case RELOPT_TYPE_REAL:
687  size = sizeof(relopt_real);
688  break;
689  case RELOPT_TYPE_ENUM:
690  size = sizeof(relopt_enum);
691  break;
692  case RELOPT_TYPE_STRING:
693  size = sizeof(relopt_string);
694  break;
695  default:
696  elog(ERROR, "unsupported reloption type %d", type);
697  return NULL; /* keep compiler quiet */
698  }
699 
700  newoption = palloc(size);
701 
702  newoption->name = pstrdup(name);
703  if (desc)
704  newoption->desc = pstrdup(desc);
705  else
706  newoption->desc = NULL;
707  newoption->kinds = kinds;
708  newoption->namelen = strlen(name);
709  newoption->type = type;
710  newoption->lockmode = lockmode;
711 
712  MemoryContextSwitchTo(oldcxt);
713 
714  return newoption;
715 }
716 
717 /*
718  * add_bool_reloption
719  * Add a new boolean reloption
720  */
721 void
722 add_bool_reloption(bits32 kinds, const char *name, const char *desc,
723  bool default_val, LOCKMODE lockmode)
724 {
725  relopt_bool *newoption;
726 
727  newoption = (relopt_bool *) allocate_reloption(kinds, RELOPT_TYPE_BOOL,
728  name, desc, lockmode);
729  newoption->default_val = default_val;
730 
731  add_reloption((relopt_gen *) newoption);
732 }
733 
734 /*
735  * add_int_reloption
736  * Add a new integer reloption
737  */
738 void
739 add_int_reloption(bits32 kinds, const char *name, const char *desc, int default_val,
740  int min_val, int max_val, LOCKMODE lockmode)
741 {
742  relopt_int *newoption;
743 
744  newoption = (relopt_int *) allocate_reloption(kinds, RELOPT_TYPE_INT,
745  name, desc, lockmode);
746  newoption->default_val = default_val;
747  newoption->min = min_val;
748  newoption->max = max_val;
749 
750  add_reloption((relopt_gen *) newoption);
751 }
752 
753 /*
754  * add_real_reloption
755  * Add a new float reloption
756  */
757 void
758 add_real_reloption(bits32 kinds, const char *name, const char *desc, double default_val,
759  double min_val, double max_val, LOCKMODE lockmode)
760 {
761  relopt_real *newoption;
762 
763  newoption = (relopt_real *) allocate_reloption(kinds, RELOPT_TYPE_REAL,
764  name, desc, lockmode);
765  newoption->default_val = default_val;
766  newoption->min = min_val;
767  newoption->max = max_val;
768 
769  add_reloption((relopt_gen *) newoption);
770 }
771 
772 /*
773  * add_enum_reloption
774  * Add a new enum reloption
775  *
776  * The members array must have a terminating NULL entry.
777  *
778  * The detailmsg is shown when unsupported values are passed, and has this
779  * form: "Valid values are \"foo\", \"bar\", and \"bar\"."
780  *
781  * The members array and detailmsg are not copied -- caller must ensure that
782  * they are valid throughout the life of the process.
783  */
784 void
785 add_enum_reloption(bits32 kinds, const char *name, const char *desc,
786  relopt_enum_elt_def *members, int default_val,
787  const char *detailmsg, LOCKMODE lockmode)
788 {
789  relopt_enum *newoption;
790 
791  newoption = (relopt_enum *) allocate_reloption(kinds, RELOPT_TYPE_ENUM,
792  name, desc, lockmode);
793  newoption->members = members;
794  newoption->default_val = default_val;
795  newoption->detailmsg = detailmsg;
796 
797  add_reloption((relopt_gen *) newoption);
798 }
799 
800 /*
801  * add_string_reloption
802  * Add a new string reloption
803  *
804  * "validator" is an optional function pointer that can be used to test the
805  * validity of the values. It must elog(ERROR) when the argument string is
806  * not acceptable for the variable. Note that the default value must pass
807  * the validation.
808  */
809 void
810 add_string_reloption(bits32 kinds, const char *name, const char *desc, const char *default_val,
811  validate_string_relopt validator, LOCKMODE lockmode)
812 {
813  relopt_string *newoption;
814 
815  /* make sure the validator/default combination is sane */
816  if (validator)
817  (validator) (default_val);
818 
819  newoption = (relopt_string *) allocate_reloption(kinds, RELOPT_TYPE_STRING,
820  name, desc, lockmode);
821  newoption->validate_cb = validator;
822  if (default_val)
823  {
825  default_val);
826  newoption->default_len = strlen(default_val);
827  newoption->default_isnull = false;
828  }
829  else
830  {
831  newoption->default_val = "";
832  newoption->default_len = 0;
833  newoption->default_isnull = true;
834  }
835 
836  add_reloption((relopt_gen *) newoption);
837 }
838 
839 /*
840  * Transform a relation options list (list of DefElem) into the text array
841  * format that is kept in pg_class.reloptions, including only those options
842  * that are in the passed namespace. The output values do not include the
843  * namespace.
844  *
845  * This is used for three cases: CREATE TABLE/INDEX, ALTER TABLE SET, and
846  * ALTER TABLE RESET. In the ALTER cases, oldOptions is the existing
847  * reloptions value (possibly NULL), and we replace or remove entries
848  * as needed.
849  *
850  * If acceptOidsOff is true, then we allow oids = false, but throw error when
851  * on. This is solely needed for backwards compatibility.
852  *
853  * Note that this is not responsible for determining whether the options
854  * are valid, but it does check that namespaces for all the options given are
855  * listed in validnsps. The NULL namespace is always valid and need not be
856  * explicitly listed. Passing a NULL pointer means that only the NULL
857  * namespace is valid.
858  *
859  * Both oldOptions and the result are text arrays (or NULL for "default"),
860  * but we declare them as Datums to avoid including array.h in reloptions.h.
861  */
862 Datum
863 transformRelOptions(Datum oldOptions, List *defList, const char *namspace,
864  char *validnsps[], bool acceptOidsOff, bool isReset)
865 {
866  Datum result;
867  ArrayBuildState *astate;
868  ListCell *cell;
869 
870  /* no change if empty list */
871  if (defList == NIL)
872  return oldOptions;
873 
874  /* We build new array using accumArrayResult */
875  astate = NULL;
876 
877  /* Copy any oldOptions that aren't to be replaced */
878  if (PointerIsValid(DatumGetPointer(oldOptions)))
879  {
880  ArrayType *array = DatumGetArrayTypeP(oldOptions);
881  Datum *oldoptions;
882  int noldoptions;
883  int i;
884 
885  deconstruct_array(array, TEXTOID, -1, false, 'i',
886  &oldoptions, NULL, &noldoptions);
887 
888  for (i = 0; i < noldoptions; i++)
889  {
890  char *text_str = VARDATA(oldoptions[i]);
891  int text_len = VARSIZE(oldoptions[i]) - VARHDRSZ;
892 
893  /* Search for a match in defList */
894  foreach(cell, defList)
895  {
896  DefElem *def = (DefElem *) lfirst(cell);
897  int kw_len;
898 
899  /* ignore if not in the same namespace */
900  if (namspace == NULL)
901  {
902  if (def->defnamespace != NULL)
903  continue;
904  }
905  else if (def->defnamespace == NULL)
906  continue;
907  else if (strcmp(def->defnamespace, namspace) != 0)
908  continue;
909 
910  kw_len = strlen(def->defname);
911  if (text_len > kw_len && text_str[kw_len] == '=' &&
912  strncmp(text_str, def->defname, kw_len) == 0)
913  break;
914  }
915  if (!cell)
916  {
917  /* No match, so keep old option */
918  astate = accumArrayResult(astate, oldoptions[i],
919  false, TEXTOID,
921  }
922  }
923  }
924 
925  /*
926  * If CREATE/SET, add new options to array; if RESET, just check that the
927  * user didn't say RESET (option=val). (Must do this because the grammar
928  * doesn't enforce it.)
929  */
930  foreach(cell, defList)
931  {
932  DefElem *def = (DefElem *) lfirst(cell);
933 
934  if (isReset)
935  {
936  if (def->arg != NULL)
937  ereport(ERROR,
938  (errcode(ERRCODE_SYNTAX_ERROR),
939  errmsg("RESET must not include values for parameters")));
940  }
941  else
942  {
943  text *t;
944  const char *value;
945  Size len;
946 
947  /*
948  * Error out if the namespace is not valid. A NULL namespace is
949  * always valid.
950  */
951  if (def->defnamespace != NULL)
952  {
953  bool valid = false;
954  int i;
955 
956  if (validnsps)
957  {
958  for (i = 0; validnsps[i]; i++)
959  {
960  if (strcmp(def->defnamespace, validnsps[i]) == 0)
961  {
962  valid = true;
963  break;
964  }
965  }
966  }
967 
968  if (!valid)
969  ereport(ERROR,
970  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
971  errmsg("unrecognized parameter namespace \"%s\"",
972  def->defnamespace)));
973  }
974 
975  /* ignore if not in the same namespace */
976  if (namspace == NULL)
977  {
978  if (def->defnamespace != NULL)
979  continue;
980  }
981  else if (def->defnamespace == NULL)
982  continue;
983  else if (strcmp(def->defnamespace, namspace) != 0)
984  continue;
985 
986  /*
987  * Flatten the DefElem into a text string like "name=arg". If we
988  * have just "name", assume "name=true" is meant. Note: the
989  * namespace is not output.
990  */
991  if (def->arg != NULL)
992  value = defGetString(def);
993  else
994  value = "true";
995 
996  /*
997  * This is not a great place for this test, but there's no other
998  * convenient place to filter the option out. As WITH (oids =
999  * false) will be removed someday, this seems like an acceptable
1000  * amount of ugly.
1001  */
1002  if (acceptOidsOff && def->defnamespace == NULL &&
1003  strcmp(def->defname, "oids") == 0)
1004  {
1005  if (defGetBoolean(def))
1006  ereport(ERROR,
1007  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1008  errmsg("tables declared WITH OIDS are not supported")));
1009  /* skip over option, reloptions machinery doesn't know it */
1010  continue;
1011  }
1012 
1013  len = VARHDRSZ + strlen(def->defname) + 1 + strlen(value);
1014  /* +1 leaves room for sprintf's trailing null */
1015  t = (text *) palloc(len + 1);
1016  SET_VARSIZE(t, len);
1017  sprintf(VARDATA(t), "%s=%s", def->defname, value);
1018 
1019  astate = accumArrayResult(astate, PointerGetDatum(t),
1020  false, TEXTOID,
1022  }
1023  }
1024 
1025  if (astate)
1026  result = makeArrayResult(astate, CurrentMemoryContext);
1027  else
1028  result = (Datum) 0;
1029 
1030  return result;
1031 }
1032 
1033 
1034 /*
1035  * Convert the text-array format of reloptions into a List of DefElem.
1036  * This is the inverse of transformRelOptions().
1037  */
1038 List *
1040 {
1041  List *result = NIL;
1042  ArrayType *array;
1043  Datum *optiondatums;
1044  int noptions;
1045  int i;
1046 
1047  /* Nothing to do if no options */
1048  if (!PointerIsValid(DatumGetPointer(options)))
1049  return result;
1050 
1051  array = DatumGetArrayTypeP(options);
1052 
1053  deconstruct_array(array, TEXTOID, -1, false, 'i',
1054  &optiondatums, NULL, &noptions);
1055 
1056  for (i = 0; i < noptions; i++)
1057  {
1058  char *s;
1059  char *p;
1060  Node *val = NULL;
1061 
1062  s = TextDatumGetCString(optiondatums[i]);
1063  p = strchr(s, '=');
1064  if (p)
1065  {
1066  *p++ = '\0';
1067  val = (Node *) makeString(pstrdup(p));
1068  }
1069  result = lappend(result, makeDefElem(pstrdup(s), val, -1));
1070  }
1071 
1072  return result;
1073 }
1074 
1075 /*
1076  * Extract and parse reloptions from a pg_class tuple.
1077  *
1078  * This is a low-level routine, expected to be used by relcache code and
1079  * callers that do not have a table's relcache entry (e.g. autovacuum). For
1080  * other uses, consider grabbing the rd_options pointer from the relcache entry
1081  * instead.
1082  *
1083  * tupdesc is pg_class' tuple descriptor. amoptions is a pointer to the index
1084  * AM's options parser function in the case of a tuple corresponding to an
1085  * index, or NULL otherwise.
1086  */
1087 bytea *
1089  amoptions_function amoptions)
1090 {
1091  bytea *options;
1092  bool isnull;
1093  Datum datum;
1094  Form_pg_class classForm;
1095 
1096  datum = fastgetattr(tuple,
1097  Anum_pg_class_reloptions,
1098  tupdesc,
1099  &isnull);
1100  if (isnull)
1101  return NULL;
1102 
1103  classForm = (Form_pg_class) GETSTRUCT(tuple);
1104 
1105  /* Parse into appropriate format; don't error out here */
1106  switch (classForm->relkind)
1107  {
1108  case RELKIND_RELATION:
1109  case RELKIND_TOASTVALUE:
1110  case RELKIND_MATVIEW:
1111  options = heap_reloptions(classForm->relkind, datum, false);
1112  break;
1113  case RELKIND_PARTITIONED_TABLE:
1114  options = partitioned_table_reloptions(datum, false);
1115  break;
1116  case RELKIND_VIEW:
1117  options = view_reloptions(datum, false);
1118  break;
1119  case RELKIND_INDEX:
1120  case RELKIND_PARTITIONED_INDEX:
1121  options = index_reloptions(amoptions, datum, false);
1122  break;
1123  case RELKIND_FOREIGN_TABLE:
1124  options = NULL;
1125  break;
1126  default:
1127  Assert(false); /* can't get here */
1128  options = NULL; /* keep compiler quiet */
1129  break;
1130  }
1131 
1132  return options;
1133 }
1134 
1135 /*
1136  * Interpret reloptions that are given in text-array format.
1137  *
1138  * options is a reloption text array as constructed by transformRelOptions.
1139  * kind specifies the family of options to be processed.
1140  *
1141  * The return value is a relopt_value * array on which the options actually
1142  * set in the options array are marked with isset=true. The length of this
1143  * array is returned in *numrelopts. Options not set are also present in the
1144  * array; this is so that the caller can easily locate the default values.
1145  *
1146  * If there are no options of the given kind, numrelopts is set to 0 and NULL
1147  * is returned (unless options are illegally supplied despite none being
1148  * defined, in which case an error occurs).
1149  *
1150  * Note: values of type int, bool and real are allocated as part of the
1151  * returned array. Values of type string are allocated separately and must
1152  * be freed by the caller.
1153  */
1154 static relopt_value *
1156  int *numrelopts)
1157 {
1158  relopt_value *reloptions = NULL;
1159  int numoptions = 0;
1160  int i;
1161  int j;
1162 
1163  if (need_initialization)
1165 
1166  /* Build a list of expected options, based on kind */
1167 
1168  for (i = 0; relOpts[i]; i++)
1169  if (relOpts[i]->kinds & kind)
1170  numoptions++;
1171 
1172  if (numoptions > 0)
1173  {
1174  reloptions = palloc(numoptions * sizeof(relopt_value));
1175 
1176  for (i = 0, j = 0; relOpts[i]; i++)
1177  {
1178  if (relOpts[i]->kinds & kind)
1179  {
1180  reloptions[j].gen = relOpts[i];
1181  reloptions[j].isset = false;
1182  j++;
1183  }
1184  }
1185  }
1186 
1187  /* Done if no options */
1188  if (PointerIsValid(DatumGetPointer(options)))
1189  {
1190  ArrayType *array = DatumGetArrayTypeP(options);
1191  Datum *optiondatums;
1192  int noptions;
1193 
1194  deconstruct_array(array, TEXTOID, -1, false, 'i',
1195  &optiondatums, NULL, &noptions);
1196 
1197  for (i = 0; i < noptions; i++)
1198  {
1199  char *text_str = VARDATA(optiondatums[i]);
1200  int text_len = VARSIZE(optiondatums[i]) - VARHDRSZ;
1201  int j;
1202 
1203  /* Search for a match in reloptions */
1204  for (j = 0; j < numoptions; j++)
1205  {
1206  int kw_len = reloptions[j].gen->namelen;
1207 
1208  if (text_len > kw_len && text_str[kw_len] == '=' &&
1209  strncmp(text_str, reloptions[j].gen->name, kw_len) == 0)
1210  {
1211  parse_one_reloption(&reloptions[j], text_str, text_len,
1212  validate);
1213  break;
1214  }
1215  }
1216 
1217  if (j >= numoptions && validate)
1218  {
1219  char *s;
1220  char *p;
1221 
1222  s = TextDatumGetCString(optiondatums[i]);
1223  p = strchr(s, '=');
1224  if (p)
1225  *p = '\0';
1226  ereport(ERROR,
1227  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1228  errmsg("unrecognized parameter \"%s\"", s)));
1229  }
1230  }
1231 
1232  /* It's worth avoiding memory leaks in this function */
1233  pfree(optiondatums);
1234  if (((void *) array) != DatumGetPointer(options))
1235  pfree(array);
1236  }
1237 
1238  *numrelopts = numoptions;
1239  return reloptions;
1240 }
1241 
1242 /*
1243  * Subroutine for parseRelOptions, to parse and validate a single option's
1244  * value
1245  */
1246 static void
1247 parse_one_reloption(relopt_value *option, char *text_str, int text_len,
1248  bool validate)
1249 {
1250  char *value;
1251  int value_len;
1252  bool parsed;
1253  bool nofree = false;
1254 
1255  if (option->isset && validate)
1256  ereport(ERROR,
1257  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1258  errmsg("parameter \"%s\" specified more than once",
1259  option->gen->name)));
1260 
1261  value_len = text_len - option->gen->namelen - 1;
1262  value = (char *) palloc(value_len + 1);
1263  memcpy(value, text_str + option->gen->namelen + 1, value_len);
1264  value[value_len] = '\0';
1265 
1266  switch (option->gen->type)
1267  {
1268  case RELOPT_TYPE_BOOL:
1269  {
1270  parsed = parse_bool(value, &option->values.bool_val);
1271  if (validate && !parsed)
1272  ereport(ERROR,
1273  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1274  errmsg("invalid value for boolean option \"%s\": %s",
1275  option->gen->name, value)));
1276  }
1277  break;
1278  case RELOPT_TYPE_INT:
1279  {
1280  relopt_int *optint = (relopt_int *) option->gen;
1281 
1282  parsed = parse_int(value, &option->values.int_val, 0, NULL);
1283  if (validate && !parsed)
1284  ereport(ERROR,
1285  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1286  errmsg("invalid value for integer option \"%s\": %s",
1287  option->gen->name, value)));
1288  if (validate && (option->values.int_val < optint->min ||
1289  option->values.int_val > optint->max))
1290  ereport(ERROR,
1291  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1292  errmsg("value %s out of bounds for option \"%s\"",
1293  value, option->gen->name),
1294  errdetail("Valid values are between \"%d\" and \"%d\".",
1295  optint->min, optint->max)));
1296  }
1297  break;
1298  case RELOPT_TYPE_REAL:
1299  {
1300  relopt_real *optreal = (relopt_real *) option->gen;
1301 
1302  parsed = parse_real(value, &option->values.real_val, 0, NULL);
1303  if (validate && !parsed)
1304  ereport(ERROR,
1305  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1306  errmsg("invalid value for floating point option \"%s\": %s",
1307  option->gen->name, value)));
1308  if (validate && (option->values.real_val < optreal->min ||
1309  option->values.real_val > optreal->max))
1310  ereport(ERROR,
1311  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1312  errmsg("value %s out of bounds for option \"%s\"",
1313  value, option->gen->name),
1314  errdetail("Valid values are between \"%f\" and \"%f\".",
1315  optreal->min, optreal->max)));
1316  }
1317  break;
1318  case RELOPT_TYPE_ENUM:
1319  {
1320  relopt_enum *optenum = (relopt_enum *) option->gen;
1321  relopt_enum_elt_def *elt;
1322 
1323  parsed = false;
1324  for (elt = optenum->members; elt->string_val; elt++)
1325  {
1326  if (pg_strcasecmp(value, elt->string_val) == 0)
1327  {
1328  option->values.enum_val = elt->symbol_val;
1329  parsed = true;
1330  break;
1331  }
1332  }
1333  if (validate && !parsed)
1334  ereport(ERROR,
1335  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1336  errmsg("invalid value for enum option \"%s\": %s",
1337  option->gen->name, value),
1338  optenum->detailmsg ?
1339  errdetail_internal("%s", _(optenum->detailmsg)) : 0));
1340 
1341  /*
1342  * If value is not among the allowed string values, but we are
1343  * not asked to validate, just use the default numeric value.
1344  */
1345  if (!parsed)
1346  option->values.enum_val = optenum->default_val;
1347  }
1348  break;
1349  case RELOPT_TYPE_STRING:
1350  {
1351  relopt_string *optstring = (relopt_string *) option->gen;
1352 
1353  option->values.string_val = value;
1354  nofree = true;
1355  if (validate && optstring->validate_cb)
1356  (optstring->validate_cb) (value);
1357  parsed = true;
1358  }
1359  break;
1360  default:
1361  elog(ERROR, "unsupported reloption type %d", option->gen->type);
1362  parsed = true; /* quiet compiler */
1363  break;
1364  }
1365 
1366  if (parsed)
1367  option->isset = true;
1368  if (!nofree)
1369  pfree(value);
1370 }
1371 
1372 /*
1373  * Given the result from parseRelOptions, allocate a struct that's of the
1374  * specified base size plus any extra space that's needed for string variables.
1375  *
1376  * "base" should be sizeof(struct) of the reloptions struct (StdRdOptions or
1377  * equivalent).
1378  */
1379 static void *
1381 {
1382  Size size = base;
1383  int i;
1384 
1385  for (i = 0; i < numoptions; i++)
1386  if (options[i].gen->type == RELOPT_TYPE_STRING)
1387  size += GET_STRING_RELOPTION_LEN(options[i]) + 1;
1388 
1389  return palloc0(size);
1390 }
1391 
1392 /*
1393  * Given the result of parseRelOptions and a parsing table, fill in the
1394  * struct (previously allocated with allocateReloptStruct) with the parsed
1395  * values.
1396  *
1397  * rdopts is the pointer to the allocated struct to be filled.
1398  * basesize is the sizeof(struct) that was passed to allocateReloptStruct.
1399  * options, of length numoptions, is parseRelOptions' output.
1400  * elems, of length numelems, is the table describing the allowed options.
1401  * When validate is true, it is expected that all options appear in elems.
1402  */
1403 static void
1404 fillRelOptions(void *rdopts, Size basesize,
1405  relopt_value *options, int numoptions,
1406  bool validate,
1407  const relopt_parse_elt *elems, int numelems)
1408 {
1409  int i;
1410  int offset = basesize;
1411 
1412  for (i = 0; i < numoptions; i++)
1413  {
1414  int j;
1415  bool found = false;
1416 
1417  for (j = 0; j < numelems; j++)
1418  {
1419  if (strcmp(options[i].gen->name, elems[j].optname) == 0)
1420  {
1421  relopt_string *optstring;
1422  char *itempos = ((char *) rdopts) + elems[j].offset;
1423  char *string_val;
1424 
1425  switch (options[i].gen->type)
1426  {
1427  case RELOPT_TYPE_BOOL:
1428  *(bool *) itempos = options[i].isset ?
1429  options[i].values.bool_val :
1430  ((relopt_bool *) options[i].gen)->default_val;
1431  break;
1432  case RELOPT_TYPE_INT:
1433  *(int *) itempos = options[i].isset ?
1434  options[i].values.int_val :
1435  ((relopt_int *) options[i].gen)->default_val;
1436  break;
1437  case RELOPT_TYPE_REAL:
1438  *(double *) itempos = options[i].isset ?
1439  options[i].values.real_val :
1440  ((relopt_real *) options[i].gen)->default_val;
1441  break;
1442  case RELOPT_TYPE_ENUM:
1443  *(int *) itempos = options[i].isset ?
1444  options[i].values.enum_val :
1445  ((relopt_enum *) options[i].gen)->default_val;
1446  break;
1447  case RELOPT_TYPE_STRING:
1448  optstring = (relopt_string *) options[i].gen;
1449  if (options[i].isset)
1450  string_val = options[i].values.string_val;
1451  else if (!optstring->default_isnull)
1452  string_val = optstring->default_val;
1453  else
1454  string_val = NULL;
1455 
1456  if (string_val == NULL)
1457  *(int *) itempos = 0;
1458  else
1459  {
1460  strcpy((char *) rdopts + offset, string_val);
1461  *(int *) itempos = offset;
1462  offset += strlen(string_val) + 1;
1463  }
1464  break;
1465  default:
1466  elog(ERROR, "unsupported reloption type %d",
1467  options[i].gen->type);
1468  break;
1469  }
1470  found = true;
1471  break;
1472  }
1473  }
1474  if (validate && !found)
1475  elog(ERROR, "reloption \"%s\" not found in parse table",
1476  options[i].gen->name);
1477  }
1478  SET_VARSIZE(rdopts, offset);
1479 }
1480 
1481 
1482 /*
1483  * Option parser for anything that uses StdRdOptions.
1484  */
1485 bytea *
1486 default_reloptions(Datum reloptions, bool validate, relopt_kind kind)
1487 {
1488  static const relopt_parse_elt tab[] = {
1489  {"fillfactor", RELOPT_TYPE_INT, offsetof(StdRdOptions, fillfactor)},
1490  {"autovacuum_enabled", RELOPT_TYPE_BOOL,
1491  offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, enabled)},
1492  {"autovacuum_vacuum_threshold", RELOPT_TYPE_INT,
1493  offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_threshold)},
1494  {"autovacuum_analyze_threshold", RELOPT_TYPE_INT,
1495  offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, analyze_threshold)},
1496  {"autovacuum_vacuum_cost_limit", RELOPT_TYPE_INT,
1497  offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_cost_limit)},
1498  {"autovacuum_freeze_min_age", RELOPT_TYPE_INT,
1499  offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, freeze_min_age)},
1500  {"autovacuum_freeze_max_age", RELOPT_TYPE_INT,
1501  offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, freeze_max_age)},
1502  {"autovacuum_freeze_table_age", RELOPT_TYPE_INT,
1503  offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, freeze_table_age)},
1504  {"autovacuum_multixact_freeze_min_age", RELOPT_TYPE_INT,
1505  offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, multixact_freeze_min_age)},
1506  {"autovacuum_multixact_freeze_max_age", RELOPT_TYPE_INT,
1507  offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, multixact_freeze_max_age)},
1508  {"autovacuum_multixact_freeze_table_age", RELOPT_TYPE_INT,
1509  offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, multixact_freeze_table_age)},
1510  {"log_autovacuum_min_duration", RELOPT_TYPE_INT,
1511  offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, log_min_duration)},
1512  {"toast_tuple_target", RELOPT_TYPE_INT,
1513  offsetof(StdRdOptions, toast_tuple_target)},
1514  {"autovacuum_vacuum_cost_delay", RELOPT_TYPE_REAL,
1515  offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_cost_delay)},
1516  {"autovacuum_vacuum_scale_factor", RELOPT_TYPE_REAL,
1517  offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_scale_factor)},
1518  {"autovacuum_analyze_scale_factor", RELOPT_TYPE_REAL,
1519  offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, analyze_scale_factor)},
1520  {"user_catalog_table", RELOPT_TYPE_BOOL,
1521  offsetof(StdRdOptions, user_catalog_table)},
1522  {"parallel_workers", RELOPT_TYPE_INT,
1523  offsetof(StdRdOptions, parallel_workers)},
1524  {"vacuum_index_cleanup", RELOPT_TYPE_BOOL,
1525  offsetof(StdRdOptions, vacuum_index_cleanup)},
1526  {"vacuum_truncate", RELOPT_TYPE_BOOL,
1527  offsetof(StdRdOptions, vacuum_truncate)}
1528  };
1529 
1530  return (bytea *) build_reloptions(reloptions, validate, kind,
1531  sizeof(StdRdOptions),
1532  tab, lengthof(tab));
1533 }
1534 
1535 /*
1536  * build_reloptions
1537  *
1538  * Parses "reloptions" provided by the caller, returning them in a
1539  * structure containing the parsed options. The parsing is done with
1540  * the help of a parsing table describing the allowed options, defined
1541  * by "relopt_elems" of length "num_relopt_elems".
1542  *
1543  * "validate" must be true if reloptions value is freshly built by
1544  * transformRelOptions(), as opposed to being read from the catalog, in which
1545  * case the values contained in it must already be valid.
1546  *
1547  * NULL is returned if the passed-in options did not match any of the options
1548  * in the parsing table, unless validate is true in which case an error would
1549  * be reported.
1550  */
1551 void *
1552 build_reloptions(Datum reloptions, bool validate,
1553  relopt_kind kind,
1554  Size relopt_struct_size,
1555  const relopt_parse_elt *relopt_elems,
1556  int num_relopt_elems)
1557 {
1558  int numoptions;
1560  void *rdopts;
1561 
1562  /* parse options specific to given relation option kind */
1563  options = parseRelOptions(reloptions, validate, kind, &numoptions);
1564  Assert(numoptions <= num_relopt_elems);
1565 
1566  /* if none set, we're done */
1567  if (numoptions == 0)
1568  {
1569  Assert(options == NULL);
1570  return NULL;
1571  }
1572 
1573  /* allocate and fill the structure */
1574  rdopts = allocateReloptStruct(relopt_struct_size, options, numoptions);
1575  fillRelOptions(rdopts, relopt_struct_size, options, numoptions,
1576  validate, relopt_elems, num_relopt_elems);
1577 
1578  pfree(options);
1579 
1580  return rdopts;
1581 }
1582 
1583 /*
1584  * Option parser for partitioned tables
1585  */
1586 bytea *
1587 partitioned_table_reloptions(Datum reloptions, bool validate)
1588 {
1589  /*
1590  * There are no options for partitioned tables yet, but this is able to do
1591  * some validation.
1592  */
1593  return (bytea *) build_reloptions(reloptions, validate,
1595  0, NULL, 0);
1596 }
1597 
1598 /*
1599  * Option parser for views
1600  */
1601 bytea *
1602 view_reloptions(Datum reloptions, bool validate)
1603 {
1604  static const relopt_parse_elt tab[] = {
1605  {"security_barrier", RELOPT_TYPE_BOOL,
1606  offsetof(ViewOptions, security_barrier)},
1607  {"check_option", RELOPT_TYPE_ENUM,
1608  offsetof(ViewOptions, check_option)}
1609  };
1610 
1611  return (bytea *) build_reloptions(reloptions, validate,
1613  sizeof(ViewOptions),
1614  tab, lengthof(tab));
1615 }
1616 
1617 /*
1618  * Parse options for heaps, views and toast tables.
1619  */
1620 bytea *
1621 heap_reloptions(char relkind, Datum reloptions, bool validate)
1622 {
1623  StdRdOptions *rdopts;
1624 
1625  switch (relkind)
1626  {
1627  case RELKIND_TOASTVALUE:
1628  rdopts = (StdRdOptions *)
1629  default_reloptions(reloptions, validate, RELOPT_KIND_TOAST);
1630  if (rdopts != NULL)
1631  {
1632  /* adjust default-only parameters for TOAST relations */
1633  rdopts->fillfactor = 100;
1634  rdopts->autovacuum.analyze_threshold = -1;
1635  rdopts->autovacuum.analyze_scale_factor = -1;
1636  }
1637  return (bytea *) rdopts;
1638  case RELKIND_RELATION:
1639  case RELKIND_MATVIEW:
1640  return default_reloptions(reloptions, validate, RELOPT_KIND_HEAP);
1641  default:
1642  /* other relkinds are not supported */
1643  return NULL;
1644  }
1645 }
1646 
1647 
1648 /*
1649  * Parse options for indexes.
1650  *
1651  * amoptions index AM's option parser function
1652  * reloptions options as text[] datum
1653  * validate error flag
1654  */
1655 bytea *
1656 index_reloptions(amoptions_function amoptions, Datum reloptions, bool validate)
1657 {
1658  Assert(amoptions != NULL);
1659 
1660  /* Assume function is strict */
1661  if (!PointerIsValid(DatumGetPointer(reloptions)))
1662  return NULL;
1663 
1664  return amoptions(reloptions, validate);
1665 }
1666 
1667 /*
1668  * Option parser for attribute reloptions
1669  */
1670 bytea *
1671 attribute_reloptions(Datum reloptions, bool validate)
1672 {
1673  static const relopt_parse_elt tab[] = {
1674  {"n_distinct", RELOPT_TYPE_REAL, offsetof(AttributeOpts, n_distinct)},
1675  {"n_distinct_inherited", RELOPT_TYPE_REAL, offsetof(AttributeOpts, n_distinct_inherited)}
1676  };
1677 
1678  return (bytea *) build_reloptions(reloptions, validate,
1680  sizeof(AttributeOpts),
1681  tab, lengthof(tab));
1682 }
1683 
1684 /*
1685  * Option parser for tablespace reloptions
1686  */
1687 bytea *
1688 tablespace_reloptions(Datum reloptions, bool validate)
1689 {
1690  static const relopt_parse_elt tab[] = {
1691  {"random_page_cost", RELOPT_TYPE_REAL, offsetof(TableSpaceOpts, random_page_cost)},
1692  {"seq_page_cost", RELOPT_TYPE_REAL, offsetof(TableSpaceOpts, seq_page_cost)},
1693  {"effective_io_concurrency", RELOPT_TYPE_INT, offsetof(TableSpaceOpts, effective_io_concurrency)}
1694  };
1695 
1696  return (bytea *) build_reloptions(reloptions, validate,
1698  sizeof(TableSpaceOpts),
1699  tab, lengthof(tab));
1700 }
1701 
1702 /*
1703  * Determine the required LOCKMODE from an option list.
1704  *
1705  * Called from AlterTableGetLockLevel(), see that function
1706  * for a longer explanation of how this works.
1707  */
1708 LOCKMODE
1710 {
1711  LOCKMODE lockmode = NoLock;
1712  ListCell *cell;
1713 
1714  if (defList == NIL)
1715  return AccessExclusiveLock;
1716 
1717  if (need_initialization)
1719 
1720  foreach(cell, defList)
1721  {
1722  DefElem *def = (DefElem *) lfirst(cell);
1723  int i;
1724 
1725  for (i = 0; relOpts[i]; i++)
1726  {
1727  if (strncmp(relOpts[i]->name,
1728  def->defname,
1729  relOpts[i]->namelen + 1) == 0)
1730  {
1731  if (lockmode < relOpts[i]->lockmode)
1732  lockmode = relOpts[i]->lockmode;
1733  }
1734  }
1735  }
1736 
1737  return lockmode;
1738 }
Value * makeString(char *str)
Definition: value.c:53
#define HASH_DEFAULT_FILLFACTOR
Definition: hash.h:294
bytea * heap_reloptions(char relkind, Datum reloptions, bool validate)
Definition: reloptions.c:1621
#define NIL
Definition: pg_list.h:65
bool bool_val
Definition: reloptions.h:81
#define MAX_IO_CONCURRENCY
Definition: bufmgr.h:78
static void initialize_reloptions(void)
Definition: reloptions.c:515
#define HASH_MIN_FILLFACTOR
Definition: hash.h:293
static relopt_gen ** custom_options
Definition: reloptions.c:492
#define SPGIST_MIN_FILLFACTOR
relopt_gen gen
Definition: reloptions.h:124
char * string_val
Definition: reloptions.h:85
#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:863
const char * desc
Definition: reloptions.h:67
int LOCKMODE
Definition: lockdefs.h:26
struct relopt_enum relopt_enum
#define VARSIZE(PTR)
Definition: postgres.h:303
#define PointerGetDatum(X)
Definition: postgres.h:556
LOCKMODE lockmode
Definition: reloptions.h:69
#define VARHDRSZ
Definition: c.h:562
char * pstrdup(const char *in)
Definition: mcxt.c:1186
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
char * defnamespace
Definition: parsenodes.h:729
static relopt_bool boolRelOpts[]
Definition: reloptions.c:96
#define gettext_noop(x)
Definition: c.h:1148
static struct @145 value
bytea * tablespace_reloptions(Datum reloptions, bool validate)
Definition: reloptions.c:1688
Definition: nodes.h:525
bool default_isnull
Definition: reloptions.h:138
int fillfactor
Definition: rel.h:266
int errcode(int sqlerrcode)
Definition: elog.c:608
static void * allocateReloptStruct(Size base, relopt_value *options, int numoptions)
Definition: reloptions.c:1380
bool parse_real(const char *value, double *result, int flags, const char **hintmsg)
Definition: guc.c:6409
bool default_val
Definition: reloptions.h:93
bool parse_bool(const char *value, bool *result)
Definition: bool.c:30
relopt_gen gen
Definition: reloptions.h:136
relopt_enum_elt_def gistBufferingOptValues[]
Definition: reloptions.c:437
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
#define lengthof(array)
Definition: c.h:669
relopt_gen * gen
Definition: reloptions.h:77
void add_int_reloption(bits32 kinds, const char *name, const char *desc, int default_val, int min_val, int max_val, LOCKMODE lockmode)
Definition: reloptions.c:739
struct relopt_bool relopt_bool
DefElem * makeDefElem(char *name, Node *arg, int location)
Definition: makefuncs.c:544
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:1671
#define TOAST_TUPLE_TARGET
Definition: heaptoast.h:50
void * build_reloptions(Datum reloptions, bool validate, relopt_kind kind, Size relopt_struct_size, const relopt_parse_elt *relopt_elems, int num_relopt_elems)
Definition: reloptions.c:1552
int errdetail_internal(const char *fmt,...)
Definition: elog.c:982
#define GET_STRING_RELOPTION_LEN(option)
Definition: reloptions.c:504
struct relopt_real relopt_real
bytea * view_reloptions(Datum reloptions, bool validate)
Definition: reloptions.c:1602
#define sprintf
Definition: port.h:194
double default_val
Definition: reloptions.h:107
#define SPGIST_DEFAULT_FILLFACTOR
double random_page_cost
Definition: costsize.c:111
bool defGetBoolean(DefElem *def)
Definition: define.c:111
void pfree(void *pointer)
Definition: mcxt.c:1056
#define MAX_KILOBYTES
Definition: guc.h:26
static relopt_gen * allocate_reloption(bits32 kinds, int type, const char *name, const char *desc, LOCKMODE lockmode)
Definition: reloptions.c:669
#define ERROR
Definition: elog.h:43
const char * detailmsg
Definition: reloptions.h:127
static void parse_one_reloption(relopt_value *option, char *text_str, int text_len, bool validate)
Definition: reloptions.c:1247
static int num_custom_options
Definition: reloptions.c:491
int fillfactor
Definition: pgbench.c:160
char * defGetString(DefElem *def)
Definition: define.c:49
union relopt_value::@47 values
relopt_gen gen
Definition: reloptions.h:92
int analyze_threshold
Definition: rel.h:249
#define NoLock
Definition: lockdefs.h:34
bool DoLockModesConflict(LOCKMODE mode1, LOCKMODE mode2)
Definition: lock.c:556
static relopt_real realRelOpts[]
Definition: reloptions.c:358
static void fillRelOptions(void *rdopts, Size basesize, relopt_value *options, int numoptions, bool validate, const relopt_parse_elt *elems, int numelems)
Definition: reloptions.c:1404
int errdetail(const char *fmt,...)
Definition: elog.c:955
int namelen
Definition: reloptions.h:70
relopt_enum_elt_def * members
Definition: reloptions.h:125
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
double real_val
Definition: reloptions.h:83
#define GIST_DEFAULT_FILLFACTOR
Definition: gist_private.h:472
#define TOAST_TUPLE_TARGET_MAIN
Definition: heaptoast.h:61
#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:170
static relopt_value * parseRelOptions(Datum options, bool validate, relopt_kind kind, int *numrelopts)
Definition: reloptions.c:1155
validate_string_relopt validate_cb
Definition: reloptions.h:139
MemoryContext TopMemoryContext
Definition: mcxt.c:44
Node * arg
Definition: parsenodes.h:731
List * lappend(List *list, void *datum)
Definition: list.c:322
#define BTREE_MIN_FILLFACTOR
Definition: nbtree.h:169
static char ** options
bits32 kinds
Definition: reloptions.h:68
bytea * partitioned_table_reloptions(Datum reloptions, bool validate)
Definition: reloptions.c:1587
int default_val
Definition: reloptions.h:126
relopt_enum_elt_def viewCheckOptValues[]
Definition: reloptions.c:446
#define TextDatumGetCString(d)
Definition: builtins.h:84
void * palloc0(Size size)
Definition: mcxt.c:980
uintptr_t Datum
Definition: postgres.h:367
relopt_gen gen
Definition: reloptions.h:98
bool parse_int(const char *value, int *result, int flags, const char **hintmsg)
Definition: guc.c:6319
const char * optname
Definition: reloptions.h:146
List * untransformRelOptions(Datum options)
Definition: reloptions.c:1039
bytea * extractRelOptions(HeapTuple tuple, TupleDesc tupdesc, amoptions_function amoptions)
Definition: reloptions.c:1088
bytea * index_reloptions(amoptions_function amoptions, Datum reloptions, bool validate)
Definition: reloptions.c:1656
float8 analyze_scale_factor
Definition: rel.h:260
#define ShareUpdateExclusiveLock
Definition: lockdefs.h:39
uint32 bits32
Definition: c.h:368
#define Assert(condition)
Definition: c.h:739
#define lfirst(lc)
Definition: pg_list.h:190
void(* validate_string_relopt)(const char *value)
Definition: reloptions.h:132
#define HEAP_MIN_FILLFACTOR
Definition: rel.h:276
relopt_type type
Definition: reloptions.h:71
#define GIST_MIN_FILLFACTOR
Definition: gist_private.h:471
struct relopt_int relopt_int
size_t Size
Definition: c.h:467
void add_real_reloption(bits32 kinds, const char *name, const char *desc, double default_val, double min_val, double max_val, LOCKMODE lockmode)
Definition: reloptions.c:758
const char * string_val
Definition: reloptions.h:118
static void add_reloption(relopt_gen *newoption)
Definition: reloptions.c:635
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1069
LOCKMODE AlterTableGetRelOptionsLockLevel(List *defList)
Definition: reloptions.c:1709
relopt_gen gen
Definition: reloptions.h:106
const char * name
Definition: encode.c:521
static relopt_string stringRelOpts[]
Definition: reloptions.c:482
relopt_kind add_reloption_kind(void)
Definition: reloptions.c:618
#define DatumGetPointer(X)
Definition: postgres.h:549
int default_val
Definition: reloptions.h:99
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:1486
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:822
void add_string_reloption(bits32 kinds, const char *name, const char *desc, const char *default_val, validate_string_relopt validator, LOCKMODE lockmode)
Definition: reloptions.c:810
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1173
const char * name
Definition: reloptions.h:65
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:796
relopt_kind
Definition: reloptions.h:39
#define elog(elevel,...)
Definition: elog.h:228
int i
static bool need_initialization
Definition: reloptions.c:493
Definition: c.h:556
char * defname
Definition: parsenodes.h:730
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:329
bytea *(* amoptions_function)(Datum reloptions, bool validate)
Definition: amapi.h:103
static relopt_enum enumRelOpts[]
Definition: reloptions.c:454
#define HEAP_DEFAULT_FILLFACTOR
Definition: rel.h:277
static relopt_int intRelOpts[]
Definition: reloptions.c:165
char * default_val
Definition: reloptions.h:140
static relopt_gen ** relOpts
Definition: reloptions.c:488
double max
Definition: reloptions.h:109
void add_enum_reloption(bits32 kinds, const char *name, const char *desc, relopt_enum_elt_def *members, int default_val, const char *detailmsg, LOCKMODE lockmode)
Definition: reloptions.c:785
double seq_page_cost
Definition: costsize.c:110
static size_t noptions
static bits32 last_assigned_kind
Definition: reloptions.c:489
void add_bool_reloption(bits32 kinds, const char *name, const char *desc, bool default_val, LOCKMODE lockmode)
Definition: reloptions.c:722
Definition: pg_list.h:50
#define PointerIsValid(pointer)
Definition: c.h:633
#define _(x)
Definition: elog.c:87
long val
Definition: informix.c:664
double min
Definition: reloptions.h:108
#define offsetof(type, field)
Definition: c.h:662
#define DatumGetArrayTypeP(X)
Definition: array.h:249
AutoVacOpts autovacuum
Definition: rel.h:269