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