Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Use the properly transformed RangeVar for expandTableLikeClause().
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 13 Sep 2020 16:51:21 +0000 (12:51 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 13 Sep 2020 16:51:21 +0000 (12:51 -0400)
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
src/test/regress/expected/create_table_like.out
src/test/regress/sql/create_table_like.sql

index 4992c22bbbff023ff647576d4978d8cb852f8ece..79aba2acbcbad98d273428de0ba69840e021185a 100644 (file)
@@ -995,6 +995,7 @@ ProcessUtilitySlow(ParseState *pstate,
                {
                    List       *stmts;
                    ListCell   *l;
+                   RangeVar   *table_rv = NULL;
 
                    /* Run parse analysis ... */
                    stmts = transformCreateStmt((CreateStmt *) parsetree,
@@ -1007,11 +1008,15 @@ ProcessUtilitySlow(ParseState *pstate,
 
                        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,
                                                     queryString);
@@ -1030,7 +1035,7 @@ ProcessUtilitySlow(ParseState *pstate,
                             * table
                             */
                            toast_options = transformRelOptions((Datum) 0,
-                                                               ((CreateStmt *) stmt)->options,
+                                                               cstmt->options,
                                                                "toast",
                                                                validnsps,
                                                                true,
@@ -1044,12 +1049,17 @@ ProcessUtilitySlow(ParseState *pstate,
                        }
                        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,
                                                     queryString);
-                           CreateForeignTable((CreateForeignTableStmt *) stmt,
+                           CreateForeignTable(cstmt,
                                               address.objectId);
                            EventTriggerCollectSimpleCommand(address,
                                                             secondaryObject,
@@ -1064,10 +1074,11 @@ ProcessUtilitySlow(ParseState *pstate,
                             * 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);
 
                            /*
index f9fad8457fb1970f6f50389370a3cc8ef8af585e..4796373e2eeb4a0e1c0c057959197da9e5aa3e6c 100644 (file)
@@ -421,6 +421,24 @@ 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 | Collation | Nullable | Default | 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)
+Statistics objects:
+    "public"."pg_attrdef_a_b_stat" (ndistinct, dependencies, mcv) ON a, b FROM 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;
 NOTICE:  drop cascades to table inhe
 /* LIKE with other relation kinds */
index 9d00f4309fa7f15b0473c7ac8a3774969cf1080a..f3e5758e15f802d78f86fb3a79f2a90eaac68c00 100644 (file)
@@ -163,6 +163,11 @@ SELECT s.stxname, objsubid, description FROM pg_description, pg_statistic_ext s
 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;