Re: COMMENTS are not being copied in CREATE TABLE LIKE

From: Jim Jones <jim(dot)jones(at)uni-muenster(dot)de>
To: Tomas Vondra <tomas(at)vondra(dot)me>, Alex Liapychev <coder(dot)sam(at)gmail(dot)com>
Cc: matheusssilv97 <matheusssilv97(at)gmail(dot)com>, Chao Li <li(dot)evan(dot)chao(at)gmail(dot)com>, "masao(dot)fujii" <masao(dot)fujii(at)gmail(dot)com>, "david(dot)g(dot)johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>, tgl <tgl(at)sss(dot)pgh(dot)pa(dot)us>, "huseyin(dot)d3r" <huseyin(dot)d3r(at)gmail(dot)com>, pgsql-hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>, chochoforwork(at)gmail(dot)com, 44973863(at)qq(dot)com
Subject: Re: COMMENTS are not being copied in CREATE TABLE LIKE
Date: 2026-09-22 19:49:00
Message-ID: c8525e6e-5789-464e-a70d-b3916e4168eb@uni-muenster.de
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Hi Alex, Eddie, and Tomas,

Thanks for the thorough review!

On 21/09/2026 15:58, Tomas Vondra wrote:
>
> On 9/20/26 22:28, Alex Liapychev wrote:
>> 1. Corner case: concatenation of big comments, whose total size exceeds MaxAllocSize, fails with an error.
>> Here is the test case to prove that:
>> ```
>> CREATE TABLE comment_1gb_test (id BIGINT);
>> -- set comment 1 GiB in size
>> UPDATE pg_catalog.pg_description
>> SET description = pg_catalog.repeat('x', 1000000000)
>> WHERE classoid = 'pg_catalog.pg_class'::regclass
>> AND objoid = 'public.comment_1gb_test'::regclass
>> AND objsubid = 0;
>> SELECT octet_length(description) as comment_size_bytes FROM pg_catalog.pg_description WHERE classoid = 'pg_catalog.pg_class'::regclass AND objoid = 'public.comment_1gb_test'::regclass AND objsubid = 0;
>> comment_size_bytes
>> --------------------
>> 1000000000
>> (1 row)
>> CREATE TABLE xxl1 (LIKE comment_1gb_test INCLUDING ALL);
>> CREATE TABLE xxl2 (LIKE comment_1gb_test INCLUDING ALL);
>> ALTER TABLE xxl2 RENAME COLUMN id TO id2;
>>
>> CREATE TABLE merge_xxl (LIKE xxl1 INCLUDING ALL, LIKE xxl2 INCLUDING ALL);
>> ERROR: string buffer exceeds maximum allowed length (1073741823 bytes)
>> DETAIL: Cannot enlarge string buffer containing 1000000001 bytes by 1000000000 more bytes.
>> ```
>> Some form of truncation should be applied, cap the total size is easiest: first table's comment takes an advantage, others - as fit.
>>
>
> I'd just reject such cases, with an ERROR that says the comment would be
> too long. It's cleaner than just silently start discarding user
> information. The number of people hitting this is about 0 anyway. Who
> would even have comments of this size?

I also doubt that anyone has a use case that justifies such a large
comment. The needed size for the merged comment is now checked and an
error is raised if it exceeds MaxAllocSize.

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

postgres=# CREATE TABLE xxl1 (a int);

CREATE TABLE xxl2 (b int);
SET allow_system_table_mods = on;
INSERT INTO pg_description VALUES ('xxl1'::regclass,
'pg_class'::regclass, 0, repeat('x',600000000));
INSERT INTO pg_description VALUES ('xxl2'::regclass,
'pg_class'::regclass, 0, repeat('y',600000000));
CREATE TABLE
CREATE TABLE
SET
INSERT 0 1
INSERT 0 1
postgres=# CREATE TABLE merge_xxl (LIKE xxl1 INCLUDING COMMENTS, LIKE
xxl2 INCLUDING COMMENTS);
ERROR: comment for relation "merge_xxl" is too long
DETAIL: The comment is the concatenation of comments copied from
multiple relations named in LIKE clauses, and the result exceeds the
maximum size allowed for a comment.

> That being said, I'm not convinced we actually want to concatenate
> comments like this. It feels a bit weird, and it can probably lead to
> weird stuff like "duplicate" comments, etc. Do we have any precedent for
> this behavior? Are we concatenating comments (or other stuff) anywhere?
> I couldn't find such place, but maybe I missed something.

