1 /*-------------------------------------------------------------------------
4 * Core support for relation options (pg_class.reloptions)
6 * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
13 *-------------------------------------------------------------------------
18 #include "access/gist_private.h"
19 #include "access/hash.h"
20 #include "access/nbtree.h"
21 #include "access/reloptions.h"
22 #include "catalog/pg_type.h"
23 #include "commands/defrem.h"
24 #include "nodes/makefuncs.h"
25 #include "utils/array.h"
26 #include "utils/builtins.h"
27 #include "utils/guc.h"
28 #include "utils/memutils.h"
29 #include "utils/rel.h"
32 * Contents of pg_class.reloptions
36 * (i) decide on a type (integer, real, bool, string), name, default value,
37 * upper and lower bounds (if applicable); for strings, consider a validation
39 * (ii) add a record below (or use add_<type>_reloption).
40 * (iii) add it to the appropriate options struct (perhaps StdRdOptions)
41 * (iv) add it to the appropriate handling routine (perhaps
43 * (v) don't forget to document the option
45 * Note that we don't handle "oids" in relOpts because it is handled by
46 * interpretOidsOption().
49 static relopt_bool boolRelOpts
[] =
54 "Enables autovacuum in this relation",
63 static relopt_int intRelOpts
[] =
68 "Packs table pages only to this percentage",
71 HEAP_DEFAULT_FILLFACTOR
, HEAP_MIN_FILLFACTOR
, 100
76 "Packs btree index pages only to this percentage",
79 BTREE_DEFAULT_FILLFACTOR
, BTREE_MIN_FILLFACTOR
, 100
84 "Packs hash index pages only to this percentage",
87 HASH_DEFAULT_FILLFACTOR
, HASH_MIN_FILLFACTOR
, 100
92 "Packs gist index pages only to this percentage",
95 GIST_DEFAULT_FILLFACTOR
, GIST_MIN_FILLFACTOR
, 100
99 "autovacuum_vacuum_threshold",
100 "Minimum number of tuple updates or deletes prior to vacuum",
107 "autovacuum_analyze_threshold",
108 "Minimum number of tuple inserts, updates or deletes prior to analyze",
115 "autovacuum_vacuum_cost_delay",
116 "Vacuum cost delay in milliseconds, for autovacuum",
123 "autovacuum_vacuum_cost_limit",
124 "Vacuum cost amount available before napping, for autovacuum",
131 "autovacuum_freeze_min_age",
132 "Minimum age at which VACUUM should freeze a table row, for autovacuum",
135 100000000, 0, 1000000000
139 "autovacuum_freeze_max_age",
140 "Age at which to autovacuum a table to prevent transaction ID wraparound",
143 200000000, 100000000, 2000000000
147 "autovacuum_freeze_table_age",
148 "Age at which VACUUM should perform a full table sweep to replace old Xid values with FrozenXID",
150 }, 150000000, 0, 2000000000
152 /* list terminator */
156 static relopt_real realRelOpts
[] =
160 "autovacuum_vacuum_scale_factor",
161 "Number of tuple updates or deletes prior to vacuum as a fraction of reltuples",
168 "autovacuum_analyze_scale_factor",
169 "Number of tuple inserts, updates or deletes prior to analyze as a fraction of reltuples",
174 /* list terminator */
178 static relopt_string stringRelOpts
[] =
180 /* list terminator */
184 static relopt_gen
**relOpts
= NULL
;
185 static int last_assigned_kind
= RELOPT_KIND_LAST_DEFAULT
+ 1;
187 static int num_custom_options
= 0;
188 static relopt_gen
**custom_options
= NULL
;
189 static bool need_initialization
= true;
191 static void initialize_reloptions(void);
192 static void parse_one_reloption(relopt_value
*option
, char *text_str
,
193 int text_len
, bool validate
);
196 * initialize_reloptions
197 * initialization routine, must be called before parsing
199 * Initialize the relOpts array and fill each variable's type and name length.
202 initialize_reloptions(void)
207 for (i
= 0; boolRelOpts
[i
].gen
.name
; i
++)
209 for (i
= 0; intRelOpts
[i
].gen
.name
; i
++)
211 for (i
= 0; realRelOpts
[i
].gen
.name
; i
++)
213 for (i
= 0; stringRelOpts
[i
].gen
.name
; i
++)
215 j
+= num_custom_options
;
219 relOpts
= MemoryContextAlloc(TopMemoryContext
,
220 (j
+ 1) * sizeof(relopt_gen
*));
223 for (i
= 0; boolRelOpts
[i
].gen
.name
; i
++)
225 relOpts
[j
] = &boolRelOpts
[i
].gen
;
226 relOpts
[j
]->type
= RELOPT_TYPE_BOOL
;
227 relOpts
[j
]->namelen
= strlen(relOpts
[j
]->name
);
231 for (i
= 0; intRelOpts
[i
].gen
.name
; i
++)
233 relOpts
[j
] = &intRelOpts
[i
].gen
;
234 relOpts
[j
]->type
= RELOPT_TYPE_INT
;
235 relOpts
[j
]->namelen
= strlen(relOpts
[j
]->name
);
239 for (i
= 0; realRelOpts
[i
].gen
.name
; i
++)
241 relOpts
[j
] = &realRelOpts
[i
].gen
;
242 relOpts
[j
]->type
= RELOPT_TYPE_REAL
;
243 relOpts
[j
]->namelen
= strlen(relOpts
[j
]->name
);
247 for (i
= 0; stringRelOpts
[i
].gen
.name
; i
++)
249 relOpts
[j
] = &stringRelOpts
[i
].gen
;
250 relOpts
[j
]->type
= RELOPT_TYPE_STRING
;
251 relOpts
[j
]->namelen
= strlen(relOpts
[j
]->name
);
255 for (i
= 0; i
< num_custom_options
; i
++)
257 relOpts
[j
] = custom_options
[i
];
261 /* add a list terminator */
267 * Create a new relopt_kind value, to be used in custom reloptions by
271 add_reloption_kind(void)
273 if (last_assigned_kind
>= RELOPT_KIND_MAX
)
275 (errmsg("user-defined relation parameter types limit exceeded")));
277 return last_assigned_kind
++;
282 * Add an already-created custom reloption to the list, and recompute the
286 add_reloption(relopt_gen
*newoption
)
288 static int max_custom_options
= 0;
290 if (num_custom_options
>= max_custom_options
)
292 MemoryContext oldcxt
;
294 oldcxt
= MemoryContextSwitchTo(TopMemoryContext
);
296 if (max_custom_options
== 0)
298 max_custom_options
= 8;
299 custom_options
= palloc(max_custom_options
* sizeof(relopt_gen
*));
303 max_custom_options
*= 2;
304 custom_options
= repalloc(custom_options
,
305 max_custom_options
* sizeof(relopt_gen
*));
307 MemoryContextSwitchTo(oldcxt
);
309 custom_options
[num_custom_options
++] = newoption
;
311 need_initialization
= true;
316 * Allocate a new reloption and initialize the type-agnostic fields
317 * (for types other than string)
320 allocate_reloption(int kind
, int type
, char *name
, char *desc
)
322 MemoryContext oldcxt
;
324 relopt_gen
*newoption
;
326 Assert(type
!= RELOPT_TYPE_STRING
);
328 oldcxt
= MemoryContextSwitchTo(TopMemoryContext
);
332 case RELOPT_TYPE_BOOL
:
333 size
= sizeof(relopt_bool
);
335 case RELOPT_TYPE_INT
:
336 size
= sizeof(relopt_int
);
338 case RELOPT_TYPE_REAL
:
339 size
= sizeof(relopt_real
);
342 elog(ERROR
, "unsupported option type");
343 return NULL
; /* keep compiler quiet */
346 newoption
= palloc(size
);
348 newoption
->name
= pstrdup(name
);
350 newoption
->desc
= pstrdup(desc
);
352 newoption
->desc
= NULL
;
353 newoption
->kind
= kind
;
354 newoption
->namelen
= strlen(name
);
355 newoption
->type
= type
;
357 MemoryContextSwitchTo(oldcxt
);
364 * Add a new boolean reloption
367 add_bool_reloption(int kind
, char *name
, char *desc
, bool default_val
)
369 relopt_bool
*newoption
;
371 newoption
= (relopt_bool
*) allocate_reloption(kind
, RELOPT_TYPE_BOOL
,
373 newoption
->default_val
= default_val
;
375 add_reloption((relopt_gen
*) newoption
);
380 * Add a new integer reloption
383 add_int_reloption(int kind
, char *name
, char *desc
, int default_val
,
384 int min_val
, int max_val
)
386 relopt_int
*newoption
;
388 newoption
= (relopt_int
*) allocate_reloption(kind
, RELOPT_TYPE_INT
,
390 newoption
->default_val
= default_val
;
391 newoption
->min
= min_val
;
392 newoption
->max
= max_val
;
394 add_reloption((relopt_gen
*) newoption
);
399 * Add a new float reloption
402 add_real_reloption(int kind
, char *name
, char *desc
, double default_val
,
403 double min_val
, double max_val
)
405 relopt_real
*newoption
;
407 newoption
= (relopt_real
*) allocate_reloption(kind
, RELOPT_TYPE_REAL
,
409 newoption
->default_val
= default_val
;
410 newoption
->min
= min_val
;
411 newoption
->max
= max_val
;
413 add_reloption((relopt_gen
*) newoption
);
417 * add_string_reloption
418 * Add a new string reloption
420 * "validator" is an optional function pointer that can be used to test the
421 * validity of the values. It must elog(ERROR) when the argument string is
422 * not acceptable for the variable. Note that the default value must pass
426 add_string_reloption(int kind
, char *name
, char *desc
, char *default_val
,
427 validate_string_relopt validator
)
429 MemoryContext oldcxt
;
430 relopt_string
*newoption
;
433 oldcxt
= MemoryContextSwitchTo(TopMemoryContext
);
436 default_len
= strlen(default_val
);
438 newoption
= palloc0(sizeof(relopt_string
) + default_len
);
440 newoption
->gen
.name
= pstrdup(name
);
442 newoption
->gen
.desc
= pstrdup(desc
);
444 newoption
->gen
.desc
= NULL
;
445 newoption
->gen
.kind
= kind
;
446 newoption
->gen
.namelen
= strlen(name
);
447 newoption
->gen
.type
= RELOPT_TYPE_STRING
;
448 newoption
->validate_cb
= validator
;
451 strcpy(newoption
->default_val
, default_val
);
452 newoption
->default_len
= default_len
;
453 newoption
->default_isnull
= false;
457 newoption
->default_val
[0] = '\0';
458 newoption
->default_len
= 0;
459 newoption
->default_isnull
= true;
462 /* make sure the validator/default combination is sane */
463 if (newoption
->validate_cb
)
464 (newoption
->validate_cb
) (newoption
->default_val
);
466 MemoryContextSwitchTo(oldcxt
);
468 add_reloption((relopt_gen
*) newoption
);
472 * Transform a relation options list (list of ReloptElem) into the text array
473 * format that is kept in pg_class.reloptions, including only those options
474 * that are in the passed namespace. The output values do not include the
477 * This is used for three cases: CREATE TABLE/INDEX, ALTER TABLE SET, and
478 * ALTER TABLE RESET. In the ALTER cases, oldOptions is the existing
479 * reloptions value (possibly NULL), and we replace or remove entries
482 * If ignoreOids is true, then we should ignore any occurrence of "oids"
483 * in the list (it will be or has been handled by interpretOidsOption()).
485 * Note that this is not responsible for determining whether the options
486 * are valid, but it does check that namespaces for all the options given are
487 * listed in validnsps. The NULL namespace is always valid and needs not be
488 * explicitely listed. Passing a NULL pointer means that only the NULL
489 * namespace is valid.
491 * Both oldOptions and the result are text arrays (or NULL for "default"),
492 * but we declare them as Datums to avoid including array.h in reloptions.h.
495 transformRelOptions(Datum oldOptions
, List
*defList
, char *namspace
,
496 char *validnsps
[], bool ignoreOids
, bool isReset
)
499 ArrayBuildState
*astate
;
502 /* no change if empty list */
506 /* We build new array using accumArrayResult */
509 /* Copy any oldOptions that aren't to be replaced */
510 if (PointerIsValid(DatumGetPointer(oldOptions
)))
512 ArrayType
*array
= DatumGetArrayTypeP(oldOptions
);
517 Assert(ARR_ELEMTYPE(array
) == TEXTOID
);
519 deconstruct_array(array
, TEXTOID
, -1, false, 'i',
520 &oldoptions
, NULL
, &noldoptions
);
522 for (i
= 0; i
< noldoptions
; i
++)
524 text
*oldoption
= DatumGetTextP(oldoptions
[i
]);
525 char *text_str
= VARDATA(oldoption
);
526 int text_len
= VARSIZE(oldoption
) - VARHDRSZ
;
528 /* Search for a match in defList */
529 foreach(cell
, defList
)
531 ReloptElem
*def
= lfirst(cell
);
534 /* ignore if not in the same namespace */
535 if (namspace
== NULL
)
537 if (def
->nmspc
!= NULL
)
540 else if (def
->nmspc
== NULL
)
542 else if (pg_strcasecmp(def
->nmspc
, namspace
) != 0)
545 kw_len
= strlen(def
->optname
);
546 if (text_len
> kw_len
&& text_str
[kw_len
] == '=' &&
547 pg_strncasecmp(text_str
, def
->optname
, kw_len
) == 0)
552 /* No match, so keep old option */
553 astate
= accumArrayResult(astate
, oldoptions
[i
],
555 CurrentMemoryContext
);
561 * If CREATE/SET, add new options to array; if RESET, just check that the
562 * user didn't say RESET (option=val). (Must do this because the grammar
563 * doesn't enforce it.)
565 foreach(cell
, defList
)
567 ReloptElem
*def
= lfirst(cell
);
572 if (def
->arg
!= NULL
)
574 (errcode(ERRCODE_SYNTAX_ERROR
),
575 errmsg("RESET must not include values for parameters")));
584 * Error out if the namespace is not valid. A NULL namespace
587 if (def
->nmspc
!= NULL
)
594 for (i
= 0; validnsps
[i
]; i
++)
596 if (pg_strcasecmp(def
->nmspc
, validnsps
[i
]) == 0)
606 (errcode(ERRCODE_INVALID_PARAMETER_VALUE
),
607 errmsg("unrecognized parameter namespace \"%s\"",
611 if (ignoreOids
&& pg_strcasecmp(def
->optname
, "oids") == 0)
614 /* ignore if not in the same namespace */
615 if (namspace
== NULL
)
617 if (def
->nmspc
!= NULL
)
620 else if (def
->nmspc
== NULL
)
622 else if (pg_strcasecmp(def
->nmspc
, namspace
) != 0)
626 * Flatten the ReloptElem into a text string like "name=arg". If we
627 * have just "name", assume "name=true" is meant. Note: the
628 * namespace is not output.
630 if (def
->arg
!= NULL
)
631 value
= reloptGetString(def
);
634 len
= VARHDRSZ
+ strlen(def
->optname
) + 1 + strlen(value
);
635 /* +1 leaves room for sprintf's trailing null */
636 t
= (text
*) palloc(len
+ 1);
638 sprintf(VARDATA(t
), "%s=%s", def
->optname
, value
);
640 astate
= accumArrayResult(astate
, PointerGetDatum(t
),
642 CurrentMemoryContext
);
647 result
= makeArrayResult(astate
, CurrentMemoryContext
);
656 * Convert the text-array format of reloptions into a List of DefElem.
657 * This is the inverse of transformRelOptions().
660 untransformRelOptions(Datum options
)
668 /* Nothing to do if no options */
669 if (!PointerIsValid(DatumGetPointer(options
)))
672 array
= DatumGetArrayTypeP(options
);
674 Assert(ARR_ELEMTYPE(array
) == TEXTOID
);
676 deconstruct_array(array
, TEXTOID
, -1, false, 'i',
677 &optiondatums
, NULL
, &noptions
);
679 for (i
= 0; i
< noptions
; i
++)
685 s
= TextDatumGetCString(optiondatums
[i
]);
690 val
= (Node
*) makeString(pstrdup(p
));
692 result
= lappend(result
, makeDefElem(pstrdup(s
), val
));
699 * Extract and parse reloptions from a pg_class tuple.
701 * This is a low-level routine, expected to be used by relcache code and
702 * callers that do not have a table's relcache entry (e.g. autovacuum). For
703 * other uses, consider grabbing the rd_options pointer from the relcache entry
706 * tupdesc is pg_class' tuple descriptor. amoptions is the amoptions regproc
707 * in the case of the tuple corresponding to an index, or InvalidOid otherwise.
710 extractRelOptions(HeapTuple tuple
, TupleDesc tupdesc
, Oid amoptions
)
715 Form_pg_class classForm
;
717 datum
= fastgetattr(tuple
,
718 Anum_pg_class_reloptions
,
724 classForm
= (Form_pg_class
) GETSTRUCT(tuple
);
726 /* Parse into appropriate format; don't error out here */
727 switch (classForm
->relkind
)
729 case RELKIND_RELATION
:
730 case RELKIND_TOASTVALUE
:
731 case RELKIND_UNCATALOGED
:
732 options
= heap_reloptions(classForm
->relkind
, datum
, false);
735 options
= index_reloptions(amoptions
, datum
, false);
738 Assert(false); /* can't get here */
739 options
= NULL
; /* keep compiler quiet */
747 * Interpret reloptions that are given in text-array format.
749 * options is a reloption text array as constructed by transformRelOptions.
750 * kind specifies the family of options to be processed.
752 * The return value is a relopt_value * array on which the options actually
753 * set in the options array are marked with isset=true. The length of this
754 * array is returned in *numrelopts. Options not set are also present in the
755 * array; this is so that the caller can easily locate the default values.
757 * If there are no options of the given kind, numrelopts is set to 0 and NULL
760 * Note: values of type int, bool and real are allocated as part of the
761 * returned array. Values of type string are allocated separately and must
762 * be freed by the caller.
765 parseRelOptions(Datum options
, bool validate
, relopt_kind kind
,
768 relopt_value
*reloptions
;
773 if (need_initialization
)
774 initialize_reloptions();
776 /* Build a list of expected options, based on kind */
778 for (i
= 0; relOpts
[i
]; i
++)
779 if (relOpts
[i
]->kind
== kind
)
788 reloptions
= palloc(numoptions
* sizeof(relopt_value
));
790 for (i
= 0, j
= 0; relOpts
[i
]; i
++)
792 if (relOpts
[i
]->kind
== kind
)
794 reloptions
[j
].gen
= relOpts
[i
];
795 reloptions
[j
].isset
= false;
800 /* Done if no options */
801 if (PointerIsValid(DatumGetPointer(options
)))
807 array
= DatumGetArrayTypeP(options
);
809 Assert(ARR_ELEMTYPE(array
) == TEXTOID
);
811 deconstruct_array(array
, TEXTOID
, -1, false, 'i',
812 &optiondatums
, NULL
, &noptions
);
814 for (i
= 0; i
< noptions
; i
++)
816 text
*optiontext
= DatumGetTextP(optiondatums
[i
]);
817 char *text_str
= VARDATA(optiontext
);
818 int text_len
= VARSIZE(optiontext
) - VARHDRSZ
;
821 /* Search for a match in reloptions */
822 for (j
= 0; j
< numoptions
; j
++)
824 int kw_len
= reloptions
[j
].gen
->namelen
;
826 if (text_len
> kw_len
&& text_str
[kw_len
] == '=' &&
827 pg_strncasecmp(text_str
, reloptions
[j
].gen
->name
,
830 parse_one_reloption(&reloptions
[j
], text_str
, text_len
,
836 if (j
>= numoptions
&& validate
)
841 s
= TextDatumGetCString(optiondatums
[i
]);
846 (errcode(ERRCODE_INVALID_PARAMETER_VALUE
),
847 errmsg("unrecognized parameter \"%s\"", s
)));
852 *numrelopts
= numoptions
;
857 * Subroutine for parseRelOptions, to parse and validate a single option's
861 parse_one_reloption(relopt_value
*option
, char *text_str
, int text_len
,
869 if (option
->isset
&& validate
)
871 (errcode(ERRCODE_INVALID_PARAMETER_VALUE
),
872 errmsg("parameter \"%s\" specified more than once",
873 option
->gen
->name
)));
875 value_len
= text_len
- option
->gen
->namelen
- 1;
876 value
= (char *) palloc(value_len
+ 1);
877 memcpy(value
, text_str
+ option
->gen
->namelen
+ 1, value_len
);
878 value
[value_len
] = '\0';
880 switch (option
->gen
->type
)
882 case RELOPT_TYPE_BOOL
:
884 parsed
= parse_bool(value
, &option
->values
.bool_val
);
885 if (validate
&& !parsed
)
887 (errmsg("invalid value for boolean option \"%s\": %s",
888 option
->gen
->name
, value
)));
891 case RELOPT_TYPE_INT
:
893 relopt_int
*optint
= (relopt_int
*) option
->gen
;
895 parsed
= parse_int(value
, &option
->values
.int_val
, 0, NULL
);
896 if (validate
&& !parsed
)
898 (errmsg("invalid value for integer option \"%s\": %s",
899 option
->gen
->name
, value
)));
900 if (validate
&& (option
->values
.int_val
< optint
->min
||
901 option
->values
.int_val
> optint
->max
))
903 (errmsg("value %s out of bounds for option \"%s\"",
904 value
, option
->gen
->name
),
905 errdetail("Valid values are between \"%d\" and \"%d\".",
906 optint
->min
, optint
->max
)));
909 case RELOPT_TYPE_REAL
:
911 relopt_real
*optreal
= (relopt_real
*) option
->gen
;
913 parsed
= parse_real(value
, &option
->values
.real_val
);
914 if (validate
&& !parsed
)
916 (errmsg("invalid value for floating point option \"%s\": %s",
917 option
->gen
->name
, value
)));
918 if (validate
&& (option
->values
.real_val
< optreal
->min
||
919 option
->values
.real_val
> optreal
->max
))
921 (errmsg("value %s out of bounds for option \"%s\"",
922 value
, option
->gen
->name
),
923 errdetail("Valid values are between \"%f\" and \"%f\".",
924 optreal
->min
, optreal
->max
)));
927 case RELOPT_TYPE_STRING
:
929 relopt_string
*optstring
= (relopt_string
*) option
->gen
;
931 option
->values
.string_val
= value
;
933 if (validate
&& optstring
->validate_cb
)
934 (optstring
->validate_cb
) (value
);
939 elog(ERROR
, "unsupported reloption type %d", option
->gen
->type
);
940 parsed
= true; /* quiet compiler */
945 option
->isset
= true;
951 * Given the result from parseRelOptions, allocate a struct that's of the
952 * specified base size plus any extra space that's needed for string variables.
954 * "base" should be sizeof(struct) of the reloptions struct (StdRdOptions or
958 allocateReloptStruct(Size base
, relopt_value
*options
, int numoptions
)
963 for (i
= 0; i
< numoptions
; i
++)
964 if (options
[i
].gen
->type
== RELOPT_TYPE_STRING
)
965 size
+= GET_STRING_RELOPTION_LEN(options
[i
]) + 1;
967 return palloc0(size
);
971 * Given the result of parseRelOptions and a parsing table, fill in the
972 * struct (previously allocated with allocateReloptStruct) with the parsed
975 * rdopts is the pointer to the allocated struct to be filled; basesize is
976 * the sizeof(struct) that was passed to allocateReloptStruct. options and
977 * numoptions are parseRelOptions' output. elems and numelems is the array
978 * of elements to be parsed. Note that when validate is true, it is expected
979 * that all options are also in elems.
982 fillRelOptions(void *rdopts
, Size basesize
, relopt_value
*options
,
983 int numoptions
, bool validate
, relopt_parse_elt
*elems
,
987 int offset
= basesize
;
989 for (i
= 0; i
< numoptions
; i
++)
994 for (j
= 0; j
< numelems
; j
++)
996 if (pg_strcasecmp(options
[i
].gen
->name
, elems
[j
].optname
) == 0)
998 relopt_string
*optstring
;
999 char *itempos
= ((char *) rdopts
) + elems
[j
].offset
;
1002 switch (options
[i
].gen
->type
)
1004 case RELOPT_TYPE_BOOL
:
1005 *(bool *) itempos
= options
[i
].isset
?
1006 options
[i
].values
.bool_val
:
1007 ((relopt_bool
*) options
[i
].gen
)->default_val
;
1009 case RELOPT_TYPE_INT
:
1010 *(int *) itempos
= options
[i
].isset
?
1011 options
[i
].values
.int_val
:
1012 ((relopt_int
*) options
[i
].gen
)->default_val
;
1014 case RELOPT_TYPE_REAL
:
1015 *(double *) itempos
= options
[i
].isset
?
1016 options
[i
].values
.real_val
:
1017 ((relopt_real
*) options
[i
].gen
)->default_val
;
1019 case RELOPT_TYPE_STRING
:
1020 optstring
= (relopt_string
*) options
[i
].gen
;
1021 if (options
[i
].isset
)
1022 string_val
= options
[i
].values
.string_val
;
1023 else if (!optstring
->default_isnull
)
1024 string_val
= optstring
->default_val
;
1028 if (string_val
== NULL
)
1029 *(int *) itempos
= 0;
1032 strcpy((char *) rdopts
+ offset
, string_val
);
1033 *(int *) itempos
= offset
;
1034 offset
+= strlen(string_val
) + 1;
1038 elog(ERROR
, "unrecognized reloption type %c",
1039 options
[i
].gen
->type
);
1046 if (validate
&& !found
)
1047 elog(ERROR
, "storate parameter \"%s\" not found in parse table",
1048 options
[i
].gen
->name
);
1050 SET_VARSIZE(rdopts
, offset
);
1055 * Option parser for anything that uses StdRdOptions (i.e. fillfactor and
1059 default_reloptions(Datum reloptions
, bool validate
, relopt_kind kind
)
1061 relopt_value
*options
;
1062 StdRdOptions
*rdopts
;
1064 relopt_parse_elt tab
[] = {
1065 {"fillfactor", RELOPT_TYPE_INT
, offsetof(StdRdOptions
, fillfactor
)},
1066 {"autovacuum_enabled", RELOPT_TYPE_BOOL
,
1067 offsetof(StdRdOptions
, autovacuum
) + offsetof(AutoVacOpts
, enabled
)},
1068 {"autovacuum_vacuum_threshold", RELOPT_TYPE_INT
,
1069 offsetof(StdRdOptions
, autovacuum
) + offsetof(AutoVacOpts
, vacuum_threshold
)},
1070 {"autovacuum_analyze_threshold", RELOPT_TYPE_INT
,
1071 offsetof(StdRdOptions
, autovacuum
) + offsetof(AutoVacOpts
, analyze_threshold
)},
1072 {"autovacuum_vacuum_cost_delay", RELOPT_TYPE_INT
,
1073 offsetof(StdRdOptions
, autovacuum
) + offsetof(AutoVacOpts
, vacuum_cost_delay
)},
1074 {"autovacuum_vacuum_cost_limit", RELOPT_TYPE_INT
,
1075 offsetof(StdRdOptions
, autovacuum
) + offsetof(AutoVacOpts
, vacuum_cost_limit
)},
1076 {"autovacuum_freeze_min_age", RELOPT_TYPE_INT
,
1077 offsetof(StdRdOptions
, autovacuum
) + offsetof(AutoVacOpts
, freeze_min_age
)},
1078 {"autovacuum_freeze_max_age", RELOPT_TYPE_INT
,
1079 offsetof(StdRdOptions
, autovacuum
) + offsetof(AutoVacOpts
, freeze_max_age
)},
1080 {"autovacuum_freeze_table_age", RELOPT_TYPE_INT
,
1081 offsetof(StdRdOptions
, autovacuum
) + offsetof(AutoVacOpts
, freeze_table_age
)},
1082 {"autovacuum_vacuum_scale_factor", RELOPT_TYPE_REAL
,
1083 offsetof(StdRdOptions
, autovacuum
) + offsetof(AutoVacOpts
, vacuum_scale_factor
)},
1084 {"autovacuum_analyze_scale_factor", RELOPT_TYPE_REAL
,
1085 offsetof(StdRdOptions
, autovacuum
) + offsetof(AutoVacOpts
, analyze_scale_factor
)}
1088 options
= parseRelOptions(reloptions
, validate
, kind
, &numoptions
);
1090 /* if none set, we're done */
1091 if (numoptions
== 0)
1094 rdopts
= allocateReloptStruct(sizeof(StdRdOptions
), options
, numoptions
);
1096 fillRelOptions((void *) rdopts
, sizeof(StdRdOptions
), options
, numoptions
,
1097 validate
, tab
, lengthof(tab
));
1101 return (bytea
*) rdopts
;
1105 * Parse options for heaps and toast tables.
1108 heap_reloptions(char relkind
, Datum reloptions
, bool validate
)
1110 return default_reloptions(reloptions
, validate
, RELOPT_KIND_HEAP
);
1115 * Parse options for indexes.
1117 * amoptions Oid of option parser
1118 * reloptions options as text[] datum
1119 * validate error flag
1122 index_reloptions(RegProcedure amoptions
, Datum reloptions
, bool validate
)
1125 FunctionCallInfoData fcinfo
;
1128 Assert(RegProcedureIsValid(amoptions
));
1130 /* Assume function is strict */
1131 if (!PointerIsValid(DatumGetPointer(reloptions
)))
1134 /* Can't use OidFunctionCallN because we might get a NULL result */
1135 fmgr_info(amoptions
, &flinfo
);
1137 InitFunctionCallInfoData(fcinfo
, &flinfo
, 2, NULL
, NULL
);
1139 fcinfo
.arg
[0] = reloptions
;
1140 fcinfo
.arg
[1] = BoolGetDatum(validate
);
1141 fcinfo
.argnull
[0] = false;
1142 fcinfo
.argnull
[1] = false;
1144 result
= FunctionCallInvoke(&fcinfo
);
1146 if (fcinfo
.isnull
|| DatumGetPointer(result
) == NULL
)
1149 return DatumGetByteaP(result
);