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