diff options
-rw-r--r-- | src/backend/tcop/utility.c | 82 | ||||
-rw-r--r-- | src/test/regress/expected/rowsecurity.out | 18 | ||||
-rw-r--r-- | src/test/regress/expected/rowtypes.out | 20 | ||||
-rw-r--r-- | src/test/regress/expected/subselect.out | 24 | ||||
-rw-r--r-- | src/test/regress/expected/updatable_views.out | 32 | ||||
-rw-r--r-- | src/test/regress/sql/rangefuncs.sql | 4 |
6 files changed, 88 insertions, 92 deletions
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 0749400ccf..6dd3845153 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -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: diff --git a/src/test/regress/expected/rowsecurity.out b/src/test/regress/expected/rowsecurity.out index 6a6492f3fb..2a40b072ab 100644 --- a/src/test/regress/expected/rowsecurity.out +++ b/src/test/regress/expected/rowsecurity.out @@ -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; diff --git a/src/test/regress/expected/rowtypes.out b/src/test/regress/expected/rowtypes.out index 635039fac9..86df2bcc2d 100644 --- a/src/test/regress/expected/rowtypes.out +++ b/src/test/regress/expected/rowtypes.out @@ -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 diff --git a/src/test/regress/expected/subselect.out b/src/test/regress/expected/subselect.out index c355f10c4c..a5d78d029d 100644 --- a/src/test/regress/expected/subselect.out +++ b/src/test/regress/expected/subselect.out @@ -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 diff --git a/src/test/regress/expected/updatable_views.out b/src/test/regress/expected/updatable_views.out index 647d8cf3f7..b9a54376ac 100644 --- a/src/test/regress/expected/updatable_views.out +++ b/src/test/regress/expected/updatable_views.out @@ -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; diff --git a/src/test/regress/sql/rangefuncs.sql b/src/test/regress/sql/rangefuncs.sql index e309f4f838..4e30a02fa0 100644 --- a/src/test/regress/sql/rangefuncs.sql +++ b/src/test/regress/sql/rangefuncs.sql @@ -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; |