From 5a238393e412c2284a93fe193b902b0db39d3bcc Mon Sep 17 00:00:00 2001
From: Michael Paquier <michael@paquier.xyz>
Date: Thu, 14 Aug 2025 12:54:58 +0900
Subject: [PATCH v5 12/15] Add relation option toast_value_type

This relation option gives the possibility to define the attribute type
that can be used for chunk_id in a TOAST table when it is created
initially.  This parameter has no effect if a TOAST table exists, even
after it is modified later on, even on rewrites.

This can be set only to "oid" currently, and will be expanded with a
second mode later.

Note: perhaps it would make sense to introduce that only when support
for 8-byte OID values are added to TOAST, the split is here to ease
review.
---
 src/include/utils/rel.h                | 17 +++++++++++++++++
 src/backend/access/common/reloptions.c | 21 +++++++++++++++++++++
 src/backend/catalog/toasting.c         |  6 ++++++
 src/bin/psql/tab-complete.in.c         |  1 +
 doc/src/sgml/ref/create_table.sgml     | 18 ++++++++++++++++++
 5 files changed, 63 insertions(+)

diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h
index b552359915f1..b846bd42103e 100644
--- a/src/include/utils/rel.h
+++ b/src/include/utils/rel.h
@@ -337,11 +337,20 @@ typedef enum StdRdOptIndexCleanup
 	STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON,
 } StdRdOptIndexCleanup;
 
+/* StdRdOptions->toast_value_type values */
+typedef enum StdRdOptToastValueType
+{
+	STDRD_OPTION_TOAST_VALUE_TYPE_INVALID = 0,
+	STDRD_OPTION_TOAST_VALUE_TYPE_OID,
+} StdRdOptToastValueType;
+
 typedef struct StdRdOptions
 {
 	int32		vl_len_;		/* varlena header (do not touch directly!) */
 	int			fillfactor;		/* page fill factor in percent (0..100) */
 	int			toast_tuple_target; /* target for tuple toasting */
+	StdRdOptToastValueType	toast_value_type;	/* type assigned to chunk_id
+												 * at toast table creation */
 	AutoVacOpts autovacuum;		/* autovacuum-related options */
 	bool		user_catalog_table; /* use as an additional catalog relation */
 	int			parallel_workers;	/* max number of parallel workers */
@@ -367,6 +376,14 @@ typedef struct StdRdOptions
 	((relation)->rd_options ? \
 	 ((StdRdOptions *) (relation)->rd_options)->toast_tuple_target : (defaulttarg))
 
+/*
+ * RelationGetToastValueType
+ *		Returns the relation's toast_value_type.  Note multiple eval of argument!
+ */
+#define RelationGetToastValueType(relation, defaulttarg) \
+	((relation)->rd_options ? \
+	 ((StdRdOptions *) (relation)->rd_options)->toast_value_type : defaulttarg)
+
 /*
  * RelationGetFillFactor
  *		Returns the relation's fillfactor.  Note multiple eval of argument!
diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c
index 0af3fea68fa4..b0447d9e39bb 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -516,6 +516,14 @@ static relopt_enum_elt_def viewCheckOptValues[] =
 	{(const char *) NULL}		/* list terminator */
 };
 
+/* values from StdRdOptToastValueType */
+static relopt_enum_elt_def StdRdOptToastValueTypes[] =
+{
+	/* no value for INVALID */
+	{"oid", STDRD_OPTION_TOAST_VALUE_TYPE_OID},
+	{(const char *) NULL}		/* list terminator */
+};
+
 static relopt_enum enumRelOpts[] =
 {
 	{
@@ -529,6 +537,17 @@ static relopt_enum enumRelOpts[] =
 		STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO,
 		gettext_noop("Valid values are \"on\", \"off\", and \"auto\".")
 	},
+	{
+		{
+			"toast_value_type",
+			"Controls the attribute type of chunk_id at toast table creation",
+			RELOPT_KIND_HEAP,
+			ShareUpdateExclusiveLock
+		},
+		StdRdOptToastValueTypes,
+		STDRD_OPTION_TOAST_VALUE_TYPE_OID,
+		gettext_noop("Valid values are \"oid\".")
+	},
 	{
 		{
 			"buffering",
@@ -1898,6 +1917,8 @@ default_reloptions(Datum reloptions, bool validate, relopt_kind kind)
 		offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, log_min_duration)},
 		{"toast_tuple_target", RELOPT_TYPE_INT,
 		offsetof(StdRdOptions, toast_tuple_target)},
+		{"toast_value_type", RELOPT_TYPE_ENUM,
+		offsetof(StdRdOptions, toast_value_type)},
 		{"autovacuum_vacuum_cost_delay", RELOPT_TYPE_REAL,
 		offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_cost_delay)},
 		{"autovacuum_vacuum_scale_factor", RELOPT_TYPE_REAL,
diff --git a/src/backend/catalog/toasting.c b/src/backend/catalog/toasting.c
index f1d76d8acd51..545983b5be9d 100644
--- a/src/backend/catalog/toasting.c
+++ b/src/backend/catalog/toasting.c
@@ -158,9 +158,15 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid,
 	 */
 	if (!IsBinaryUpgrade)
 	{
+		StdRdOptToastValueType value_type;
+
 		/* Normal mode, normal check */
 		if (!needs_toast_table(rel))
 			return false;
+
+		value_type = RelationGetToastValueType(rel, STDRD_OPTION_TOAST_VALUE_TYPE_OID);
+		if (value_type == STDRD_OPTION_TOAST_VALUE_TYPE_OID)
+			toast_chunkid_typid = OIDOID;
 	}
 	else
 	{
diff --git a/src/bin/psql/tab-complete.in.c b/src/bin/psql/tab-complete.in.c
index 8b10f2313f39..2b1cf063ebc2 100644
--- a/src/bin/psql/tab-complete.in.c
+++ b/src/bin/psql/tab-complete.in.c
@@ -1431,6 +1431,7 @@ static const char *const table_storage_parameters[] = {
 	"toast.vacuum_max_eager_freeze_failure_rate",
 	"toast.vacuum_truncate",
 	"toast_tuple_target",
+	"toast_value_type",
 	"user_catalog_table",
 	"vacuum_index_cleanup",
 	"vacuum_max_eager_freeze_failure_rate",
diff --git a/doc/src/sgml/ref/create_table.sgml b/doc/src/sgml/ref/create_table.sgml
index dc000e913c14..84ad78afa3de 100644
--- a/doc/src/sgml/ref/create_table.sgml
+++ b/doc/src/sgml/ref/create_table.sgml
@@ -1632,6 +1632,24 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM
     </listitem>
    </varlistentry>
 
+   <varlistentry id="reloption-toast-value-type" xreflabel="toast_value_type">
+    <term><literal>toast_value_type</literal> (<type>enum</type>)
+    <indexterm>
+     <primary><varname>toast_value_type</varname> storage parameter</primary>
+    </indexterm>
+    </term>
+    <listitem>
+     <para>
+      The toast_value_type specifies the attribute type of
+      <literal>chunk_id</literal> used when initially creating  a toast
+      relation for this table.
+      By default this parameter is <literal>oid</literal>, to assign
+      <type>oid</type> as attribute type to <literal>chunk_id</literal>.
+      This parameter cannot be set for TOAST tables.
+     </para>
+    </listitem>
+   </varlistentry>
+
    <varlistentry id="reloption-parallel-workers" xreflabel="parallel_workers">
     <term><literal>parallel_workers</literal> (<type>integer</type>)
      <indexterm>
-- 
2.50.0

