1
0
mirror of https://github.com/postgres/postgres.git synced 2026-10-23 13:29:09 +03:00

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 initially
created.  An update of this parameter has no effect if a TOAST table
already exists under the relation, even on rewrites.  It cannot be set
for TOAST relations.

This new option can be set only to "oid" as of this commit.  This
feature is extracted as a patch of its own to ease the introduction of a
second mode in a follow-up change, related to the introduction of 8-byte
OIDs in external TOAST pointers.

Bump catalog version, as StdRdOptions has changed.

Author: Michael Paquier <michael@paquier.xyz>
Reviewed-by: Greg Burd <greg@burd.me>
Reviewed-by: Bharath Rupireddy <bharath.rupireddyforpostgres@gmail.com>
Reviewed-by: Yugo Nagata <nagata@sraoss.co.jp>
Discussion: https://postgr.es/m/af19kUjwjhaoUTLn@paquier.xyz
This commit is contained in:
Michael Paquier
2026-09-11 12:26:58 +09:00
parent 1497ea77ed
commit f33844889b
9 changed files with 117 additions and 1 deletions

View File

@@ -1653,6 +1653,32 @@ 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>
Specifies the attribute type of <literal>chunk_id</literal> to use when
creating a <acronym>TOAST</acronym> relation for this table. The
default is <literal>oid</literal>.
This parameter cannot be set for <acronym>TOAST</acronym> tables.
</para>
<para>
The value is only consulted when the <acronym>TOAST</acronym> relation
is created. Changing it afterwards has no effect on an existing
<acronym>TOAST</acronym> relation, and a table rewrite such as
<link linkend="sql-cluster"><command>CLUSTER</command></link> or
<link linkend="sql-vacuum"><command>VACUUM FULL</command></link>
preserves the type already in use. A dump and restore, on the other
hand, recreates the <acronym>TOAST</acronym> relation and therefore
applies the current value of this parameter.
</para>
</listitem>
</varlistentry>
<varlistentry id="reloption-parallel-workers" xreflabel="parallel_workers">
<term><literal>parallel_workers</literal> (<type>integer</type>)
<indexterm>

View File

@@ -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,

View File

@@ -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
{

View File

@@ -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",

View File

@@ -57,6 +57,6 @@
*/
/* yyyymmddN */
#define CATALOG_VERSION_NO 202609111
#define CATALOG_VERSION_NO 202609112
#endif

View File

@@ -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!

View File

@@ -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

View File

@@ -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;

View File

@@ -3000,6 +3000,7 @@ StatsElem
StatsExtInfo
StdAnalyzeData
StdRdOptIndexCleanup
StdRdOptToastValueType
StdRdOptions
Step
StopList