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 v3 1/4] Re-read subscription state after lock in AlterSubscription
@ 2026-07-03 12:28 Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 268+ messages in thread

From: Bertrand Drouvot @ 2026-07-03 12:28 UTC (permalink / raw)

AlterSubscription() reads the subscription's catalog state via GetSubscription()
before acquiring AccessExclusiveLock on the subscription object. A concurrent
session that commits a DROP or ALTER between the read and the lock acquisition
leaves the other session acting with stale information once it unblocks.

Fix by moving the GetSubscription() call, the password_required privilege check,
and the local variable assignments to after LockSharedObject(), with a re-read of
the subscription tuple to ensure we operate on current catalog state.

Remark:

The ownership check is intentionally not re-done after the lock because
AlterSubscriptionOwner() does not take AccessExclusiveLock on the subscription
object: it only takes RowExclusiveLock on the pg_subscription catalog table.
This means ownership can change regardless of our lock, making a re-check after
lock acquisition pointless. The existing "tuple concurrently updated" error from
CatalogTupleUpdate() already provides a protection if ownership changes
concurrently.

Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Dilip Kumar <dilipbalaut@gmail.com>
Reviewed-by: Hayato Kuroda (Fujitsu) <kuroda.hayato@fujitsu.com>
Reviewed-by: Zhijie Hou <houzj.fnst@fujitsu.com>
Reviewed-by: Amit Kapila <amit.kapila16@gmail.com>
Discussion: https://postgr.es/m/akZUpiDa1UfmzYxL%40bdtpg
---
 src/backend/commands/subscriptioncmds.c | 30 +++++++++++++++++++------
 1 file changed, 23 insertions(+), 7 deletions(-)
 100.0% src/backend/commands/

diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c
index 4292e7fb8f4..517d46f47f9 100644
--- a/src/backend/commands/subscriptioncmds.c
+++ b/src/backend/commands/subscriptioncmds.c
@@ -1686,6 +1686,25 @@ AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt,
 			orig_conninfo_needed = false;
 	}
 
+	heap_freetuple(tup);
+
+	/* Lock the subscription so nobody else can do anything with it. */
+	LockSharedObject(SubscriptionRelationId, subid, 0, AccessExclusiveLock);
+
+	/*
+	 * Re-read the subscription tuple after acquiring the lock. A concurrent
+	 * DROP or ALTER may have committed before we acquired the lock.
+	 */
+	tup = SearchSysCacheCopy1(SUBSCRIPTIONOID, ObjectIdGetDatum(subid));
+
+	if (!HeapTupleIsValid(tup))
+		ereport(ERROR,
+				(errcode(ERRCODE_UNDEFINED_OBJECT),
+				 errmsg("subscription \"%s\" does not exist",
+						stmt->subname)));
+
+	form = (Form_pg_subscription) GETSTRUCT(tup);
+
 	/*
 	 * Skip ACL checks on the subscription's foreign server, if any. If
 	 * changing the server (or replacing it with a raw connection), then the
@@ -1695,11 +1714,6 @@ AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt,
 	 */
 	sub = GetSubscription(subid, false, orig_conninfo_needed, false);
 
-	retain_dead_tuples = sub->retaindeadtuples;
-	origin = sub->origin;
-	max_retention = sub->maxretention;
-	retention_active = sub->retentionactive;
-
 	/*
 	 * Don't allow non-superuser modification of a subscription with
 	 * password_required=false.
@@ -1710,8 +1724,10 @@ AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt,
 				 errmsg("password_required=false is superuser-only"),
 				 errhint("Subscriptions with the password_required option set to false may only be created or modified by the superuser.")));
 
-	/* Lock the subscription so nobody else can do anything with it. */
-	LockSharedObject(SubscriptionRelationId, subid, 0, AccessExclusiveLock);
+	retain_dead_tuples = sub->retaindeadtuples;
+	origin = sub->origin;
+	max_retention = sub->maxretention;
+	retention_active = sub->retentionactive;
 
 	/* Form a new tuple. */
 	memset(values, 0, sizeof(values));
-- 
2.34.1


--3eAVwo4vDNlHc8RC
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v3-0002-Re-read-subscription-state-after-lock-in-DropSubs.patch"



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


end of thread, other threads:[~2026-07-03 12:28 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 12:28 [PATCH v3 1/4] Re-read subscription state after lock in AlterSubscription Bertrand Drouvot <bertranddrouvot.pg@gmail.com>

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox