agora inbox for [email protected]  
help / color / mirror / Atom feed
[PATCH v1] create table (like .. including ACCESS METHOD)
539+ messages / 2 participants
[nested] [flat]

* [PATCH v1] create table (like .. including ACCESS METHOD)
@ 2020-11-15 22:54 Justin Pryzby <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Justin Pryzby @ 2020-11-15 22:54 UTC (permalink / raw)

---
 doc/src/sgml/ref/create_table.sgml              | 12 +++++++++++-
 src/backend/parser/gram.y                       |  3 ++-
 src/backend/parser/parse_utilcmd.c              |  7 +++++++
 src/include/nodes/parsenodes.h                  | 17 +++++++++--------
 src/test/regress/expected/create_table_like.out |  2 +-
 src/test/regress/sql/create_table_like.sql      |  2 +-
 6 files changed, 31 insertions(+), 12 deletions(-)

diff --git a/doc/src/sgml/ref/create_table.sgml b/doc/src/sgml/ref/create_table.sgml
index 569f4c9da7..cb95177e92 100644
--- a/doc/src/sgml/ref/create_table.sgml
+++ b/doc/src/sgml/ref/create_table.sgml
@@ -87,7 +87,7 @@ class="parameter">referential_action</replaceable> ] [ ON UPDATE <replaceable cl
 
 <phrase>and <replaceable class="parameter">like_option</replaceable> is:</phrase>
 
-{ INCLUDING | EXCLUDING } { COMMENTS | CONSTRAINTS | DEFAULTS | GENERATED | IDENTITY | INDEXES | STATISTICS | STORAGE | ALL }
+{ INCLUDING | EXCLUDING } { ACCESS METHOD | COMMENTS | CONSTRAINTS | DEFAULTS | GENERATED | IDENTITY | INDEXES | STATISTICS | STORAGE | ALL }
 
 <phrase>and <replaceable class="parameter">partition_bound_spec</replaceable> is:</phrase>
 
@@ -593,6 +593,16 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM
       available options are:
 
       <variablelist>
+       <varlistentry>
+        <term><literal>INCLUDING ACCESS METHOD</literal></term>
+        <listitem>
+         <para>
+          The table's access method will be copied.  By default, the
+          <literal>default_table_access_method</literal> is used.
+         </para>
+        </listitem>
+       </varlistentry>
+
        <varlistentry>
         <term><literal>INCLUDING COMMENTS</literal></term>
         <listitem>
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 8f341ac006..b32861a04e 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -3651,7 +3651,8 @@ TableLikeOptionList:
 		;
 
 TableLikeOption:
-				COMMENTS			{ $$ = CREATE_TABLE_LIKE_COMMENTS; }
+				ACCESS METHOD			{ $$ = CREATE_TABLE_LIKE_ACCESSMETHOD; }
+				| COMMENTS			{ $$ = CREATE_TABLE_LIKE_COMMENTS; }
 				| CONSTRAINTS		{ $$ = CREATE_TABLE_LIKE_CONSTRAINTS; }
 				| DEFAULTS			{ $$ = CREATE_TABLE_LIKE_DEFAULTS; }
 				| IDENTITY_P		{ $$ = CREATE_TABLE_LIKE_IDENTITY; }
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index 89ee990599..3507fd4738 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -96,6 +96,7 @@ typedef struct
 	bool		ispartitioned;	/* true if table is partitioned */
 	PartitionBoundSpec *partbound;	/* transformed FOR VALUES */
 	bool		ofType;			/* true if statement contains OF typename */
+	char		*accessMethod;	/* table access method */
 } CreateStmtContext;
 
 /* State shared by transformCreateSchemaStmt and its subroutines */
@@ -252,6 +253,7 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString)
 	cxt.ispartitioned = stmt->partspec != NULL;
 	cxt.partbound = stmt->partbound;
 	cxt.ofType = (stmt->ofTypename != NULL);
+	cxt.accessMethod = NULL;
 
 	Assert(!stmt->ofTypename || !stmt->inhRelations);	/* grammar enforces */
 
@@ -345,6 +347,8 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString)
 	 */
 	stmt->tableElts = cxt.columns;
 	stmt->constraints = cxt.ckconstraints;
+	if (cxt.accessMethod != NULL)
+		stmt->accessMethod = cxt.accessMethod;
 
 	result = lappend(cxt.blist, stmt);
 	result = list_concat(result, cxt.alist);
@@ -1118,6 +1122,9 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla
 		cxt->likeclauses = lappend(cxt->likeclauses, table_like_clause);
 	}
 
