agora inbox for pgsql-hackers@postgresql.org  
help / color / mirror / Atom feed
[PATCH v1 1/4] Add trenary reloption type
268+ messages / 2 participants
[nested] [flat]

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



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

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

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

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

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

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

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

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

---

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

---

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

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH v1 1/4] Add trenary reloption type
@ 2025-08-30 12:12  Nikolay Shaplov <dhyan@nataraj.su>
  0 siblings, 0 replies; 268+ messages in thread

From: Nikolay Shaplov @ 2025-08-30 12:12 UTC (permalink / raw)

There is a tendency for boolean reloptions in PostgreSQL code, one with "on"
and "off" values, to be replaced with options with "on", "off",
"[use_global_settings]" behaviour.

For `vacuum_index_cleanup" and gist's `buffering` reloption such behavior have
been implemented as enum-tyoe option.

For vacuum_truncate this behaviour have been umplemented by adding additional
`is_set` flag to `bytea` representation of the reloptions.

Both solutions looks like workaround hacks to implement option with three
available states.

This patch introduce "trenary" reloption type, that behave like bool option,
but also has an additional "unset" state. This state may be reachable only by
not setting or RESETting an option, like in `vacuum_truncate` option, or it
may have some text alias that allow user to explicitly set it, like "auto" in
`vacuum_index_cleanup` or gist's `buffering`

`vacuum_truncate`, `vacuum_index_cleanup` and gist's `buffering` reloptions are
reimplemented as trenary  reloptions without significant behaviour changes.

---

This patch is split into four parts, to help reviewer grasp the login behind
it. I guess it is better to commit it as a single commit

---

Part1: Add regression tests that would be tests for trenary reloptions in
future, but now it checks the behaviour of reloptions that would become
trenary. There behaviour should not change, so adding tests before changing
anything. These tests should pass before applying the patch, and after it.
---
 src/test/regress/expected/reloptions.out | 36 ++++++++++++++++++++++++
 src/test/regress/sql/reloptions.sql      | 21 ++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index 9de19b4e3f1..e32431ca067 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -98,6 +98,42 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
  {fillfactor=13,autovacuum_enabled=false}
 (1 row)
 
+-- Tests for future (FIXME) trenary options
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=true}
+(1 row)
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+       reloptions       
+------------------------
+ {vacuum_truncate=fals}
+(1 row)
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+        reloptions         
+---------------------------
+ {vacuum_index_cleanup=on}
+(1 row)
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+         reloptions          
+-----------------------------
+ {vacuum_index_cleanup=auto}
+(1 row)
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 CREATE TEMP TABLE reloptions_test(i INT NOT NULL, j text)
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 24fbe0b478d..051142eed5f 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -59,6 +59,27 @@ UPDATE pg_class
 ALTER TABLE reloptions_test RESET (illegal_option);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 
+-- Tests for future (FIXME) trenary options
+
+-- behave as boolean option: accept unassigned name and truncated value
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_truncate=FaLS);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- preferred "true" alias is used when storing
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=on);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
+-- custom "third" value is available
+DROP TABLE reloptions_test;
+CREATE TABLE reloptions_test(i INT) WITH (vacuum_index_cleanup=auto);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 -- Test vacuum_truncate option
 DROP TABLE reloptions_test;
 
-- 
2.39.2


--nextPart6784952.tM3a2QDmDi
Content-Disposition: attachment;
 filename="v1-0002-Introduce-trenary-reloptions.patch"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-patch; charset="unicode-2-0-utf-8";
 name="v1-0002-Introduce-trenary-reloptions.patch"



^ permalink  raw  reply  [nested|flat] 268+ messages in thread

* [PATCH] REPACK CONCURRENTLY: Initialize the range table more honestly
@ 2026-07-03 10:47  Álvaro Herrera <alvherre@kurilemu.de>
  0 siblings, 0 replies; 268+ messages in thread

From: Álvaro Herrera @ 2026-07-03 10:47 UTC (permalink / raw)

We were skipping a bunch of things that are mostly unnecessary for
REPACK.  However, one thing that seems would be better to pass closer to
truth, is the updatedCols bitmapset in the range table entry for the
repacked table.  Cons up an RTE and install it into the EState.

This only has an effect on btree indexes, because certain operations are
optimized in the case of unchanged columns; and even then, correctnesss
is not being compromised.

The values we pass after this commit are not fully trustworthy either,
because we simply say "all columns were updated" for all insert/updates,
regardless of whether their values were actually modified or not.
However, this way we err to the side of caution rather than to the
opposite direction as we were originally doing.  This could be refined
in the future, but there's a trade-off: determining whether the column
was in fact updated could be expensive.

Author: Antonin Houska <ah@cybertec.at>
Reviewed-by: Ewan Young <kdbase.hack@gmail.com>
Backpatch-through: 19
Discussion: https://postgr.es/m/18222.1782126731@localhost
---
 src/backend/commands/repack.c | 57 +++++++++++++++++++++++++++++++++--
 1 file changed, 55 insertions(+), 2 deletions(-)

diff --git a/src/backend/commands/repack.c b/src/backend/commands/repack.c
index 83a49afe7e1..faa07d1a118 100644
--- a/src/backend/commands/repack.c
+++ b/src/backend/commands/repack.c
@@ -63,6 +63,7 @@
 #include "libpq/pqmq.h"
 #include "miscadmin.h"
 #include "optimizer/optimizer.h"
+#include "parser/parse_relation.h"
 #include "pgstat.h"
 #include "replication/logicalrelation.h"
 #include "storage/bufmgr.h"
@@ -3019,8 +3020,60 @@ initialize_change_context(ChangeContext *chgcxt,
 	/* Only initialize fields needed by ExecInsertIndexTuples(). */
 	chgcxt->cc_estate = CreateExecutorState();
 
-	chgcxt->cc_rri = (ResultRelInfo *) palloc(sizeof(ResultRelInfo));
-	InitResultRelInfo(chgcxt->cc_rri, relation, 0, 0, 0);
+	/*
+	 * Set up a range table for the executor, containing our repacked table as
+	 * its only member.
+	 */
+	{
+		RangeTblEntry *rte;
+		TupleDesc	desc = RelationGetDescr(relation);
+		List	   *perminfos = NIL;
+		Bitmapset  *updatedCols = NULL;
+		RTEPermissionInfo *perminfo;
+
+		/*
+		 * For our use, the RTE only needs to have perminfoindex initialized,
+		 * but there's no reason to not set the fields whose values we have at
+		 * hand.
+		 */
+		rte = makeNode(RangeTblEntry);
+		rte->rtekind = RTE_RELATION;
+		rte->relid = RelationGetRelid(relation);
+		rte->relkind = RelationGetForm(relation)->relkind;
+		/* Create the RTEPermissionInfo instance (and set ->perminfoindex). */
+		addRTEPermissionInfo(&perminfos, rte);
+
+		/*
+		 * Initialize updatedCols to show that all columns are updated.  This
+		 * is of course not necessarily true, and we cannot know this early;
+		 * but this is only used by ExecInsertIndexTuples to flag index
+		 * updates with no logical value changes, so if it's wrong, nothing
+		 * terribly bad happens. We may want to improve this someday though.
+		 *
+		 * Don't claim that dropped columns are changed though.
+		 */
+		for (int i = 0; i < desc->natts; i++)
+		{
+			CompactAttribute *attr = TupleDescCompactAttr(desc, i);
+
+			if (attr->attisdropped)
+				continue;
+			updatedCols = bms_add_member(updatedCols,
+										 i + 1 - FirstLowInvalidHeapAttributeNumber);
+		}
+
+		/* install updatedCols in the right place */
+		perminfo = getRTEPermissionInfo(perminfos, rte);
+		perminfo->updatedCols = updatedCols;
+
+		/* finally we can initialize the range table proper */
+		ExecInitRangeTable(chgcxt->cc_estate, list_make1(rte), perminfos,
+						   bms_make_singleton(1));
+	}
+
+	/* Set up our ResultRelInfo to use for index updates */
+	chgcxt->cc_rri = makeNode(ResultRelInfo);
+	InitResultRelInfo(chgcxt->cc_rri, relation, 1, NULL, 0);
 	ExecOpenIndices(chgcxt->cc_rri, false);
 
 	/*
-- 
2.47.3


--pi6rmivyoaehyqn6--





^ permalink  raw  reply  [nested|flat] 268+ messages in thread


end of thread, other threads:[~2026-07-03 10:47 UTC | newest]

Thread overview: 268+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2025-08-30 12:12 [PATCH v1 1/4] Add trenary reloption type Nikolay Shaplov <dhyan@nataraj.su>
2026-07-03 10:47 [PATCH] REPACK CONCURRENTLY: Initialize the range table more honestly Álvaro Herrera <alvherre@kurilemu.de>

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox