[PATCH v2 3/4] Add alias to be used as "unset" state.
Nikolay Shaplov <dhyan@nataraj.su>
From: Nikolay Shaplov <dhyan@nataraj.su>
To:
Date: 2025-09-04T16:22:21Z
Lists: pgsql-hackers
Add `unset_alias` string parameter to ternary reloption definition. This will allow
user explicitly switch ternary option to "unset" state. Use this feature to
implement `vacuum_index_cleanup` and gist's `buffering` reloptions as ternary
reloptions
---
src/backend/access/common/reloptions.c | 91 +++++++++++---------------
src/backend/access/gist/gistbuild.c | 4 +-
src/backend/commands/vacuum.c | 11 ++--
src/include/access/gist_private.h | 10 +--
src/include/access/reloptions.h | 7 +-
src/include/utils/rel.h | 10 +--
src/test/regress/expected/gist.out | 3 +-
7 files changed, 54 insertions(+), 82 deletions(-)
diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c
index f543f11001..3637646641 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -170,6 +170,27 @@ static relopt_ternary ternaryRelOpts[] =
RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
ShareUpdateExclusiveLock
},
+ NULL,
+ TERNARY_UNSET
+ },
+ {
+ {
+ "vacuum_index_cleanup",
+ "Controls index vacuuming and index cleanup",
+ RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
+ ShareUpdateExclusiveLock
+ },
+ "auto",
+ TERNARY_UNSET
+ },
+ {
+ {
+ "buffering",
+ "Enables buffering build for this GiST index",
+ RELOPT_KIND_GIST,
+ AccessExclusiveLock
+ },
+ "auto",
TERNARY_UNSET
},
/* list terminator */
@@ -489,30 +510,6 @@ static relopt_real realRelOpts[] =
{{NULL}}
};
-/* values from StdRdOptIndexCleanup */
-static relopt_enum_elt_def StdRdOptIndexCleanupValues[] =
-{
- {"auto", STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO},
- {"on", STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON},
- {"off", STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF},
- {"true", STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON},
- {"false", STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF},
- {"yes", STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON},
- {"no", STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF},
- {"1", STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON},
- {"0", STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF},
- {(const char *) NULL} /* list terminator */
-};
-
-/* values from GistOptBufferingMode */
-static 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 */
static relopt_enum_elt_def viewCheckOptValues[] =
{
@@ -524,28 +521,6 @@ static relopt_enum_elt_def viewCheckOptValues[] =
static relopt_enum enumRelOpts[] =
{
- {
- {
- "vacuum_index_cleanup",
- "Controls index vacuuming and index cleanup",
- RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
- ShareUpdateExclusiveLock
- },
- StdRdOptIndexCleanupValues,
- STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO,
- gettext_noop("Valid values are \"on\", \"off\", and \"auto\".")
- },
- {
- {
- "buffering",
- "Enables buffering build for this GiST index",
- RELOPT_KIND_GIST,
- AccessExclusiveLock
- },
- gistBufferingOptValues,
- GIST_OPTION_BUFFERING_AUTO,
- gettext_noop("Valid values are \"on\", \"off\", and \"auto\".")
- },
{
{
"check_option",
@@ -913,13 +888,14 @@ add_local_bool_reloption(local_relopts *relopts, const char *name,
*/
static relopt_ternary *
init_ternary_reloption(bits32 kinds, const char *name, const char *desc,
- ternary default_val, LOCKMODE lockmode)
+ ternary default_val, const char* unset_alias, LOCKMODE lockmode)
{
relopt_ternary *newoption;
newoption = (relopt_ternary *) allocate_reloption(kinds,
RELOPT_TYPE_TERNARY, name, desc, lockmode);
newoption->default_val = default_val;
+ newoption->unset_alias = unset_alias;
return newoption;
}
@@ -930,10 +906,10 @@ init_ternary_reloption(bits32 kinds, const char *name, const char *desc,
*/
void
add_ternary_reloption(bits32 kinds, const char *name, const char *desc,
- ternary default_val, LOCKMODE lockmode)
+ ternary default_val, const char* unset_alias, LOCKMODE lockmode)
{
relopt_ternary *newoption = init_ternary_reloption(kinds, name, desc,
- default_val, lockmode);
+ default_val, unset_alias, lockmode);
add_reloption((relopt_gen *) newoption);
}
@@ -947,11 +923,11 @@ add_ternary_reloption(bits32 kinds, const char *name, const char *desc,
void
add_local_ternary_reloption(local_relopts *relopts, const char *name,
const char *desc, ternary default_val,
- int offset)
+ const char* unset_alias, int offset)
{
relopt_ternary *newoption = init_ternary_reloption(RELOPT_KIND_LOCAL,
name, desc,
- default_val, 0);
+ default_val, unset_alias, 0);
add_local_reloption(relopts, (relopt_gen *) newoption, offset);
}
@@ -1692,8 +1668,19 @@ parse_one_reloption(relopt_value *option, char *text_str, int text_len,
case RELOPT_TYPE_TERNARY:
{
bool b;
+ relopt_ternary *opt = (relopt_ternary *) option->gen;
+
parsed = parse_bool(value, &b);
option->values.ternary_val = b ? TERNARY_TRUE : TERNARY_FALSE;
+
+ if (!parsed && opt->unset_alias)
+ {
+ if (pg_strcasecmp(value, opt->unset_alias) == 0)
+ {
+ option->values.ternary_val = TERNARY_UNSET;
+ parsed = true;
+ }
+ }
if (validate && !parsed)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
@@ -1988,7 +1975,7 @@ default_reloptions(Datum reloptions, bool validate, relopt_kind kind)
offsetof(StdRdOptions, user_catalog_table)},
{"parallel_workers", RELOPT_TYPE_INT,
offsetof(StdRdOptions, parallel_workers)},
- {"vacuum_index_cleanup", RELOPT_TYPE_ENUM,
+ {"vacuum_index_cleanup", RELOPT_TYPE_TERNARY,
offsetof(StdRdOptions, vacuum_index_cleanup)},
{"vacuum_truncate", RELOPT_TYPE_TERNARY,
offsetof(StdRdOptions, vacuum_truncate)},
diff --git a/src/backend/access/gist/gistbuild.c b/src/backend/access/gist/gistbuild.c
index 9b2ec9815f..7f641f7825 100644
--- a/src/backend/access/gist/gistbuild.c
+++ b/src/backend/access/gist/gistbuild.c
@@ -213,9 +213,9 @@ gistbuild(Relation heap, Relation index, IndexInfo *indexInfo)
*/
if (options)
{
- if (options->buffering_mode == GIST_OPTION_BUFFERING_ON)
+ if (options->buffering_mode == TERNARY_TRUE)
buildstate.buildMode = GIST_BUFFERING_STATS;
- else if (options->buffering_mode == GIST_OPTION_BUFFERING_OFF)
+ else if (options->buffering_mode == TERNARY_FALSE)
buildstate.buildMode = GIST_BUFFERING_DISABLED;
else /* must be "auto" */
buildstate.buildMode = GIST_BUFFERING_AUTO;
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 977babff54..61b4bdb682 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -2175,22 +2175,21 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams params,
*/
if (params.index_cleanup == VACOPTVALUE_UNSPECIFIED)
{
- StdRdOptIndexCleanup vacuum_index_cleanup;
+ ternary vacuum_index_cleanup;
if (rel->rd_options == NULL)
- vacuum_index_cleanup = STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO;
+ vacuum_index_cleanup = TERNARY_UNSET;
else
vacuum_index_cleanup =
((StdRdOptions *) rel->rd_options)->vacuum_index_cleanup;
- if (vacuum_index_cleanup == STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO)
+ if (vacuum_index_cleanup == TERNARY_UNSET)
params.index_cleanup = VACOPTVALUE_AUTO;
- else if (vacuum_index_cleanup == STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON)
+ else if (vacuum_index_cleanup == TERNARY_TRUE)
params.index_cleanup = VACOPTVALUE_ENABLED;
else
{
- Assert(vacuum_index_cleanup ==
- STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF);
+ Assert(vacuum_index_cleanup == TERNARY_FALSE);
params.index_cleanup = VACOPTVALUE_DISABLED;
}
}
diff --git a/src/include/access/gist_private.h b/src/include/access/gist_private.h
index 39404ec7cd..a931c988fb 100644
--- a/src/include/access/gist_private.h
+++ b/src/include/access/gist_private.h
@@ -380,14 +380,6 @@ typedef struct GISTBuildBuffers
int rootlevel;
} GISTBuildBuffers;
-/* GiSTOptions->buffering_mode values */
-typedef enum GistOptBufferingMode
-{
- GIST_OPTION_BUFFERING_AUTO,
- GIST_OPTION_BUFFERING_ON,
- GIST_OPTION_BUFFERING_OFF,
-} GistOptBufferingMode;
-
/*
* Storage type for GiST's reloptions
*/
@@ -395,7 +387,7 @@ typedef struct GiSTOptions
{
int32 vl_len_; /* varlena header (do not touch directly!) */
int fillfactor; /* page fill factor in percent (0..100) */
- GistOptBufferingMode buffering_mode; /* buffering build mode */
+ ternary buffering_mode; /* buffering build mode */
} GiSTOptions;
/* gist.c */
diff --git a/src/include/access/reloptions.h b/src/include/access/reloptions.h
index a436697658..d2a1c7afb7 100644
--- a/src/include/access/reloptions.h
+++ b/src/include/access/reloptions.h
@@ -99,6 +99,7 @@ typedef struct relopt_bool
typedef struct relopt_rernary
{
relopt_gen gen;
+ const char *unset_alias; /* word that will be treaed as unset value */
int default_val;
} relopt_ternary;
@@ -191,7 +192,8 @@ extern relopt_kind add_reloption_kind(void);
extern void add_bool_reloption(bits32 kinds, const char *name, const char *desc,
bool default_val, LOCKMODE lockmode);
extern void add_ternary_reloption(bits32 kinds, const char *name,
- const char *desc, int default_val, LOCKMODE lockmode);
+ const char *desc, ternary default_val,
+ const char* unset_alias, LOCKMODE lockmode);
extern void add_int_reloption(bits32 kinds, const char *name, const char *desc,
int default_val, int min_val, int max_val,
LOCKMODE lockmode);
@@ -213,7 +215,8 @@ extern void add_local_bool_reloption(local_relopts *relopts, const char *name,
int offset);
extern void add_local_ternary_reloption(local_relopts *relopts,
const char *name, const char *desc,
- ternary default_val, int offset);
+ ternary default_val, const char* unset_alias,
+ int offset);
extern void add_local_int_reloption(local_relopts *relopts, const char *name,
const char *desc, int default_val,
int min_val, int max_val, int offset);
diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h
index 7346d618f9..95a18c6d16 100644
--- a/src/include/utils/rel.h
+++ b/src/include/utils/rel.h
@@ -329,14 +329,6 @@ typedef struct AutoVacOpts
float8 analyze_scale_factor;
} AutoVacOpts;
-/* StdRdOptions->vacuum_index_cleanup values */
-typedef enum StdRdOptIndexCleanup
-{
- STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO = 0,
- STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF,
- STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON,
-} StdRdOptIndexCleanup;
-
typedef struct StdRdOptions
{
int32 vl_len_; /* varlena header (do not touch directly!) */
@@ -345,7 +337,7 @@ typedef struct StdRdOptions
AutoVacOpts autovacuum; /* autovacuum-related options */
bool user_catalog_table; /* use as an additional catalog relation */
int parallel_workers; /* max number of parallel workers */
- StdRdOptIndexCleanup vacuum_index_cleanup; /* controls index vacuuming */
+ ternary vacuum_index_cleanup; /* controls index vacuuming */
ternary vacuum_truncate; /* enables vacuum to truncate a relation */
/*
diff --git a/src/test/regress/expected/gist.out b/src/test/regress/expected/gist.out
index c75bbb23b6..76751d1859 100644
--- a/src/test/regress/expected/gist.out
+++ b/src/test/regress/expected/gist.out
@@ -12,8 +12,7 @@ create index gist_pointidx4 on gist_point_tbl using gist(p) with (buffering = au
drop index gist_pointidx2, gist_pointidx3, gist_pointidx4;
-- Make sure bad values are refused
create index gist_pointidx5 on gist_point_tbl using gist(p) with (buffering = invalid_value);
-ERROR: invalid value for enum option "buffering": invalid_value
-DETAIL: Valid values are "on", "off", and "auto".
+ERROR: invalid value for ternary option "buffering": invalid_value
create index gist_pointidx5 on gist_point_tbl using gist(p) with (fillfactor=9);
ERROR: value 9 out of bounds for option "fillfactor"
DETAIL: Valid values are between "10" and "100".
--
2.39.2
--nextPart5129932.5fSG56mABF
Content-Disposition: attachment; filename="v2-0004-Extra-tests.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
name="v2-0004-Extra-tests.patch"