Hi,

While reviewing another patch[1] I saw that COMMENTS on tables are being
ignored in CREATE TABLE LIKE:

psql (18.1 (Debian 18.1-1.pgdg13+2))
Type "help" for help.

postgres=# \pset null '(null)'
Null display is "(null)".
postgres=# CREATE TABLE t1 (id int, name text);
COMMENT ON TABLE t1 IS 'table comment';
CREATE TABLE t2 (LIKE t1 INCLUDING ALL);
CREATE TABLE t3 (LIKE t1 INCLUDING COMMENTS);

SELECT
  obj_description('t1'::regclass, 'pg_class') AS t1_comment,
  obj_description('t2'::regclass, 'pg_class') AS t2_comment,
  obj_description('t3'::regclass, 'pg_class') AS t3_comment;
CREATE TABLE
COMMENT
CREATE TABLE
CREATE TABLE
  t1_comment   | t2_comment | t3_comment
---------------+------------+------------
 table comment | (null)     | (null)
(1 row)


v1 attached attempts to fix it by expanding expandTableLikeClause() to
retrieve and copy the table-level comment when the INCLUDING COMMENTS
[ALL] option is specified:


psql (19devel)
Type "help" for help.

postgres=# CREATE TABLE t1 (id int, name text);
COMMENT ON TABLE t1 IS 'table comment';
CREATE TABLE t2 (LIKE t1 INCLUDING ALL);
CREATE TABLE t3 (LIKE t1 INCLUDING COMMENTS);

SELECT
  obj_description('t1'::regclass, 'pg_class') AS t1_comment,
  obj_description('t2'::regclass, 'pg_class') AS t2_comment,
  obj_description('t3'::regclass, 'pg_class') AS t3_comment;
CREATE TABLE
COMMENT
CREATE TABLE
CREATE TABLE
  t1_comment   |  t2_comment   |  t3_comment
---------------+---------------+---------------
 table comment | table comment | table comment
(1 row)



Thoughts?

Best, Jim

1 -
https://www.postgresql.org/message-id/flat/DG7Y34A6VBEG.76L7K1OML5DI%40gmail.com
From 5afdb72e13092a94d01d40dcdc78a96c2632b423 Mon Sep 17 00:00:00 2001
From: Jim Jones <[email protected]>
Date: Thu, 12 Feb 2026 10:39:25 +0100
Subject: [PATCH v1] Fix missing table-level comment copying in CREATE TABLE
 LIKE

When using CREATE TABLE ... LIKE ... INCLUDING COMMENTS (or INCLUDING
ALL), table-level comments were not being copied to the new table, even
though column comments, constraint comments, index comments, and
statistics comments were properly copied.
---
 src/backend/parser/parse_utilcmd.c            | 36 +++++++++++++++----
 .../regress/expected/create_table_like.out    |  7 ++++
 src/test/regress/sql/create_table_like.sql    |  2 ++
 3 files changed, 39 insertions(+), 6 deletions(-)

diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index b5f4c72459..bc6c9175a3 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -1307,17 +1307,18 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla
 	}
 
 	/*
-	 * We cannot yet deal with defaults, CHECK constraints, indexes, or
-	 * statistics, since we don't yet know what column numbers the copied
-	 * columns will have in the finished table.  If any of those options are
-	 * specified, add the LIKE clause to cxt->likeclauses so that
-	 * expandTableLikeClause will be called after we do know that.
+	 * We cannot yet deal with defaults, CHECK constraints, indexes,
+	 * statistics, or table comments, since we don't yet know what column
+	 * numbers the copied columns will have in the finished table.  If any of
+	 * those options are specified, add the LIKE clause to cxt->likeclauses
+	 * so that expandTableLikeClause will be called after we do know that.
 	 *
 	 * In order for this to work, we remember the relation OID so that
 	 * expandTableLikeClause is certain to open the same table.
 	 */
 	if (table_like_clause->options &
-		(CREATE_TABLE_LIKE_DEFAULTS |
+		(CREATE_TABLE_LIKE_COMMENTS |
+		 CREATE_TABLE_LIKE_DEFAULTS |
 		 CREATE_TABLE_LIKE_GENERATED |
 		 CREATE_TABLE_LIKE_CONSTRAINTS |
 		 CREATE_TABLE_LIKE_INDEXES |
@@ -1625,6 +1626,29 @@ expandTableLikeClause(RangeVar *heapRel, TableLikeClause *table_like_clause)
 		list_free(parent_extstats);
 	}
 
+	/*
+	 * Copy comment on the relation itself, if requested.
+	 */
+	if (table_like_clause->options & CREATE_TABLE_LIKE_COMMENTS)
+	{
+		comment = GetComment(RelationGetRelid(relation), RelationRelationId, 0);
+
+		if (comment != NULL)
+		{
+			CommentStmt *stmt = makeNode(CommentStmt);
+
+			stmt->objtype = OBJECT_TABLE;
+			if (heapRel->schemaname)
+				stmt->object = (Node *)list_make2(makeString(heapRel->schemaname),
+												  makeString(heapRel->relname));
+			else
+				stmt->object = (Node *)list_make1(makeString(heapRel->relname));
+			stmt->comment = comment;
+
+			result = lappend(result, stmt);
+		}
+	}
+
 	/* Done with child rel */
 	table_close(childrel, NoLock);
 
diff --git a/src/test/regress/expected/create_table_like.out b/src/test/regress/expected/create_table_like.out
index d3c35c1484..765155912f 100644
--- a/src/test/regress/expected/create_table_like.out
+++ b/src/test/regress/expected/create_table_like.out
@@ -341,6 +341,7 @@ CREATE TABLE ctlt3 (a text CHECK (length(a) < 5), c text CHECK (length(c) < 7));
 ALTER TABLE ctlt3 ALTER COLUMN c SET STORAGE EXTERNAL;
 ALTER TABLE ctlt3 ALTER COLUMN a SET STORAGE MAIN;
 CREATE INDEX ctlt3_fnidx ON ctlt3 ((a || c));
+COMMENT ON TABLE ctlt3 IS 'ctlt3 table comment';
 COMMENT ON COLUMN ctlt3.a IS 'A3';
 COMMENT ON COLUMN ctlt3.c IS 'C';
 COMMENT ON CONSTRAINT ctlt3_a_check ON ctlt3 IS 't3_a_check';
@@ -449,6 +450,12 @@ SELECT description FROM pg_description, pg_constraint c WHERE classoid = 'pg_con
  t3_a_check
 (1 row)
 
+SELECT obj_description('ctlt13_like'::regclass, 'pg_class') AS table_comment;
+    table_comment    
+---------------------
+ ctlt3 table comment
+(1 row)
+
 CREATE TABLE ctlt_all (LIKE ctlt1 INCLUDING ALL);
 \d+ ctlt_all
                                 Table "public.ctlt_all"
diff --git a/src/test/regress/sql/create_table_like.sql b/src/test/regress/sql/create_table_like.sql
index 93389b57db..0390834186 100644
--- a/src/test/regress/sql/create_table_like.sql
+++ b/src/test/regress/sql/create_table_like.sql
@@ -153,6 +153,7 @@ CREATE TABLE ctlt3 (a text CHECK (length(a) < 5), c text CHECK (length(c) < 7));
 ALTER TABLE ctlt3 ALTER COLUMN c SET STORAGE EXTERNAL;
 ALTER TABLE ctlt3 ALTER COLUMN a SET STORAGE MAIN;
 CREATE INDEX ctlt3_fnidx ON ctlt3 ((a || c));
+COMMENT ON TABLE ctlt3 IS 'ctlt3 table comment';
 COMMENT ON COLUMN ctlt3.a IS 'A3';
 COMMENT ON COLUMN ctlt3.c IS 'C';
 COMMENT ON CONSTRAINT ctlt3_a_check ON ctlt3 IS 't3_a_check';
@@ -173,6 +174,7 @@ CREATE TABLE ctlt13_inh () INHERITS (ctlt1, ctlt3);
 CREATE TABLE ctlt13_like (LIKE ctlt3 INCLUDING CONSTRAINTS INCLUDING INDEXES INCLUDING COMMENTS INCLUDING STORAGE) INHERITS (ctlt1);
 \d+ ctlt13_like
 SELECT description FROM pg_description, pg_constraint c WHERE classoid = 'pg_constraint'::regclass AND objoid = c.oid AND c.conrelid = 'ctlt13_like'::regclass;
+SELECT obj_description('ctlt13_like'::regclass, 'pg_class') AS table_comment;
 
 CREATE TABLE ctlt_all (LIKE ctlt1 INCLUDING ALL);
 \d+ ctlt_all
-- 
2.43.0

Reply via email to