Refactor code building relation options

Historically, the code to build relation options has been shaped the
same way in multiple code paths by using a set of datums in input with
the options parsed with a static table which is then filled with the
option values.  This introduces a new common routine in reloptions.c to
do most of the legwork for the in-core code paths.

Author: Amit Langote
Reviewed-by: Michael Paquier
Discussion: https://postgr.es/m/CA+HiwqGsoSn_uTPPYT19WrtR7oYpYtv4CdS0xuedTKiHHWuk_g@mail.gmail.com
This commit is contained in:
Michael Paquier 2019-11-05 09:17:05 +09:00
parent 5102f39440
commit 3534fa2233
7 changed files with 82 additions and 133 deletions

View File

@ -475,18 +475,18 @@ BloomInitMetapage(Relation index)
bytea * bytea *
bloptions(Datum reloptions, bool validate) bloptions(Datum reloptions, bool validate)
{ {
relopt_value *options;
int numoptions;
BloomOptions *rdopts; BloomOptions *rdopts;
/* Parse the user-given reloptions */ /* Parse the user-given reloptions */
options = parseRelOptions(reloptions, validate, bl_relopt_kind, &numoptions); rdopts = (BloomOptions *) build_reloptions(reloptions, validate,
rdopts = allocateReloptStruct(sizeof(BloomOptions), options, numoptions); bl_relopt_kind,
fillRelOptions((void *) rdopts, sizeof(BloomOptions), options, numoptions, sizeof(BloomOptions),
validate, bl_relopt_tab, lengthof(bl_relopt_tab)); bl_relopt_tab,
lengthof(bl_relopt_tab));
/* Convert signature length from # of bits to # to words, rounding up */ /* Convert signature length from # of bits to # to words, rounding up */
rdopts->bloomLength = (rdopts->bloomLength + SIGNWORDBITS - 1) / SIGNWORDBITS; if (rdopts)
rdopts->bloomLength = (rdopts->bloomLength + SIGNWORDBITS - 1) / SIGNWORDBITS;
return (bytea *) rdopts; return (bytea *) rdopts;
} }

View File

