diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index 5a3eaefebd..0551c64798 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -1449,7 +1449,8 @@ grouping_planner(PlannerInfo *root, double tuple_fraction) * This may add new security barrier subquery RTEs to the rangetable. */ expand_security_quals(root, tlist); - root->glob->hasRowSecurity = parse->hasRowSecurity; + if (parse->hasRowSecurity) + root->glob->hasRowSecurity = true; /* * Locate any window functions in the tlist. (We don't need to look diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c index 77a694a771..8a5ee01ab6 100644 --- a/src/backend/optimizer/plan/setrefs.c +++ b/src/backend/optimizer/plan/setrefs.c @@ -2392,7 +2392,8 @@ extract_query_dependencies_walker(Node *node, PlannerInfo *context) ListCell *lc; /* Collect row security information */ - context->glob->hasRowSecurity = query->hasRowSecurity; + if (query->hasRowSecurity) + context->glob->hasRowSecurity = true; if (query->commandType == CMD_UTILITY) { diff --git a/src/test/regress/expected/rowsecurity.out b/src/test/regress/expected/rowsecurity.out index d4b9c70646..2102eab457 100644 --- a/src/test/regress/expected/rowsecurity.out +++ b/src/test/regress/expected/rowsecurity.out @@ -1649,7 +1649,8 @@ ERROR: new row violates row-level security policy for table "document" -- SET SESSION AUTHORIZATION rls_regress_user0; CREATE TABLE z1 (a int, b text); -GRANT SELECT ON z1 TO rls_regress_group1, rls_regress_group2, +CREATE TABLE z2 (a int, b text); +GRANT SELECT ON z1,z2 TO rls_regress_group1, rls_regress_group2, rls_regress_user1, rls_regress_user2; INSERT INTO z1 VALUES (1, 'aaa'), @@ -1678,6 +1679,46 @@ EXPLAIN (COSTS OFF) SELECT * FROM z1 WHERE f_leak(b); Filter: ((a % 2) = 0) (4 rows) +PREPARE plancache_test AS SELECT * FROM z1 WHERE f_leak(b); +EXPLAIN EXECUTE plancache_test; + QUERY PLAN +--------------------------------------------------------------- + Subquery Scan on z1 (cost=0.00..29.11 rows=2 width=36) + Filter: f_leak(z1.b) + -> Seq Scan on z1 z1_1 (cost=0.00..29.05 rows=6 width=36) + Filter: ((a % 2) = 0) +(4 rows) + +PREPARE plancache_test2 AS WITH q AS (SELECT * FROM z1 WHERE f_leak(b)) SELECT * FROM q,z2; +EXPLAIN EXECUTE plancache_test2; + QUERY PLAN +----------------------------------------------------------------------- + Nested Loop (cost=29.11..86.78 rows=2540 width=72) + CTE q + -> Subquery Scan on z1 (cost=0.00..29.11 rows=2 width=36) + Filter: f_leak(z1.b) + -> Seq Scan on z1 z1_1 (cost=0.00..29.05 rows=6 width=36) + Filter: ((a % 2) = 0) + -> CTE Scan on q (cost=0.00..0.04 rows=2 width=36) + -> Materialize (cost=0.00..29.05 rows=1270 width=36) + -> Seq Scan on z2 (cost=0.00..22.70 rows=1270 width=36) +(9 rows) + +PREPARE plancache_test3 AS WITH q AS (SELECT * FROM z2) SELECT * FROM q,z1 WHERE f_leak(z1.b); +EXPLAIN EXECUTE plancache_test3; + QUERY PLAN +--------------------------------------------------------------------------- + Nested Loop (cost=22.70..108.97 rows=2540 width=72) + CTE q + -> Seq Scan on z2 (cost=0.00..22.70 rows=1270 width=36) + -> CTE Scan on q (cost=0.00..25.40 rows=1270 width=36) + -> Materialize (cost=0.00..29.12 rows=2 width=36) + -> Subquery Scan on z1 (cost=0.00..29.11 rows=2 width=36) + Filter: f_leak(z1.b) + -> Seq Scan on z1 z1_1 (cost=0.00..29.05 rows=6 width=36) + Filter: ((a % 2) = 0) +(9 rows) + SET ROLE rls_regress_group1; SELECT * FROM z1 WHERE f_leak(b); NOTICE: f_leak => bbb @@ -1697,6 +1738,43 @@ EXPLAIN (COSTS OFF) SELECT * FROM z1 WHERE f_leak(b); Filter: ((a % 2) = 0) (4 rows) +EXPLAIN EXECUTE plancache_test; + QUERY PLAN +--------------------------------------------------------------- + Subquery Scan on z1 (cost=0.00..29.11 rows=2 width=36) + Filter: f_leak(z1.b) + -> Seq Scan on z1 z1_1 (cost=0.00..29.05 rows=6 width=36) + Filter: ((a % 2) = 0) +(4 rows) + +EXPLAIN EXECUTE plancache_test2; + QUERY PLAN +----------------------------------------------------------------------- + Nested Loop (cost=29.11..86.78 rows=2540 width=72) + CTE q + -> Subquery Scan on z1 (cost=0.00..29.11 rows=2 width=36) + Filter: f_leak(z1.b) + -> Seq Scan on z1 z1_1 (cost=0.00..29.05 rows=6 width=36) + Filter: ((a % 2) = 0) + -> CTE Scan on q (cost=0.00..0.04 rows=2 width=36) + -> Materialize (cost=0.00..29.05 rows=1270 width=36) + -> Seq Scan on z2 (cost=0.00..22.70 rows=1270 width=36) +(9 rows) + +EXPLAIN EXECUTE plancache_test3; + QUERY PLAN +--------------------------------------------------------------------------- + Nested Loop (cost=22.70..108.97 rows=2540 width=72) + CTE q + -> Seq Scan on z2 (cost=0.00..22.70 rows=1270 width=36) + -> CTE Scan on q (cost=0.00..25.40 rows=1270 width=36) + -> Materialize (cost=0.00..29.12 rows=2 width=36) + -> Subquery Scan on z1 (cost=0.00..29.11 rows=2 width=36) + Filter: f_leak(z1.b) + -> Seq Scan on z1 z1_1 (cost=0.00..29.05 rows=6 width=36) + Filter: ((a % 2) = 0) +(9 rows) + SET SESSION AUTHORIZATION rls_regress_user2; SELECT * FROM z1 WHERE f_leak(b); NOTICE: f_leak => aaa @@ -1716,6 +1794,43 @@ EXPLAIN (COSTS OFF) SELECT * FROM z1 WHERE f_leak(b); Filter: ((a % 2) = 1) (4 rows) +EXPLAIN EXECUTE plancache_test; + QUERY PLAN +--------------------------------------------------------------- + Subquery Scan on z1 (cost=0.00..29.11 rows=2 width=36) + Filter: f_leak(z1.b) + -> Seq Scan on z1 z1_1 (cost=0.00..29.05 rows=6 width=36) + Filter: ((a % 2) = 1) +(4 rows) + +EXPLAIN EXECUTE plancache_test2; + QUERY PLAN +----------------------------------------------------------------------- + Nested Loop (cost=29.11..86.78 rows=2540 width=72) + CTE q + -> Subquery Scan on z1 (cost=0.00..29.11 rows=2 width=36) + Filter: f_leak(z1.b) + -> Seq Scan on z1 z1_1 (cost=0.00..29.05 rows=6 width=36) + Filter: ((a % 2) = 1) + -> CTE Scan on q (cost=0.00..0.04 rows=2 width=36) + -> Materialize (cost=0.00..29.05 rows=1270 width=36) + -> Seq Scan on z2 (cost=0.00..22.70 rows=1270 width=36) +(9 rows) + +EXPLAIN EXECUTE plancache_test3; + QUERY PLAN +--------------------------------------------------------------------------- + Nested Loop (cost=22.70..108.97 rows=2540 width=72) + CTE q + -> Seq Scan on z2 (cost=0.00..22.70 rows=1270 width=36) + -> CTE Scan on q (cost=0.00..25.40 rows=1270 width=36) + -> Materialize (cost=0.00..29.12 rows=2 width=36) + -> Subquery Scan on z1 (cost=0.00..29.11 rows=2 width=36) + Filter: f_leak(z1.b) + -> Seq Scan on z1 z1_1 (cost=0.00..29.05 rows=6 width=36) + Filter: ((a % 2) = 1) +(9 rows) + SET ROLE rls_regress_group2; SELECT * FROM z1 WHERE f_leak(b); NOTICE: f_leak => aaa @@ -1735,6 +1850,43 @@ EXPLAIN (COSTS OFF) SELECT * FROM z1 WHERE f_leak(b); Filter: ((a % 2) = 1) (4 rows) +EXPLAIN EXECUTE plancache_test; + QUERY PLAN +--------------------------------------------------------------- + Subquery Scan on z1 (cost=0.00..29.11 rows=2 width=36) + Filter: f_leak(z1.b) + -> Seq Scan on z1 z1_1 (cost=0.00..29.05 rows=6 width=36) + Filter: ((a % 2) = 1) +(4 rows) + +EXPLAIN EXECUTE plancache_test2; + QUERY PLAN +----------------------------------------------------------------------- + Nested Loop (cost=29.11..86.78 rows=2540 width=72) + CTE q + -> Subquery Scan on z1 (cost=0.00..29.11 rows=2 width=36) + Filter: f_leak(z1.b) + -> Seq Scan on z1 z1_1 (cost=0.00..29.05 rows=6 width=36) + Filter: ((a % 2) = 1) + -> CTE Scan on q (cost=0.00..0.04 rows=2 width=36) + -> Materialize (cost=0.00..29.05 rows=1270 width=36) + -> Seq Scan on z2 (cost=0.00..22.70 rows=1270 width=36) +(9 rows) + +EXPLAIN EXECUTE plancache_test3; + QUERY PLAN +--------------------------------------------------------------------------- + Nested Loop (cost=22.70..108.97 rows=2540 width=72) + CTE q + -> Seq Scan on z2 (cost=0.00..22.70 rows=1270 width=36) + -> CTE Scan on q (cost=0.00..25.40 rows=1270 width=36) + -> Materialize (cost=0.00..29.12 rows=2 width=36) + -> Subquery Scan on z1 (cost=0.00..29.11 rows=2 width=36) + Filter: f_leak(z1.b) + -> Seq Scan on z1 z1_1 (cost=0.00..29.05 rows=6 width=36) + Filter: ((a % 2) = 1) +(9 rows) + -- -- Views should follow policy for view owner. -- diff --git a/src/test/regress/sql/rowsecurity.sql b/src/test/regress/sql/rowsecurity.sql index 3966a55f2c..34c551da82 100644 --- a/src/test/regress/sql/rowsecurity.sql +++ b/src/test/regress/sql/rowsecurity.sql @@ -629,8 +629,9 @@ INSERT INTO document VALUES (1, (SELECT cid from category WHERE cname = 'novel') -- SET SESSION AUTHORIZATION rls_regress_user0; CREATE TABLE z1 (a int, b text); +CREATE TABLE z2 (a int, b text); -GRANT SELECT ON z1 TO rls_regress_group1, rls_regress_group2, +GRANT SELECT ON z1,z2 TO rls_regress_group1, rls_regress_group2, rls_regress_user1, rls_regress_user2; INSERT INTO z1 VALUES @@ -648,18 +649,39 @@ SET SESSION AUTHORIZATION rls_regress_user1; SELECT * FROM z1 WHERE f_leak(b); EXPLAIN (COSTS OFF) SELECT * FROM z1 WHERE f_leak(b); +PREPARE plancache_test AS SELECT * FROM z1 WHERE f_leak(b); +EXPLAIN EXECUTE plancache_test; + +PREPARE plancache_test2 AS WITH q AS (SELECT * FROM z1 WHERE f_leak(b)) SELECT * FROM q,z2; +EXPLAIN EXECUTE plancache_test2; + +PREPARE plancache_test3 AS WITH q AS (SELECT * FROM z2) SELECT * FROM q,z1 WHERE f_leak(z1.b); +EXPLAIN EXECUTE plancache_test3; + SET ROLE rls_regress_group1; SELECT * FROM z1 WHERE f_leak(b); EXPLAIN (COSTS OFF) SELECT * FROM z1 WHERE f_leak(b); +EXPLAIN EXECUTE plancache_test; +EXPLAIN EXECUTE plancache_test2; +EXPLAIN EXECUTE plancache_test3; + SET SESSION AUTHORIZATION rls_regress_user2; SELECT * FROM z1 WHERE f_leak(b); EXPLAIN (COSTS OFF) SELECT * FROM z1 WHERE f_leak(b); +EXPLAIN EXECUTE plancache_test; +EXPLAIN EXECUTE plancache_test2; +EXPLAIN EXECUTE plancache_test3; + SET ROLE rls_regress_group2; SELECT * FROM z1 WHERE f_leak(b); EXPLAIN (COSTS OFF) SELECT * FROM z1 WHERE f_leak(b); +EXPLAIN EXECUTE plancache_test; +EXPLAIN EXECUTE plancache_test2; +EXPLAIN EXECUTE plancache_test3; + -- -- Views should follow policy for view owner. --