On 21.01.2026 22:23, Álvaro Herrera wrote:
I've rebased the rest of patches, and the whole patchset is in the
attachment.
I'm not a fan of how these commit messages are structured. You explain
the point of the whole patch series in the commit message for 0001, but
that one only adds some tests for the existing behavior. If I were to
commit that, it would make no sense in the overall Postgres commit
history. So I have squashed 0001 with 0002, and also with the fraction
of 0004 that includes tests for the feature in 0002.
I guess that comes from my frustration with big reloptions patch. I've
been looking
for a way to make iy more easy to read and understand. My thought was
that if
I split them into logical "layers" showing the development of the
patch's idea, it
would be more easy to understand them as a whole. And they were intended
to be squashed before commit, may be I should state that more clearly.
I think it's
strange to submit those tests in 0004, when the other half of the tests
are for the feature in 0003.
Yeah, here you are right, I should add tests both to 0003 and 0004. I
did not think
they can be committed separately
I recommend to consider how you structure
your patch splits so that they would make sense in the Postgres commit
history assuming they are committed on separate days, and that there are
multiple other commits in between.
Second part of ternary options patch is consist of one piece, so now it
is not a problem,
and as for big reloptions patch, I think we can discuss it later. I
doubt it is readable
when it is provided in single piece.
I do agree with Nathan that there seems to be little point in the
message saying this new type is different from Boolean. The user can
still say only "on" or "off". Even with your "alias" proposal, there
will only be a mechanism to let the system choose between those two
values, but it will still be one or the other. There's no provision to
have the system behave as if the user set the value to half.
For ternary options with explicit "third" value, I added another error
message, it says nothing
about option type, it just lists possible values. This can be good solution.
Another thing I did is remove default_val for ternaries. As far as I
can see, it makes no sense. If your reloption defaults to either on or
off, then it's just a Boolean, right? It can no longer be unset,
because if you unset it, then it becomes the default.
For the part you've committed that is correct. But with explicit "third"
option, you can't tell
for sure which value is default. Like:
prefer_XXXX_optimization: yes/no/never
It can be implemented as ternary option, but default value here can be
"yes".
I would not try to predict what behavior option developer will need, and
try to provide all
possibilities.
That's why I put default value back. But I will not be much upset if you
still decide to remove it.
Or I can remove it myself if you insist. We can add it later when
someone runs into this "never" case.
Anyway, I have pushed the first part, after rewriting the commit
message.
Thanks! Now the world is better place, from my point of view.
You can resubmit the rest after rebasing on the current tree.
I have also marked the commitfest item as committed. Please create a
new one for the next part.
I've reworked second part of the patch, It is in the attachment, and I
am going to create new commitfest record for it. Thank you for your work.From 3403340bc1b6c52c012fbbe392dcd7ab53a39780 Mon Sep 17 00:00:00 2001
From: Nikolay Shaplov <[email protected]>
Date: Thu, 4 Sep 2025 19:22:21 +0300
Subject: [PATCH v1a 1/1] Convert `vacuum_index_cleanup` and gist's `buffering`
reloptions from enum to ternary type
Enum reloptions `vacuum_index_cleanup` and gist's `buffering` behaves almost
like ternary options, except that their third "unset" value can be explicitly
set by specifying keyword "auto".
Here we add `unset_alias` into ternary option definition, that will permit
explicitly setting third "unest" value, and convert `vacuum_index_cleanup`
and `buffering` reloptions to ternary type.
---
src/backend/access/common/reloptions.c | 111 +++++++++---------
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 | 11 +-
src/include/utils/rel.h | 10 +-
src/test/modules/dummy_index_am/README | 3 +-
.../modules/dummy_index_am/dummy_index_am.c | 11 +-
.../dummy_index_am/expected/reloptions.out | 27 +++--
.../modules/dummy_index_am/sql/reloptions.sql | 7 ++
src/test/regress/expected/gist.out | 2 +-
src/test/regress/expected/reloptions.out | 18 +++
src/test/regress/sql/reloptions.sql | 10 ++
13 files changed, 139 insertions(+), 96 deletions(-)
diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c
index 237ab8d0ed9..2ca45c98662 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -173,7 +173,29 @@ static relopt_ternary ternaryRelOpts[] =
"Enables vacuum to truncate empty pages at the end of this table",
RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
ShareUpdateExclusiveLock
- }
+ },
+ NULL,
+ PG_TERNARY_UNSET
+ },
+ {
+ {
+ "vacuum_index_cleanup",
+ "Controls index vacuuming and index cleanup",
+ RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
+ ShareUpdateExclusiveLock
+ },
+ "auto",
+ PG_TERNARY_UNSET
+ },
+ {
+ {
+ "buffering",
+ "Enables buffering build for this GiST index",
+ RELOPT_KIND_GIST,
+ AccessExclusiveLock
+ },
+ "auto",
+ PG_TERNARY_UNSET
},
/* list terminator */
{
@@ -505,30 +527,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[] =
{
@@ -540,28 +538,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",
@@ -929,12 +905,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,
- LOCKMODE lockmode)
+ pg_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;
}
@@ -945,12 +923,12 @@ init_ternary_reloption(bits32 kinds, const char *name, const char *desc,
*/
void
add_ternary_reloption(bits32 kinds, const char *name, const char *desc,
- LOCKMODE lockmode)
+ pg_ternary default_val, const char* unset_alias, LOCKMODE lockmode)
{
relopt_ternary *newoption;
- newoption =
- init_ternary_reloption(kinds, name, desc, lockmode);
+ newoption = init_ternary_reloption(kinds, name, desc, default_val,
+ unset_alias, lockmode);
add_reloption((relopt_gen *) newoption);
}
@@ -963,12 +941,13 @@ 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, int offset)
+ const char *desc, pg_ternary default_val,
+ const char* unset_alias, int offset)
{
relopt_ternary *newoption;
- newoption =
- init_ternary_reloption(RELOPT_KIND_LOCAL, name, desc, 0);
+ newoption = init_ternary_reloption(RELOPT_KIND_LOCAL, name, desc,
+ default_val, unset_alias, 0);
add_local_reloption(relopts, (relopt_gen *) newoption, offset);
}
@@ -1709,15 +1688,35 @@ 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->ternary_val = b ? PG_TERNARY_TRUE :
PG_TERNARY_FALSE;
- if (validate && !parsed)
+
+ /* If no "unset alias" set, this option behaves almost like
+ * boolean, so report error accordingly */
+ if (!opt->unset_alias && validate && !parsed)
ereport(ERROR,
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("invalid value for boolean option \"%s\": %s",
option->gen->name, value));
+
+ if (!parsed && opt->unset_alias)
+ {
+ if (pg_strcasecmp(value, opt->unset_alias) == 0)
+ {
+ option->ternary_val = PG_TERNARY_UNSET;
+ parsed = true;
+ }
+ }
+ if (validate && !parsed)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("invalid value for option \"%s\": %s",
+ option->gen->name, value),
+ errdetail("Valid values are \"on\", \"off\", and \"%s\".",
+ opt->unset_alias)));
}
break;
case RELOPT_TYPE_INT:
@@ -2008,7 +2007,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 7f57c787f4c..4031a07de0e 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 == PG_TERNARY_TRUE)
buildstate.buildMode = GIST_BUFFERING_STATS;
- else if (options->buffering_mode == GIST_OPTION_BUFFERING_OFF)
+ else if (options->buffering_mode == PG_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 03932f45c8a..895a7d2e3a1 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -2178,22 +2178,21 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams params,
*/
if (params.index_cleanup == VACOPTVALUE_UNSPECIFIED)
{
- StdRdOptIndexCleanup vacuum_index_cleanup;
+ pg_ternary vacuum_index_cleanup;
if (rel->rd_options == NULL)
- vacuum_index_cleanup = STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO;
+ vacuum_index_cleanup = PG_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 == PG_TERNARY_UNSET)
params.index_cleanup = VACOPTVALUE_AUTO;
- else if (vacuum_index_cleanup == STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON)
+ else if (vacuum_index_cleanup == PG_TERNARY_TRUE)
params.index_cleanup = VACOPTVALUE_ENABLED;
else
{
- Assert(vacuum_index_cleanup ==
- STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF);
+ Assert(vacuum_index_cleanup == PG_TERNARY_FALSE);
params.index_cleanup = VACOPTVALUE_DISABLED;
}
}
diff --git a/src/include/access/gist_private.h b/src/include/access/gist_private.h
index 552f605c0aa..6db5f0a1c9c 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 */
+ pg_ternary buffering_mode; /* buffering build mode */
} GiSTOptions;
/* gist.c */
diff --git a/src/include/access/reloptions.h b/src/include/access/reloptions.h
index 0bd17b30ca7..40ce291c894 100644
--- a/src/include/access/reloptions.h
+++ b/src/include/access/reloptions.h
@@ -99,7 +99,8 @@ typedef struct relopt_bool
typedef struct relopt_ternary
{
relopt_gen gen;
- /* ternaries have no default_val: otherwise they'd just be bools */
+ const char *unset_alias; /* word that will be treated as unset value */
+ int default_val;
} relopt_ternary;
typedef struct relopt_int
@@ -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, LOCKMODE lockmode);
+ const char *desc, pg_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);
@@ -212,8 +214,9 @@ extern void add_local_bool_reloption(local_relopts *relopts, const char *name,
const char *desc, bool default_val,
int offset);
extern void add_local_ternary_reloption(local_relopts *relopts,
- const char *name, const char *desc,
- int offset);
+ const char *name, const char *desc,
+ pg_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 236830f6b93..db6b043d2d0 100644
--- a/src/include/utils/rel.h
+++ b/src/include/utils/rel.h
@@ -330,14 +330,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!) */
@@ -346,7 +338,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 */
+ pg_ternary vacuum_index_cleanup; /* controls index vacuuming */
pg_ternary vacuum_truncate; /* enables vacuum to truncate a relation */
/*
diff --git a/src/test/modules/dummy_index_am/README b/src/test/modules/dummy_index_am/README
index 604d823c2e4..d80aff0db19 100644
--- a/src/test/modules/dummy_index_am/README
+++ b/src/test/modules/dummy_index_am/README
@@ -5,7 +5,8 @@ Dummy index AM is a module for testing any facility usable by an index
access method, whose code is kept a maximum simple.
This includes tests for all relation option types:
-- boolean & ternary
+- boolean
+- ternary
- enum
- integer
- real
diff --git a/src/test/modules/dummy_index_am/dummy_index_am.c b/src/test/modules/dummy_index_am/dummy_index_am.c
index 31f8d2b8161..e8f6dcac9de 100644
--- a/src/test/modules/dummy_index_am/dummy_index_am.c
+++ b/src/test/modules/dummy_index_am/dummy_index_am.c
@@ -41,6 +41,7 @@ typedef struct DummyIndexOptions
double option_real;
bool option_bool;
pg_ternary option_ternary_1;
+ pg_ternary option_ternary_2;
DummyAmEnum option_enum;
int option_string_val_offset;
int option_string_null_offset;
@@ -104,12 +105,20 @@ create_reloptions_table(void)
add_ternary_reloption(di_relopt_kind, "option_ternary_1",
"One ternary option for dummy_index_am",
- AccessExclusiveLock);
+ PG_TERNARY_UNSET, NULL, AccessExclusiveLock);
di_relopt_tab[i].optname = "option_ternary_1";
di_relopt_tab[i].opttype = RELOPT_TYPE_TERNARY;
di_relopt_tab[i].offset = offsetof(DummyIndexOptions, option_ternary_1);
i++;
+ add_ternary_reloption(di_relopt_kind, "option_ternary_2",
+ "Second ternary option for dummy_index_am",
+ PG_TERNARY_TRUE, "do_not_know_yet", AccessExclusiveLock);
+ di_relopt_tab[i].optname = "option_ternary_2";
+ di_relopt_tab[i].opttype = RELOPT_TYPE_TERNARY;
+ di_relopt_tab[i].offset = offsetof(DummyIndexOptions, option_ternary_2);
+ i++;
+
add_enum_reloption(di_relopt_kind, "option_enum",
"Enum option for dummy_index_am",
dummyAmEnumValues,
diff --git a/src/test/modules/dummy_index_am/expected/reloptions.out b/src/test/modules/dummy_index_am/expected/reloptions.out
index 3b06d514995..90abbe2e373 100644
--- a/src/test/modules/dummy_index_am/expected/reloptions.out
+++ b/src/test/modules/dummy_index_am/expected/reloptions.out
@@ -19,6 +19,7 @@ CREATE INDEX dummy_test_idx ON dummy_test_tab
USING dummy_index_am (i) WITH (
option_bool = false,
option_ternary_1,
+ option_ternary_2 = off,
option_int = 5,
option_real = 3.1,
option_enum = 'two',
@@ -33,17 +34,19 @@ SELECT unnest(reloptions) FROM pg_class WHERE relname = 'dummy_test_idx';
------------------------
option_bool=false
option_ternary_1=true
+ option_ternary_2=off
option_int=5
option_real=3.1
option_enum=two
option_string_val=null
option_string_null=val
-(7 rows)
+(8 rows)
-- ALTER INDEX .. SET
ALTER INDEX dummy_test_idx SET (option_int = 10);
ALTER INDEX dummy_test_idx SET (option_bool = true);
ALTER INDEX dummy_test_idx SET (option_ternary_1 = false);
+ALTER INDEX dummy_test_idx SET (option_ternary_2 = Do_Not_Know_YET);
ALTER INDEX dummy_test_idx SET (option_real = 3.2);
ALTER INDEX dummy_test_idx SET (option_string_val = 'val2');
ALTER INDEX dummy_test_idx SET (option_string_null = NULL);
@@ -52,21 +55,23 @@ ALTER INDEX dummy_test_idx SET (option_enum = 'three');
ERROR: invalid value for enum option "option_enum": three
DETAIL: Valid values are "one" and "two".
SELECT unnest(reloptions) FROM pg_class WHERE relname = 'dummy_test_idx';
- unnest
--------------------------
+ unnest
+----------------------------------
option_int=10
option_bool=true
option_ternary_1=false
+ option_ternary_2=do_not_know_yet
option_real=3.2
option_string_val=val2
option_string_null=null
option_enum=one
-(7 rows)
+(8 rows)
-- ALTER INDEX .. RESET
ALTER INDEX dummy_test_idx RESET (option_int);
ALTER INDEX dummy_test_idx RESET (option_bool);
ALTER INDEX dummy_test_idx RESET (option_ternary_1);
+ALTER INDEX dummy_test_idx RESET (option_ternary_2);
ALTER INDEX dummy_test_idx RESET (option_real);
ALTER INDEX dummy_test_idx RESET (option_enum);
ALTER INDEX dummy_test_idx RESET (option_string_val);
@@ -113,13 +118,21 @@ ALTER INDEX dummy_test_idx SET (option_ternary_1 = 3.4); -- error
ERROR: invalid value for boolean option "option_ternary_1": 3.4
ALTER INDEX dummy_test_idx SET (option_ternary_1 = 'val4'); -- error
ERROR: invalid value for boolean option "option_ternary_1": val4
+ALTER INDEX dummy_test_idx SET (option_ternary_1 = 'do_not_know_yet'); -- error. Valid for ternary2 not for ternary1
+ERROR: invalid value for boolean option "option_ternary_1": do_not_know_yet
+ALTER INDEX dummy_test_idx SET (option_ternary_2 = 'do_not_know_yet'); -- ok
+ALTER INDEX dummy_test_idx SET (option_ternary_2 = 'illegal_value'); -- error
+ERROR: invalid value for option "option_ternary_2": illegal_value
+DETAIL: Valid values are "on", "off", and "do_not_know_yet".
SELECT unnest(reloptions) FROM pg_class WHERE relname = 'dummy_test_idx';
- unnest
---------------------
+ unnest
+----------------------------------
option_ternary_1=1
-(1 row)
+ option_ternary_2=do_not_know_yet
+(2 rows)
ALTER INDEX dummy_test_idx RESET (option_ternary_1);
+ALTER INDEX dummy_test_idx RESET (option_ternary_2);
-- Float
ALTER INDEX dummy_test_idx SET (option_real = 4); -- ok
ALTER INDEX dummy_test_idx SET (option_real = true); -- error
diff --git a/src/test/modules/dummy_index_am/sql/reloptions.sql b/src/test/modules/dummy_index_am/sql/reloptions.sql
index 2cdff0820f6..f8b985055c1 100644
--- a/src/test/modules/dummy_index_am/sql/reloptions.sql
+++ b/src/test/modules/dummy_index_am/sql/reloptions.sql
@@ -19,6 +19,7 @@ CREATE INDEX dummy_test_idx ON dummy_test_tab
USING dummy_index_am (i) WITH (
option_bool = false,
option_ternary_1,
+ option_ternary_2 = off,
option_int = 5,
option_real = 3.1,
option_enum = 'two',
@@ -32,6 +33,7 @@ SELECT unnest(reloptions) FROM pg_class WHERE relname = 'dummy_test_idx';
ALTER INDEX dummy_test_idx SET (option_int = 10);
ALTER INDEX dummy_test_idx SET (option_bool = true);
ALTER INDEX dummy_test_idx SET (option_ternary_1 = false);
+ALTER INDEX dummy_test_idx SET (option_ternary_2 = Do_Not_Know_YET);
ALTER INDEX dummy_test_idx SET (option_real = 3.2);
ALTER INDEX dummy_test_idx SET (option_string_val = 'val2');
ALTER INDEX dummy_test_idx SET (option_string_null = NULL);
@@ -43,6 +45,7 @@ SELECT unnest(reloptions) FROM pg_class WHERE relname = 'dummy_test_idx';
ALTER INDEX dummy_test_idx RESET (option_int);
ALTER INDEX dummy_test_idx RESET (option_bool);
ALTER INDEX dummy_test_idx RESET (option_ternary_1);
+ALTER INDEX dummy_test_idx RESET (option_ternary_2);
ALTER INDEX dummy_test_idx RESET (option_real);
ALTER INDEX dummy_test_idx RESET (option_enum);
ALTER INDEX dummy_test_idx RESET (option_string_val);
@@ -68,8 +71,12 @@ ALTER INDEX dummy_test_idx SET (option_ternary_1 = 4); -- error
ALTER INDEX dummy_test_idx SET (option_ternary_1 = 1); -- ok, as true
ALTER INDEX dummy_test_idx SET (option_ternary_1 = 3.4); -- error
ALTER INDEX dummy_test_idx SET (option_ternary_1 = 'val4'); -- error
+ALTER INDEX dummy_test_idx SET (option_ternary_1 = 'do_not_know_yet'); -- error. Valid for ternary2 not for ternary1
+ALTER INDEX dummy_test_idx SET (option_ternary_2 = 'do_not_know_yet'); -- ok
+ALTER INDEX dummy_test_idx SET (option_ternary_2 = 'illegal_value'); -- error
SELECT unnest(reloptions) FROM pg_class WHERE relname = 'dummy_test_idx';
ALTER INDEX dummy_test_idx RESET (option_ternary_1);
+ALTER INDEX dummy_test_idx RESET (option_ternary_2);
-- Float
ALTER INDEX dummy_test_idx SET (option_real = 4); -- ok
ALTER INDEX dummy_test_idx SET (option_real = true); -- error
diff --git a/src/test/regress/expected/gist.out b/src/test/regress/expected/gist.out
index c75bbb23b6e..19dc547d5f8 100644
--- a/src/test/regress/expected/gist.out
+++ b/src/test/regress/expected/gist.out
@@ -12,7 +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
+ERROR: invalid value for option "buffering": invalid_value
DETAIL: Valid values are "on", "off", and "auto".
create index gist_pointidx5 on gist_point_tbl using gist(p) with (fillfactor=9);
ERROR: value 9 out of bounds for option "fillfactor"
diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index e3a974f2611..6e65cd5c3da 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -116,6 +116,24 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
{vacuum_truncate=fals}
(1 row)
+-- preferred "true" alias is stored in pg_class
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+ reloptions
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+ reloptions
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
-- Test vacuum_truncate option
DROP TABLE reloptions_test;
CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 680c8bf8614..c99673db9ec 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -70,6 +70,16 @@ DROP TABLE reloptions_test;
CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+-- preferred "true" alias is stored in pg_class
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
-- Test vacuum_truncate option
DROP TABLE reloptions_test;
--
2.47.3