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;
/* 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;
* 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;
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:
{
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:
switch (relkind_str)
{
- case RELKIND_SEQUENCE:
case RELKIND_RELATION:
case RELKIND_PARTITIONED_TABLE:
if ((*is_temp = IsTempTable(relid)))
/* 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
{
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:
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"
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"
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);
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%';
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;
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
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
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;
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;