+	if (table_like_clause->options & CREATE_TABLE_LIKE_ACCESSMETHOD)
+		cxt->accessMethod = get_am_name(relation->rd_rel->relam);
+
 	/*
 	 * We may copy extended statistics if requested, since the representation
 	 * of CreateStatsStmt doesn't depend on column numbers.
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 48a79a7657..589fd0cab0 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -677,14 +677,15 @@ typedef struct TableLikeClause
 
 typedef enum TableLikeOption
 {
-	CREATE_TABLE_LIKE_COMMENTS = 1 << 0,
-	CREATE_TABLE_LIKE_CONSTRAINTS = 1 << 1,
-	CREATE_TABLE_LIKE_DEFAULTS = 1 << 2,
-	CREATE_TABLE_LIKE_GENERATED = 1 << 3,
-	CREATE_TABLE_LIKE_IDENTITY = 1 << 4,
-	CREATE_TABLE_LIKE_INDEXES = 1 << 5,
-	CREATE_TABLE_LIKE_STATISTICS = 1 << 6,
-	CREATE_TABLE_LIKE_STORAGE = 1 << 7,
+	CREATE_TABLE_LIKE_ACCESSMETHOD = 1 << 0,
+	CREATE_TABLE_LIKE_COMMENTS = 1 << 1,
+	CREATE_TABLE_LIKE_CONSTRAINTS = 1 << 2,
+	CREATE_TABLE_LIKE_DEFAULTS = 1 << 3,
+	CREATE_TABLE_LIKE_GENERATED = 1 << 4,
+	CREATE_TABLE_LIKE_IDENTITY = 1 << 5,
+	CREATE_TABLE_LIKE_INDEXES = 1 << 6,
+	CREATE_TABLE_LIKE_STATISTICS = 1 << 7,
+	CREATE_TABLE_LIKE_STORAGE = 1 << 8,
 	CREATE_TABLE_LIKE_ALL = PG_INT32_MAX
 } TableLikeOption;
 
diff --git a/src/test/regress/expected/create_table_like.out b/src/test/regress/expected/create_table_like.out
index 10d17be23c..cac3c57c76 100644
--- a/src/test/regress/expected/create_table_like.out
+++ b/src/test/regress/expected/create_table_like.out
@@ -490,7 +490,7 @@ Check constraints:
     "noinh_con_copy_a_check" CHECK (a > 0) NO INHERIT
 
 -- fail, as partitioned tables don't allow NO INHERIT constraints
-CREATE TABLE noinh_con_copy1_parted (LIKE noinh_con_copy INCLUDING ALL)
+CREATE TABLE noinh_con_copy1_parted (LIKE noinh_con_copy INCLUDING ALL EXCLUDING ACCESS METHOD)
   PARTITION BY LIST (a);
 ERROR:  cannot add NO INHERIT constraint to partitioned table "noinh_con_copy1_parted"
 DROP TABLE noinh_con_copy, noinh_con_copy1;
diff --git a/src/test/regress/sql/create_table_like.sql b/src/test/regress/sql/create_table_like.sql
index 06b76f949d..eda9f39078 100644
--- a/src/test/regress/sql/create_table_like.sql
+++ b/src/test/regress/sql/create_table_like.sql
@@ -189,7 +189,7 @@ CREATE TABLE noinh_con_copy1 (LIKE noinh_con_copy INCLUDING CONSTRAINTS);
 \d noinh_con_copy1
 
 -- fail, as partitioned tables don't allow NO INHERIT constraints
-CREATE TABLE noinh_con_copy1_parted (LIKE noinh_con_copy INCLUDING ALL)
+CREATE TABLE noinh_con_copy1_parted (LIKE noinh_con_copy INCLUDING ALL EXCLUDING ACCESS METHOD)
   PARTITION BY LIST (a);
 
 DROP TABLE noinh_con_copy, noinh_con_copy1;
-- 
2.17.0


--ClNI7qcIuZbdM87U--





^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2a 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart4155600.3ZeAukHxDK
Content-Disposition: attachment;
 filename="v2a-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2a-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread

* [PATCH v2 1/4] Add ternary reloption type
@ 2025-09-04 14:34 Nikolay Shaplov <[email protected]>
  0 siblings, 0 replies; 539+ messages in thread

From: Nikolay Shaplov @ 2025-09-04 14:34 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "ternary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as ternary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for ternary reloptions in
future, but now it checks the behaviour of reloptions that would become
ternary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f..1c99f79ab0 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) ternary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+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 24fbe0b478..f5980dafcb 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) ternary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+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 used when storing
+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.39.2


--nextPart5129932.5fSG56mABF
Content-Disposition: attachment;
 filename="v2-0002-Introduce-ternary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v2-0002-Introduce-ternary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 539+ messages in thread


end of thread, other threads:[~2025-09-04 14:34 UTC | newest]

Thread overview: 539+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2020-11-15 22:54 [PATCH v1] create table (like .. including ACCESS METHOD) Justin Pryzby <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2a 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>
2025-09-04 14:34 [PATCH v2 1/4] Add ternary reloption type Nikolay Shaplov <[email protected]>

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox