Ensure that database objects are created consistently.
authorPavan Deolasee <[email protected]>
Tue, 12 Sep 2017 06:47:19 +0000 (12:17 +0530)
committerPavan Deolasee <[email protected]>
Tue, 12 Sep 2017 07:02:41 +0000 (12:32 +0530)
We now create views/materialised views on all nodes, unless they are temporary
objects in which case they are created only on the local coordinator and the
datanodes. Similarly, temporary sequences are created on the local coordinator
and the datanodes.

This solves many outstanding problems in the regression results where remote
nodes used to fail because of non-existent type for a view or similar such
issues. A few other test cases now started to work correctly and produce output
matching upstream PG. So the expected output for those test cases has been
appropriated fixed.

Couple of sequences in the rangefuncs test case have been converted into
permanent sequences because the subsequent SQL functions refer to them and
hence fail if they do not exist on the remote coordinators.

The problem with special RULE converting a regular table into a view goes away
with the fix since DROP VIEW commands are now propgataed to the datanodes too.

src/backend/tcop/utility.c
src/test/regress/expected/rowsecurity.out
src/test/regress/expected/rowtypes.out
src/test/regress/expected/subselect.out
src/test/regress/expected/updatable_views.out
src/test/regress/sql/rangefuncs.sql

index 0749400ccf844d853dd1c1af7af2654cf8860d1c..6dd3845153e71b26fcc85d8008c315fa544f33e0 100644 (file)
@@ -1231,8 +1231,8 @@ ProcessUtilityPost(PlannedStmt *pstmt,
                        if (IS_PGXC_LOCAL_COORDINATOR)
                        {
                                ViewStmt *stmt = (ViewStmt *) parsetree;
-                               if (stmt->view->relpersistence != RELPERSISTENCE_TEMP)
-                                       exec_type = EXEC_ON_COORDS;
+                               is_temp = stmt->view->relpersistence == RELPERSISTENCE_TEMP;
+                               exec_type = is_temp ? EXEC_ON_DATANODES : EXEC_ON_ALL_NODES;
                        }
                        break;
 
@@ -1252,7 +1252,7 @@ ProcessUtilityPost(PlannedStmt *pstmt,
                                /* In case this query is related to a SERIAL execution, just bypass */
                                if (!stmt->is_serial)
                                        is_temp = stmt->sequence->relpersistence == RELPERSISTENCE_TEMP;
-                               exec_type = EXEC_ON_ALL_NODES;
+                               exec_type = is_temp ? EXEC_ON_DATANODES : EXEC_ON_ALL_NODES;
                        }
                        break;
 
@@ -1287,8 +1287,8 @@ ProcessUtilityPost(PlannedStmt *pstmt,
                                 * CREATE TABLE + SELECT INTO
                                 */
                                Assert(stmt->relkind == OBJECT_MATVIEW);
-                               if (stmt->into->rel->relpersistence != RELPERSISTENCE_TEMP)
-                                       exec_type = EXEC_ON_COORDS;
+                               is_temp = stmt->into->rel->relpersistence == RELPERSISTENCE_TEMP;
+                               exec_type = is_temp ? EXEC_ON_DATANODES : EXEC_ON_ALL_NODES;
                        }
                        break;
 
@@ -2578,9 +2578,14 @@ ProcessUtilitySlow(ParseState *pstate,
                                break;
 
                        case T_CreateTableAsStmt:
-                               address = ExecCreateTableAs((CreateTableAsStmt *) parsetree,
-                                                                                       queryString, params, queryEnv,
-                                                                                       completionTag);
+                               {
+                                       CreateTableAsStmt *stmt = (CreateTableAsStmt *) parsetree;
+                                       if (IS_PGXC_DATANODE && stmt->relkind == OBJECT_MATVIEW)
+                                               stmt->into->skipData = true;
+                                       address = ExecCreateTableAs((CreateTableAsStmt *) parsetree,
+                                                                                               queryString, params, queryEnv,
+                                                                                               completionTag);
+                               }
                                break;
 
                        case T_RefreshMatViewStmt:
@@ -4697,55 +4702,18 @@ ExecUtilityFindNodes(ObjectType object_type,
        {
                case OBJECT_SEQUENCE:
                        *is_temp = IsTempTable(object_id);
-                       exec_type = EXEC_ON_ALL_NODES;
+                       if (*is_temp)
+                               exec_type = EXEC_ON_DATANODES;
+                       else
+                               exec_type = EXEC_ON_ALL_NODES;
                        break;
 
                case OBJECT_TABLE:
-                       /* Do the check on relation kind */
-                       exec_type = ExecUtilityFindNodesRelkind(object_id, is_temp);
-                       break;
-
-                       /*
-                        * Views and rules, both permanent or temporary are created
-                        * on Coordinators only.
-                        */
                case OBJECT_RULE:
                case OBJECT_VIEW:
                case OBJECT_MATVIEW:
-                       /* Check if object is a temporary view */
-                       if ((*is_temp = IsTempTable(object_id)))
-                               exec_type = EXEC_ON_NONE;
-                       else
-                               exec_type = EXEC_ON_COORDS;
-                       break;
-
                case OBJECT_INDEX:
-                       /* Check if given index uses temporary tables */
-                       {
-                               Relation        rel;
-                               bool            is_matview;
-
-                               rel = relation_open(object_id, NoLock);
-                               
-                               *is_temp = (rel->rd_rel->relpersistence == RELPERSISTENCE_TEMP);
-                               is_matview = (rel->rd_rel->relkind == RELKIND_MATVIEW);
-                               
-                               relation_close(rel, NoLock);
-
-                               exec_type = EXEC_ON_NONE;
-                               if (*is_temp)
-                               {
-                                       if (!is_matview)
-                                               exec_type = EXEC_ON_DATANODES;
-                               }
-                               else
-                               {
-                                       if (!is_matview)
-                                               exec_type = EXEC_ON_ALL_NODES;
-                                       else
-                                               exec_type = EXEC_ON_COORDS;
-                               }
-                       }
+                       exec_type = ExecUtilityFindNodesRelkind(object_id, is_temp);
                        break;
 
                default:
@@ -4771,7 +4739,6 @@ ExecUtilityFindNodesRelkind(Oid relid, bool *is_temp)
 
        switch (relkind_str)
        {
-               case RELKIND_SEQUENCE:
                case RELKIND_RELATION:
                case RELKIND_PARTITIONED_TABLE:
                        if ((*is_temp = IsTempTable(relid)))
@@ -4798,7 +4765,7 @@ ExecUtilityFindNodesRelkind(Oid relid, bool *is_temp)
 
                                        /* Release system cache BEFORE looking at the parent table */
                                        ReleaseSysCache(tuple);
-                                       return ExecUtilityFindNodesRelkind(table_relid, is_temp);
+                                       exec_type = ExecUtilityFindNodesRelkind(table_relid, is_temp);
                                }
                                else
                                {
@@ -4809,18 +4776,13 @@ ExecUtilityFindNodesRelkind(Oid relid, bool *is_temp)
                        break;
 
                case RELKIND_VIEW:
-                       if ((*is_temp = IsTempTable(relid)))
-                               exec_type = EXEC_ON_NONE;
-                       else
-                               exec_type = EXEC_ON_COORDS;
-                       break;
-
+               case RELKIND_SEQUENCE:
                case RELKIND_MATVIEW:
                        /* Check if object is a temporary view */
                        if ((*is_temp = IsTempTable(relid)))
-                               exec_type = EXEC_ON_NONE;
+                               exec_type = EXEC_ON_DATANODES;
                        else
-                               exec_type = EXEC_ON_COORDS;
+                               exec_type = EXEC_ON_ALL_NODES;
                        break;
 
                default:
index 6a6492f3fb98b18fea0d0db4edec5c3e49944f65..2a40b072ab963a9bc8a25f9b4ad4118ef136272f 100644 (file)
@@ -1275,9 +1275,7 @@ CREATE VIEW rec1v AS SELECT * FROM rec1;
 CREATE VIEW rec2v AS SELECT * FROM rec2;
 SET SESSION AUTHORIZATION regress_rls_alice;
 ALTER POLICY r1 ON rec1 USING (x = (SELECT a FROM rec2v WHERE b = y));
-ERROR:  relation "rec2v" does not exist
 ALTER POLICY r2 ON rec2 USING (a = (SELECT x FROM rec1v WHERE y = b));
-ERROR:  relation "rec1v" does not exist
 SET SESSION AUTHORIZATION regress_rls_bob;
 SELECT * FROM rec1;    -- fail, mutual recursion via views
 ERROR:  infinite recursion detected in policy for relation "rec1"
@@ -1287,14 +1285,13 @@ ERROR:  infinite recursion detected in policy for relation "rec1"
 SET SESSION AUTHORIZATION regress_rls_bob;
 \set VERBOSITY terse \\ -- suppress cascade details
 DROP VIEW rec1v, rec2v CASCADE;
+NOTICE:  drop cascades to 2 other objects
 \set VERBOSITY default
 CREATE VIEW rec1v WITH (security_barrier) AS SELECT * FROM rec1;
 CREATE VIEW rec2v WITH (security_barrier) AS SELECT * FROM rec2;
 SET SESSION AUTHORIZATION regress_rls_alice;
 CREATE POLICY r1 ON rec1 USING (x = (SELECT a FROM rec2v WHERE b = y));
-ERROR:  policy "r1" for table "rec1" already exists
 CREATE POLICY r2 ON rec2 USING (a = (SELECT x FROM rec1v WHERE y = b));
-ERROR:  policy "r2" for table "rec2" already exists
 SET SESSION AUTHORIZATION regress_rls_bob;
 SELECT * FROM rec1;    -- fail, mutual recursion via s.b. views
 ERROR:  infinite recursion detected in policy for relation "rec1"
@@ -1343,13 +1340,12 @@ EXPLAIN (COSTS OFF) SELECT * FROM only s1 WHERE f_leak(b);
 
 SET SESSION AUTHORIZATION regress_rls_alice;
 ALTER POLICY p1 ON s1 USING (a in (select x from v2)); -- using VIEW in RLS policy
-ERROR:  relation "v2" does not exist
 SET SESSION AUTHORIZATION regress_rls_bob;
 SELECT * FROM s1 WHERE f_leak(b);      -- OK
- a |                b                 
----+----------------------------------
- 2 | c81e728d9d4c2f636f067f89cc14862c
4 | a87ff679a2f3e71d9181a67b7542122c
+ a  |                b                 
+----+----------------------------------
+ -4 | 0267aaf632e87a63288a08331f22c7c3
 6 | 1679091c5a880faf6fb5e6087eb1b2dc
 (2 rows)
 
 EXPLAIN (COSTS OFF) SELECT * FROM s1 WHERE f_leak(b);
@@ -1361,7 +1357,7 @@ EXPLAIN (COSTS OFF) SELECT * FROM s1 WHERE f_leak(b);
          SubPlan 1
            ->  Remote Subquery Scan on all (datanode_1,datanode_2)
                  ->  Seq Scan on s2
-                       Filter: (((x % 2) = 0) AND (y ~~ '%2f%'::text))
+                       Filter: (((x % 2) = 0) AND (y ~~ '%af%'::text))
 (7 rows)
 
 SELECT (SELECT x FROM s1 LIMIT 1) xx, * FROM s2 WHERE y like '%28%';
@@ -1387,7 +1383,7 @@ EXPLAIN (COSTS OFF) SELECT (SELECT x FROM s1 LIMIT 1) xx, * FROM s2 WHERE y like
                                    SubPlan 1
                                      ->  Remote Subquery Scan on all (datanode_1,datanode_2)
                                            ->  Seq Scan on s2 s2_1
-                                                 Filter: (((x % 2) = 0) AND (y ~~ '%2f%'::text))
+                                                 Filter: (((x % 2) = 0) AND (y ~~ '%af%'::text))
 (13 rows)
 
 SET SESSION AUTHORIZATION regress_rls_alice;
index 635039fac9bd4d9d0291a3be143d912e58bdee9f..86df2bcc2d91eaf187fec4ea2eebfd3d12306286 100644 (file)
@@ -525,9 +525,25 @@ select row_to_json(i) from int8_tbl i(x,y);
 
 create temp view vv1 as select * from int8_tbl;
 select row_to_json(i) from vv1 i;
-ERROR:  cache lookup failed for type 0
+                  row_to_json                   
+------------------------------------------------
+ {"q1":123,"q2":456}
+ {"q1":123,"q2":4567890123456789}
+ {"q1":4567890123456789,"q2":123}
+ {"q1":4567890123456789,"q2":4567890123456789}
+ {"q1":4567890123456789,"q2":-4567890123456789}
+(5 rows)
+
 select row_to_json(i) from vv1 i(x,y);
-ERROR:  cache lookup failed for type 0
+                 row_to_json                  
+----------------------------------------------
+ {"x":123,"y":456}
+ {"x":123,"y":4567890123456789}
+ {"x":4567890123456789,"y":123}
+ {"x":4567890123456789,"y":4567890123456789}
+ {"x":4567890123456789,"y":-4567890123456789}
+(5 rows)
+
 select row_to_json(ss) from
   (select q1, q2 from int8_tbl) as ss;
                   row_to_json                   
index c355f10c4c09b806c4976f018b2bcadee3ecc69f..a5d78d029ddb22303a53422b026171cf738216ce 100644 (file)
@@ -650,13 +650,29 @@ create temp table table_a(id integer);
 insert into table_a values (42);
 create temp view view_a as select * from table_a;
 select view_a from view_a;
-ERROR:  cache lookup failed for type 0
+ view_a 
+--------
+ (42)
+(1 row)
+
 select (select view_a) from view_a;
-ERROR:  cache lookup failed for type 0
+ view_a 
+--------
+ (42)
+(1 row)
+
 select (select (select view_a)) from view_a;
-ERROR:  cache lookup failed for type 0
+ view_a 
+--------
+ (42)
+(1 row)
+
 select (select (a.*)::text) from view_a a;
-ERROR:  cache lookup failed for type 0
+  a   
+------
+ (42)
+(1 row)
+
 --
 -- Check that whole-row Vars reading the result of a subselect don't include
 -- any junk columns therein
index 647d8cf3f79c302c45e2b776d898102f0d7e2ce1..b9a54376acd37a7e705f520644b97dd982c4fa58 100644 (file)
@@ -911,32 +911,38 @@ INSERT INTO base_tbl SELECT i, 'Row ' || i FROM generate_series(-2, 2) g(i);
 CREATE VIEW rw_view1 AS SELECT b AS bb, a AS aa FROM base_tbl;
 CREATE FUNCTION rw_view1_aa(x rw_view1)
   RETURNS int AS $$ SELECT x.aa $$ LANGUAGE sql;
-ERROR:  type rw_view1 does not exist
 UPDATE rw_view1 v SET bb='Updated row 2' WHERE rw_view1_aa(v)=2
   RETURNING rw_view1_aa(v), v.bb;
-ERROR:  function rw_view1_aa(rw_view1) does not exist
-LINE 1: UPDATE rw_view1 v SET bb='Updated row 2' WHERE rw_view1_aa(v...
-                                                       ^
-HINT:  No function matches the given name and argument types. You might need to add explicit type casts.
+ rw_view1_aa |      bb       
+-------------+---------------
+           2 | Updated row 2
+(1 row)
+
 SELECT * FROM base_tbl;
- a  |   b    
-----+--------
+ a  |       b       
+----+---------------
  -2 | Row -2
  -1 | Row -1
   0 | Row 0
   1 | Row 1
-  2 | Row 2
+  2 | Updated row 2
 (5 rows)
 
 EXPLAIN (costs off, nodes off)
 UPDATE rw_view1 v SET bb='Updated row 2' WHERE rw_view1_aa(v)=2
   RETURNING rw_view1_aa(v), v.bb;
-ERROR:  function rw_view1_aa(rw_view1) does not exist
-LINE 2: UPDATE rw_view1 v SET bb='Updated row 2' WHERE rw_view1_aa(v...
-                                                       ^
-HINT:  No function matches the given name and argument types. You might need to add explicit type casts.
+                       QUERY PLAN                       
+--------------------------------------------------------
+ Remote Subquery Scan on any
+   ->  Update on base_tbl
+         ->  Index Scan using base_tbl_pkey on base_tbl
+               Index Cond: (a = 2)
+(4 rows)
+
 DROP TABLE base_tbl CASCADE;
-NOTICE:  drop cascades to view rw_view1
+NOTICE:  drop cascades to 2 other objects
+DETAIL:  drop cascades to view rw_view1
+drop cascades to function rw_view1_aa(rw_view1)
 -- permissions checks
 CREATE USER regress_view_user1;
 CREATE USER regress_view_user2;
index e309f4f838ec93aee364e8b199fecf5f317de9f0..4e30a02fa0faeb7597a375154da0777facfdee36 100644 (file)
@@ -228,8 +228,8 @@ DROP TABLE foo2;
 DROP TABLE foo;
 
 -- Rescan tests --
-CREATE TEMPORARY SEQUENCE foo_rescan_seq1;
-CREATE TEMPORARY SEQUENCE foo_rescan_seq2;
+CREATE SEQUENCE foo_rescan_seq1;
+CREATE SEQUENCE foo_rescan_seq2;
 CREATE TYPE foo_rescan_t AS (i integer, s bigint);
 
 CREATE FUNCTION foo_sql(int,int) RETURNS setof foo_rescan_t AS 'SELECT i, nextval(''foo_rescan_seq1'') FROM generate_series($1,$2) i;' LANGUAGE SQL;