1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-28 23:42:10 +03:00

Simplify the writing of amoptions routines by introducing a convenience

fillRelOptions routine that stores the parsed values in the struct using a
table-based approach.  Per Tom suggestion.  Also remove the "continue"
in HANDLE_*_RELOPTION macros, which were useless and in spirit they were
assuming too much of how the macros were going to be used.  (Note that these
macros are now unused, but the intention is to introduce some usage in a
future autovacuum patch, which is why they weren't completely removed.)

Also, do not call the string validation routine when not validating.  It seems
less error-prone this way, per commentary on the amoptions SGML docs.
This commit is contained in:
Alvaro Herrera
2009-01-12 21:02:15 +00:00
parent 8a4505013d
commit 8ebe1e356c
2 changed files with 208 additions and 89 deletions

View File

@ -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;
@ -762,6 +763,110 @@ parse_one_reloption(relopt_value *option, char *text_str, int text_len,
pfree(value);
}
/*
* 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)
*/
@ -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;
}