]> granicus.if.org Git - postgresql/blob - src/test/regress/sql/rowsecurity.sql
Reset plan->row_security_env and planUserId
[postgresql] / src / test / regress / sql / rowsecurity.sql
1 --
2 -- Test of Row-level security feature
3 --
4
5 -- Clean up in case a prior regression run failed
6
7 -- Suppress NOTICE messages when users/groups don't exist
8 SET client_min_messages TO 'warning';
9
10 DROP USER IF EXISTS rls_regress_user0;
11 DROP USER IF EXISTS rls_regress_user1;
12 DROP USER IF EXISTS rls_regress_user2;
13 DROP USER IF EXISTS rls_regress_exempt_user;
14 DROP ROLE IF EXISTS rls_regress_group1;
15 DROP ROLE IF EXISTS rls_regress_group2;
16
17 DROP SCHEMA IF EXISTS rls_regress_schema CASCADE;
18
19 RESET client_min_messages;
20
21 -- initial setup
22 CREATE USER rls_regress_user0;
23 CREATE USER rls_regress_user1;
24 CREATE USER rls_regress_user2;
25 CREATE USER rls_regress_exempt_user BYPASSRLS;
26 CREATE ROLE rls_regress_group1 NOLOGIN;
27 CREATE ROLE rls_regress_group2 NOLOGIN;
28
29 GRANT rls_regress_group1 TO rls_regress_user1;
30 GRANT rls_regress_group2 TO rls_regress_user2;
31
32 CREATE SCHEMA rls_regress_schema;
33 GRANT ALL ON SCHEMA rls_regress_schema to public;
34 SET search_path = rls_regress_schema;
35
36 -- setup of malicious function
37 CREATE OR REPLACE FUNCTION f_leak(text) RETURNS bool
38     COST 0.0000001 LANGUAGE plpgsql
39     AS 'BEGIN RAISE NOTICE ''f_leak => %'', $1; RETURN true; END';
40 GRANT EXECUTE ON FUNCTION f_leak(text) TO public;
41
42 -- BASIC Row-Level Security Scenario
43
44 SET SESSION AUTHORIZATION rls_regress_user0;
45 CREATE TABLE uaccount (
46     pguser      name primary key,
47     seclv       int
48 );
49 GRANT SELECT ON uaccount TO public;
50 INSERT INTO uaccount VALUES
51     ('rls_regress_user0', 99),
52     ('rls_regress_user1', 1),
53     ('rls_regress_user2', 2),
54     ('rls_regress_user3', 3);
55
56 CREATE TABLE category (
57     cid        int primary key,
58     cname      text
59 );
60 GRANT ALL ON category TO public;
61 INSERT INTO category VALUES
62     (11, 'novel'),
63     (22, 'science fiction'),
64     (33, 'technology'),
65     (44, 'manga');
66
67 CREATE TABLE document (
68     did         int primary key,
69     cid         int references category(cid),
70     dlevel      int not null,
71     dauthor     name,
72     dtitle      text
73 );
74 GRANT ALL ON document TO public;
75 INSERT INTO document VALUES
76     ( 1, 11, 1, 'rls_regress_user1', 'my first novel'),
77     ( 2, 11, 2, 'rls_regress_user1', 'my second novel'),
78     ( 3, 22, 2, 'rls_regress_user1', 'my science fiction'),
79     ( 4, 44, 1, 'rls_regress_user1', 'my first manga'),
80     ( 5, 44, 2, 'rls_regress_user1', 'my second manga'),
81     ( 6, 22, 1, 'rls_regress_user2', 'great science fiction'),
82     ( 7, 33, 2, 'rls_regress_user2', 'great technology book'),
83     ( 8, 44, 1, 'rls_regress_user2', 'great manga');
84
85 ALTER TABLE document ENABLE ROW LEVEL SECURITY;
86
87 -- user's security level must be higher than or equal to document's
88 CREATE POLICY p1 ON document
89     USING (dlevel <= (SELECT seclv FROM uaccount WHERE pguser = current_user));
90
91 -- viewpoint from rls_regress_user1
92 SET SESSION AUTHORIZATION rls_regress_user1;
93 SET row_security TO ON;
94 SELECT * FROM document WHERE f_leak(dtitle) ORDER BY did;
95 SELECT * FROM document NATURAL JOIN category WHERE f_leak(dtitle) ORDER BY did;
96
97 -- try a sampled version
98 SELECT * FROM document TABLESAMPLE BERNOULLI(50) REPEATABLE(0)
99   WHERE f_leak(dtitle) ORDER BY did;
100
101 -- viewpoint from rls_regress_user2
102 SET SESSION AUTHORIZATION rls_regress_user2;
103 SELECT * FROM document WHERE f_leak(dtitle) ORDER BY did;
104 SELECT * FROM document NATURAL JOIN category WHERE f_leak(dtitle) ORDER BY did;
105
106 -- try a sampled version
107 SELECT * FROM document TABLESAMPLE BERNOULLI(50) REPEATABLE(0)
108   WHERE f_leak(dtitle) ORDER BY did;
109
110 EXPLAIN (COSTS OFF) SELECT * FROM document WHERE f_leak(dtitle);
111 EXPLAIN (COSTS OFF) SELECT * FROM document NATURAL JOIN category WHERE f_leak(dtitle);
112
113 -- only owner can change policies
114 ALTER POLICY p1 ON document USING (true);    --fail
115 DROP POLICY p1 ON document;                  --fail
116
117 SET SESSION AUTHORIZATION rls_regress_user0;
118 ALTER POLICY p1 ON document USING (dauthor = current_user);
119
120 -- viewpoint from rls_regress_user1 again
121 SET SESSION AUTHORIZATION rls_regress_user1;
122 SELECT * FROM document WHERE f_leak(dtitle) ORDER BY did;
123 SELECT * FROM document NATURAL JOIN category WHERE f_leak(dtitle) ORDER by did;
124
125 -- viewpoint from rls_regres_user2 again
126 SET SESSION AUTHORIZATION rls_regress_user2;
127 SELECT * FROM document WHERE f_leak(dtitle) ORDER BY did;
128 SELECT * FROM document NATURAL JOIN category WHERE f_leak(dtitle) ORDER by did;
129
130 EXPLAIN (COSTS OFF) SELECT * FROM document WHERE f_leak(dtitle);
131 EXPLAIN (COSTS OFF) SELECT * FROM document NATURAL JOIN category WHERE f_leak(dtitle);
132
133 -- interaction of FK/PK constraints
134 SET SESSION AUTHORIZATION rls_regress_user0;
135 CREATE POLICY p2 ON category
136     USING (CASE WHEN current_user = 'rls_regress_user1' THEN cid IN (11, 33)
137            WHEN current_user = 'rls_regress_user2' THEN cid IN (22, 44)
138            ELSE false END);
139
140 ALTER TABLE category ENABLE ROW LEVEL SECURITY;
141
142 -- cannot delete PK referenced by invisible FK
143 SET SESSION AUTHORIZATION rls_regress_user1;
144 SELECT * FROM document d FULL OUTER JOIN category c on d.cid = c.cid;
145 DELETE FROM category WHERE cid = 33;    -- fails with FK violation
146
147 -- can insert FK referencing invisible PK
148 SET SESSION AUTHORIZATION rls_regress_user2;
149 SELECT * FROM document d FULL OUTER JOIN category c on d.cid = c.cid;
150 INSERT INTO document VALUES (10, 33, 1, current_user, 'hoge');
151
152 -- UNIQUE or PRIMARY KEY constraint violation DOES reveal presence of row
153 SET SESSION AUTHORIZATION rls_regress_user1;
154 INSERT INTO document VALUES (8, 44, 1, 'rls_regress_user1', 'my third manga'); -- Must fail with unique violation, revealing presence of did we can't see
155 SELECT * FROM document WHERE did = 8; -- and confirm we can't see it
156
157 -- RLS policies are checked before constraints
158 INSERT INTO document VALUES (8, 44, 1, 'rls_regress_user2', 'my third manga'); -- Should fail with RLS check violation, not duplicate key violation
159 UPDATE document SET did = 8, dauthor = 'rls_regress_user2' WHERE did = 5; -- Should fail with RLS check violation, not duplicate key violation
160
161 -- database superuser does bypass RLS policy when enabled
162 RESET SESSION AUTHORIZATION;
163 SET row_security TO ON;
164 SELECT * FROM document;
165 SELECT * FROM category;
166
167 -- database superuser does bypass RLS policy when disabled
168 RESET SESSION AUTHORIZATION;
169 SET row_security TO OFF;
170 SELECT * FROM document;
171 SELECT * FROM category;
172
173 -- database non-superuser with bypass privilege can bypass RLS policy when disabled
174 SET SESSION AUTHORIZATION rls_regress_exempt_user;
175 SET row_security TO OFF;
176 SELECT * FROM document;
177 SELECT * FROM category;
178
179 -- RLS policy does not apply to table owner when RLS enabled.
180 SET SESSION AUTHORIZATION rls_regress_user0;
181 SET row_security TO ON;
182 SELECT * FROM document;
183 SELECT * FROM category;
184
185 -- RLS policy does not apply to table owner when RLS disabled.
186 SET SESSION AUTHORIZATION rls_regress_user0;
187 SET row_security TO OFF;
188 SELECT * FROM document;
189 SELECT * FROM category;
190
191 --
192 -- Table inheritance and RLS policy
193 --
194 SET SESSION AUTHORIZATION rls_regress_user0;
195
196 SET row_security TO ON;
197
198 CREATE TABLE t1 (a int, junk1 text, b text) WITH OIDS;
199 ALTER TABLE t1 DROP COLUMN junk1;    -- just a disturbing factor
200 GRANT ALL ON t1 TO public;
201
202 COPY t1 FROM stdin WITH (oids);
203 101     1       aaa
204 102     2       bbb
205 103     3       ccc
206 104     4       ddd
207 \.
208
209 CREATE TABLE t2 (c float) INHERITS (t1);
210 GRANT ALL ON t2 TO public;
211
212 COPY t2 FROM stdin WITH (oids);
213 201     1       abc     1.1
214 202     2       bcd     2.2
215 203     3       cde     3.3
216 204     4       def     4.4
217 \.
218
219 CREATE TABLE t3 (c text, b text, a int) WITH OIDS;
220 ALTER TABLE t3 INHERIT t1;
221 GRANT ALL ON t3 TO public;
222
223 COPY t3(a,b,c) FROM stdin WITH (oids);
224 301     1       xxx     X
225 302     2       yyy     Y
226 303     3       zzz     Z
227 \.
228
229 CREATE POLICY p1 ON t1 FOR ALL TO PUBLIC USING (a % 2 = 0); -- be even number
230 CREATE POLICY p2 ON t2 FOR ALL TO PUBLIC USING (a % 2 = 1); -- be odd number
231
232 ALTER TABLE t1 ENABLE ROW LEVEL SECURITY;
233 ALTER TABLE t2 ENABLE ROW LEVEL SECURITY;
234
235 SET SESSION AUTHORIZATION rls_regress_user1;
236
237 SELECT * FROM t1;
238 EXPLAIN (COSTS OFF) SELECT * FROM t1;
239
240 SELECT * FROM t1 WHERE f_leak(b);
241 EXPLAIN (COSTS OFF) SELECT * FROM t1 WHERE f_leak(b);
242
243 -- reference to system column
244 SELECT oid, * FROM t1;
245 EXPLAIN (COSTS OFF) SELECT *, t1 FROM t1;
246
247 -- reference to whole-row reference
248 SELECT *, t1 FROM t1;
249 EXPLAIN (COSTS OFF) SELECT *, t1 FROM t1;
250
251 -- for share/update lock
252 SELECT * FROM t1 FOR SHARE;
253 EXPLAIN (COSTS OFF) SELECT * FROM t1 FOR SHARE;
254
255 SELECT * FROM t1 WHERE f_leak(b) FOR SHARE;
256 EXPLAIN (COSTS OFF) SELECT * FROM t1 WHERE f_leak(b) FOR SHARE;
257
258 -- union all query
259 SELECT a, b, oid FROM t2 UNION ALL SELECT a, b, oid FROM t3;
260 EXPLAIN (COSTS OFF) SELECT a, b, oid FROM t2 UNION ALL SELECT a, b, oid FROM t3;
261
262 -- superuser is allowed to bypass RLS checks
263 RESET SESSION AUTHORIZATION;
264 SET row_security TO OFF;
265 SELECT * FROM t1 WHERE f_leak(b);
266 EXPLAIN (COSTS OFF) SELECT * FROM t1 WHERE f_leak(b);
267
268 -- non-superuser with bypass privilege can bypass RLS policy when disabled
269 SET SESSION AUTHORIZATION rls_regress_exempt_user;
270 SET row_security TO OFF;
271 SELECT * FROM t1 WHERE f_leak(b);
272 EXPLAIN (COSTS OFF) SELECT * FROM t1 WHERE f_leak(b);
273
274 ----- Dependencies -----
275 SET SESSION AUTHORIZATION rls_regress_user0;
276 SET row_security TO ON;
277
278 CREATE TABLE dependee (x integer, y integer);
279
280 CREATE TABLE dependent (x integer, y integer);
281 CREATE POLICY d1 ON dependent FOR ALL
282     TO PUBLIC
283     USING (x = (SELECT d.x FROM dependee d WHERE d.y = y));
284
285 DROP TABLE dependee; -- Should fail without CASCADE due to dependency on row security qual?
286
287 DROP TABLE dependee CASCADE;
288
289 EXPLAIN (COSTS OFF) SELECT * FROM dependent; -- After drop, should be unqualified
290
291 -----   RECURSION    ----
292
293 --
294 -- Simple recursion
295 --
296 SET SESSION AUTHORIZATION rls_regress_user0;
297 CREATE TABLE rec1 (x integer, y integer);
298 CREATE POLICY r1 ON rec1 USING (x = (SELECT r.x FROM rec1 r WHERE y = r.y));
299 ALTER TABLE rec1 ENABLE ROW LEVEL SECURITY;
300 SET SESSION AUTHORIZATION rls_regress_user1;
301 SELECT * FROM rec1; -- fail, direct recursion
302
303 --
304 -- Mutual recursion
305 --
306 SET SESSION AUTHORIZATION rls_regress_user0;
307 CREATE TABLE rec2 (a integer, b integer);
308 ALTER POLICY r1 ON rec1 USING (x = (SELECT a FROM rec2 WHERE b = y));
309 CREATE POLICY r2 ON rec2 USING (a = (SELECT x FROM rec1 WHERE y = b));
310 ALTER TABLE rec2 ENABLE ROW LEVEL SECURITY;
311
312 SET SESSION AUTHORIZATION rls_regress_user1;
313 SELECT * FROM rec1;    -- fail, mutual recursion
314
315 --
316 -- Mutual recursion via views
317 --
318 SET SESSION AUTHORIZATION rls_regress_user1;
319 CREATE VIEW rec1v AS SELECT * FROM rec1;
320 CREATE VIEW rec2v AS SELECT * FROM rec2;
321 SET SESSION AUTHORIZATION rls_regress_user0;
322 ALTER POLICY r1 ON rec1 USING (x = (SELECT a FROM rec2v WHERE b = y));
323 ALTER POLICY r2 ON rec2 USING (a = (SELECT x FROM rec1v WHERE y = b));
324
325 SET SESSION AUTHORIZATION rls_regress_user1;
326 SELECT * FROM rec1;    -- fail, mutual recursion via views
327
328 --
329 -- Mutual recursion via .s.b views
330 --
331 SET SESSION AUTHORIZATION rls_regress_user1;
332 -- Suppress NOTICE messages when doing a cascaded drop.
333 SET client_min_messages TO 'warning';
334
335 DROP VIEW rec1v, rec2v CASCADE;
336 RESET client_min_messages;
337
338 CREATE VIEW rec1v WITH (security_barrier) AS SELECT * FROM rec1;
339 CREATE VIEW rec2v WITH (security_barrier) AS SELECT * FROM rec2;
340 SET SESSION AUTHORIZATION rls_regress_user0;
341 CREATE POLICY r1 ON rec1 USING (x = (SELECT a FROM rec2v WHERE b = y));
342 CREATE POLICY r2 ON rec2 USING (a = (SELECT x FROM rec1v WHERE y = b));
343
344 SET SESSION AUTHORIZATION rls_regress_user1;
345 SELECT * FROM rec1;    -- fail, mutual recursion via s.b. views
346
347 --
348 -- recursive RLS and VIEWs in policy
349 --
350 SET SESSION AUTHORIZATION rls_regress_user0;
351 CREATE TABLE s1 (a int, b text);
352 INSERT INTO s1 (SELECT x, md5(x::text) FROM generate_series(-10,10) x);
353
354 CREATE TABLE s2 (x int, y text);
355 INSERT INTO s2 (SELECT x, md5(x::text) FROM generate_series(-6,6) x);
356
357 GRANT SELECT ON s1, s2 TO rls_regress_user1;
358
359 CREATE POLICY p1 ON s1 USING (a in (select x from s2 where y like '%2f%'));
360 CREATE POLICY p2 ON s2 USING (x in (select a from s1 where b like '%22%'));
361 CREATE POLICY p3 ON s1 FOR INSERT WITH CHECK (a = (SELECT a FROM s1));
362
363 ALTER TABLE s1 ENABLE ROW LEVEL SECURITY;
364 ALTER TABLE s2 ENABLE ROW LEVEL SECURITY;
365
366 SET SESSION AUTHORIZATION rls_regress_user1;
367 CREATE VIEW v2 AS SELECT * FROM s2 WHERE y like '%af%';
368 SELECT * FROM s1 WHERE f_leak(b); -- fail (infinite recursion)
369
370 INSERT INTO s1 VALUES (1, 'foo'); -- fail (infinite recursion)
371
372 SET SESSION AUTHORIZATION rls_regress_user0;
373 DROP POLICY p3 on s1;
374 ALTER POLICY p2 ON s2 USING (x % 2 = 0);
375
376 SET SESSION AUTHORIZATION rls_regress_user1;
377 SELECT * FROM s1 WHERE f_leak(b);       -- OK
378 EXPLAIN (COSTS OFF) SELECT * FROM only s1 WHERE f_leak(b);
379
380 SET SESSION AUTHORIZATION rls_regress_user0;
381 ALTER POLICY p1 ON s1 USING (a in (select x from v2)); -- using VIEW in RLS policy
382 SET SESSION AUTHORIZATION rls_regress_user1;
383 SELECT * FROM s1 WHERE f_leak(b);       -- OK
384 EXPLAIN (COSTS OFF) SELECT * FROM s1 WHERE f_leak(b);
385
386 SELECT (SELECT x FROM s1 LIMIT 1) xx, * FROM s2 WHERE y like '%28%';
387 EXPLAIN (COSTS OFF) SELECT (SELECT x FROM s1 LIMIT 1) xx, * FROM s2 WHERE y like '%28%';
388
389 SET SESSION AUTHORIZATION rls_regress_user0;
390 ALTER POLICY p2 ON s2 USING (x in (select a from s1 where b like '%d2%'));
391 SET SESSION AUTHORIZATION rls_regress_user1;
392 SELECT * FROM s1 WHERE f_leak(b);       -- fail (infinite recursion via view)
393
394 -- prepared statement with rls_regress_user0 privilege
395 PREPARE p1(int) AS SELECT * FROM t1 WHERE a <= $1;
396 EXECUTE p1(2);
397 EXPLAIN (COSTS OFF) EXECUTE p1(2);
398
399 -- superuser is allowed to bypass RLS checks
400 RESET SESSION AUTHORIZATION;
401 SET row_security TO OFF;
402 SELECT * FROM t1 WHERE f_leak(b);
403 EXPLAIN (COSTS OFF) SELECT * FROM t1 WHERE f_leak(b);
404
405 -- plan cache should be invalidated
406 EXECUTE p1(2);
407 EXPLAIN (COSTS OFF) EXECUTE p1(2);
408
409 PREPARE p2(int) AS SELECT * FROM t1 WHERE a = $1;
410 EXECUTE p2(2);
411 EXPLAIN (COSTS OFF) EXECUTE p2(2);
412
413 -- also, case when privilege switch from superuser
414 SET SESSION AUTHORIZATION rls_regress_user1;
415 SET row_security TO ON;
416 EXECUTE p2(2);
417 EXPLAIN (COSTS OFF) EXECUTE p2(2);
418
419 --
420 -- UPDATE / DELETE and Row-level security
421 --
422 SET SESSION AUTHORIZATION rls_regress_user1;
423 EXPLAIN (COSTS OFF) UPDATE t1 SET b = b || b WHERE f_leak(b);
424 UPDATE t1 SET b = b || b WHERE f_leak(b);
425
426 EXPLAIN (COSTS OFF) UPDATE only t1 SET b = b || '_updt' WHERE f_leak(b);
427 UPDATE only t1 SET b = b || '_updt' WHERE f_leak(b);
428
429 -- returning clause with system column
430 UPDATE only t1 SET b = b WHERE f_leak(b) RETURNING oid, *, t1;
431 UPDATE t1 SET b = b WHERE f_leak(b) RETURNING *;
432 UPDATE t1 SET b = b WHERE f_leak(b) RETURNING oid, *, t1;
433
434 -- updates with from clause
435 EXPLAIN (COSTS OFF) UPDATE t2 SET b=t2.b FROM t3
436 WHERE t2.a = 3 and t3.a = 2 AND f_leak(t2.b) AND f_leak(t3.b);
437
438 UPDATE t2 SET b=t2.b FROM t3
439 WHERE t2.a = 3 and t3.a = 2 AND f_leak(t2.b) AND f_leak(t3.b);
440
441 EXPLAIN (COSTS OFF) UPDATE t1 SET b=t1.b FROM t2
442 WHERE t1.a = 3 and t2.a = 3 AND f_leak(t1.b) AND f_leak(t2.b);
443
444 UPDATE t1 SET b=t1.b FROM t2
445 WHERE t1.a = 3 and t2.a = 3 AND f_leak(t1.b) AND f_leak(t2.b);
446
447 EXPLAIN (COSTS OFF) UPDATE t2 SET b=t2.b FROM t1
448 WHERE t1.a = 3 and t2.a = 3 AND f_leak(t1.b) AND f_leak(t2.b);
449
450 UPDATE t2 SET b=t2.b FROM t1
451 WHERE t1.a = 3 and t2.a = 3 AND f_leak(t1.b) AND f_leak(t2.b);
452
453 -- updates with from clause self join
454 EXPLAIN (COSTS OFF) UPDATE t2 t2_1 SET b = t2_2.b FROM t2 t2_2
455 WHERE t2_1.a = 3 AND t2_2.a = t2_1.a AND t2_2.b = t2_1.b
456 AND f_leak(t2_1.b) AND f_leak(t2_2.b) RETURNING *, t2_1, t2_2;
457
458 UPDATE t2 t2_1 SET b = t2_2.b FROM t2 t2_2
459 WHERE t2_1.a = 3 AND t2_2.a = t2_1.a AND t2_2.b = t2_1.b
460 AND f_leak(t2_1.b) AND f_leak(t2_2.b) RETURNING *, t2_1, t2_2;
461
462 EXPLAIN (COSTS OFF) UPDATE t1 t1_1 SET b = t1_2.b FROM t1 t1_2
463 WHERE t1_1.a = 4 AND t1_2.a = t1_1.a AND t1_2.b = t1_1.b
464 AND f_leak(t1_1.b) AND f_leak(t1_2.b) RETURNING *, t1_1, t1_2;
465
466 UPDATE t1 t1_1 SET b = t1_2.b FROM t1 t1_2
467 WHERE t1_1.a = 4 AND t1_2.a = t1_1.a AND t1_2.b = t1_1.b
468 AND f_leak(t1_1.b) AND f_leak(t1_2.b) RETURNING *, t1_1, t1_2;
469
470 RESET SESSION AUTHORIZATION;
471 SET row_security TO OFF;
472 SELECT * FROM t1 ORDER BY a,b;
473
474 SET SESSION AUTHORIZATION rls_regress_user1;
475 SET row_security TO ON;
476 EXPLAIN (COSTS OFF) DELETE FROM only t1 WHERE f_leak(b);
477 EXPLAIN (COSTS OFF) DELETE FROM t1 WHERE f_leak(b);
478
479 DELETE FROM only t1 WHERE f_leak(b) RETURNING oid, *, t1;
480 DELETE FROM t1 WHERE f_leak(b) RETURNING oid, *, t1;
481
482 --
483 -- S.b. view on top of Row-level security
484 --
485 SET SESSION AUTHORIZATION rls_regress_user0;
486 CREATE TABLE b1 (a int, b text);
487 INSERT INTO b1 (SELECT x, md5(x::text) FROM generate_series(-10,10) x);
488
489 CREATE POLICY p1 ON b1 USING (a % 2 = 0);
490 ALTER TABLE b1 ENABLE ROW LEVEL SECURITY;
491 GRANT ALL ON b1 TO rls_regress_user1;
492
493 SET SESSION AUTHORIZATION rls_regress_user1;
494 CREATE VIEW bv1 WITH (security_barrier) AS SELECT * FROM b1 WHERE a > 0 WITH CHECK OPTION;
495 GRANT ALL ON bv1 TO rls_regress_user2;
496
497 SET SESSION AUTHORIZATION rls_regress_user2;
498
499 EXPLAIN (COSTS OFF) SELECT * FROM bv1 WHERE f_leak(b);
500 SELECT * FROM bv1 WHERE f_leak(b);
501
502 INSERT INTO bv1 VALUES (-1, 'xxx'); -- should fail view WCO
503 INSERT INTO bv1 VALUES (11, 'xxx'); -- should fail RLS check
504 INSERT INTO bv1 VALUES (12, 'xxx'); -- ok
505
506 EXPLAIN (COSTS OFF) UPDATE bv1 SET b = 'yyy' WHERE a = 4 AND f_leak(b);
507 UPDATE bv1 SET b = 'yyy' WHERE a = 4 AND f_leak(b);
508
509 EXPLAIN (COSTS OFF) DELETE FROM bv1 WHERE a = 6 AND f_leak(b);
510 DELETE FROM bv1 WHERE a = 6 AND f_leak(b);
511
512 SET SESSION AUTHORIZATION rls_regress_user0;
513 SELECT * FROM b1;
514 --
515 -- INSERT ... ON CONFLICT DO UPDATE and Row-level security
516 --
517
518 SET SESSION AUTHORIZATION rls_regress_user0;
519 DROP POLICY p1 ON document;
520
521 CREATE POLICY p1 ON document FOR SELECT USING (true);
522 CREATE POLICY p2 ON document FOR INSERT WITH CHECK (dauthor = current_user);
523 CREATE POLICY p3 ON document FOR UPDATE
524   USING (cid = (SELECT cid from category WHERE cname = 'novel'))
525   WITH CHECK (dauthor = current_user);
526
527 SET SESSION AUTHORIZATION rls_regress_user1;
528
529 -- Exists...
530 SELECT * FROM document WHERE did = 2;
531
532 -- ...so violates actual WITH CHECK OPTION within UPDATE (not INSERT, since
533 -- alternative UPDATE path happens to be taken):
534 INSERT INTO document VALUES (2, (SELECT cid from category WHERE cname = 'novel'), 1, 'rls_regress_user2', 'my first novel')
535     ON CONFLICT (did) DO UPDATE SET dtitle = EXCLUDED.dtitle, dauthor = EXCLUDED.dauthor;
536
537 -- Violates USING qual for UPDATE policy p3.
538 --
539 -- UPDATE path is taken, but UPDATE fails purely because *existing* row to be
540 -- updated is not a "novel"/cid 11 (row is not leaked, even though we have
541 -- SELECT privileges sufficient to see the row in this instance):
542 INSERT INTO document VALUES (33, 22, 1, 'rls_regress_user1', 'okay science fiction'); -- preparation for next statement
543 INSERT INTO document VALUES (33, (SELECT cid from category WHERE cname = 'novel'), 1, 'rls_regress_user1', 'Some novel, replaces sci-fi') -- takes UPDATE path
544     ON CONFLICT (did) DO UPDATE SET dtitle = EXCLUDED.dtitle;
545 -- Fine (we UPDATE, since INSERT WCOs and UPDATE security barrier quals + WCOs
546 -- not violated):
547 INSERT INTO document VALUES (2, (SELECT cid from category WHERE cname = 'novel'), 1, 'rls_regress_user1', 'my first novel')
548     ON CONFLICT (did) DO UPDATE SET dtitle = EXCLUDED.dtitle RETURNING *;
549 -- Fine (we INSERT, so "cid = 33" ("technology") isn't evaluated):
550 INSERT INTO document VALUES (78, (SELECT cid from category WHERE cname = 'novel'), 1, 'rls_regress_user1', 'some technology novel')
551     ON CONFLICT (did) DO UPDATE SET dtitle = EXCLUDED.dtitle, cid = 33 RETURNING *;
552 -- Fine (same query, but we UPDATE, so "cid = 33", ("technology") is not the
553 -- case in respect of *existing* tuple):
554 INSERT INTO document VALUES (78, (SELECT cid from category WHERE cname = 'novel'), 1, 'rls_regress_user1', 'some technology novel')
555     ON CONFLICT (did) DO UPDATE SET dtitle = EXCLUDED.dtitle, cid = 33 RETURNING *;
556 -- Same query a third time, but now fails due to existing tuple finally not
557 -- passing quals:
558 INSERT INTO document VALUES (78, (SELECT cid from category WHERE cname = 'novel'), 1, 'rls_regress_user1', 'some technology novel')
559     ON CONFLICT (did) DO UPDATE SET dtitle = EXCLUDED.dtitle, cid = 33 RETURNING *;
560 -- Don't fail just because INSERT doesn't satisfy WITH CHECK option that
561 -- originated as a barrier/USING() qual from the UPDATE.  Note that the UPDATE
562 -- path *isn't* taken, and so UPDATE-related policy does not apply:
563 INSERT INTO document VALUES (79, (SELECT cid from category WHERE cname = 'technology'), 1, 'rls_regress_user1', 'technology book, can only insert')
564     ON CONFLICT (did) DO UPDATE SET dtitle = EXCLUDED.dtitle RETURNING *;
565 -- But this time, the same statement fails, because the UPDATE path is taken,
566 -- and updating the row just inserted falls afoul of security barrier qual
567 -- (enforced as WCO) -- what we might have updated target tuple to is
568 -- irrelevant, in fact.
569 INSERT INTO document VALUES (79, (SELECT cid from category WHERE cname = 'technology'), 1, 'rls_regress_user1', 'technology book, can only insert')
570     ON CONFLICT (did) DO UPDATE SET dtitle = EXCLUDED.dtitle RETURNING *;
571
572 -- Test default USING qual enforced as WCO
573 SET SESSION AUTHORIZATION rls_regress_user0;
574 DROP POLICY p1 ON document;
575 DROP POLICY p2 ON document;
576 DROP POLICY p3 ON document;
577
578 CREATE POLICY p3_with_default ON document FOR UPDATE
579   USING (cid = (SELECT cid from category WHERE cname = 'novel'));
580
581 SET SESSION AUTHORIZATION rls_regress_user1;
582 -- Just because WCO-style enforcement of USING quals occurs with
583 -- existing/target tuple does not mean that the implementation can be allowed
584 -- to fail to also enforce this qual against the final tuple appended to
585 -- relation (since in the absence of an explicit WCO, this is also interpreted
586 -- as an UPDATE/ALL WCO in general).
587 --
588 -- UPDATE path is taken here (fails due to existing tuple).  Note that this is
589 -- not reported as a "USING expression", because it's an RLS UPDATE check that originated as
590 -- a USING qual for the purposes of RLS in general, as opposed to an explicit
591 -- USING qual that is ordinarily a security barrier.  We leave it up to the
592 -- UPDATE to make this fail:
593 INSERT INTO document VALUES (79, (SELECT cid from category WHERE cname = 'technology'), 1, 'rls_regress_user1', 'technology book, can only insert')
594     ON CONFLICT (did) DO UPDATE SET dtitle = EXCLUDED.dtitle RETURNING *;
595
596 -- UPDATE path is taken here.  Existing tuple passes, since it's cid
597 -- corresponds to "novel", but default USING qual is enforced against
598 -- post-UPDATE tuple too (as always when updating with a policy that lacks an
599 -- explicit WCO), and so this fails:
600 INSERT INTO document VALUES (2, (SELECT cid from category WHERE cname = 'technology'), 1, 'rls_regress_user1', 'my first novel')
601     ON CONFLICT (did) DO UPDATE SET cid = EXCLUDED.cid, dtitle = EXCLUDED.dtitle RETURNING *;
602
603 SET SESSION AUTHORIZATION rls_regress_user0;
604 DROP POLICY p3_with_default ON document;
605
606 --
607 -- Test ALL policies with ON CONFLICT DO UPDATE (much the same as existing UPDATE
608 -- tests)
609 --
610 CREATE POLICY p3_with_all ON document FOR ALL
611   USING (cid = (SELECT cid from category WHERE cname = 'novel'))
612   WITH CHECK (dauthor = current_user);
613
614 SET SESSION AUTHORIZATION rls_regress_user1;
615
616 -- Fails, since ALL WCO is enforced in insert path:
617 INSERT INTO document VALUES (80, (SELECT cid from category WHERE cname = 'novel'), 1, 'rls_regress_user2', 'my first novel')
618     ON CONFLICT (did) DO UPDATE SET dtitle = EXCLUDED.dtitle, cid = 33;
619 -- Fails, since ALL policy USING qual is enforced (existing, target tuple is in
620 -- violation, since it has the "manga" cid):
621 INSERT INTO document VALUES (4, (SELECT cid from category WHERE cname = 'novel'), 1, 'rls_regress_user1', 'my first novel')
622     ON CONFLICT (did) DO UPDATE SET dtitle = EXCLUDED.dtitle;
623 -- Fails, since ALL WCO are enforced:
624 INSERT INTO document VALUES (1, (SELECT cid from category WHERE cname = 'novel'), 1, 'rls_regress_user1', 'my first novel')
625     ON CONFLICT (did) DO UPDATE SET dauthor = 'rls_regress_user2';
626
627 --
628 -- ROLE/GROUP
629 --
630 SET SESSION AUTHORIZATION rls_regress_user0;
631 CREATE TABLE z1 (a int, b text);
632 CREATE TABLE z2 (a int, b text);
633
634 GRANT SELECT ON z1,z2 TO rls_regress_group1, rls_regress_group2,
635     rls_regress_user1, rls_regress_user2;
636
637 INSERT INTO z1 VALUES
638     (1, 'aaa'),
639     (2, 'bbb'),
640     (3, 'ccc'),
641     (4, 'ddd');
642
643 CREATE POLICY p1 ON z1 TO rls_regress_group1 USING (a % 2 = 0);
644 CREATE POLICY p2 ON z1 TO rls_regress_group2 USING (a % 2 = 1);
645
646 ALTER TABLE z1 ENABLE ROW LEVEL SECURITY;
647
648 SET SESSION AUTHORIZATION rls_regress_user1;
649 SELECT * FROM z1 WHERE f_leak(b);
650 EXPLAIN (COSTS OFF) SELECT * FROM z1 WHERE f_leak(b);
651
652 PREPARE plancache_test AS SELECT * FROM z1 WHERE f_leak(b);
653 EXPLAIN (COSTS OFF) EXECUTE plancache_test;
654
655 PREPARE plancache_test2 AS WITH q AS (SELECT * FROM z1 WHERE f_leak(b)) SELECT * FROM q,z2;
656 EXPLAIN (COSTS OFF) EXECUTE plancache_test2;
657
658 PREPARE plancache_test3 AS WITH q AS (SELECT * FROM z2) SELECT * FROM q,z1 WHERE f_leak(z1.b);
659 EXPLAIN (COSTS OFF) EXECUTE plancache_test3;
660
661 SET ROLE rls_regress_group1;
662 SELECT * FROM z1 WHERE f_leak(b);
663 EXPLAIN (COSTS OFF) SELECT * FROM z1 WHERE f_leak(b);
664
665 EXPLAIN (COSTS OFF) EXECUTE plancache_test;
666 EXPLAIN (COSTS OFF) EXECUTE plancache_test2;
667 EXPLAIN (COSTS OFF) EXECUTE plancache_test3;
668
669 SET SESSION AUTHORIZATION rls_regress_user2;
670 SELECT * FROM z1 WHERE f_leak(b);
671 EXPLAIN (COSTS OFF) SELECT * FROM z1 WHERE f_leak(b);
672
673 EXPLAIN (COSTS OFF) EXECUTE plancache_test;
674 EXPLAIN (COSTS OFF) EXECUTE plancache_test2;
675 EXPLAIN (COSTS OFF) EXECUTE plancache_test3;
676
677 SET ROLE rls_regress_group2;
678 SELECT * FROM z1 WHERE f_leak(b);
679 EXPLAIN (COSTS OFF) SELECT * FROM z1 WHERE f_leak(b);
680
681 EXPLAIN (COSTS OFF) EXECUTE plancache_test;
682 EXPLAIN (COSTS OFF) EXECUTE plancache_test2;
683 EXPLAIN (COSTS OFF) EXECUTE plancache_test3;
684
685 --
686 -- Views should follow policy for view owner.
687 --
688 -- View and Table owner are the same.
689 SET SESSION AUTHORIZATION rls_regress_user0;
690 CREATE VIEW rls_view AS SELECT * FROM z1 WHERE f_leak(b);
691 GRANT SELECT ON rls_view TO rls_regress_user1;
692
693 -- Query as role that is not owner of view or table.  Should return all records.
694 SET SESSION AUTHORIZATION rls_regress_user1;
695 SELECT * FROM rls_view;
696 EXPLAIN (COSTS OFF) SELECT * FROM rls_view;
697
698 -- Query as view/table owner.  Should return all records.
699 SET SESSION AUTHORIZATION rls_regress_user0;
700 SELECT * FROM rls_view;
701 EXPLAIN (COSTS OFF) SELECT * FROM rls_view;
702 DROP VIEW rls_view;
703
704 -- View and Table owners are different.
705 SET SESSION AUTHORIZATION rls_regress_user1;
706 CREATE VIEW rls_view AS SELECT * FROM z1 WHERE f_leak(b);
707 GRANT SELECT ON rls_view TO rls_regress_user0;
708
709 -- Query as role that is not owner of view but is owner of table.
710 -- Should return records based on view owner policies.
711 SET SESSION AUTHORIZATION rls_regress_user0;
712 SELECT * FROM rls_view;
713 EXPLAIN (COSTS OFF) SELECT * FROM rls_view;
714
715 -- Query as role that is not owner of table but is owner of view.
716 -- Should return records based on view owner policies.
717 SET SESSION AUTHORIZATION rls_regress_user1;
718 SELECT * FROM rls_view;
719 EXPLAIN (COSTS OFF) SELECT * FROM rls_view;
720
721 -- Query as role that is not the owner of the table or view without permissions.
722 SET SESSION AUTHORIZATION rls_regress_user2;
723 SELECT * FROM rls_view; --fail - permission denied.
724 EXPLAIN (COSTS OFF) SELECT * FROM rls_view; --fail - permission denied.
725
726 -- Query as role that is not the owner of the table or view with permissions.
727 SET SESSION AUTHORIZATION rls_regress_user1;
728 GRANT SELECT ON rls_view TO rls_regress_user2;
729 SELECT * FROM rls_view;
730 EXPLAIN (COSTS OFF) SELECT * FROM rls_view;
731
732 SET SESSION AUTHORIZATION rls_regress_user1;
733 DROP VIEW rls_view;
734
735 --
736 -- Command specific
737 --
738 SET SESSION AUTHORIZATION rls_regress_user0;
739
740 CREATE TABLE x1 (a int, b text, c text);
741 GRANT ALL ON x1 TO PUBLIC;
742
743 INSERT INTO x1 VALUES
744     (1, 'abc', 'rls_regress_user1'),
745     (2, 'bcd', 'rls_regress_user1'),
746     (3, 'cde', 'rls_regress_user2'),
747     (4, 'def', 'rls_regress_user2'),
748     (5, 'efg', 'rls_regress_user1'),
749     (6, 'fgh', 'rls_regress_user1'),
750     (7, 'fgh', 'rls_regress_user2'),
751     (8, 'fgh', 'rls_regress_user2');
752
753 CREATE POLICY p0 ON x1 FOR ALL USING (c = current_user);
754 CREATE POLICY p1 ON x1 FOR SELECT USING (a % 2 = 0);
755 CREATE POLICY p2 ON x1 FOR INSERT WITH CHECK (a % 2 = 1);
756 CREATE POLICY p3 ON x1 FOR UPDATE USING (a % 2 = 0);
757 CREATE POLICY p4 ON x1 FOR DELETE USING (a < 8);
758
759 ALTER TABLE x1 ENABLE ROW LEVEL SECURITY;
760
761 SET SESSION AUTHORIZATION rls_regress_user1;
762 SELECT * FROM x1 WHERE f_leak(b) ORDER BY a ASC;
763 UPDATE x1 SET b = b || '_updt' WHERE f_leak(b) RETURNING *;
764
765 SET SESSION AUTHORIZATION rls_regress_user2;
766 SELECT * FROM x1 WHERE f_leak(b) ORDER BY a ASC;
767 UPDATE x1 SET b = b || '_updt' WHERE f_leak(b) RETURNING *;
768 DELETE FROM x1 WHERE f_leak(b) RETURNING *;
769
770 --
771 -- Duplicate Policy Names
772 --
773 SET SESSION AUTHORIZATION rls_regress_user0;
774 CREATE TABLE y1 (a int, b text);
775 CREATE TABLE y2 (a int, b text);
776
777 GRANT ALL ON y1, y2 TO rls_regress_user1;
778
779 CREATE POLICY p1 ON y1 FOR ALL USING (a % 2 = 0);
780 CREATE POLICY p2 ON y1 FOR SELECT USING (a > 2);
781 CREATE POLICY p1 ON y1 FOR SELECT USING (a % 2 = 1);  --fail
782 CREATE POLICY p1 ON y2 FOR ALL USING (a % 2 = 0);  --OK
783
784 ALTER TABLE y1 ENABLE ROW LEVEL SECURITY;
785 ALTER TABLE y2 ENABLE ROW LEVEL SECURITY;
786
787 --
788 -- Expression structure with SBV
789 --
790 -- Create view as table owner.  RLS should NOT be applied.
791 SET SESSION AUTHORIZATION rls_regress_user0;
792 CREATE VIEW rls_sbv WITH (security_barrier) AS
793     SELECT * FROM y1 WHERE f_leak(b);
794 EXPLAIN (COSTS OFF) SELECT * FROM rls_sbv WHERE (a = 1);
795 DROP VIEW rls_sbv;
796
797 -- Create view as role that does not own table.  RLS should be applied.
798 SET SESSION AUTHORIZATION rls_regress_user1;
799 CREATE VIEW rls_sbv WITH (security_barrier) AS
800     SELECT * FROM y1 WHERE f_leak(b);
801 EXPLAIN (COSTS OFF) SELECT * FROM rls_sbv WHERE (a = 1);
802 DROP VIEW rls_sbv;
803
804 --
805 -- Expression structure
806 --
807 SET SESSION AUTHORIZATION rls_regress_user0;
808 INSERT INTO y2 (SELECT x, md5(x::text) FROM generate_series(0,20) x);
809 CREATE POLICY p2 ON y2 USING (a % 3 = 0);
810 CREATE POLICY p3 ON y2 USING (a % 4 = 0);
811
812 SET SESSION AUTHORIZATION rls_regress_user1;
813 SELECT * FROM y2 WHERE f_leak(b);
814 EXPLAIN (COSTS OFF) SELECT * FROM y2 WHERE f_leak(b);
815
816 --
817 -- Qual push-down of leaky functions, when not referring to table
818 --
819 SELECT * FROM y2 WHERE f_leak('abc');
820 EXPLAIN (COSTS OFF) SELECT * FROM y2 WHERE f_leak('abc');
821
822 CREATE TABLE test_qual_pushdown (
823     abc text
824 );
825
826 INSERT INTO test_qual_pushdown VALUES ('abc'),('def');
827
828 SELECT * FROM y2 JOIN test_qual_pushdown ON (b = abc) WHERE f_leak(abc);
829 EXPLAIN (COSTS OFF) SELECT * FROM y2 JOIN test_qual_pushdown ON (b = abc) WHERE f_leak(abc);
830
831 SELECT * FROM y2 JOIN test_qual_pushdown ON (b = abc) WHERE f_leak(b);
832 EXPLAIN (COSTS OFF) SELECT * FROM y2 JOIN test_qual_pushdown ON (b = abc) WHERE f_leak(b);
833
834 DROP TABLE test_qual_pushdown;
835
836 --
837 -- Plancache invalidate on user change.
838 --
839 RESET SESSION AUTHORIZATION;
840 -- Suppress NOTICE messages when doing a cascaded drop.
841 SET client_min_messages TO 'warning';
842
843 DROP TABLE t1 CASCADE;
844 RESET client_min_messages;
845
846 CREATE TABLE t1 (a integer);
847
848 GRANT SELECT ON t1 TO rls_regress_user1, rls_regress_user2;
849
850 CREATE POLICY p1 ON t1 TO rls_regress_user1 USING ((a % 2) = 0);
851 CREATE POLICY p2 ON t1 TO rls_regress_user2 USING ((a % 4) = 0);
852
853 ALTER TABLE t1 ENABLE ROW LEVEL SECURITY;
854
855 -- Prepare as rls_regress_user1
856 SET ROLE rls_regress_user1;
857 PREPARE role_inval AS SELECT * FROM t1;
858 -- Check plan
859 EXPLAIN (COSTS OFF) EXECUTE role_inval;
860
861 -- Change to rls_regress_user2
862 SET ROLE rls_regress_user2;
863 -- Check plan- should be different
864 EXPLAIN (COSTS OFF) EXECUTE role_inval;
865
866 -- Change back to rls_regress_user1
867 SET ROLE rls_regress_user1;
868 -- Check plan- should be back to original
869 EXPLAIN (COSTS OFF) EXECUTE role_inval;
870
871 --
872 -- CTE and RLS
873 --
874 RESET SESSION AUTHORIZATION;
875 DROP TABLE t1 CASCADE;
876 CREATE TABLE t1 (a integer, b text);
877 CREATE POLICY p1 ON t1 USING (a % 2 = 0);
878
879 ALTER TABLE t1 ENABLE ROW LEVEL SECURITY;
880
881 GRANT ALL ON t1 TO rls_regress_user1;
882
883 INSERT INTO t1 (SELECT x, md5(x::text) FROM generate_series(0,20) x);
884
885 SET SESSION AUTHORIZATION rls_regress_user1;
886
887 WITH cte1 AS (SELECT * FROM t1 WHERE f_leak(b)) SELECT * FROM cte1;
888 EXPLAIN (COSTS OFF) WITH cte1 AS (SELECT * FROM t1 WHERE f_leak(b)) SELECT * FROM cte1;
889
890 WITH cte1 AS (UPDATE t1 SET a = a + 1 RETURNING *) SELECT * FROM cte1; --fail
891 WITH cte1 AS (UPDATE t1 SET a = a RETURNING *) SELECT * FROM cte1; --ok
892
893 WITH cte1 AS (INSERT INTO t1 VALUES (21, 'Fail') RETURNING *) SELECT * FROM cte1; --fail
894 WITH cte1 AS (INSERT INTO t1 VALUES (20, 'Success') RETURNING *) SELECT * FROM cte1; --ok
895
896 --
897 -- Rename Policy
898 --
899 RESET SESSION AUTHORIZATION;
900 ALTER POLICY p1 ON t1 RENAME TO p1; --fail
901
902 SELECT polname, relname
903     FROM pg_policy pol
904     JOIN pg_class pc ON (pc.oid = pol.polrelid)
905     WHERE relname = 't1';
906
907 ALTER POLICY p1 ON t1 RENAME TO p2; --ok
908
909 SELECT polname, relname
910     FROM pg_policy pol
911     JOIN pg_class pc ON (pc.oid = pol.polrelid)
912     WHERE relname = 't1';
913
914 --
915 -- Check INSERT SELECT
916 --
917 SET SESSION AUTHORIZATION rls_regress_user1;
918 CREATE TABLE t2 (a integer, b text);
919 INSERT INTO t2 (SELECT * FROM t1);
920 EXPLAIN (COSTS OFF) INSERT INTO t2 (SELECT * FROM t1);
921 SELECT * FROM t2;
922 EXPLAIN (COSTS OFF) SELECT * FROM t2;
923 CREATE TABLE t3 AS SELECT * FROM t1;
924 SELECT * FROM t3;
925 SELECT * INTO t4 FROM t1;
926 SELECT * FROM t4;
927
928 --
929 -- RLS with JOIN
930 --
931 SET SESSION AUTHORIZATION rls_regress_user0;
932 CREATE TABLE blog (id integer, author text, post text);
933 CREATE TABLE comment (blog_id integer, message text);
934
935 GRANT ALL ON blog, comment TO rls_regress_user1;
936
937 CREATE POLICY blog_1 ON blog USING (id % 2 = 0);
938
939 ALTER TABLE blog ENABLE ROW LEVEL SECURITY;
940
941 INSERT INTO blog VALUES
942     (1, 'alice', 'blog #1'),
943     (2, 'bob', 'blog #1'),
944     (3, 'alice', 'blog #2'),
945     (4, 'alice', 'blog #3'),
946     (5, 'john', 'blog #1');
947
948 INSERT INTO comment VALUES
949     (1, 'cool blog'),
950     (1, 'fun blog'),
951     (3, 'crazy blog'),
952     (5, 'what?'),
953     (4, 'insane!'),
954     (2, 'who did it?');
955
956 SET SESSION AUTHORIZATION rls_regress_user1;
957 -- Check RLS JOIN with Non-RLS.
958 SELECT id, author, message FROM blog JOIN comment ON id = blog_id;
959 -- Check Non-RLS JOIN with RLS.
960 SELECT id, author, message FROM comment JOIN blog ON id = blog_id;
961
962 SET SESSION AUTHORIZATION rls_regress_user0;
963 CREATE POLICY comment_1 ON comment USING (blog_id < 4);
964
965 ALTER TABLE comment ENABLE ROW LEVEL SECURITY;
966
967 SET SESSION AUTHORIZATION rls_regress_user1;
968 -- Check RLS JOIN RLS
969 SELECT id, author, message FROM blog JOIN comment ON id = blog_id;
970 SELECT id, author, message FROM comment JOIN blog ON id = blog_id;
971
972 SET SESSION AUTHORIZATION rls_regress_user0;
973 DROP TABLE blog, comment;
974
975 --
976 -- Default Deny Policy
977 --
978 RESET SESSION AUTHORIZATION;
979 DROP POLICY p2 ON t1;
980 ALTER TABLE t1 OWNER TO rls_regress_user0;
981
982 -- Check that default deny does not apply to superuser.
983 RESET SESSION AUTHORIZATION;
984 SELECT * FROM t1;
985 EXPLAIN (COSTS OFF) SELECT * FROM t1;
986
987 -- Check that default deny does not apply to table owner.
988 SET SESSION AUTHORIZATION rls_regress_user0;
989 SELECT * FROM t1;
990 EXPLAIN (COSTS OFF) SELECT * FROM t1;
991
992 -- Check that default deny applies to non-owner/non-superuser when RLS on.
993 SET SESSION AUTHORIZATION rls_regress_user1;
994 SET row_security TO ON;
995 SELECT * FROM t1;
996 EXPLAIN (COSTS OFF) SELECT * FROM t1;
997 SET SESSION AUTHORIZATION rls_regress_user1;
998 SELECT * FROM t1;
999 EXPLAIN (COSTS OFF) SELECT * FROM t1;
1000
1001 --
1002 -- COPY TO/FROM
1003 --
1004
1005 RESET SESSION AUTHORIZATION;
1006 DROP TABLE copy_t CASCADE;
1007 CREATE TABLE copy_t (a integer, b text);
1008 CREATE POLICY p1 ON copy_t USING (a % 2 = 0);
1009
1010 ALTER TABLE copy_t ENABLE ROW LEVEL SECURITY;
1011
1012 GRANT ALL ON copy_t TO rls_regress_user1, rls_regress_exempt_user;
1013
1014 INSERT INTO copy_t (SELECT x, md5(x::text) FROM generate_series(0,10) x);
1015
1016 -- Check COPY TO as Superuser/owner.
1017 RESET SESSION AUTHORIZATION;
1018 SET row_security TO OFF;
1019 COPY (SELECT * FROM copy_t ORDER BY a ASC) TO STDOUT WITH DELIMITER ',';
1020 SET row_security TO ON;
1021 COPY (SELECT * FROM copy_t ORDER BY a ASC) TO STDOUT WITH DELIMITER ',';
1022
1023 -- Check COPY TO as user with permissions.
1024 SET SESSION AUTHORIZATION rls_regress_user1;
1025 SET row_security TO OFF;
1026 COPY (SELECT * FROM copy_t ORDER BY a ASC) TO STDOUT WITH DELIMITER ','; --fail - would be affected by RLS
1027 SET row_security TO ON;
1028 COPY (SELECT * FROM copy_t ORDER BY a ASC) TO STDOUT WITH DELIMITER ','; --ok
1029
1030 -- Check COPY TO as user with permissions and BYPASSRLS
1031 SET SESSION AUTHORIZATION rls_regress_exempt_user;
1032 SET row_security TO OFF;
1033 COPY (SELECT * FROM copy_t ORDER BY a ASC) TO STDOUT WITH DELIMITER ','; --ok
1034 SET row_security TO ON;
1035 COPY (SELECT * FROM copy_t ORDER BY a ASC) TO STDOUT WITH DELIMITER ','; --ok
1036
1037 -- Check COPY TO as user without permissions. SET row_security TO OFF;
1038 SET SESSION AUTHORIZATION rls_regress_user2;
1039 SET row_security TO OFF;
1040 COPY (SELECT * FROM copy_t ORDER BY a ASC) TO STDOUT WITH DELIMITER ','; --fail - would be affected by RLS
1041 SET row_security TO ON;
1042 COPY (SELECT * FROM copy_t ORDER BY a ASC) TO STDOUT WITH DELIMITER ','; --fail - permission denied
1043
1044 -- Check COPY relation TO; keep it just one row to avoid reordering issues
1045 RESET SESSION AUTHORIZATION;
1046 SET row_security TO ON;
1047 CREATE TABLE copy_rel_to (a integer, b text);
1048 CREATE POLICY p1 ON copy_rel_to USING (a % 2 = 0);
1049
1050 ALTER TABLE copy_rel_to ENABLE ROW LEVEL SECURITY;
1051
1052 GRANT ALL ON copy_rel_to TO rls_regress_user1, rls_regress_exempt_user;
1053
1054 INSERT INTO copy_rel_to VALUES (1, md5('1'));
1055
1056 -- Check COPY TO as Superuser/owner.
1057 RESET SESSION AUTHORIZATION;
1058 SET row_security TO OFF;
1059 COPY copy_rel_to TO STDOUT WITH DELIMITER ',';
1060 SET row_security TO ON;
1061 COPY copy_rel_to TO STDOUT WITH DELIMITER ',';
1062
1063 -- Check COPY TO as user with permissions.
1064 SET SESSION AUTHORIZATION rls_regress_user1;
1065 SET row_security TO OFF;
1066 COPY copy_rel_to TO STDOUT WITH DELIMITER ','; --fail - would be affected by RLS
1067 SET row_security TO ON;
1068 COPY copy_rel_to TO STDOUT WITH DELIMITER ','; --ok
1069
1070 -- Check COPY TO as user with permissions and BYPASSRLS
1071 SET SESSION AUTHORIZATION rls_regress_exempt_user;
1072 SET row_security TO OFF;
1073 COPY copy_rel_to TO STDOUT WITH DELIMITER ','; --ok
1074 SET row_security TO ON;
1075 COPY copy_rel_to TO STDOUT WITH DELIMITER ','; --ok
1076
1077 -- Check COPY TO as user without permissions. SET row_security TO OFF;
1078 SET SESSION AUTHORIZATION rls_regress_user2;
1079 SET row_security TO OFF;
1080 COPY copy_rel_to TO STDOUT WITH DELIMITER ','; --fail - permission denied
1081 SET row_security TO ON;
1082 COPY copy_rel_to TO STDOUT WITH DELIMITER ','; --fail - permission denied
1083
1084 -- Check COPY FROM as Superuser/owner.
1085 RESET SESSION AUTHORIZATION;
1086 SET row_security TO OFF;
1087 COPY copy_t FROM STDIN; --ok
1088 1       abc
1089 2       bcd
1090 3       cde
1091 4       def
1092 \.
1093 SET row_security TO ON;
1094 COPY copy_t FROM STDIN; --ok
1095 1       abc
1096 2       bcd
1097 3       cde
1098 4       def
1099 \.
1100
1101 -- Check COPY FROM as user with permissions.
1102 SET SESSION AUTHORIZATION rls_regress_user1;
1103 SET row_security TO OFF;
1104 COPY copy_t FROM STDIN; --fail - would be affected by RLS.
1105 SET row_security TO ON;
1106 COPY copy_t FROM STDIN; --fail - COPY FROM not supported by RLS.
1107
1108 -- Check COPY FROM as user with permissions and BYPASSRLS
1109 SET SESSION AUTHORIZATION rls_regress_exempt_user;
1110 SET row_security TO ON;
1111 COPY copy_t FROM STDIN; --ok
1112 1       abc
1113 2       bcd
1114 3       cde
1115 4       def
1116 \.
1117
1118 -- Check COPY FROM as user without permissions.
1119 SET SESSION AUTHORIZATION rls_regress_user2;
1120 SET row_security TO OFF;
1121 COPY copy_t FROM STDIN; --fail - permission denied.
1122 SET row_security TO ON;
1123 COPY copy_t FROM STDIN; --fail - permission denied.
1124
1125 RESET SESSION AUTHORIZATION;
1126 DROP TABLE copy_t;
1127 DROP TABLE copy_rel_to CASCADE;
1128
1129 -- Check WHERE CURRENT OF
1130 SET SESSION AUTHORIZATION rls_regress_user0;
1131
1132 CREATE TABLE current_check (currentid int, payload text, rlsuser text);
1133 GRANT ALL ON current_check TO PUBLIC;
1134
1135 INSERT INTO current_check VALUES
1136     (1, 'abc', 'rls_regress_user1'),
1137     (2, 'bcd', 'rls_regress_user1'),
1138     (3, 'cde', 'rls_regress_user1'),
1139     (4, 'def', 'rls_regress_user1');
1140
1141 CREATE POLICY p1 ON current_check FOR SELECT USING (currentid % 2 = 0);
1142 CREATE POLICY p2 ON current_check FOR DELETE USING (currentid = 4 AND rlsuser = current_user);
1143 CREATE POLICY p3 ON current_check FOR UPDATE USING (currentid = 4) WITH CHECK (rlsuser = current_user);
1144
1145 ALTER TABLE current_check ENABLE ROW LEVEL SECURITY;
1146
1147 SET SESSION AUTHORIZATION rls_regress_user1;
1148
1149 -- Can SELECT even rows
1150 SELECT * FROM current_check;
1151
1152 -- Cannot UPDATE row 2
1153 UPDATE current_check SET payload = payload || '_new' WHERE currentid = 2 RETURNING *;
1154
1155 BEGIN;
1156
1157 DECLARE current_check_cursor SCROLL CURSOR FOR SELECT * FROM current_check;
1158 -- Returns rows that can be seen according to SELECT policy, like plain SELECT
1159 -- above (even rows)
1160 FETCH ABSOLUTE 1 FROM current_check_cursor;
1161 -- Still cannot UPDATE row 2 through cursor
1162 UPDATE current_check SET payload = payload || '_new' WHERE CURRENT OF current_check_cursor RETURNING *;
1163 -- Can update row 4 through cursor, which is the next visible row
1164 FETCH RELATIVE 1 FROM current_check_cursor;
1165 UPDATE current_check SET payload = payload || '_new' WHERE CURRENT OF current_check_cursor RETURNING *;
1166 SELECT * FROM current_check;
1167 -- Plan should be a subquery TID scan
1168 EXPLAIN (COSTS OFF) UPDATE current_check SET payload = payload WHERE CURRENT OF current_check_cursor;
1169 -- Similarly can only delete row 4
1170 FETCH ABSOLUTE 1 FROM current_check_cursor;
1171 DELETE FROM current_check WHERE CURRENT OF current_check_cursor RETURNING *;
1172 FETCH RELATIVE 1 FROM current_check_cursor;
1173 DELETE FROM current_check WHERE CURRENT OF current_check_cursor RETURNING *;
1174 SELECT * FROM current_check;
1175
1176 COMMIT;
1177
1178 --
1179 -- check pg_stats view filtering
1180 --
1181 SET row_security TO ON;
1182 SET SESSION AUTHORIZATION rls_regress_user0;
1183 ANALYZE current_check;
1184 -- Stats visible
1185 SELECT row_security_active('current_check');
1186 SELECT attname, most_common_vals FROM pg_stats
1187   WHERE tablename = 'current_check'
1188   ORDER BY 1;
1189
1190 SET SESSION AUTHORIZATION rls_regress_user1;
1191 -- Stats not visible
1192 SELECT row_security_active('current_check');
1193 SELECT attname, most_common_vals FROM pg_stats
1194   WHERE tablename = 'current_check'
1195   ORDER BY 1;
1196
1197 --
1198 -- Collation support
1199 --
1200 BEGIN;
1201 CREATE TABLE coll_t (c) AS VALUES ('bar'::text);
1202 CREATE POLICY coll_p ON coll_t USING (c < ('foo'::text COLLATE "C"));
1203 ALTER TABLE coll_t ENABLE ROW LEVEL SECURITY;
1204 GRANT SELECT ON coll_t TO rls_regress_user0;
1205 SELECT (string_to_array(polqual, ':'))[7] AS inputcollid FROM pg_policy WHERE polrelid = 'coll_t'::regclass;
1206 SET SESSION AUTHORIZATION rls_regress_user0;
1207 SELECT * FROM coll_t;
1208 ROLLBACK;
1209
1210 --
1211 -- Shared Object Dependencies
1212 --
1213 RESET SESSION AUTHORIZATION;
1214 BEGIN;
1215 CREATE ROLE alice;
1216 CREATE ROLE bob;
1217 CREATE TABLE tbl1 (c) AS VALUES ('bar'::text);
1218 GRANT SELECT ON TABLE tbl1 TO alice;
1219 CREATE POLICY P ON tbl1 TO alice, bob USING (true);
1220 SELECT refclassid::regclass, deptype
1221   FROM pg_depend
1222   WHERE classid = 'pg_policy'::regclass
1223   AND refobjid = 'tbl1'::regclass;
1224 SELECT refclassid::regclass, deptype
1225   FROM pg_shdepend
1226   WHERE classid = 'pg_policy'::regclass
1227   AND refobjid IN ('alice'::regrole, 'bob'::regrole);
1228
1229 SAVEPOINT q;
1230 DROP ROLE alice; --fails due to dependency on POLICY p
1231 ROLLBACK TO q;
1232
1233 ALTER POLICY p ON tbl1 TO bob USING (true);
1234 SAVEPOINT q;
1235 DROP ROLE alice; --fails due to dependency on GRANT SELECT
1236 ROLLBACK TO q;
1237
1238 REVOKE ALL ON TABLE tbl1 FROM alice;
1239 SAVEPOINT q;
1240 DROP ROLE alice; --succeeds
1241 ROLLBACK TO q;
1242
1243 SAVEPOINT q;
1244 DROP ROLE bob; --fails due to dependency on POLICY p
1245 ROLLBACK TO q;
1246
1247 DROP POLICY p ON tbl1;
1248 SAVEPOINT q;
1249 DROP ROLE bob; -- succeeds
1250 ROLLBACK TO q;
1251
1252 ROLLBACK; -- cleanup
1253
1254 --
1255 -- Converting table to view
1256 --
1257 BEGIN;
1258 CREATE TABLE t (c int);
1259 CREATE POLICY p ON t USING (c % 2 = 1);
1260 ALTER TABLE t ENABLE ROW LEVEL SECURITY;
1261
1262 SAVEPOINT q;
1263 CREATE RULE "_RETURN" AS ON SELECT TO t DO INSTEAD
1264   SELECT * FROM generate_series(1,5) t0(c); -- fails due to row level security enabled
1265 ROLLBACK TO q;
1266
1267 ALTER TABLE t DISABLE ROW LEVEL SECURITY;
1268 SAVEPOINT q;
1269 CREATE RULE "_RETURN" AS ON SELECT TO t DO INSTEAD
1270   SELECT * FROM generate_series(1,5) t0(c); -- fails due to policy p on t
1271 ROLLBACK TO q;
1272
1273 DROP POLICY p ON t;
1274 CREATE RULE "_RETURN" AS ON SELECT TO t DO INSTEAD
1275   SELECT * FROM generate_series(1,5) t0(c); -- succeeds
1276 ROLLBACK;
1277
1278 --
1279 -- Policy expression handling
1280 --
1281 BEGIN;
1282 CREATE TABLE t (c) AS VALUES ('bar'::text);
1283 CREATE POLICY p ON t USING (max(c)); -- fails: aggregate functions are not allowed in policy expressions
1284 ROLLBACK;
1285
1286 --
1287 -- Non-target relations are only subject to SELECT policies
1288 --
1289 SET SESSION AUTHORIZATION rls_regress_user0;
1290 CREATE TABLE r1 (a int);
1291 CREATE TABLE r2 (a int);
1292 INSERT INTO r1 VALUES (10), (20);
1293 INSERT INTO r2 VALUES (10), (20);
1294
1295 GRANT ALL ON r1, r2 TO rls_regress_user1;
1296
1297 CREATE POLICY p1 ON r1 USING (true);
1298 ALTER TABLE r1 ENABLE ROW LEVEL SECURITY;
1299
1300 CREATE POLICY p1 ON r2 FOR SELECT USING (true);
1301 CREATE POLICY p2 ON r2 FOR INSERT WITH CHECK (false);
1302 CREATE POLICY p3 ON r2 FOR UPDATE USING (false);
1303 CREATE POLICY p4 ON r2 FOR DELETE USING (false);
1304 ALTER TABLE r2 ENABLE ROW LEVEL SECURITY;
1305
1306 SET SESSION AUTHORIZATION rls_regress_user1;
1307 SELECT * FROM r1;
1308 SELECT * FROM r2;
1309
1310 -- r2 is read-only
1311 INSERT INTO r2 VALUES (2); -- Not allowed
1312 UPDATE r2 SET a = 2 RETURNING *; -- Updates nothing
1313 DELETE FROM r2 RETURNING *; -- Deletes nothing
1314
1315 -- r2 can be used as a non-target relation in DML
1316 INSERT INTO r1 SELECT a + 1 FROM r2 RETURNING *; -- OK
1317 UPDATE r1 SET a = r2.a + 2 FROM r2 WHERE r1.a = r2.a RETURNING *; -- OK
1318 DELETE FROM r1 USING r2 WHERE r1.a = r2.a + 2 RETURNING *; -- OK
1319 SELECT * FROM r1;
1320 SELECT * FROM r2;
1321
1322 SET SESSION AUTHORIZATION rls_regress_user0;
1323 DROP TABLE r1;
1324 DROP TABLE r2;
1325
1326 --
1327 -- FORCE ROW LEVEL SECURITY applies RLS to owners too
1328 --
1329 SET SESSION AUTHORIZATION rls_regress_user0;
1330 SET row_security = on;
1331 CREATE TABLE r1 (a int);
1332 INSERT INTO r1 VALUES (10), (20);
1333
1334 CREATE POLICY p1 ON r1 USING (false);
1335 ALTER TABLE r1 ENABLE ROW LEVEL SECURITY;
1336 ALTER TABLE r1 FORCE ROW LEVEL SECURITY;
1337
1338 -- No error, but no rows
1339 TABLE r1;
1340
1341 -- RLS error
1342 INSERT INTO r1 VALUES (1);
1343
1344 -- No error (unable to see any rows to update)
1345 UPDATE r1 SET a = 1;
1346 TABLE r1;
1347
1348 -- No error (unable to see any rows to delete)
1349 DELETE FROM r1;
1350 TABLE r1;
1351
1352 SET row_security = off;
1353 -- these all fail, would be affected by RLS
1354 TABLE r1;
1355 UPDATE r1 SET a = 1;
1356 DELETE FROM r1;
1357
1358 DROP TABLE r1;
1359
1360 --
1361 -- FORCE ROW LEVEL SECURITY does not break RI
1362 --
1363 SET SESSION AUTHORIZATION rls_regress_user0;
1364 SET row_security = on;
1365 CREATE TABLE r1 (a int PRIMARY KEY);
1366 CREATE TABLE r2 (a int REFERENCES r1);
1367 INSERT INTO r1 VALUES (10), (20);
1368 INSERT INTO r2 VALUES (10), (20);
1369
1370 -- Create policies on r2 which prevent the
1371 -- owner from seeing any rows, but RI should
1372 -- still see them.
1373 CREATE POLICY p1 ON r2 USING (false);
1374 ALTER TABLE r2 ENABLE ROW LEVEL SECURITY;
1375 ALTER TABLE r2 FORCE ROW LEVEL SECURITY;
1376
1377 -- Errors due to rows in r2
1378 DELETE FROM r1;
1379
1380 -- Reset r2 to no-RLS
1381 DROP POLICY p1 ON r2;
1382 ALTER TABLE r2 NO FORCE ROW LEVEL SECURITY;
1383 ALTER TABLE r2 DISABLE ROW LEVEL SECURITY;
1384
1385 -- clean out r2 for INSERT test below
1386 DELETE FROM r2;
1387
1388 -- Change r1 to not allow rows to be seen
1389 CREATE POLICY p1 ON r1 USING (false);
1390 ALTER TABLE r1 ENABLE ROW LEVEL SECURITY;
1391 ALTER TABLE r1 FORCE ROW LEVEL SECURITY;
1392
1393 -- No rows seen
1394 TABLE r1;
1395
1396 -- No error, RI still sees that row exists in r1
1397 INSERT INTO r2 VALUES (10);
1398
1399 DROP TABLE r2;
1400 DROP TABLE r1;
1401
1402 -- Ensure cascaded DELETE works
1403 CREATE TABLE r1 (a int PRIMARY KEY);
1404 CREATE TABLE r2 (a int REFERENCES r1 ON DELETE CASCADE);
1405 INSERT INTO r1 VALUES (10), (20);
1406 INSERT INTO r2 VALUES (10), (20);
1407
1408 -- Create policies on r2 which prevent the
1409 -- owner from seeing any rows, but RI should
1410 -- still see them.
1411 CREATE POLICY p1 ON r2 USING (false);
1412 ALTER TABLE r2 ENABLE ROW LEVEL SECURITY;
1413 ALTER TABLE r2 FORCE ROW LEVEL SECURITY;
1414
1415 -- Deletes all records from both
1416 DELETE FROM r1;
1417
1418 -- Remove FORCE from r2
1419 ALTER TABLE r2 NO FORCE ROW LEVEL SECURITY;
1420
1421 -- As owner, we now bypass RLS
1422 -- verify no rows in r2 now
1423 TABLE r2;
1424
1425 DROP TABLE r2;
1426 DROP TABLE r1;
1427
1428 -- Ensure cascaded UPDATE works
1429 CREATE TABLE r1 (a int PRIMARY KEY);
1430 CREATE TABLE r2 (a int REFERENCES r1 ON UPDATE CASCADE);
1431 INSERT INTO r1 VALUES (10), (20);
1432 INSERT INTO r2 VALUES (10), (20);
1433
1434 -- Create policies on r2 which prevent the
1435 -- owner from seeing any rows, but RI should
1436 -- still see them.
1437 CREATE POLICY p1 ON r2 USING (false);
1438 ALTER TABLE r2 ENABLE ROW LEVEL SECURITY;
1439 ALTER TABLE r2 FORCE ROW LEVEL SECURITY;
1440
1441 -- Updates records in both
1442 UPDATE r1 SET a = a+5;
1443
1444 -- Remove FORCE from r2
1445 ALTER TABLE r2 NO FORCE ROW LEVEL SECURITY;
1446
1447 -- As owner, we now bypass RLS
1448 -- verify records in r2 updated
1449 TABLE r2;
1450
1451 DROP TABLE r2;
1452 DROP TABLE r1;
1453
1454 --
1455 -- Test INSERT+RETURNING applies SELECT policies as
1456 -- WithCheckOptions (meaning an error is thrown)
1457 --
1458 SET SESSION AUTHORIZATION rls_regress_user0;
1459 SET row_security = on;
1460 CREATE TABLE r1 (a int);
1461
1462 CREATE POLICY p1 ON r1 FOR SELECT USING (false);
1463 CREATE POLICY p2 ON r1 FOR INSERT WITH CHECK (true);
1464 ALTER TABLE r1 ENABLE ROW LEVEL SECURITY;
1465 ALTER TABLE r1 FORCE ROW LEVEL SECURITY;
1466
1467 -- Works fine
1468 INSERT INTO r1 VALUES (10), (20);
1469
1470 -- No error, but no rows
1471 TABLE r1;
1472
1473 SET row_security = off;
1474 -- fail, would be affected by RLS
1475 TABLE r1;
1476
1477 SET row_security = on;
1478
1479 -- Error
1480 INSERT INTO r1 VALUES (10), (20) RETURNING *;
1481
1482 DROP TABLE r1;
1483
1484 --
1485 -- Test UPDATE+RETURNING applies SELECT policies as
1486 -- WithCheckOptions (meaning an error is thrown)
1487 --
1488 SET SESSION AUTHORIZATION rls_regress_user0;
1489 SET row_security = on;
1490 CREATE TABLE r1 (a int);
1491
1492 CREATE POLICY p1 ON r1 FOR SELECT USING (a < 20);
1493 CREATE POLICY p2 ON r1 FOR UPDATE USING (a < 20) WITH CHECK (true);
1494 INSERT INTO r1 VALUES (10);
1495 ALTER TABLE r1 ENABLE ROW LEVEL SECURITY;
1496 ALTER TABLE r1 FORCE ROW LEVEL SECURITY;
1497
1498 -- Works fine
1499 UPDATE r1 SET a = 30;
1500
1501 -- Show updated rows
1502 ALTER TABLE r1 NO FORCE ROW LEVEL SECURITY;
1503 TABLE r1;
1504 -- reset value in r1 for test with RETURNING
1505 UPDATE r1 SET a = 10;
1506
1507 -- Verify row reset
1508 TABLE r1;
1509
1510 ALTER TABLE r1 FORCE ROW LEVEL SECURITY;
1511
1512 -- Error
1513 UPDATE r1 SET a = 30 RETURNING *;
1514
1515 DROP TABLE r1;
1516
1517 -- Check dependency handling
1518 RESET SESSION AUTHORIZATION;
1519 CREATE TABLE dep1 (c1 int);
1520 CREATE TABLE dep2 (c1 int);
1521
1522 CREATE POLICY dep_p1 ON dep1 TO rls_regress_user1 USING (c1 > (select max(dep2.c1) from dep2));
1523 ALTER POLICY dep_p1 ON dep1 TO rls_regress_user1,rls_regress_user2;
1524
1525 -- Should return one
1526 SELECT count(*) = 1 FROM pg_depend
1527                                    WHERE objid = (SELECT oid FROM pg_policy WHERE polname = 'dep_p1')
1528                                          AND refobjid = (SELECT oid FROM pg_class WHERE relname = 'dep2');
1529
1530 ALTER POLICY dep_p1 ON dep1 USING (true);
1531
1532 -- Should return one
1533 SELECT count(*) = 1 FROM pg_shdepend
1534                                    WHERE objid = (SELECT oid FROM pg_policy WHERE polname = 'dep_p1')
1535                                          AND refobjid = (SELECT oid FROM pg_authid WHERE rolname = 'rls_regress_user1');
1536
1537 -- Should return one
1538 SELECT count(*) = 1 FROM pg_shdepend
1539                                    WHERE objid = (SELECT oid FROM pg_policy WHERE polname = 'dep_p1')
1540                                          AND refobjid = (SELECT oid FROM pg_authid WHERE rolname = 'rls_regress_user2');
1541
1542 -- Should return zero
1543 SELECT count(*) = 0 FROM pg_depend
1544                                    WHERE objid = (SELECT oid FROM pg_policy WHERE polname = 'dep_p1')
1545                                          AND refobjid = (SELECT oid FROM pg_class WHERE relname = 'dep2');
1546
1547 -- DROP OWNED BY testing
1548 RESET SESSION AUTHORIZATION;
1549
1550 CREATE ROLE dob_role1;
1551 CREATE ROLE dob_role2;
1552
1553 CREATE TABLE dob_t1 (c1 int);
1554
1555 CREATE POLICY p1 ON dob_t1 TO dob_role1 USING (true);
1556 DROP OWNED BY dob_role1;
1557 DROP POLICY p1 ON dob_t1; -- should fail, already gone
1558
1559 CREATE POLICY p1 ON dob_t1 TO dob_role1,dob_role2 USING (true);
1560 DROP OWNED BY dob_role1;
1561 DROP POLICY p1 ON dob_t1; -- should succeed
1562
1563 DROP USER dob_role1;
1564 DROP USER dob_role2;
1565
1566 --
1567 -- Clean up objects
1568 --
1569 RESET SESSION AUTHORIZATION;
1570
1571 -- Suppress NOTICE messages when doing a cascaded drop.
1572 SET client_min_messages TO 'warning';
1573
1574 DROP SCHEMA rls_regress_schema CASCADE;
1575 RESET client_min_messages;
1576
1577 DROP USER rls_regress_user0;
1578 DROP USER rls_regress_user1;
1579 DROP USER rls_regress_user2;
1580 DROP USER rls_regress_exempt_user;
1581 DROP ROLE rls_regress_group1;
1582 DROP ROLE rls_regress_group2;
1583
1584 -- Arrange to have a few policies left over, for testing
1585 -- pg_dump/pg_restore
1586 CREATE SCHEMA rls_regress_schema;
1587 CREATE TABLE rls_tbl (c1 int);
1588 ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY;
1589 CREATE POLICY p1 ON rls_tbl USING (c1 > 5);
1590 CREATE POLICY p2 ON rls_tbl FOR SELECT USING (c1 <= 3);
1591 CREATE POLICY p3 ON rls_tbl FOR UPDATE USING (c1 <= 3) WITH CHECK (c1 > 5);
1592 CREATE POLICY p4 ON rls_tbl FOR DELETE USING (c1 <= 3);
1593
1594 CREATE TABLE rls_tbl_force (c1 int);
1595 ALTER TABLE rls_tbl_force ENABLE ROW LEVEL SECURITY;
1596 ALTER TABLE rls_tbl_force FORCE ROW LEVEL SECURITY;
1597 CREATE POLICY p1 ON rls_tbl_force USING (c1 = 5) WITH CHECK (c1 < 5);
1598 CREATE POLICY p2 ON rls_tbl_force FOR SELECT USING (c1 = 8);
1599 CREATE POLICY p3 ON rls_tbl_force FOR UPDATE USING (c1 = 8) WITH CHECK (c1 >= 5);
1600 CREATE POLICY p4 ON rls_tbl_force FOR DELETE USING (c1 = 8);