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

Reply via email to