diff --git a/doc/src/sgml/ref/create_table.sgml b/doc/src/sgml/ref/create_table.sgml
index e342585c7f0..79622c1a23d 100644
--- a/doc/src/sgml/ref/create_table.sgml
+++ b/doc/src/sgml/ref/create_table.sgml
@@ -1653,6 +1653,32 @@ WITH ( MODULUS numeric_literal, REM
+
+ toast_value_type (enum)
+
+ toast_value_type storage parameter
+
+
+
+
+ Specifies the attribute type of chunk_id to use when
+ creating a TOAST relation for this table. The
+ default is oid.
+ This parameter cannot be set for TOAST tables.
+
+
+ The value is only consulted when the TOAST relation
+ is created. Changing it afterwards has no effect on an existing
+ TOAST relation, and a table rewrite such as
+ CLUSTER or
+ VACUUM FULL
+ preserves the type already in use. A dump and restore, on the other
+ hand, recreates the TOAST relation and therefore
+ applies the current value of this parameter.
+
+
+
+
parallel_workers (integer)
diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c
index c3f6f45f460..82491a31a9a 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -548,6 +548,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[] =
{
{
@@ -561,6 +569,17 @@ static relopt_enum enumRelOpts[] =
STDRD_OPTION_VACUUM_INDEX_CLEANUP_NOT_SET,
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",
@@ -2078,6 +2097,8 @@ static const relopt_parse_elt stdRdOptionsTab[] = {
offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, log_analyze_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 b19478ba072..a4a7b7c91b3 100644
--- a/src/backend/catalog/toasting.c
+++ b/src/backend/catalog/toasting.c
@@ -159,9 +159,25 @@ 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);
+
+ /* no default clause to catch new values added */
+ switch (value_type)
+ {
+ case STDRD_OPTION_TOAST_VALUE_TYPE_OID:
+ toast_chunkid_typid = OIDOID;
+ break;
+ case STDRD_OPTION_TOAST_VALUE_TYPE_INVALID:
+ elog(ERROR, "unexpected toast_value_type value %d",
+ value_type);
+ break;
+ }
}
else
{
diff --git a/src/bin/psql/tab-complete.in.c b/src/bin/psql/tab-complete.in.c
index 8e1a1d69740..84a129efff5 100644
--- a/src/bin/psql/tab-complete.in.c
+++ b/src/bin/psql/tab-complete.in.c
@@ -1441,6 +1441,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/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index 12ae8f4331a..97d367cdd42 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -57,6 +57,6 @@
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 202609111
+#define CATALOG_VERSION_NO 202609112
#endif
diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h
index 41ab4586c6b..a88549dcc55 100644
--- a/src/include/utils/rel.h
+++ b/src/include/utils/rel.h
@@ -341,11 +341,20 @@ typedef enum StdRdOptIndexCleanup
STDRD_OPTION_VACUUM_INDEX_CLEANUP_NOT_SET,
} 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 */
@@ -370,6 +379,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/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index e3a974f2611..9b4c8587aa4 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -194,6 +194,28 @@ SELECT reloptions FROM pg_class WHERE oid = :toast_oid;
-- Fail on non-existent options in toast namespace
CREATE TABLE reloptions_test2 (i int) WITH (toast.not_existing_option = 42);
ERROR: unrecognized parameter "not_existing_option"
+-- Test toast_value_type.
+CREATE TABLE reloptions_test2 (s VARCHAR) WITH (toast.toast_value_type = 'oid');
+ERROR: unrecognized parameter "toast_value_type"
+CREATE TABLE reloptions_test2 (s VARCHAR) WITH (toast_value_type = 'int8');
+ERROR: invalid value for enum option "toast_value_type": int8
+DETAIL: Valid values are "oid".
+CREATE TABLE reloptions_test2 (s VARCHAR) WITH (toast_value_type = 'oid');
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test2'::regclass;
+ reloptions
+------------------------
+ {toast_value_type=oid}
+(1 row)
+
+DROP TABLE reloptions_test2;
+-- relkinds not supported.
+CREATE INDEX reloptions_test_idx0 ON reloptions_test (s)
+ WITH (toast_value_type = 'oid');
+ERROR: unrecognized parameter "toast_value_type"
+CREATE TABLE reloptions_test2 (i int) PARTITION BY RANGE (i)
+ WITH (toast_value_type = 'oid');
+ERROR: cannot specify storage parameters for a partitioned table
+HINT: Specify storage parameters for its leaf partitions instead.
-- Mix TOAST & heap
DROP TABLE reloptions_test;
CREATE TABLE reloptions_test (s VARCHAR) WITH
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 680c8bf8614..503d15d16e5 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -112,6 +112,18 @@ SELECT reloptions FROM pg_class WHERE oid = :toast_oid;
-- Fail on non-existent options in toast namespace
CREATE TABLE reloptions_test2 (i int) WITH (toast.not_existing_option = 42);
+-- Test toast_value_type.
+CREATE TABLE reloptions_test2 (s VARCHAR) WITH (toast.toast_value_type = 'oid');
+CREATE TABLE reloptions_test2 (s VARCHAR) WITH (toast_value_type = 'int8');
+CREATE TABLE reloptions_test2 (s VARCHAR) WITH (toast_value_type = 'oid');
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test2'::regclass;
+DROP TABLE reloptions_test2;
+-- relkinds not supported.
+CREATE INDEX reloptions_test_idx0 ON reloptions_test (s)
+ WITH (toast_value_type = 'oid');
+CREATE TABLE reloptions_test2 (i int) PARTITION BY RANGE (i)
+ WITH (toast_value_type = 'oid');
+
-- Mix TOAST & heap
DROP TABLE reloptions_test;
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 7aedaafab90..de21cea65f9 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -3000,6 +3000,7 @@ StatsElem
StatsExtInfo
StdAnalyzeData
StdRdOptIndexCleanup
+StdRdOptToastValueType
StdRdOptions
Step
StopList