CREATE TABLE .. LIKE copies comments to an unrelated table

From: Jim Jones <jim(dot)jones(at)uni-muenster(dot)de>
To: PostgreSQL Hackers <pgsql-hackers(at)postgresql(dot)org>
Subject: CREATE TABLE .. LIKE copies comments to an unrelated table
Date: 2026-10-01 14:35:15
Message-ID: 479d75af-1ab5-41f7-aa9b-e34d6581d7c0@uni-muenster.de
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Hi

While working on another patch I found that CREATE TABLE ... LIKE
INCLUDING COMMENTS copies the comments to the wrong table when the
target is a temp table and a table with the same name exists in a schema
listed before pg_temp in search_path.

Example:

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

db=> CREATE TABLE src (a int);
CREATE TABLE
db=> COMMENT ON COLUMN src.a IS 'col comment';
COMMENT
db=> CREATE TABLE foo (a int); -- unrelated table
CREATE TABLE
db=> COMMENT ON COLUMN foo.a IS 'important comment';
COMMENT
db=> SET search_path = public, pg_temp;
SET
db=> CREATE TEMP TABLE foo (LIKE src INCLUDING COMMENTS);
CREATE TABLE
db=> SELECT n.nspname, relname, col_description(c.oid, 1) AS colcomment
FROM pg_class c JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE c.relname = 'foo';
nspname | relname | colcomment
------------+---------+-------------
public | foo | col comment
pg_temp_24 | foo |
(2 rows)

The unrelated public.foo got the column comment and the created
temporary table got none -- public.foo.a comment was overwritten. Is
this the expected behaviour?

Setting the schema to pg_temp in case of RELPERSISTENCE_TEMP in
transformCreateStmt seems to do the trick (but I didn't dive too deep in
the code just yet):

- if (stmt->relation->schemaname == NULL
- && stmt->relation->relpersistence != RELPERSISTENCE_TEMP)
- stmt->relation->schemaname =
get_namespace_name(namespaceid);
+ if (stmt->relation->schemaname == NULL)
+ {
+ if (stmt->relation->relpersistence == RELPERSISTENCE_TEMP)
+ stmt->relation->schemaname = pstrdup("pg_temp");
+ else
+ stmt->relation->schemaname =
get_namespace_name(namespaceid);
+ }

With my changes in HEAD:

db=> CREATE TABLE src (a int);
CREATE TABLE
db=> COMMENT ON COLUMN src.a IS 'col comment';
COMMENT
db=> CREATE TABLE foo (a int); -- unrelated table
CREATE TABLE
db=> COMMENT ON COLUMN foo.a IS 'important comment';
COMMENT
db=> SET search_path = public, pg_temp;
SET
db=> CREATE TEMP TABLE foo (LIKE src INCLUDING COMMENTS);
CREATE TABLE
db=> SELECT n.nspname, relname, col_description(c.oid, 1) AS colcomment
FROM pg_class c JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE c.relname = 'foo';
nspname | relname | colcomment
------------+---------+-------------------
public | foo | important comment
pg_temp_92 | foo | col comment
(2 rows)

WDYT?

Best, Jim

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Jelte Fennema-Nio 2026-10-01 14:47:28 Re: postgres_fdw: Fix costing of remote sorts without remote estimates
Previous Message David Christensen 2026-10-01 14:31:25 Re: SSI: ON CONFLICT DO SELECT takes no predicate lock on the returned row