Neither am I. I'm just not sure that ignoring the comments when using
multiple tables is a better alternative. I can live with it, but so far
I didn't find enough arguments to remove it. The alternatives I see are:

1) concatenate with a (\n) separator (current behaviour)
2) concatenate without a separator
3) first one wins
4) last one wins
5) ignore it altogether when multiple comments are detected (my least
favourite)
6) your idea? :)

WDYT?
>> 2. Code review notes:
>> 2.1. nitpick: parse_utilcmd.c:46: order of includes would be better if added include ("lib/stringinfo.h") was placed either before "miscadmin.h" (alphabetical order) or before "utils/..." (functional order).
>
> Before miscadmin.h, please. We keep includes in alphabetical order.

Fixed.

>> 2.2. nitpick: parse_utilcmd.c:1652: it would match style of surrounding code better if local variable `CommentStmt *stmt` would be named `comment_stmt`; see code above in the same function: `stats_stmt` (line 1618), `index_stmt` (line 1577), etc.
>
> Seems very cosmetic, and there's also a lot of places using 'stmt'.
>
>> 2.3. nitpick: create_table_like.out:486 & create_table_like.sql:198: Since behaviour of INCLUDING ALL has also been changed by this patch. It would be better to update the tests to cover it.
>>
>
> Yes, that's a fair point. It'd be good to test INCLUDING ALL copies
> comments too. The existing INCLUDING ALL test does not check that.

Fixed. I also included a few tests with views, custom types, foreign
tables, and temporary tables.

>
> Aside from that, I don't understand why this patch needs to add
> CREATE_TABLE_LIKE_COMMENTS to the last block in transformTableLikeClause
> intended to deal with options that need column numbers. I mean, this
> deals with a comment on the table itself, no? Or does it need to wait
> for some other reason, and the comment is misleading?
While revisiting the code I found a much larger problem: v3 hard codes
OBJECT_TABLE in obj_type, which breaks the feature when the target is a
foreign table:

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

postgres=# CREATE TABLE t1 (a int);
COMMENT ON TABLE t1 IS 't1 comment';
CREATE SERVER s FOREIGN DATA WRAPPER dummy;
CREATE FOREIGN TABLE ft (LIKE t1 INCLUDING ALL) SERVER s;
CREATE TABLE
COMMENT
CREATE SERVER
ERROR: "ft" is not a table

-- PG18
psql (18.4 (Debian 18.4-1.pgdg13+1))
Type "help" for help.

postgres=# CREATE TABLE t1 (a int);
COMMENT ON TABLE t1 IS 't1 comment';
CREATE SERVER s FOREIGN DATA WRAPPER dummy;
CREATE FOREIGN TABLE ft (LIKE t1 INCLUDING ALL) SERVER s;
CREATE TABLE
COMMENT
CREATE SERVER
CREATE FOREIGN TABLE
postgres=# \d ft
Foreign table "public.ft"
Column | Type | Collation | Nullable | Default | FDW options
--------+---------+-----------+----------+---------+-------------
a | integer | | | |
Server: s

I moved the logic to transformCreateStmt, where I can use cxt.isforeign
to feed cstmt->objtype with OBJECT_FOREIGN_TABLE or OBJECT_TABLE.

Another open question: should we also copy the comments from custom
types when they're used in the LIKE clause?

Example (copied from the regression tests):

CREATE TYPE ctlty_comment6 AS (f int);
COMMENT ON TYPE ctlty_comment6 IS 'comment6';
CREATE TABLE ctlt_type_comment (LIKE ctlty_comment6 INCLUDING COMMENTS);
SELECT obj_description('ctlt_type_comment'::regclass, 'pg_class') AS
table_comment;
table_comment
---------------
comment6
(1 row)

I'd be inclined to leave it out, since types and tables aren't
semantically very close, but I'd like to hear your thoughts first --
removing it would be quick.

PFA v4.

WDYT?

Best, Jim

Attachment Content-Type Size
v4-0001-Add-table-comments-in-CREATE-TABLE-LIKE-INCLUDING.patch text/x-patch 15.0 KB

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Nathan Bossart 2026-09-22 19:50:19 Re: convert various variables to atomics
Previous Message Gustavo William 2026-09-22 19:39:58 Re: enhancing pg_basebackup speeds up to ~23Gbps (small fixes + io_uring/Direct I/O)