diff options
Diffstat (limited to 'src/backend/access/common/reloptions.c')
-rw-r--r-- | src/backend/access/common/reloptions.c | 143 |
1 files changed, 120 insertions, 23 deletions
diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c index 600e6c7243d..46e2d00bc64 100644 --- a/src/backend/access/common/reloptions.c +++ b/src/backend/access/common/reloptions.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/common/reloptions.c,v 1.17 2009/01/08 19:34:41 alvherre Exp $ + * $PostgreSQL: pgsql/src/backend/access/common/reloptions.c,v 1.18 2009/01/12 21:02:14 alvherre Exp $ * *------------------------------------------------------------------------- */ @@ -33,11 +33,12 @@ * * To add an option: * - * (i) decide on a class (integer, real, bool, string), name, default value, - * upper and lower bounds (if applicable). - * (ii) add a record below. - * (iii) add it to StdRdOptions if appropriate - * (iv) add a block to the appropriate handling routine (probably + * (i) decide on a type (integer, real, bool, string), name, default value, + * upper and lower bounds (if applicable); for strings, consider a validation + * routine. + * (ii) add a record below (or use add_<type>_reloption). + * (iii) add it to the appropriate options struct (perhaps StdRdOptions) + * (iv) add it to the appropriate handling routine (perhaps * default_reloptions) * (v) don't forget to document the option * @@ -381,7 +382,7 @@ add_string_reloption(int kind, char *name, char *desc, char *default_val, /* make sure the validator/default combination is sane */ if (newoption->validate_cb) - (newoption->validate_cb) (newoption->default_val, true); + (newoption->validate_cb) (newoption->default_val); MemoryContextSwitchTo(oldcxt); @@ -745,8 +746,8 @@ parse_one_reloption(relopt_value *option, char *text_str, int text_len, option->values.string_val = value; nofree = true; - if (optstring->validate_cb) - (optstring->validate_cb) (value, validate); + if (validate && optstring->validate_cb) + (optstring->validate_cb) (value); parsed = true; } break; @@ -763,6 +764,110 @@ parse_one_reloption(relopt_value *option, char *text_str, int text_len, } /* + * Given the result from parseRelOptions, allocate a struct that's of the + * specified base size plus any extra space that's needed for string variables. + * + * "base" should be sizeof(struct) of the reloptions struct (StdRdOptions or + * equivalent). + */ +void * +allocateReloptStruct(Size base, relopt_value *options, int numoptions) +{ + Size size = base; + int i; + + for (i = 0; i < numoptions; i++) + if (options[i].gen->type == RELOPT_TYPE_STRING) + size += GET_STRING_RELOPTION_LEN(options[i]) + 1; + + return palloc0(size); +} + +/* + * Given the result of parseRelOptions and a parsing table, fill in the + * struct (previously allocated with allocateReloptStruct) with the parsed + * values. + * + * rdopts is the pointer to the allocated struct to be filled; basesize is + * the sizeof(struct) that was passed to allocateReloptStruct. options and + * numoptions are parseRelOptions' output. elems and numelems is the array + * of elements to be parsed. Note that when validate is true, it is expected + * that all options are also in elems. + */ +void +fillRelOptions(void *rdopts, Size basesize, relopt_value *options, + int numoptions, bool validate, relopt_parse_elt *elems, + int numelems) +{ + int i; + int offset = basesize; + + for (i = 0; i < numoptions; i++) + { + int j; + bool found = false; + + for (j = 0; j < numelems; j++) + { + if (pg_strcasecmp(options[i].gen->name, elems[j].optname) == 0) + { + relopt_string *optstring; + char *itempos = ((char *) rdopts) + elems[j].offset; + char *string_val; + + switch (options[i].gen->type) + { + case RELOPT_TYPE_BOOL: + *(bool *) itempos = options[i].isset ? + options[i].values.bool_val : + ((relopt_bool *) options[i].gen)->default_val; + break; + case RELOPT_TYPE_INT: + *(int *) itempos = options[i].isset ? + options[i].values.int_val : + ((relopt_int *) options[i].gen)->default_val; + break; + case RELOPT_TYPE_REAL: + *(double *) itempos = options[i].isset ? + options[i].values.real_val : + ((relopt_real *) options[i].gen)->default_val; + break; + case RELOPT_TYPE_STRING: + optstring = (relopt_string *) options[i].gen; + if (options[i].isset) + string_val = options[i].values.string_val; + else if (!optstring->default_isnull) + string_val = optstring->default_val; + else + string_val = NULL; + + if (string_val == NULL) + *(int *) itempos = 0; + else + { + strcpy((char *) rdopts + offset, string_val); + *(int *) itempos = offset; + offset += strlen(string_val) + 1; + } + break; + default: + elog(ERROR, "unrecognized reloption type %c", + options[i].gen->type); + break; + } + found = true; + break; + } + } + if (validate && !found) + elog(ERROR, "storate parameter \"%s\" not found in parse table", + options[i].gen->name); + } + SET_VARSIZE(rdopts, offset); +} + + +/* * Option parser for anything that uses StdRdOptions (i.e. fillfactor only) */ bytea * @@ -770,10 +875,10 @@ default_reloptions(Datum reloptions, bool validate, relopt_kind kind) { relopt_value *options; StdRdOptions *rdopts; - StdRdOptions lopts; int numoptions; - int len; - int i; + relopt_parse_elt tab[] = { + {"fillfactor", RELOPT_TYPE_INT, offsetof(StdRdOptions, fillfactor)} + }; options = parseRelOptions(reloptions, validate, kind, &numoptions); @@ -781,21 +886,13 @@ default_reloptions(Datum reloptions, bool validate, relopt_kind kind) if (numoptions == 0) return NULL; - MemSet(&lopts, 0, sizeof(StdRdOptions)); + rdopts = allocateReloptStruct(sizeof(StdRdOptions), options, numoptions); - for (i = 0; i < numoptions; i++) - { - HANDLE_INT_RELOPTION("fillfactor", lopts.fillfactor, options[i], - (char *) NULL); - } + fillRelOptions((void *) rdopts, sizeof(StdRdOptions), options, numoptions, + validate, tab, lengthof(tab)); pfree(options); - len = sizeof(StdRdOptions); - rdopts = palloc(len); - memcpy(rdopts, &lopts, len); - SET_VARSIZE(rdopts, len); - return (bytea *) rdopts; } |