@ -820,29 +820,15 @@ brinvacuumcleanup(IndexVacuumInfo *info, IndexBulkDeleteResult *stats)
bytea * bytea *
brinoptions(Datum reloptions, bool validate) brinoptions(Datum reloptions, bool validate)
{ {
relopt_value *options;
BrinOptions *rdopts;
int numoptions;
static const relopt_parse_elt tab[] = { static const relopt_parse_elt tab[] = {
{"pages_per_range", RELOPT_TYPE_INT, offsetof(BrinOptions, pagesPerRange)}, {"pages_per_range", RELOPT_TYPE_INT, offsetof(BrinOptions, pagesPerRange)},
{"autosummarize", RELOPT_TYPE_BOOL, offsetof(BrinOptions, autosummarize)} {"autosummarize", RELOPT_TYPE_BOOL, offsetof(BrinOptions, autosummarize)}
}; };
options = parseRelOptions(reloptions, validate, RELOPT_KIND_BRIN, return (bytea *) build_reloptions(reloptions, validate,
&numoptions); RELOPT_KIND_BRIN,
sizeof(BrinOptions),
/* if none set, we're done */ tab, lengthof(tab));
if (numoptions == 0)
return NULL;
rdopts = allocateReloptStruct(sizeof(BrinOptions), options, numoptions);
fillRelOptions((void *) rdopts, sizeof(BrinOptions), options, numoptions,
validate, tab, lengthof(tab));
pfree(options);
return (bytea *) rdopts;
} }
/* /*

View File

@ -1474,9 +1474,6 @@ fillRelOptions(void *rdopts, Size basesize,
bytea * bytea *
default_reloptions(Datum reloptions, bool validate, relopt_kind kind) default_reloptions(Datum reloptions, bool validate, relopt_kind kind)
{ {
relopt_value *options;
StdRdOptions *rdopts;
int numoptions;
static const relopt_parse_elt tab[] = { static const relopt_parse_elt tab[] = {
{"fillfactor", RELOPT_TYPE_INT, offsetof(StdRdOptions, fillfactor)}, {"fillfactor", RELOPT_TYPE_INT, offsetof(StdRdOptions, fillfactor)},
{"autovacuum_enabled", RELOPT_TYPE_BOOL, {"autovacuum_enabled", RELOPT_TYPE_BOOL,
@ -1521,20 +1518,57 @@ default_reloptions(Datum reloptions, bool validate, relopt_kind kind)
offsetof(StdRdOptions, vacuum_truncate)} offsetof(StdRdOptions, vacuum_truncate)}
}; };
return (bytea *) build_reloptions(reloptions, validate, kind,
sizeof(StdRdOptions),
tab, lengthof(tab));
}
/*
* build_reloptions
*
* Parses "reloptions" provided by the caller, returning them in a
* structure containing the parsed options. The parsing is done with
* the help of a parsing table describing the allowed options, defined
* by "relopt_elems" of length "num_relopt_elems".
*
* "validate" must be true if reloptions value is freshly built by
* transformRelOptions(), as opposed to being read from the catalog, in which
* case the values contained in it must already be valid.
*
* NULL is returned if the passed-in options did not match any of the options
* in the parsing table, unless validate is true in which case an error would
* be reported.
*/
void *
build_reloptions(Datum reloptions, bool validate,
relopt_kind kind,
Size relopt_struct_size,
const relopt_parse_elt *relopt_elems,
int num_relopt_elems)
{
int numoptions;
relopt_value *options;
void *rdopts;
/* parse options specific to given relation option kind */
options = parseRelOptions(reloptions, validate, kind, &numoptions); options = parseRelOptions(reloptions, validate, kind, &numoptions);
Assert(numoptions <= num_relopt_elems);
/* if none set, we're done */ /* if none set, we're done */
if (numoptions == 0) if (numoptions == 0)
{
Assert(options == NULL);
return NULL; return NULL;
}
rdopts = allocateReloptStruct(sizeof(StdRdOptions), options, numoptions); /* allocate and fill the structure */
rdopts = allocateReloptStruct(relopt_struct_size, options, numoptions);
fillRelOptions((void *) rdopts, sizeof(StdRdOptions), options, numoptions, fillRelOptions(rdopts, relopt_struct_size, options, numoptions,
validate, tab, lengthof(tab)); validate, relopt_elems, num_relopt_elems);
pfree(options); pfree(options);
return (bytea *) rdopts; return rdopts;
} }
/* /*
@ -1543,9 +1577,6 @@ default_reloptions(Datum reloptions, bool validate, relopt_kind kind)
bytea * bytea *
view_reloptions(Datum reloptions, bool validate) view_reloptions(Datum reloptions, bool validate)
{ {
relopt_value *options;
ViewOptions *vopts;
int numoptions;
static const relopt_parse_elt tab[] = { static const relopt_parse_elt tab[] = {
{"security_barrier", RELOPT_TYPE_BOOL, {"security_barrier", RELOPT_TYPE_BOOL,
offsetof(ViewOptions, security_barrier)}, offsetof(ViewOptions, security_barrier)},
@ -1553,20 +1584,10 @@ view_reloptions(Datum reloptions, bool validate)
offsetof(ViewOptions, check_option)} offsetof(ViewOptions, check_option)}
}; };
options = parseRelOptions(reloptions, validate, RELOPT_KIND_VIEW, &numoptions); return (bytea *) build_reloptions(reloptions, validate,
RELOPT_KIND_VIEW,
/* if none set, we're done */ sizeof(ViewOptions),
if (numoptions == 0) tab, lengthof(tab));
return NULL;
vopts = allocateReloptStruct(sizeof(ViewOptions), options, numoptions);
fillRelOptions((void *) vopts, sizeof(ViewOptions), options, numoptions,
validate, tab, lengthof(tab));
pfree(options);
return (bytea *) vopts;
} }
/* /*
@ -1628,29 +1649,15 @@ index_reloptions(amoptions_function amoptions, Datum reloptions, bool validate)
bytea * bytea *
attribute_reloptions(Datum reloptions, bool validate) attribute_reloptions(Datum reloptions, bool validate)
{ {
relopt_value *options;
AttributeOpts *aopts;
int numoptions;
static const relopt_parse_elt tab[] = { static const relopt_parse_elt tab[] = {
{"n_distinct", RELOPT_TYPE_REAL, offsetof(AttributeOpts, n_distinct)}, {"n_distinct", RELOPT_TYPE_REAL, offsetof(AttributeOpts, n_distinct)},
{"n_distinct_inherited", RELOPT_TYPE_REAL, offsetof(AttributeOpts, n_distinct_inherited)} {"n_distinct_inherited", RELOPT_TYPE_REAL, offsetof(AttributeOpts, n_distinct_inherited)}
}; };
options = parseRelOptions(reloptions, validate, RELOPT_KIND_ATTRIBUTE, return (bytea *) build_reloptions(reloptions, validate,
&numoptions); RELOPT_KIND_ATTRIBUTE,
sizeof(AttributeOpts),
/* if none set, we're done */ tab, lengthof(tab));
if (numoptions == 0)
return NULL;
aopts = allocateReloptStruct(sizeof(AttributeOpts), options, numoptions);
fillRelOptions((void *) aopts, sizeof(AttributeOpts), options, numoptions,
validate, tab, lengthof(tab));
pfree(options);
return (bytea *) aopts;
} }
/* /*
@ -1659,30 +1666,16 @@ attribute_reloptions(Datum reloptions, bool validate)
bytea * bytea *
tablespace_reloptions(Datum reloptions, bool validate) tablespace_reloptions(Datum reloptions, bool validate)
{ {
relopt_value *options;
TableSpaceOpts *tsopts;
int numoptions;
static const relopt_parse_elt tab[] = { static const relopt_parse_elt tab[] = {
{"random_page_cost", RELOPT_TYPE_REAL, offsetof(TableSpaceOpts, random_page_cost)}, {"random_page_cost", RELOPT_TYPE_REAL, offsetof(TableSpaceOpts, random_page_cost)},
{"seq_page_cost", RELOPT_TYPE_REAL, offsetof(TableSpaceOpts, seq_page_cost)}, {"seq_page_cost", RELOPT_TYPE_REAL, offsetof(TableSpaceOpts, seq_page_cost)},
{"effective_io_concurrency", RELOPT_TYPE_INT, offsetof(TableSpaceOpts, effective_io_concurrency)} {"effective_io_concurrency", RELOPT_TYPE_INT, offsetof(TableSpaceOpts, effective_io_concurrency)}
}; };
options = parseRelOptions(reloptions, validate, RELOPT_KIND_TABLESPACE, return (bytea *) build_reloptions(reloptions, validate,
&numoptions); RELOPT_KIND_TABLESPACE,
sizeof(TableSpaceOpts),
/* if none set, we're done */ tab, lengthof(tab));
if (numoptions == 0)
return NULL;
tsopts = allocateReloptStruct(sizeof(TableSpaceOpts), options, numoptions);
fillRelOptions((void *) tsopts, sizeof(TableSpaceOpts), options, numoptions,
validate, tab, lengthof(tab));
pfree(options);
return (bytea *) tsopts;
} }
/* /*

View File

@ -602,30 +602,16 @@ ginExtractEntries(GinState *ginstate, OffsetNumber attnum,
bytea * bytea *
ginoptions(Datum reloptions, bool validate) ginoptions(Datum reloptions, bool validate)
{ {
relopt_value *options;
GinOptions *rdopts;
int numoptions;
static const relopt_parse_elt tab[] = { static const relopt_parse_elt tab[] = {
{"fastupdate", RELOPT_TYPE_BOOL, offsetof(GinOptions, useFastUpdate)}, {"fastupdate", RELOPT_TYPE_BOOL, offsetof(GinOptions, useFastUpdate)},
{"gin_pending_list_limit", RELOPT_TYPE_INT, offsetof(GinOptions, {"gin_pending_list_limit", RELOPT_TYPE_INT, offsetof(GinOptions,
pendingListCleanupSize)} pendingListCleanupSize)}
}; };
options = parseRelOptions(reloptions, validate, RELOPT_KIND_GIN, return (bytea *) build_reloptions(reloptions, validate,
&numoptions); RELOPT_KIND_GIN,
sizeof(GinOptions),
/* if none set, we're done */ tab, lengthof(tab));
if (numoptions == 0)
return NULL;
rdopts = allocateReloptStruct(sizeof(GinOptions), options, numoptions);
fillRelOptions((void *) rdopts, sizeof(GinOptions), options, numoptions,
validate, tab, lengthof(tab));
pfree(options);
return (bytea *) rdopts;
} }
/* /*

View File

@ -908,29 +908,15 @@ gistPageRecyclable(Page page)
bytea * bytea *
gistoptions(Datum reloptions, bool validate) gistoptions(Datum reloptions, bool validate)
{ {
relopt_value *options;
GiSTOptions *rdopts;
int numoptions;
static const relopt_parse_elt tab[] = { static const relopt_parse_elt tab[] = {
{"fillfactor", RELOPT_TYPE_INT, offsetof(GiSTOptions, fillfactor)}, {"fillfactor", RELOPT_TYPE_INT, offsetof(GiSTOptions, fillfactor)},
{"buffering", RELOPT_TYPE_ENUM, offsetof(GiSTOptions, buffering_mode)} {"buffering", RELOPT_TYPE_ENUM, offsetof(GiSTOptions, buffering_mode)}
}; };
options = parseRelOptions(reloptions, validate, RELOPT_KIND_GIST, return (bytea *) build_reloptions(reloptions, validate,
&numoptions); RELOPT_KIND_GIST,
sizeof(GiSTOptions),
/* if none set, we're done */ tab, lengthof(tab));
if (numoptions == 0)
return NULL;
rdopts = allocateReloptStruct(sizeof(GiSTOptions), options, numoptions);
fillRelOptions((void *) rdopts, sizeof(GiSTOptions), options, numoptions,
validate, tab, lengthof(tab));
pfree(options);
return (bytea *) rdopts;
} }
/* /*

View File

@ -296,6 +296,11 @@ extern void fillRelOptions(void *rdopts, Size basesize,
relopt_value *options, int numoptions, relopt_value *options, int numoptions,
bool validate, bool validate,
const relopt_parse_elt *elems, int nelems); const relopt_parse_elt *elems, int nelems);
extern void *build_reloptions(Datum reloptions, bool validate,
relopt_kind kind,
Size relopt_struct_size,
const relopt_parse_elt *relopt_elems,
int num_relopt_elems);
extern bytea *default_reloptions(Datum reloptions, bool validate, extern bytea *default_reloptions(Datum reloptions, bool validate,
relopt_kind kind); relopt_kind kind);

View File

@ -222,17 +222,10 @@ dicostestimate(PlannerInfo *root, IndexPath *path, double loop_count,
static bytea * static bytea *
dioptions(Datum reloptions, bool validate) dioptions(Datum reloptions, bool validate)
{ {
relopt_value *options; return (bytea *) build_reloptions(reloptions, validate,
int numoptions; di_relopt_kind,
DummyIndexOptions *rdopts; sizeof(DummyIndexOptions),
di_relopt_tab, lengthof(di_relopt_tab));
/* Parse the user-given reloptions */
options = parseRelOptions(reloptions, validate, di_relopt_kind, &numoptions);
rdopts = allocateReloptStruct(sizeof(DummyIndexOptions), options, numoptions);
fillRelOptions((void *) rdopts, sizeof(DummyIndexOptions), options, numoptions,
validate, di_relopt_tab, lengthof(di_relopt_tab));
return (bytea *) rdopts;
} }
/* /*