Re: COMMENTS are not being copied in CREATE TABLE LIKE - Mailing list pgsql-hackers
| From | Jim Jones |
|---|---|
| Subject | Re: COMMENTS are not being copied in CREATE TABLE LIKE |
| Date | |
| Msg-id | c8525e6e-5789-464e-a70d-b3916e4168eb@uni-muenster.de Whole thread |
| In response to | Re: COMMENTS are not being copied in CREATE TABLE LIKE (Tomas Vondra <tomas@vondra.me>) |
| Responses |
Re: COMMENTS are not being copied in CREATE TABLE LIKE
|
| List | 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'::regclassAND 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
eitherbefore "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
changedby 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
pgsql-hackers by date: