CREATE TABLE .. LIKE copies comments to an unrelated table - Mailing list pgsql-hackers

From Jim Jones
Subject CREATE TABLE .. LIKE copies comments to an unrelated table
Date
Msg-id 479d75af-1ab5-41f7-aa9b-e34d6581d7c0@uni-muenster.de
Whole thread
Responses Re: CREATE TABLE .. LIKE copies comments to an unrelated table
List 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




pgsql-hackers by date:

Previous
From: David Christensen
Date:
Subject: Re: SSI: ON CONFLICT DO SELECT takes no predicate lock on the returned row
Next
From: Jelte Fennema-Nio
Date:
Subject: Re: postgres_fdw: Fix costing of remote sorts without remote estimates