WHERE f_leak(dtitle) ORDER BY did;
did | cid | dlevel | dauthor | dtitle
-----+-----+--------+-------------------+-----------------------
- 6 | 22 | 1 | rls_regress_user2 | great science fiction
- 8 | 44 | 1 | rls_regress_user2 | great manga
+ 6 | 22 | 1 | regress_rls_carol | great science fiction
+ 8 | 44 | 1 | regress_rls_carol | great manga
(2 rows)
-- viewpoint from regress_rls_carol
WHERE f_leak(dtitle) ORDER BY did;
did | cid | dlevel | dauthor | dtitle
-----+-----+--------+-------------------+-----------------------
- 6 | 22 | 1 | rls_regress_user2 | great science fiction
- 8 | 44 | 1 | rls_regress_user2 | great manga
+ 6 | 22 | 1 | regress_rls_carol | great science fiction
+ 8 | 44 | 1 | regress_rls_carol | great manga
(2 rows)
EXPLAIN (COSTS OFF) SELECT * FROM document WHERE f_leak(dtitle);
-- viewpoint from regress_rls_bob again
SET SESSION AUTHORIZATION regress_rls_bob;
SELECT * FROM document WHERE f_leak(dtitle) ORDER BY did;
- did | cid | dlevel | dauthor | dtitle
------+-----+--------+-------------------+--------------------
- 1 | 11 | 1 | rls_regress_user1 | my first novel
- 2 | 11 | 2 | rls_regress_user1 | my second novel
- 3 | 22 | 2 | rls_regress_user1 | my science fiction
- 4 | 44 | 1 | rls_regress_user1 | my first manga
- 5 | 44 | 2 | rls_regress_user1 | my second manga
+ did | cid | dlevel | dauthor | dtitle
+-----+-----+--------+-----------------+--------------------
+ 1 | 11 | 1 | regress_rls_bob | my first novel
+ 2 | 11 | 2 | regress_rls_bob | my second novel
+ 3 | 22 | 2 | regress_rls_bob | my science fiction
+ 4 | 44 | 1 | regress_rls_bob | my first manga
+ 5 | 44 | 2 | regress_rls_bob | my second manga
(5 rows)
SELECT * FROM document NATURAL JOIN category WHERE f_leak(dtitle) ORDER by did;
- cid | did | dlevel | dauthor | dtitle | cname
------+-----+--------+-------------------+--------------------+-----------------
- 11 | 1 | 1 | rls_regress_user1 | my first novel | novel
- 11 | 2 | 2 | rls_regress_user1 | my second novel | novel
- 22 | 3 | 2 | rls_regress_user1 | my science fiction | science fiction
- 44 | 4 | 1 | rls_regress_user1 | my first manga | manga
- 44 | 5 | 2 | rls_regress_user1 | my second manga | manga
+ cid | did | dlevel | dauthor | dtitle | cname
+-----+-----+--------+-----------------+--------------------+-----------------
+ 11 | 1 | 1 | regress_rls_bob | my first novel | novel
+ 11 | 2 | 2 | regress_rls_bob | my second novel | novel
+ 22 | 3 | 2 | regress_rls_bob | my science fiction | science fiction
+ 44 | 4 | 1 | regress_rls_bob | my first manga | manga
+ 44 | 5 | 2 | regress_rls_bob | my second manga | manga
(5 rows)
-- viewpoint from rls_regres_carol again
-- cannot delete PK referenced by invisible FK
SET SESSION AUTHORIZATION regress_rls_bob;
SELECT * FROM document d FULL OUTER JOIN category c on d.cid = c.cid;
- did | cid | dlevel | dauthor | dtitle | cid | cname
------+-----+--------+-------------------+--------------------+-----+------------
- 4 | 44 | 1 | rls_regress_user1 | my first manga | |
- 5 | 44 | 2 | rls_regress_user1 | my second manga | |
- 2 | 11 | 2 | rls_regress_user1 | my second novel | 11 | novel
- 1 | 11 | 1 | rls_regress_user1 | my first novel | 11 | novel
- | | | | | 33 | technology
- 3 | 22 | 2 | rls_regress_user1 | my science fiction | |
+ did | cid | dlevel | dauthor | dtitle | cid | cname
+-----+-----+--------+-----------------+--------------------+-----+------------
+ 4 | 44 | 1 | regress_rls_bob | my first manga | |
+ 5 | 44 | 2 | regress_rls_bob | my second manga | |
+ 2 | 11 | 2 | regress_rls_bob | my second novel | 11 | novel
+ 1 | 11 | 1 | regress_rls_bob | my first novel | 11 | novel
+ | | | | | 33 | technology
+ 3 | 22 | 2 | regress_rls_bob | my science fiction | |
(6 rows)
DELETE FROM category WHERE cid = 33; -- fails with FK violation
SELECT * FROM document d FULL OUTER JOIN category c on d.cid = c.cid;
did | cid | dlevel | dauthor | dtitle | cid | cname
-----+-----+--------+-------------------+-----------------------+-----+-----------------
- 8 | 44 | 1 | rls_regress_user2 | great manga | 44 | manga
- 6 | 22 | 1 | rls_regress_user2 | great science fiction | 22 | science fiction
- 7 | 33 | 2 | rls_regress_user2 | great technology book | |
+ 8 | 44 | 1 | regress_rls_carol | great manga | 44 | manga
+ 6 | 22 | 1 | regress_rls_carol | great science fiction | 22 | science fiction
+ 7 | 33 | 2 | regress_rls_carol | great technology book | |
(3 rows)
INSERT INTO document VALUES (10, 33, 1, current_user, 'hoge');
(0 rows)
-- RLS policies are checked before constraints
-INSERT INTO document VALUES (8, 44, 1, 'rls_regress_user2', 'my third manga'); -- Should fail with RLS check violation, not duplicate key violation
-ERROR: new row violates row level security policy for "document"
-UPDATE document SET did = 8, dauthor = 'rls_regress_user2' WHERE did = 5; -- Should fail with RLS check violation, not duplicate key violation
+INSERT INTO document VALUES (8, 44, 1, 'regress_rls_carol', 'my third manga'); -- Should fail with RLS check violation, not duplicate key violation
+ERROR: new row violates row-level security policy for table "document"
+UPDATE document SET did = 8, dauthor = 'regress_rls_carol' WHERE did = 5; -- Should fail with RLS check violation, not duplicate key violation
ERROR: could not plan this distributed update
DETAIL: correlated UPDATE or updating distribution column currently not supported in Postgres-XL.
-- database superuser does bypass RLS policy when enabled
SELECT * FROM document;
did | cid | dlevel | dauthor | dtitle
-----+-----+--------+-------------------+-----------------------
- 1 | 11 | 1 | rls_regress_user1 | my first novel
- 2 | 11 | 2 | rls_regress_user1 | my second novel
- 5 | 44 | 2 | rls_regress_user1 | my second manga
- 6 | 22 | 1 | rls_regress_user2 | great science fiction
- 8 | 44 | 1 | rls_regress_user2 | great manga
- 3 | 22 | 2 | rls_regress_user1 | my science fiction
- 4 | 44 | 1 | rls_regress_user1 | my first manga
- 7 | 33 | 2 | rls_regress_user2 | great technology book
- 10 | 33 | 1 | rls_regress_user2 | hoge
+ 1 | 11 | 1 | regress_rls_bob | my first novel
+ 2 | 11 | 2 | regress_rls_bob | my second novel
+ 5 | 44 | 2 | regress_rls_bob | my second manga
+ 6 | 22 | 1 | regress_rls_carol | great science fiction
+ 8 | 44 | 1 | regress_rls_carol | great manga
+ 3 | 22 | 2 | regress_rls_bob | my science fiction
+ 4 | 44 | 1 | regress_rls_bob | my first manga
+ 7 | 33 | 2 | regress_rls_carol | great technology book
+ 10 | 33 | 1 | regress_rls_carol | hoge
(9 rows)
SELECT * FROM category;
SELECT * FROM document;
did | cid | dlevel | dauthor | dtitle
-----+-----+--------+-------------------+-----------------------
- 1 | 11 | 1 | rls_regress_user1 | my first novel
- 2 | 11 | 2 | rls_regress_user1 | my second novel
- 5 | 44 | 2 | rls_regress_user1 | my second manga
- 6 | 22 | 1 | rls_regress_user2 | great science fiction
- 8 | 44 | 1 | rls_regress_user2 | great manga
- 3 | 22 | 2 | rls_regress_user1 | my science fiction
- 4 | 44 | 1 | rls_regress_user1 | my first manga
- 7 | 33 | 2 | rls_regress_user2 | great technology book
- 10 | 33 | 1 | rls_regress_user2 | hoge
+ 1 | 11 | 1 | regress_rls_bob | my first novel
+ 2 | 11 | 2 | regress_rls_bob | my second novel
+ 5 | 44 | 2 | regress_rls_bob | my second manga
+ 6 | 22 | 1 | regress_rls_carol | great science fiction
+ 8 | 44 | 1 | regress_rls_carol | great manga
+ 3 | 22 | 2 | regress_rls_bob | my science fiction
+ 4 | 44 | 1 | regress_rls_bob | my first manga
+ 7 | 33 | 2 | regress_rls_carol | great technology book
+ 10 | 33 | 1 | regress_rls_carol | hoge
(9 rows)
SELECT * FROM category;
SELECT * FROM document;
did | cid | dlevel | dauthor | dtitle
-----+-----+--------+-------------------+-----------------------
- 1 | 11 | 1 | rls_regress_user1 | my first novel
- 2 | 11 | 2 | rls_regress_user1 | my second novel
- 5 | 44 | 2 | rls_regress_user1 | my second manga
- 6 | 22 | 1 | rls_regress_user2 | great science fiction
- 8 | 44 | 1 | rls_regress_user2 | great manga
- 3 | 22 | 2 | rls_regress_user1 | my science fiction
- 4 | 44 | 1 | rls_regress_user1 | my first manga
- 7 | 33 | 2 | rls_regress_user2 | great technology book
- 10 | 33 | 1 | rls_regress_user2 | hoge
+ 1 | 11 | 1 | regress_rls_bob | my first novel
+ 2 | 11 | 2 | regress_rls_bob | my second novel
+ 5 | 44 | 2 | regress_rls_bob | my second manga
+ 6 | 22 | 1 | regress_rls_carol | great science fiction
+ 8 | 44 | 1 | regress_rls_carol | great manga
+ 3 | 22 | 2 | regress_rls_bob | my science fiction
+ 4 | 44 | 1 | regress_rls_bob | my first manga
+ 7 | 33 | 2 | regress_rls_carol | great technology book
+ 10 | 33 | 1 | regress_rls_carol | hoge
(9 rows)
SELECT * FROM category;
SELECT * FROM document;
did | cid | dlevel | dauthor | dtitle
-----+-----+--------+-------------------+-----------------------
- 1 | 11 | 1 | rls_regress_user1 | my first novel
- 2 | 11 | 2 | rls_regress_user1 | my second novel
- 5 | 44 | 2 | rls_regress_user1 | my second manga
- 6 | 22 | 1 | rls_regress_user2 | great science fiction
- 8 | 44 | 1 | rls_regress_user2 | great manga
- 3 | 22 | 2 | rls_regress_user1 | my science fiction
- 4 | 44 | 1 | rls_regress_user1 | my first manga
- 7 | 33 | 2 | rls_regress_user2 | great technology book
- 10 | 33 | 1 | rls_regress_user2 | hoge
+ 1 | 11 | 1 | regress_rls_bob | my first novel
+ 2 | 11 | 2 | regress_rls_bob | my second novel
+ 5 | 44 | 2 | regress_rls_bob | my second manga
+ 6 | 22 | 1 | regress_rls_carol | great science fiction
+ 8 | 44 | 1 | regress_rls_carol | great manga
+ 3 | 22 | 2 | regress_rls_bob | my science fiction
+ 4 | 44 | 1 | regress_rls_bob | my first manga
+ 7 | 33 | 2 | regress_rls_carol | great technology book
+ 10 | 33 | 1 | regress_rls_carol | hoge
(9 rows)
SELECT * FROM category;
SELECT * FROM document;
did | cid | dlevel | dauthor | dtitle
-----+-----+--------+-------------------+-----------------------
- 1 | 11 | 1 | rls_regress_user1 | my first novel
- 2 | 11 | 2 | rls_regress_user1 | my second novel
- 5 | 44 | 2 | rls_regress_user1 | my second manga
- 6 | 22 | 1 | rls_regress_user2 | great science fiction
- 8 | 44 | 1 | rls_regress_user2 | great manga
- 3 | 22 | 2 | rls_regress_user1 | my science fiction
- 4 | 44 | 1 | rls_regress_user1 | my first manga
- 7 | 33 | 2 | rls_regress_user2 | great technology book
- 10 | 33 | 1 | rls_regress_user2 | hoge
+ 1 | 11 | 1 | regress_rls_bob | my first novel
+ 2 | 11 | 2 | regress_rls_bob | my second novel
+ 5 | 44 | 2 | regress_rls_bob | my second manga
+ 6 | 22 | 1 | regress_rls_carol | great science fiction
+ 8 | 44 | 1 | regress_rls_carol | great manga
+ 3 | 22 | 2 | regress_rls_bob | my science fiction
+ 4 | 44 | 1 | regress_rls_bob | my first manga
+ 7 | 33 | 2 | regress_rls_carol | great technology book
+ 10 | 33 | 1 | regress_rls_carol | hoge
(9 rows)
SELECT * FROM category;
-> Seq Scan on t3
(6 rows)
--- union all query
-SELECT a, b, oid FROM t2 UNION ALL SELECT a, b, oid FROM t3;
- a | b | oid
----+-----+-----
- 1 | abc | 201
- 3 | cde | 203
- 1 | xxx | 301
- 2 | yyy | 302
- 3 | zzz | 303
-(5 rows)
-
-EXPLAIN (COSTS OFF) SELECT a, b, oid FROM t2 UNION ALL SELECT a, b, oid FROM t3;
- QUERY PLAN
--------------------------------
- Append
- -> Seq Scan on t2
- Filter: ((a % 2) = 1)
- -> Seq Scan on t3
-(4 rows)
-
-- superuser is allowed to bypass RLS checks
RESET SESSION AUTHORIZATION;
SET row_security TO OFF;
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 rls_regress_user1;
+SET SESSION AUTHORIZATION regress_rls_bob;
SELECT * FROM rec1; -- fail, mutual recursion via views
ERROR: infinite recursion detected in policy for relation "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 relation "rec1" already exists
+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 relation "rec2" already exists
-SET SESSION AUTHORIZATION rls_regress_user1;
+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 rls_regress_user1;
+SET SESSION AUTHORIZATION regress_rls_bob;
SELECT * FROM s1 WHERE f_leak(b); -- OK
a | b
---+----------------------------------
2 | bbbbbb_updt
2 | bcdbcd
2 | yyyyyy
- 4 | dddddd_updt
+ 4 | daddad_updt
4 | defdef
(5 rows)
102 | 2 | bbbbbb_updt | (2,bbbbbb_updt)
202 | 2 | bcdbcd | (2,bcdbcd)
302 | 2 | yyyyyy | (2,yyyyyy)
- 104 | 4 | dddddd_updt | (4,dddddd_updt)
+ 104 | 4 | daddad_updt | (4,daddad_updt)
204 | 4 | defdef | (4,defdef)
(5 rows)
(8 rows)
DELETE FROM bv1 WHERE a = 6 AND f_leak(b);
-SET SESSION AUTHORIZATION rls_regress_user0;
+SET SESSION AUTHORIZATION regress_rls_alice;
SELECT * FROM b1;
a | b
-----+----------------------------------
UPDATE x1 SET b = b || '_updt' WHERE f_leak(b) RETURNING *;
a | b | c
---+----------+-------------------
- 1 | abc_updt | rls_regress_user1
- 2 | bcd_updt | rls_regress_user1
- 5 | efg_updt | rls_regress_user1
- 6 | fgh_updt | rls_regress_user1
- 8 | fgh_updt | rls_regress_user2
- 4 | def_updt | rls_regress_user2
+ 1 | abc_updt | regress_rls_bob
+ 2 | bcd_updt | regress_rls_bob
+ 5 | efg_updt | regress_rls_bob
+ 6 | fgh_updt | regress_rls_bob
+ 8 | fgh_updt | regress_rls_carol
+ 4 | def_updt | regress_rls_carol
(6 rows)
SET SESSION AUTHORIZATION regress_rls_carol;
UPDATE x1 SET b = b || '_updt' WHERE f_leak(b) RETURNING *;
a | b | c
---+---------------+-------------------
- 2 | bcd_updt_updt | rls_regress_user1
- 6 | fgh_updt_updt | rls_regress_user1
- 8 | fgh_updt_updt | rls_regress_user2
- 3 | cde_updt | rls_regress_user2
- 7 | fgh_updt | rls_regress_user2
- 4 | def_updt_updt | rls_regress_user2
+ 2 | bcd_updt_updt | regress_rls_bob
+ 6 | fgh_updt_updt | regress_rls_bob
+ 8 | fgh_updt_updt | regress_rls_carol
+ 3 | cde_updt | regress_rls_carol
+ 7 | fgh_updt | regress_rls_carol
+ 4 | def_updt_updt | regress_rls_carol
(6 rows)
DELETE FROM x1 WHERE f_leak(b) RETURNING *;
a | b | c
---+---------------+-------------------
- 2 | bcd_updt_updt | rls_regress_user1
- 6 | fgh_updt_updt | rls_regress_user1
- 8 | fgh_updt_updt | rls_regress_user2
- 3 | cde_updt | rls_regress_user2
- 7 | fgh_updt | rls_regress_user2
- 4 | def_updt_updt | rls_regress_user2
+ 2 | bcd_updt_updt | regress_rls_bob
+ 6 | fgh_updt_updt | regress_rls_bob
+ 8 | fgh_updt_updt | regress_rls_carol
+ 3 | cde_updt | regress_rls_carol
+ 7 | fgh_updt | regress_rls_carol
+ 4 | def_updt_updt | regress_rls_carol
(6 rows)
--
9,45c48cce2e2d7fbdea1afc51c7c6ad26
10,d3d9446802a44259755d38e6d163e820
-- Check COPY TO as user without permissions. SET row_security TO OFF;
-SET SESSION AUTHORIZATION rls_regress_user2;
+SET SESSION AUTHORIZATION regress_rls_carol;
SET row_security TO OFF;
COPY (SELECT * FROM copy_t ORDER BY a ASC) TO STDOUT WITH DELIMITER ','; --fail - would be affected by RLS
ERROR: query would be affected by row-level security policy for table "copy_t"
CREATE TABLE copy_rel_to (a integer, b text);
CREATE POLICY p1 ON copy_rel_to USING (a % 2 = 0);
ALTER TABLE copy_rel_to ENABLE ROW LEVEL SECURITY;
-GRANT ALL ON copy_rel_to TO rls_regress_user1, rls_regress_exempt_user;
+GRANT ALL ON copy_rel_to TO regress_rls_bob, regress_rls_exempt_user;
INSERT INTO copy_rel_to VALUES (1, md5('1'));
-- Check COPY TO as Superuser/owner.
RESET SESSION AUTHORIZATION;
COPY copy_rel_to TO STDOUT WITH DELIMITER ',';
1,c4ca4238a0b923820dcc509a6f75849b
-- Check COPY TO as user with permissions.
-SET SESSION AUTHORIZATION rls_regress_user1;
+SET SESSION AUTHORIZATION regress_rls_bob;
SET row_security TO OFF;
-COPY copy_rel_to TO STDOUT WITH DELIMITER ','; --fail - insufficient to bypass rls
-ERROR: insufficient privilege to bypass row security.
+COPY copy_rel_to TO STDOUT WITH DELIMITER ','; --fail - would be affected by RLS
+ERROR: query would be affected by row-level security policy for table "copy_rel_to"
SET row_security TO ON;
COPY copy_rel_to TO STDOUT WITH DELIMITER ','; --ok
-- Check COPY TO as user with permissions and BYPASSRLS
-SET SESSION AUTHORIZATION rls_regress_exempt_user;
+SET SESSION AUTHORIZATION regress_rls_exempt_user;
SET row_security TO OFF;
COPY copy_rel_to TO STDOUT WITH DELIMITER ','; --ok
1,c4ca4238a0b923820dcc509a6f75849b
SET row_security TO ON;
COPY copy_rel_to TO STDOUT WITH DELIMITER ','; --ok
-- Check COPY TO as user without permissions. SET row_security TO OFF;
-SET SESSION AUTHORIZATION rls_regress_user2;
+SET SESSION AUTHORIZATION regress_rls_carol;
SET row_security TO OFF;
COPY copy_rel_to TO STDOUT WITH DELIMITER ','; --fail - permission denied
ERROR: permission denied for relation copy_rel_to
-- Returns rows that can be seen according to SELECT policy, like plain SELECT
-- above (even rows)
FETCH ABSOLUTE 1 FROM current_check_cursor;
- currentid | payload | rlsuser
------------+---------+-------------------
- 2 | bcd | rls_regress_user1
+ currentid | payload | rlsuser
+-----------+---------+-----------------
+ 2 | bcd | regress_rls_bob
(1 row)
-- Still cannot UPDATE row 2 through cursor
SAVEPOINT q;
ERROR: SAVEPOINT is not yet supported.
-DROP ROLE alice; --fails due to dependency on POLICY p
+DROP ROLE regress_rls_eve; --fails due to dependency on POLICY p
ERROR: current transaction is aborted, commands ignored until end of transaction block
ROLLBACK TO q;
ERROR: no such savepoint
-ALTER POLICY p ON tbl1 TO bob USING (true);
+ALTER POLICY p ON tbl1 TO regress_rls_frank USING (true);
ERROR: current transaction is aborted, commands ignored until end of transaction block
SAVEPOINT q;
ERROR: current transaction is aborted, commands ignored until end of transaction block
-DROP ROLE alice; --fails due to dependency on GRANT SELECT
+DROP ROLE regress_rls_eve; --fails due to dependency on GRANT SELECT
ERROR: current transaction is aborted, commands ignored until end of transaction block
ROLLBACK TO q;
ERROR: no such savepoint
-REVOKE ALL ON TABLE tbl1 FROM alice;
+REVOKE ALL ON TABLE tbl1 FROM regress_rls_eve;
ERROR: current transaction is aborted, commands ignored until end of transaction block
SAVEPOINT q;
ERROR: current transaction is aborted, commands ignored until end of transaction block
-DROP ROLE alice; --succeeds
+DROP ROLE regress_rls_eve; --succeeds
ERROR: current transaction is aborted, commands ignored until end of transaction block
ROLLBACK TO q;
ERROR: no such savepoint
SAVEPOINT q;
ERROR: current transaction is aborted, commands ignored until end of transaction block
-DROP ROLE bob; --fails due to dependency on POLICY p
+DROP ROLE regress_rls_frank; --fails due to dependency on POLICY p
ERROR: current transaction is aborted, commands ignored until end of transaction block
ROLLBACK TO q;
ERROR: no such savepoint
ERROR: current transaction is aborted, commands ignored until end of transaction block
SAVEPOINT q;
ERROR: current transaction is aborted, commands ignored until end of transaction block
-DROP ROLE bob; -- succeeds
+DROP ROLE regress_rls_frank; -- succeeds
ERROR: current transaction is aborted, commands ignored until end of transaction block
ROLLBACK TO q;
ERROR: no such savepoint