On Mon, Dec 15, 2025, at 5:48 AM, jian he wrote:
> rebased, with minor comment polishing.
>
I started reviewing this patch. Why don't you reuse untransformRelOptions()?
Even if this function is used by various extensions [1][2], that's not an
excuse to duplicate code. I adjusted the code in the fixup. I did a bunch of
stylish changes and fixed a few typos. I also ran pgindent. I removed some
superfluous comments ("Fetch heap tuple", "Get the toast reloptions",). Don't
think they are saying something important. Coverage looks good. As a homework,
add a nice commit message. Showing how it works is not a good commit message.
This v6 is your v5 plus my suggestions.
[1] https://codesearch.debian.net/search?q=untransformRelOptions&literal=1
[2] https://github.com/search?q=untransformRelOptions&type=code
--
Euler Taveira
EDB https://www.enterprisedb.com/From 423eeaeef069ee3c1fa9725e20bbfcfa0464916d Mon Sep 17 00:00:00 2001
From: jian he <[email protected]>
Date: Mon, 15 Dec 2025 16:41:59 +0800
Subject: [PATCH v6 1/2] create table like incluing parameters
demo:
create table t(a text) with (fillfactor = 100, toast.vacuum_truncate=true);
create table t2(like t including parameters);
\d+ t2
Table "public.t2"
Column | Type | Collation | Nullable | Default | Storage | Compression | Stats target | Description
--------+------+-----------+----------+---------+----------+-------------+--------------+-------------
a | text | | | | extended | | |
Access method: heap
Options: fillfactor=100, toast.vacuum_truncate=true
commitfest: https://commitfest.postgresql.org/patch/6088
discussion: https://postgr.es/m/CACJufxHr=nKEsS66M7rTHgB+mXdQ948=_ej1jztac7pt-ej...@mail.gmail.com
---
doc/src/sgml/ref/create_table.sgml | 14 +++-
src/backend/access/common/reloptions.c | 50 ++++++++++++
src/backend/parser/gram.y | 5 +-
src/backend/parser/parse_utilcmd.c | 76 +++++++++++++++++++
src/include/access/reloptions.h | 1 +
src/include/nodes/parsenodes.h | 1 +
src/include/parser/kwlist.h | 1 +
.../regress/expected/create_table_like.out | 39 ++++++++++
src/test/regress/sql/create_table_like.sql | 28 +++++++
9 files changed, 213 insertions(+), 2 deletions(-)
diff --git a/doc/src/sgml/ref/create_table.sgml b/doc/src/sgml/ref/create_table.sgml
index 77c5a763d45..d645ab4ed31 100644
--- a/doc/src/sgml/ref/create_table.sgml
+++ b/doc/src/sgml/ref/create_table.sgml
@@ -88,7 +88,7 @@ class="parameter">referential_action</replaceable> ] [ ON UPDATE <replaceable cl
<phrase>and <replaceable class="parameter">like_option</replaceable> is:</phrase>
-{ INCLUDING | EXCLUDING } { COMMENTS | COMPRESSION | CONSTRAINTS | DEFAULTS | GENERATED | IDENTITY | INDEXES | STATISTICS | STORAGE | ALL }
+{ INCLUDING | EXCLUDING } { COMMENTS | COMPRESSION | CONSTRAINTS | DEFAULTS | GENERATED | IDENTITY | INDEXES | STATISTICS | STORAGE | PARAMETERS | ALL }
<phrase>and <replaceable class="parameter">partition_bound_spec</replaceable> is:</phrase>
@@ -753,6 +753,18 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM
</listitem>
</varlistentry>
+ <varlistentry id="sql-createtable-parms-like-opt-storage-paramter">
+ <term><literal>INCLUDING PARAMETERS</literal></term>
+ <listitem>
+ <para>
+ All table parameters, such as the <literal>storage parameter</literal>
+ settings of the source table, will be copied. For table storage
+ parameters, see <xref linkend="sql-createtable-storage-parameters"/>
+ below for more information.
+ </para>
+ </listitem>
+ </varlistentry>
+
<varlistentry id="sql-createtable-parms-like-opt-statistics">
<term><literal>INCLUDING STATISTICS</literal></term>
<listitem>
diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c
index 31926d8a368..9289caef7ba 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -1392,6 +1392,56 @@ untransformRelOptions(Datum options)
return result;
}
+/*
+ * Convert the reloptions from text-array format into a List of DefElem. This
+ * is the reverse operation of transformRelOptions().
+ *
+ * If any option includes a namespace qualification, create the DefElem in that
+ * namespace, otherwise this behave the same as untransformRelOptions.
+ */
+List *
+untransformRelOptionsExtended(Datum options, char* nameSpace)
+{
+ List *result = NIL;
+ ArrayType *array;
+ Datum *optiondatums;
+ int noptions;
+ int i;
+
+ /* Nothing to do if no options */
+ if (DatumGetPointer(options) == NULL)
+ return result;
+
+ array = DatumGetArrayTypeP(options);
+
+ deconstruct_array_builtin(array, TEXTOID, &optiondatums, NULL, &noptions);
+
+ for (i = 0; i < noptions; i++)
+ {
+ char *s;
+ char *p;
+ Node *val = NULL;
+
+ s = TextDatumGetCString(optiondatums[i]);
+ p = strchr(s, '=');
+ if (p)
+ {
+ *p++ = '\0';
+ val = (Node *) makeString(p);
+ }
+
+ if (nameSpace == NULL)
+ result = lappend(result, makeDefElem(s, val, -1));
+ else
+ result = lappend(result, makeDefElemExtended(nameSpace, s, val,
+ DEFELEM_UNSPEC,
+ -1));
+ }
+
+ return result;
+}
+
+
/*
* Extract and parse reloptions from a pg_class tuple.
*
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 28f4e11e30f..732cbe8dbab 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -765,7 +765,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
ORDER ORDINALITY OTHERS OUT_P OUTER_P
OVER OVERLAPS OVERLAY OVERRIDING OWNED OWNER
- PARALLEL PARAMETER PARSER PARTIAL PARTITION PARTITIONS PASSING PASSWORD PATH
+ PARALLEL PARAMETER PARAMETERS PARSER PARTIAL PARTITION PARTITIONS PASSING PASSWORD PATH
PERIOD PLACING PLAN PLANS POLICY
POSITION PRECEDING PRECISION PRESERVE PREPARE PREPARED PRIMARY
PRIOR PRIVILEGES PROCEDURAL PROCEDURE PROCEDURES PROGRAM PUBLICATION
@@ -4296,6 +4296,7 @@ TableLikeOption:
| INDEXES { $$ = CREATE_TABLE_LIKE_INDEXES; }
| STATISTICS { $$ = CREATE_TABLE_LIKE_STATISTICS; }
| STORAGE { $$ = CREATE_TABLE_LIKE_STORAGE; }
+ | PARAMETERS { $$ = CREATE_TABLE_LIKE_PARAMETERS; }
| ALL { $$ = CREATE_TABLE_LIKE_ALL; }
;
@@ -18087,6 +18088,7 @@ unreserved_keyword:
| OWNER
| PARALLEL
| PARAMETER
+ | PARAMETERS
| PARSER
| PARTIAL
| PARTITION
@@ -18719,6 +18721,7 @@ bare_label_keyword:
| OWNER
| PARALLEL
| PARAMETER
+ | PARAMETERS
| PARSER
| PARTIAL
| PARTITION
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index 375b40b29af..2e77c2db19b 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -88,6 +88,7 @@ typedef struct
List *fkconstraints; /* FOREIGN KEY constraints */
List *ixconstraints; /* index-creating constraints */
List *likeclauses; /* LIKE clauses that need post-processing */
+ List *options; /* options from WITH clause, table AM specific parameters */
List *blist; /* "before list" of things to do before
* creating the table */
List *alist; /* "after list" of things to do after creating
@@ -248,6 +249,7 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString)
cxt.fkconstraints = NIL;
cxt.ixconstraints = NIL;
cxt.likeclauses = NIL;
+ cxt.options = stmt->options;
cxt.blist = NIL;
cxt.alist = NIL;
cxt.pkey = NULL;
@@ -372,6 +374,7 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString)
stmt->tableElts = cxt.columns;
stmt->constraints = cxt.ckconstraints;
stmt->nnconstraints = cxt.nnconstraints;
+ stmt->options = cxt.options;
result = lappend(cxt.blist, stmt);
result = list_concat(result, cxt.alist);
@@ -1271,6 +1274,78 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla
}
}
+ /* Likewise, copy stoarge paramters if requested */
+ if ((table_like_clause->options & CREATE_TABLE_LIKE_PARAMETERS) &&
+ !cxt->isforeign)
+ {
+ HeapTuple tuple;
+ HeapTuple toast_tuple;
+ Datum reloptions;
+ bool isnull;
+ Oid relid;
+ List *oldoptions = NIL;
+ List *oldtoastoptions = NIL;
+
+ relid = RelationGetRelid(relation);
+ tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
+
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for relation %u", relid);
+
+ reloptions = SysCacheGetAttr(RELOID, tuple,
+ Anum_pg_class_reloptions, &isnull);
+ if (!isnull)
+ {
+ oldoptions = untransformRelOptions(reloptions);
+
+ foreach_node(DefElem, option, oldoptions)
+ cxt->options = lappend(cxt->options, option);
+ }
+
+ ReleaseSysCache(tuple);
+
+ /* get the toast relation's reloptions */
+ if (OidIsValid(relation->rd_rel->reltoastrelid))
+ {
+ Relation toastrel;
+
+ Oid toastid = relation->rd_rel->reltoastrelid;
+
+ /*
+ * The referenced table is already locked; acquire the lock on its
+ * associated TOAST relation now.
+ */
+ toastrel = table_open(toastid, AccessShareLock);
+
+ /* Fetch heap tuple */
+ toast_tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(toastid));
+
+ if (!HeapTupleIsValid(toast_tuple))
+ elog(ERROR, "cache lookup failed for toast relation %u", toastid);
+
+ /* Get the toast reloptions */
+ reloptions = SysCacheGetAttr(RELOID, toast_tuple, Anum_pg_class_reloptions,
+ &isnull);
+ if (!isnull)
+ {
+ oldtoastoptions = untransformRelOptionsExtended(reloptions, "toast");
+
+ foreach_node(DefElem, option, oldtoastoptions)
+ cxt->options = lappend(cxt->options, option);
+ }
+
+ ReleaseSysCache(toast_tuple);
+
+ /*
+ * Close the parent TOAST rel, but keep our AccessShareLock on it
+ * until xact commit. That will prevent someone else from deleting
+ * or ALTERing the parent TOAST before we can run
+ * expandTableLikeClause.
+ */
+ table_close(toastrel, NoLock);
+ }
+ }
+
/*
* Reproduce not-null constraints, if any, by copying them. We do this
* regardless of options given.
@@ -3860,6 +3935,7 @@ transformAlterTableStmt(Oid relid, AlterTableStmt *stmt,
cxt.fkconstraints = NIL;
cxt.ixconstraints = NIL;
cxt.likeclauses = NIL;
+ cxt.options = NIL;
cxt.blist = NIL;
cxt.alist = NIL;
cxt.pkey = NULL;
diff --git a/src/include/access/reloptions.h b/src/include/access/reloptions.h
index a604a4702c3..8589616d08b 100644
--- a/src/include/access/reloptions.h
+++ b/src/include/access/reloptions.h
@@ -236,6 +236,7 @@ extern Datum transformRelOptions(Datum oldOptions, List *defList,
const char *nameSpace, const char *const validnsps[],
bool acceptOidsOff, bool isReset);
extern List *untransformRelOptions(Datum options);
+extern List *untransformRelOptionsExtended(Datum options, char* nameSpace);
extern bytea *extractRelOptions(HeapTuple tuple, TupleDesc tupdesc,
amoptions_function amoptions);
extern void *build_reloptions(Datum reloptions, bool validate,
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index bc7adba4a0f..9e0296aee39 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -795,6 +795,7 @@ typedef enum TableLikeOption
CREATE_TABLE_LIKE_INDEXES = 1 << 6,
CREATE_TABLE_LIKE_STATISTICS = 1 << 7,
CREATE_TABLE_LIKE_STORAGE = 1 << 8,
+ CREATE_TABLE_LIKE_PARAMETERS = 1 << 9,
CREATE_TABLE_LIKE_ALL = PG_INT32_MAX
} TableLikeOption;
diff --git a/src/include/parser/kwlist.h b/src/include/parser/kwlist.h
index 9fde58f541c..aad64e7ccca 100644
--- a/src/include/parser/kwlist.h
+++ b/src/include/parser/kwlist.h
@@ -336,6 +336,7 @@ PG_KEYWORD("owned", OWNED, UNRESERVED_KEYWORD, BARE_LABEL)
PG_KEYWORD("owner", OWNER, UNRESERVED_KEYWORD, BARE_LABEL)
PG_KEYWORD("parallel", PARALLEL, UNRESERVED_KEYWORD, BARE_LABEL)
PG_KEYWORD("parameter", PARAMETER, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("parameters", PARAMETERS, UNRESERVED_KEYWORD, BARE_LABEL)
PG_KEYWORD("parser", PARSER, UNRESERVED_KEYWORD, BARE_LABEL)
PG_KEYWORD("partial", PARTIAL, UNRESERVED_KEYWORD, BARE_LABEL)
PG_KEYWORD("partition", PARTITION, UNRESERVED_KEYWORD, BARE_LABEL)
diff --git a/src/test/regress/expected/create_table_like.out b/src/test/regress/expected/create_table_like.out
index d3c35c14847..3eb079e24ed 100644
--- a/src/test/regress/expected/create_table_like.out
+++ b/src/test/regress/expected/create_table_like.out
@@ -699,3 +699,42 @@ DROP FOREIGN TABLE ctl_foreign_table1;
DROP FOREIGN TABLE ctl_foreign_table2;
DROP FOREIGN DATA WRAPPER ctl_dummy CASCADE;
NOTICE: drop cascades to server ctl_s0
+--CREATE TABLE LIKE with PARAMETERS
+create table t_sp(a text) with (
+ fillfactor = 100,
+ toast_tuple_target = 128,
+ vacuum_index_cleanup = auto,
+ toast.vacuum_index_cleanup = auto,
+ vacuum_truncate = true,
+ toast.vacuum_truncate = false,
+ log_autovacuum_min_duration = 100,
+ toast.log_autovacuum_min_duration = 100);
+create table t_sp1(like t_sp including parameters) with (fillfactor = 100); --error
+ERROR: parameter "fillfactor" specified more than once
+create table t_sp1(like t_sp excluding parameters) with (fillfactor = 100); --ok
+\d+ t_sp1
+ Table "public.t_sp1"
+ Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
+--------+------+-----------+----------+---------+----------+--------------+-------------
+ a | text | | | | extended | |
+Options: fillfactor=100
+
+create table t_sp2(like t_sp including parameters) with (
+ parallel_workers = 3,
+ toast.autovacuum_vacuum_threshold = 101,
+ toast.autovacuum_vacuum_scale_factor = 0.3);
+select c.relname, c.reloptions, tc.reloptions as toast_options
+from pg_catalog.pg_class c
+left join pg_catalog.pg_class tc ON (c.reltoastrelid = tc.oid)
+where c.relname in ('t_sp1', 't_sp2')
+order by c.relname \gx
+-[ RECORD 1 ]-+-----------------------------------------------------------------------------------------------------------------------------------------------------
+relname | t_sp1
+reloptions | {fillfactor=100}
+toast_options |
+-[ RECORD 2 ]-+-----------------------------------------------------------------------------------------------------------------------------------------------------
+relname | t_sp2
+reloptions | {parallel_workers=3,fillfactor=100,toast_tuple_target=128,vacuum_index_cleanup=auto,vacuum_truncate=true,log_autovacuum_min_duration=100}
+toast_options | {autovacuum_vacuum_threshold=101,autovacuum_vacuum_scale_factor=0.3,vacuum_index_cleanup=auto,vacuum_truncate=false,log_autovacuum_min_duration=100}
+
+drop table t_sp, t_sp1, t_sp2;
diff --git a/src/test/regress/sql/create_table_like.sql b/src/test/regress/sql/create_table_like.sql
index 93389b57dbf..afc8ffe6ad5 100644
--- a/src/test/regress/sql/create_table_like.sql
+++ b/src/test/regress/sql/create_table_like.sql
@@ -280,3 +280,31 @@ DROP TABLE ctl_table;
DROP FOREIGN TABLE ctl_foreign_table1;
DROP FOREIGN TABLE ctl_foreign_table2;
DROP FOREIGN DATA WRAPPER ctl_dummy CASCADE;
+
+--CREATE TABLE LIKE with PARAMETERS
+create table t_sp(a text) with (
+ fillfactor = 100,
+ toast_tuple_target = 128,
+ vacuum_index_cleanup = auto,
+ toast.vacuum_index_cleanup = auto,
+ vacuum_truncate = true,
+ toast.vacuum_truncate = false,
+ log_autovacuum_min_duration = 100,
+ toast.log_autovacuum_min_duration = 100);
+
+create table t_sp1(like t_sp including parameters) with (fillfactor = 100); --error
+create table t_sp1(like t_sp excluding parameters) with (fillfactor = 100); --ok
+\d+ t_sp1
+
+create table t_sp2(like t_sp including parameters) with (
+ parallel_workers = 3,
+ toast.autovacuum_vacuum_threshold = 101,
+ toast.autovacuum_vacuum_scale_factor = 0.3);
+
+select c.relname, c.reloptions, tc.reloptions as toast_options
+from pg_catalog.pg_class c
+left join pg_catalog.pg_class tc ON (c.reltoastrelid = tc.oid)
+where c.relname in ('t_sp1', 't_sp2')
+order by c.relname \gx
+
+drop table t_sp, t_sp1, t_sp2;
--
2.39.5
From a87da89dea951c78b62e796eb13e4f75f171a6c8 Mon Sep 17 00:00:00 2001
From: Euler Taveira <[email protected]>
Date: Mon, 15 Dec 2025 11:11:43 -0300
Subject: [PATCH v6 2/2] fixup! create table like incluing parameters
---
src/backend/access/common/reloptions.c | 40 ++-------------
src/backend/parser/parse_utilcmd.c | 33 ++++++-------
src/include/access/reloptions.h | 2 +-
.../regress/expected/create_table_like.out | 49 +++++++++----------
src/test/regress/sql/create_table_like.sql | 36 +++++++-------
5 files changed, 60 insertions(+), 100 deletions(-)
diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c
index 9289caef7ba..93db86acad3 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -1359,48 +1359,14 @@ transformRelOptions(Datum oldOptions, List *defList, const char *nameSpace,
List *
untransformRelOptions(Datum options)
{
- List *result = NIL;
- ArrayType *array;
- Datum *optiondatums;
- int noptions;
- int i;
-
- /* Nothing to do if no options */
- if (DatumGetPointer(options) == NULL)
- return result;
-
- array = DatumGetArrayTypeP(options);
-
- deconstruct_array_builtin(array, TEXTOID, &optiondatums, NULL, &noptions);
-
- for (i = 0; i < noptions; i++)
- {
- char *s;
- char *p;
- Node *val = NULL;
-
- s = TextDatumGetCString(optiondatums[i]);
- p = strchr(s, '=');
- if (p)
- {
- *p++ = '\0';
- val = (Node *) makeString(p);
- }
- result = lappend(result, makeDefElem(s, val, -1));
- }
-
- return result;
+ return untransformRelOptionsExtended(options, NULL);
}
/*
- * Convert the reloptions from text-array format into a List of DefElem. This
- * is the reverse operation of transformRelOptions().
- *
- * If any option includes a namespace qualification, create the DefElem in that
- * namespace, otherwise this behave the same as untransformRelOptions.
+ * Same as untransformRelOptions() but includes a namespace into DefElem.
*/
List *
-untransformRelOptionsExtended(Datum options, char* nameSpace)
+untransformRelOptionsExtended(Datum options, char *nameSpace)
{
List *result = NIL;
ArrayType *array;
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index 2e77c2db19b..c9056c4f22e 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -88,7 +88,8 @@ typedef struct
List *fkconstraints; /* FOREIGN KEY constraints */
List *ixconstraints; /* index-creating constraints */
List *likeclauses; /* LIKE clauses that need post-processing */
- List *options; /* options from WITH clause, table AM specific parameters */
+ List *options; /* options from WITH clause, table AM specific
+ * parameters */
List *blist; /* "before list" of things to do before
* creating the table */
List *alist; /* "after list" of things to do after creating
@@ -1125,8 +1126,8 @@ transformTableConstraint(CreateStmtContext *cxt, Constraint *constraint)
* table has been created.
*
* Some options are ignored. For example, as foreign tables have no storage,
- * these INCLUDING options have no effect: STORAGE, COMPRESSION, IDENTITY
- * and INDEXES. Similarly, INCLUDING INDEXES is ignored from a view.
+ * these INCLUDING options have no effect: STORAGE, COMPRESSION, IDENTITY,
+ * INDEXES and PARAMETERS. Similarly, INCLUDING INDEXES is ignored from a view.
*/
static void
transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_clause)
@@ -1274,17 +1275,16 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla
}
}
- /* Likewise, copy stoarge paramters if requested */
+ /* Likewise, copy storage parameters if requested */
if ((table_like_clause->options & CREATE_TABLE_LIKE_PARAMETERS) &&
!cxt->isforeign)
{
HeapTuple tuple;
- HeapTuple toast_tuple;
Datum reloptions;
bool isnull;
Oid relid;
- List *oldoptions = NIL;
- List *oldtoastoptions = NIL;
+ List *oldoptions = NIL;
+ List *oldtoastoptions = NIL;
relid = RelationGetRelid(relation);
tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
@@ -1308,7 +1308,6 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla
if (OidIsValid(relation->rd_rel->reltoastrelid))
{
Relation toastrel;
-
Oid toastid = relation->rd_rel->reltoastrelid;
/*
@@ -1317,14 +1316,12 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla
*/
toastrel = table_open(toastid, AccessShareLock);
- /* Fetch heap tuple */
- toast_tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(toastid));
+ tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(toastid));
- if (!HeapTupleIsValid(toast_tuple))
- elog(ERROR, "cache lookup failed for toast relation %u", toastid);
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for relation %u", toastid);
- /* Get the toast reloptions */
- reloptions = SysCacheGetAttr(RELOID, toast_tuple, Anum_pg_class_reloptions,
+ reloptions = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_reloptions,
&isnull);
if (!isnull)
{
@@ -1334,12 +1331,12 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla
cxt->options = lappend(cxt->options, option);
}
- ReleaseSysCache(toast_tuple);
+ ReleaseSysCache(tuple);
/*
- * Close the parent TOAST rel, but keep our AccessShareLock on it
- * until xact commit. That will prevent someone else from deleting
- * or ALTERing the parent TOAST before we can run
+ * Close the toast relation, but keep our AccessShareLock on it
+ * until xact commit. That will prevent someone else from
+ * deleting or ALTERing the parent TOAST before we can run
* expandTableLikeClause.
*/
table_close(toastrel, NoLock);
diff --git a/src/include/access/reloptions.h b/src/include/access/reloptions.h
index 8589616d08b..0c29f5df229 100644
--- a/src/include/access/reloptions.h
+++ b/src/include/access/reloptions.h
@@ -236,7 +236,7 @@ extern Datum transformRelOptions(Datum oldOptions, List *defList,
const char *nameSpace, const char *const validnsps[],
bool acceptOidsOff, bool isReset);
extern List *untransformRelOptions(Datum options);
-extern List *untransformRelOptionsExtended(Datum options, char* nameSpace);
+extern List *untransformRelOptionsExtended(Datum options, char *nameSpace);
extern bytea *extractRelOptions(HeapTuple tuple, TupleDesc tupdesc,
amoptions_function amoptions);
extern void *build_reloptions(Datum reloptions, bool validate,
diff --git a/src/test/regress/expected/create_table_like.out b/src/test/regress/expected/create_table_like.out
index 3eb079e24ed..89145882aef 100644
--- a/src/test/regress/expected/create_table_like.out
+++ b/src/test/regress/expected/create_table_like.out
@@ -700,18 +700,18 @@ DROP FOREIGN TABLE ctl_foreign_table2;
DROP FOREIGN DATA WRAPPER ctl_dummy CASCADE;
NOTICE: drop cascades to server ctl_s0
--CREATE TABLE LIKE with PARAMETERS
-create table t_sp(a text) with (
- fillfactor = 100,
- toast_tuple_target = 128,
- vacuum_index_cleanup = auto,
- toast.vacuum_index_cleanup = auto,
- vacuum_truncate = true,
- toast.vacuum_truncate = false,
- log_autovacuum_min_duration = 100,
- toast.log_autovacuum_min_duration = 100);
-create table t_sp1(like t_sp including parameters) with (fillfactor = 100); --error
+CREATE TABLE t_sp (a text) WITH (
+ fillfactor = 100,
+ toast_tuple_target = 128,
+ vacuum_index_cleanup = auto,
+ toast.vacuum_index_cleanup = auto,
+ vacuum_truncate = true,
+ toast.vacuum_truncate = false,
+ log_autovacuum_min_duration = 100,
+ toast.log_autovacuum_min_duration = 100);
+CREATE TABLE t_sp1 (LIKE t_sp INCLUDING PARAMETERS) WITH (fillfactor = 100); -- fail
ERROR: parameter "fillfactor" specified more than once
-create table t_sp1(like t_sp excluding parameters) with (fillfactor = 100); --ok
+CREATE TABLE T_sp1 (LIKE t_sp EXCLUDING PARAMETERS) WITH (fillfactor = 100); -- ok
\d+ t_sp1
Table "public.t_sp1"
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
@@ -719,22 +719,19 @@ create table t_sp1(like t_sp excluding parameters) with (fillfactor = 100); --ok
a | text | | | | extended | |
Options: fillfactor=100
-create table t_sp2(like t_sp including parameters) with (
+CREATE TABLE t_sp2 (LIKE t_sp INCLUDING PARAMETERS) WITH (
parallel_workers = 3,
toast.autovacuum_vacuum_threshold = 101,
toast.autovacuum_vacuum_scale_factor = 0.3);
-select c.relname, c.reloptions, tc.reloptions as toast_options
-from pg_catalog.pg_class c
-left join pg_catalog.pg_class tc ON (c.reltoastrelid = tc.oid)
-where c.relname in ('t_sp1', 't_sp2')
-order by c.relname \gx
--[ RECORD 1 ]-+-----------------------------------------------------------------------------------------------------------------------------------------------------
-relname | t_sp1
-reloptions | {fillfactor=100}
-toast_options |
--[ RECORD 2 ]-+-----------------------------------------------------------------------------------------------------------------------------------------------------
-relname | t_sp2
-reloptions | {parallel_workers=3,fillfactor=100,toast_tuple_target=128,vacuum_index_cleanup=auto,vacuum_truncate=true,log_autovacuum_min_duration=100}
-toast_options | {autovacuum_vacuum_threshold=101,autovacuum_vacuum_scale_factor=0.3,vacuum_index_cleanup=auto,vacuum_truncate=false,log_autovacuum_min_duration=100}
+SELECT c.relname, c.reloptions, t.reloptions as toast_reloptions
+ FROM pg_catalog.pg_class c
+ LEFT JOIN pg_catalog.pg_class t ON (c.reltoastrelid = t.oid)
+ WHERE c.relname IN ('t_sp1', 't_sp2')
+ ORDER BY c.relname;
+ relname | reloptions | toast_reloptions
+---------+-------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------
+ t_sp1 | {fillfactor=100} |
+ t_sp2 | {parallel_workers=3,fillfactor=100,toast_tuple_target=128,vacuum_index_cleanup=auto,vacuum_truncate=true,log_autovacuum_min_duration=100} | {autovacuum_vacuum_threshold=101,autovacuum_vacuum_scale_factor=0.3,vacuum_index_cleanup=auto,vacuum_truncate=false,log_autovacuum_min_duration=100}
+(2 rows)
-drop table t_sp, t_sp1, t_sp2;
+DROP TABLE t_sp, t_sp1, t_sp2;
diff --git a/src/test/regress/sql/create_table_like.sql b/src/test/regress/sql/create_table_like.sql
index afc8ffe6ad5..c357c2dec0d 100644
--- a/src/test/regress/sql/create_table_like.sql
+++ b/src/test/regress/sql/create_table_like.sql
@@ -282,29 +282,29 @@ DROP FOREIGN TABLE ctl_foreign_table2;
DROP FOREIGN DATA WRAPPER ctl_dummy CASCADE;
--CREATE TABLE LIKE with PARAMETERS
-create table t_sp(a text) with (
- fillfactor = 100,
- toast_tuple_target = 128,
- vacuum_index_cleanup = auto,
- toast.vacuum_index_cleanup = auto,
- vacuum_truncate = true,
- toast.vacuum_truncate = false,
- log_autovacuum_min_duration = 100,
- toast.log_autovacuum_min_duration = 100);
+CREATE TABLE t_sp (a text) WITH (
+ fillfactor = 100,
+ toast_tuple_target = 128,
+ vacuum_index_cleanup = auto,
+ toast.vacuum_index_cleanup = auto,
+ vacuum_truncate = true,
+ toast.vacuum_truncate = false,
+ log_autovacuum_min_duration = 100,
+ toast.log_autovacuum_min_duration = 100);
-create table t_sp1(like t_sp including parameters) with (fillfactor = 100); --error
-create table t_sp1(like t_sp excluding parameters) with (fillfactor = 100); --ok
+CREATE TABLE t_sp1 (LIKE t_sp INCLUDING PARAMETERS) WITH (fillfactor = 100); -- fail
+CREATE TABLE T_sp1 (LIKE t_sp EXCLUDING PARAMETERS) WITH (fillfactor = 100); -- ok
\d+ t_sp1
-create table t_sp2(like t_sp including parameters) with (
+CREATE TABLE t_sp2 (LIKE t_sp INCLUDING PARAMETERS) WITH (
parallel_workers = 3,
toast.autovacuum_vacuum_threshold = 101,
toast.autovacuum_vacuum_scale_factor = 0.3);
-select c.relname, c.reloptions, tc.reloptions as toast_options
-from pg_catalog.pg_class c
-left join pg_catalog.pg_class tc ON (c.reltoastrelid = tc.oid)
-where c.relname in ('t_sp1', 't_sp2')
-order by c.relname \gx
+SELECT c.relname, c.reloptions, t.reloptions as toast_reloptions
+ FROM pg_catalog.pg_class c
+ LEFT JOIN pg_catalog.pg_class t ON (c.reltoastrelid = t.oid)
+ WHERE c.relname IN ('t_sp1', 't_sp2')
+ ORDER BY c.relname;
-drop table t_sp, t_sp1, t_sp2;
+DROP TABLE t_sp, t_sp1, t_sp2;
--
2.39.5