diff options
Diffstat (limited to 'src/backend/access')
-rw-r--r-- | src/backend/access/common/reloptions.c | 132 | ||||
-rw-r--r-- | src/backend/access/gist/gistbuild.c | 25 | ||||
-rw-r--r-- | src/backend/access/gist/gistutil.c | 2 |
3 files changed, 125 insertions, 34 deletions
diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c index 3b8517efeaa..85627a05a35 100644 --- a/src/backend/access/common/reloptions.c +++ b/src/backend/access/common/reloptions.c @@ -433,7 +433,25 @@ static relopt_real realRelOpts[] = {{NULL}} }; -static relopt_string stringRelOpts[] = +/* values from GistOptBufferingMode */ +relopt_enum_elt_def gistBufferingOptValues[] = +{ + {"auto", GIST_OPTION_BUFFERING_AUTO}, + {"on", GIST_OPTION_BUFFERING_ON}, + {"off", GIST_OPTION_BUFFERING_OFF}, + {(const char *) NULL} /* list terminator */ +}; + +/* values from ViewOptCheckOption */ +relopt_enum_elt_def viewCheckOptValues[] = +{ + /* no value for NOT_SET */ + {"local", VIEW_OPTION_CHECK_OPTION_LOCAL}, + {"cascaded", VIEW_OPTION_CHECK_OPTION_CASCADED}, + {(const char *) NULL} /* list terminator */ +}; + +static relopt_enum enumRelOpts[] = { { { @@ -442,10 +460,9 @@ static relopt_string stringRelOpts[] = RELOPT_KIND_GIST, AccessExclusiveLock }, - 4, - false, - gistValidateBufferingOption, - "auto" + gistBufferingOptValues, + GIST_OPTION_BUFFERING_AUTO, + gettext_noop("Valid values are \"on\", \"off\", and \"auto\".") }, { { @@ -454,15 +471,20 @@ static relopt_string stringRelOpts[] = RELOPT_KIND_VIEW, AccessExclusiveLock }, - 0, - true, - validateWithCheckOption, - NULL + viewCheckOptValues, + VIEW_OPTION_CHECK_OPTION_NOT_SET, + gettext_noop("Valid values are \"local\" and \"cascaded\".") }, /* list terminator */ {{NULL}} }; +static relopt_string stringRelOpts[] = +{ + /* list terminator */ + {{NULL}} +}; + static relopt_gen **relOpts = NULL; static bits32 last_assigned_kind = RELOPT_KIND_LAST_DEFAULT; @@ -505,6 +527,12 @@ initialize_reloptions(void) realRelOpts[i].gen.lockmode)); j++; } + for (i = 0; enumRelOpts[i].gen.name; i++) + { + Assert(DoLockModesConflict(enumRelOpts[i].gen.lockmode, + enumRelOpts[i].gen.lockmode)); + j++; + } for (i = 0; stringRelOpts[i].gen.name; i++) { Assert(DoLockModesConflict(stringRelOpts[i].gen.lockmode, @@ -543,6 +571,14 @@ initialize_reloptions(void) j++; } + for (i = 0; enumRelOpts[i].gen.name; i++) + { + relOpts[j] = &enumRelOpts[i].gen; + relOpts[j]->type = RELOPT_TYPE_ENUM; + relOpts[j]->namelen = strlen(relOpts[j]->name); + j++; + } + for (i = 0; stringRelOpts[i].gen.name; i++) { relOpts[j] = &stringRelOpts[i].gen; @@ -641,6 +677,9 @@ allocate_reloption(bits32 kinds, int type, const char *name, const char *desc, case RELOPT_TYPE_REAL: size = sizeof(relopt_real); break; + case RELOPT_TYPE_ENUM: + size = sizeof(relopt_enum); + break; case RELOPT_TYPE_STRING: size = sizeof(relopt_string); break; @@ -661,6 +700,13 @@ allocate_reloption(bits32 kinds, int type, const char *name, const char *desc, newoption->type = type; newoption->lockmode = lockmode; + /* + * Set the default lock mode for this option. There is no actual way + * for a module to enforce it when declaring a custom relation option, + * so just use the highest level, which is safe for all cases. + */ + newoption->lockmode = AccessExclusiveLock; + MemoryContextSwitchTo(oldcxt); return newoption; @@ -722,6 +768,34 @@ add_real_reloption(bits32 kinds, const char *name, const char *desc, double defa } /* + * add_enum_reloption + * Add a new enum reloption + * + * The members array must have a terminating NULL entry. + * + * The detailmsg is shown when unsupported values are passed, and has this + * form: "Valid values are \"foo\", \"bar\", and \"bar\"." + * + * The members array and detailmsg are not copied -- caller must ensure that + * they are valid throughout the life of the process. + */ +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) +{ + relopt_enum *newoption; + + newoption = (relopt_enum *) allocate_reloption(kinds, RELOPT_TYPE_ENUM, + name, desc, lockmode); + newoption->members = members; + newoption->default_val = default_val; + newoption->detailmsg = detailmsg; + + add_reloption((relopt_gen *) newoption); +} + +/* * add_string_reloption * Add a new string reloption * @@ -1237,6 +1311,37 @@ parse_one_reloption(relopt_value *option, char *text_str, int text_len, optreal->min, optreal->max))); } break; + case RELOPT_TYPE_ENUM: + { + relopt_enum *optenum = (relopt_enum *) option->gen; + relopt_enum_elt_def *elt; + + parsed = false; + for (elt = optenum->members; elt->string_val; elt++) + { + if (pg_strcasecmp(value, elt->string_val) == 0) + { + option->values.enum_val = elt->symbol_val; + parsed = true; + break; + } + } + if (validate && !parsed) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid value for enum option \"%s\": %s", + option->gen->name, value), + optenum->detailmsg ? + errdetail_internal("%s", _(optenum->detailmsg)) : 0)); + + /* + * If value is not among the allowed string values, but we are + * not asked to validate, just use the default numeric value. + */ + if (!parsed) + option->values.enum_val = optenum->default_val; + } + break; case RELOPT_TYPE_STRING: { relopt_string *optstring = (relopt_string *) option->gen; @@ -1330,6 +1435,11 @@ fillRelOptions(void *rdopts, Size basesize, options[i].values.real_val : ((relopt_real *) options[i].gen)->default_val; break; + case RELOPT_TYPE_ENUM: + *(int *) itempos = options[i].isset ? + options[i].values.enum_val : + ((relopt_enum *) options[i].gen)->default_val; + break; case RELOPT_TYPE_STRING: optstring = (relopt_string *) options[i].gen; if (options[i].isset) @@ -1446,8 +1556,8 @@ view_reloptions(Datum reloptions, bool validate) static const relopt_parse_elt tab[] = { {"security_barrier", RELOPT_TYPE_BOOL, offsetof(ViewOptions, security_barrier)}, - {"check_option", RELOPT_TYPE_STRING, - offsetof(ViewOptions, check_option_offset)} + {"check_option", RELOPT_TYPE_ENUM, + offsetof(ViewOptions, check_option)} }; options = parseRelOptions(reloptions, validate, RELOPT_KIND_VIEW, &numoptions); diff --git a/src/backend/access/gist/gistbuild.c b/src/backend/access/gist/gistbuild.c index ecef0ff0724..2f4543dee52 100644 --- a/src/backend/access/gist/gistbuild.c +++ b/src/backend/access/gist/gistbuild.c @@ -125,15 +125,15 @@ gistbuild(Relation heap, Relation index, IndexInfo *indexInfo) buildstate.indexrel = index; buildstate.heaprel = heap; + if (index->rd_options) { /* Get buffering mode from the options string */ GiSTOptions *options = (GiSTOptions *) index->rd_options; - char *bufferingMode = (char *) options + options->bufferingModeOffset; - if (strcmp(bufferingMode, "on") == 0) + if (options->buffering_mode == GIST_OPTION_BUFFERING_ON) buildstate.bufferingMode = GIST_BUFFERING_STATS; - else if (strcmp(bufferingMode, "off") == 0) + else if (options->buffering_mode == GIST_OPTION_BUFFERING_OFF) buildstate.bufferingMode = GIST_BUFFERING_DISABLED; else buildstate.bufferingMode = GIST_BUFFERING_AUTO; @@ -237,25 +237,6 @@ gistbuild(Relation heap, Relation index, IndexInfo *indexInfo) } /* - * Validator for "buffering" reloption on GiST indexes. Allows "on", "off" - * and "auto" values. - */ -void -gistValidateBufferingOption(const char *value) -{ - if (value == NULL || - (strcmp(value, "on") != 0 && - strcmp(value, "off") != 0 && - strcmp(value, "auto") != 0)) - { - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid value for \"buffering\" option"), - errdetail("Valid values are \"on\", \"off\", and \"auto\"."))); - } -} - -/* * Attempt to switch to buffering mode. * * If there is not enough memory for buffering build, sets bufferingMode diff --git a/src/backend/access/gist/gistutil.c b/src/backend/access/gist/gistutil.c index 97260201dcd..45804d7a91e 100644 --- a/src/backend/access/gist/gistutil.c +++ b/src/backend/access/gist/gistutil.c @@ -913,7 +913,7 @@ gistoptions(Datum reloptions, bool validate) int numoptions; static const relopt_parse_elt tab[] = { {"fillfactor", RELOPT_TYPE_INT, offsetof(GiSTOptions, fillfactor)}, - {"buffering", RELOPT_TYPE_STRING, offsetof(GiSTOptions, bufferingModeOffset)} + {"buffering", RELOPT_TYPE_ENUM, offsetof(GiSTOptions, buffering_mode)} }; options = parseRelOptions(reloptions, validate, RELOPT_KIND_GIST, |