From 86b8ef139457d10620d313ada91c497e1e522493 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Sun, 13 Sep 2020 12:51:21 -0400 Subject: [PATCH] Use the properly transformed RangeVar for expandTableLikeClause(). transformCreateStmt() adjusts the transformed statement's RangeVar to specify the target schema explicitly, for the express reason of making sure that auxiliary statements derived by parse transformation operate on the right table. But the refactoring I did in commit 502898192 got this wrong and passed the untransformed RangeVar to expandTableLikeClause(). This could lead to assertion failures or weird misbehavior if the wrong table was accessed. Per report from Alexander Lakhin. Like the previous patch, back-patch to all supported branches. Discussion: https://postgr.es/m/05051f9d-b32b-cb35-6735-0e9f2ab86b5f@gmail.com --- src/backend/tcop/utility.c | 23 ++++++++++++++----- .../regress/expected/create_table_like.out | 16 +++++++++++++ src/test/regress/sql/create_table_like.sql | 5 ++++ 3 files changed, 38 insertions(+), 6 deletions(-) diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index e890ebfd516..3a26a81f169 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -949,6 +949,7 @@ ProcessUtilitySlow(Node *parsetree, { List *stmts; ListCell *l; + RangeVar *table_rv = NULL; /* Run parse analysis ... */ stmts = transformCreateStmt((CreateStmt *) parsetree, @@ -961,11 +962,15 @@ ProcessUtilitySlow(Node *parsetree, if (IsA(stmt, CreateStmt)) { + CreateStmt *cstmt = (CreateStmt *) stmt; Datum toast_options; static char *validnsps[] = HEAP_RELOPT_NAMESPACES; + /* Remember transformed RangeVar for LIKE */ + table_rv = cstmt->relation; + /* Create the table itself */ - address = DefineRelation((CreateStmt *) stmt, + address = DefineRelation(cstmt, RELKIND_RELATION, InvalidOid, NULL); EventTriggerCollectSimpleCommand(address, @@ -983,7 +988,7 @@ ProcessUtilitySlow(Node *parsetree, * table */ toast_options = transformRelOptions((Datum) 0, - ((CreateStmt *) stmt)->options, + cstmt->options, "toast", validnsps, true, @@ -997,11 +1002,16 @@ ProcessUtilitySlow(Node *parsetree, } else if (IsA(stmt, CreateForeignTableStmt)) { + CreateForeignTableStmt *cstmt = (CreateForeignTableStmt *) stmt; + + /* Remember transformed RangeVar for LIKE */ + table_rv = cstmt->base.relation; + /* Create the table itself */ - address = DefineRelation((CreateStmt *) stmt, + address = DefineRelation(&cstmt->base, RELKIND_FOREIGN_TABLE, InvalidOid, NULL); - CreateForeignTable((CreateForeignTableStmt *) stmt, + CreateForeignTable(cstmt, address.objectId); EventTriggerCollectSimpleCommand(address, secondaryObject, @@ -1016,10 +1026,11 @@ ProcessUtilitySlow(Node *parsetree, * to-do list. */ TableLikeClause *like = (TableLikeClause *) stmt; - RangeVar *rv = ((CreateStmt *) parsetree)->relation; List *morestmts; - morestmts = expandTableLikeClause(rv, like); + Assert(table_rv != NULL); + + morestmts = expandTableLikeClause(table_rv, like); stmts = list_concat(stmts, morestmts); /* diff --git a/src/test/regress/expected/create_table_like.out b/src/test/regress/expected/create_table_like.out index c25737dcfdb..eef56037160 100644 --- a/src/test/regress/expected/create_table_like.out +++ b/src/test/regress/expected/create_table_like.out @@ -243,6 +243,22 @@ CREATE TABLE inh_error2 (LIKE ctlt4 INCLUDING STORAGE) INHERITS (ctlt1); NOTICE: merging column "a" with inherited definition ERROR: column "a" has a storage parameter conflict DETAIL: MAIN versus EXTENDED +-- Check that LIKE isn't confused by a system catalog of the same name +CREATE TABLE pg_attrdef (LIKE ctlt1 INCLUDING ALL); +\d+ public.pg_attrdef + Table "public.pg_attrdef" + Column | Type | Modifiers | Storage | Stats target | Description +--------+------+-----------+----------+--------------+------------- + a | text | not null | main | | A + b | text | | extended | | B +Indexes: + "pg_attrdef_pkey" PRIMARY KEY, btree (a) + "pg_attrdef_b_idx" btree (b) + "pg_attrdef_expr_idx" btree ((a || b)) +Check constraints: + "ctlt1_a_check" CHECK (length(a) > 2) + +DROP TABLE public.pg_attrdef; DROP TABLE ctlt1, ctlt2, ctlt3, ctlt4, ctlt12_storage, ctlt12_comments, ctlt1_inh, ctlt13_inh, ctlt13_like, ctlt_all, ctla, ctlb CASCADE; NOTICE: drop cascades to table inhe /* LIKE with other relation kinds */ diff --git a/src/test/regress/sql/create_table_like.sql b/src/test/regress/sql/create_table_like.sql index b5fc6cca7eb..5a5b204251d 100644 --- a/src/test/regress/sql/create_table_like.sql +++ b/src/test/regress/sql/create_table_like.sql @@ -112,6 +112,11 @@ SELECT c.relname, objsubid, description FROM pg_description, pg_index i, pg_clas CREATE TABLE inh_error1 () INHERITS (ctlt1, ctlt4); CREATE TABLE inh_error2 (LIKE ctlt4 INCLUDING STORAGE) INHERITS (ctlt1); +-- Check that LIKE isn't confused by a system catalog of the same name +CREATE TABLE pg_attrdef (LIKE ctlt1 INCLUDING ALL); +\d+ public.pg_attrdef +DROP TABLE public.pg_attrdef; + DROP TABLE ctlt1, ctlt2, ctlt3, ctlt4, ctlt12_storage, ctlt12_comments, ctlt1_inh, ctlt13_inh, ctlt13_like, ctlt_all, ctla, ctlb CASCADE; -- 2.39.5