]> granicus.if.org Git - postgresql/blob - src/test/regress/expected/updatable_views.out
86a2642d39517da8570a7274d0990250df487057
[postgresql] / src / test / regress / expected / updatable_views.out
1 --
2 -- UPDATABLE VIEWS
3 --
4 -- avoid bit-exact output here because operations may not be bit-exact.
5 SET extra_float_digits = 0;
6 -- check that non-updatable views and columns are rejected with useful error
7 -- messages
8 CREATE TABLE base_tbl (a int PRIMARY KEY, b text DEFAULT 'Unspecified');
9 INSERT INTO base_tbl SELECT i, 'Row ' || i FROM generate_series(-2, 2) g(i);
10 CREATE VIEW ro_view1 AS SELECT DISTINCT a, b FROM base_tbl; -- DISTINCT not supported
11 CREATE VIEW ro_view2 AS SELECT a, b FROM base_tbl GROUP BY a, b; -- GROUP BY not supported
12 CREATE VIEW ro_view3 AS SELECT 1 FROM base_tbl HAVING max(a) > 0; -- HAVING not supported
13 CREATE VIEW ro_view4 AS SELECT count(*) FROM base_tbl; -- Aggregate functions not supported
14 CREATE VIEW ro_view5 AS SELECT a, rank() OVER() FROM base_tbl; -- Window functions not supported
15 CREATE VIEW ro_view6 AS SELECT a, b FROM base_tbl UNION SELECT -a, b FROM base_tbl; -- Set ops not supported
16 CREATE VIEW ro_view7 AS WITH t AS (SELECT a, b FROM base_tbl) SELECT * FROM t; -- WITH not supported
17 CREATE VIEW ro_view8 AS SELECT a, b FROM base_tbl ORDER BY a OFFSET 1; -- OFFSET not supported
18 CREATE VIEW ro_view9 AS SELECT a, b FROM base_tbl ORDER BY a LIMIT 1; -- LIMIT not supported
19 CREATE VIEW ro_view10 AS SELECT 1 AS a; -- No base relations
20 CREATE VIEW ro_view11 AS SELECT b1.a, b2.b FROM base_tbl b1, base_tbl b2; -- Multiple base relations
21 CREATE VIEW ro_view12 AS SELECT * FROM generate_series(1, 10) AS g(a); -- SRF in rangetable
22 CREATE VIEW ro_view13 AS SELECT a, b FROM (SELECT * FROM base_tbl) AS t; -- Subselect in rangetable
23 CREATE VIEW rw_view14 AS SELECT ctid, a, b FROM base_tbl; -- System columns may be part of an updatable view
24 CREATE VIEW rw_view15 AS SELECT a, upper(b) FROM base_tbl; -- Expression/function may be part of an updatable view
25 CREATE VIEW rw_view16 AS SELECT a, b, a AS aa FROM base_tbl; -- Repeated column may be part of an updatable view
26 CREATE VIEW ro_view17 AS SELECT * FROM ro_view1; -- Base relation not updatable
27 CREATE VIEW ro_view18 AS SELECT * FROM (VALUES(1)) AS tmp(a); -- VALUES in rangetable
28 CREATE SEQUENCE uv_seq;
29 CREATE VIEW ro_view19 AS SELECT * FROM uv_seq; -- View based on a sequence
30 CREATE VIEW ro_view20 AS SELECT a, b, generate_series(1, a) g FROM base_tbl; -- SRF in targetlist not supported
31 SELECT table_name, is_insertable_into
32   FROM information_schema.tables
33  WHERE table_name LIKE E'r_\\_view%'
34  ORDER BY table_name;
35  table_name | is_insertable_into 
36 ------------+--------------------
37  ro_view1   | NO
38  ro_view10  | NO
39  ro_view11  | NO
40  ro_view12  | NO
41  ro_view13  | NO
42  ro_view17  | NO
43  ro_view18  | NO
44  ro_view19  | NO
45  ro_view2   | NO
46  ro_view20  | NO
47  ro_view3   | NO
48  ro_view4   | NO
49  ro_view5   | NO
50  ro_view6   | NO
51  ro_view7   | NO
52  ro_view8   | NO
53  ro_view9   | NO
54  rw_view14  | YES
55  rw_view15  | YES
56  rw_view16  | YES
57 (20 rows)
58
59 SELECT table_name, is_updatable, is_insertable_into
60   FROM information_schema.views
61  WHERE table_name LIKE E'r_\\_view%'
62  ORDER BY table_name;
63  table_name | is_updatable | is_insertable_into 
64 ------------+--------------+--------------------
65  ro_view1   | NO           | NO
66  ro_view10  | NO           | NO
67  ro_view11  | NO           | NO
68  ro_view12  | NO           | NO
69  ro_view13  | NO           | NO
70  ro_view17  | NO           | NO
71  ro_view18  | NO           | NO
72  ro_view19  | NO           | NO
73  ro_view2   | NO           | NO
74  ro_view20  | NO           | NO
75  ro_view3   | NO           | NO
76  ro_view4   | NO           | NO
77  ro_view5   | NO           | NO
78  ro_view6   | NO           | NO
79  ro_view7   | NO           | NO
80  ro_view8   | NO           | NO
81  ro_view9   | NO           | NO
82  rw_view14  | YES          | YES
83  rw_view15  | YES          | YES
84  rw_view16  | YES          | YES
85 (20 rows)
86
87 SELECT table_name, column_name, is_updatable
88   FROM information_schema.columns
89  WHERE table_name LIKE E'r_\\_view%'
90  ORDER BY table_name, ordinal_position;
91  table_name | column_name | is_updatable 
92 ------------+-------------+--------------
93  ro_view1   | a           | NO
94  ro_view1   | b           | NO
95  ro_view10  | a           | NO
96  ro_view11  | a           | NO
97  ro_view11  | b           | NO
98  ro_view12  | a           | NO
99  ro_view13  | a           | NO
100  ro_view13  | b           | NO
101  ro_view17  | a           | NO
102  ro_view17  | b           | NO
103  ro_view18  | a           | NO
104  ro_view19  | last_value  | NO
105  ro_view19  | log_cnt     | NO
106  ro_view19  | is_called   | NO
107  ro_view2   | a           | NO
108  ro_view2   | b           | NO
109  ro_view20  | a           | NO
110  ro_view20  | b           | NO
111  ro_view20  | g           | NO
112  ro_view3   | ?column?    | NO
113  ro_view4   | count       | NO
114  ro_view5   | a           | NO
115  ro_view5   | rank        | NO
116  ro_view6   | a           | NO
117  ro_view6   | b           | NO
118  ro_view7   | a           | NO
119  ro_view7   | b           | NO
120  ro_view8   | a           | NO
121  ro_view8   | b           | NO
122  ro_view9   | a           | NO
123  ro_view9   | b           | NO
124  rw_view14  | ctid        | NO
125  rw_view14  | a           | YES
126  rw_view14  | b           | YES
127  rw_view15  | a           | YES
128  rw_view15  | upper       | NO
129  rw_view16  | a           | YES
130  rw_view16  | b           | YES
131  rw_view16  | aa          | YES
132 (39 rows)
133
134 -- Read-only views
135 DELETE FROM ro_view1;
136 ERROR:  cannot delete from view "ro_view1"
137 DETAIL:  Views containing DISTINCT are not automatically updatable.
138 HINT:  To enable deleting from the view, provide an INSTEAD OF DELETE trigger or an unconditional ON DELETE DO INSTEAD rule.
139 DELETE FROM ro_view2;
140 ERROR:  cannot delete from view "ro_view2"
141 DETAIL:  Views containing GROUP BY are not automatically updatable.
142 HINT:  To enable deleting from the view, provide an INSTEAD OF DELETE trigger or an unconditional ON DELETE DO INSTEAD rule.
143 DELETE FROM ro_view3;
144 ERROR:  cannot delete from view "ro_view3"
145 DETAIL:  Views containing HAVING are not automatically updatable.
146 HINT:  To enable deleting from the view, provide an INSTEAD OF DELETE trigger or an unconditional ON DELETE DO INSTEAD rule.
147 DELETE FROM ro_view4;
148 ERROR:  cannot delete from view "ro_view4"
149 DETAIL:  Views that return aggregate functions are not automatically updatable.
150 HINT:  To enable deleting from the view, provide an INSTEAD OF DELETE trigger or an unconditional ON DELETE DO INSTEAD rule.
151 DELETE FROM ro_view5;
152 ERROR:  cannot delete from view "ro_view5"
153 DETAIL:  Views that return window functions are not automatically updatable.
154 HINT:  To enable deleting from the view, provide an INSTEAD OF DELETE trigger or an unconditional ON DELETE DO INSTEAD rule.
155 DELETE FROM ro_view6;
156 ERROR:  cannot delete from view "ro_view6"
157 DETAIL:  Views containing UNION, INTERSECT, or EXCEPT are not automatically updatable.
158 HINT:  To enable deleting from the view, provide an INSTEAD OF DELETE trigger or an unconditional ON DELETE DO INSTEAD rule.
159 UPDATE ro_view7 SET a=a+1;
160 ERROR:  cannot update view "ro_view7"
161 DETAIL:  Views containing WITH are not automatically updatable.
162 HINT:  To enable updating the view, provide an INSTEAD OF UPDATE trigger or an unconditional ON UPDATE DO INSTEAD rule.
163 UPDATE ro_view8 SET a=a+1;
164 ERROR:  cannot update view "ro_view8"
165 DETAIL:  Views containing LIMIT or OFFSET are not automatically updatable.
166 HINT:  To enable updating the view, provide an INSTEAD OF UPDATE trigger or an unconditional ON UPDATE DO INSTEAD rule.
167 UPDATE ro_view9 SET a=a+1;
168 ERROR:  cannot update view "ro_view9"
169 DETAIL:  Views containing LIMIT or OFFSET are not automatically updatable.
170 HINT:  To enable updating the view, provide an INSTEAD OF UPDATE trigger or an unconditional ON UPDATE DO INSTEAD rule.
171 UPDATE ro_view10 SET a=a+1;
172 ERROR:  cannot update view "ro_view10"
173 DETAIL:  Views that do not select from a single table or view are not automatically updatable.
174 HINT:  To enable updating the view, provide an INSTEAD OF UPDATE trigger or an unconditional ON UPDATE DO INSTEAD rule.
175 UPDATE ro_view11 SET a=a+1;
176 ERROR:  cannot update view "ro_view11"
177 DETAIL:  Views that do not select from a single table or view are not automatically updatable.
178 HINT:  To enable updating the view, provide an INSTEAD OF UPDATE trigger or an unconditional ON UPDATE DO INSTEAD rule.
179 UPDATE ro_view12 SET a=a+1;
180 ERROR:  cannot update view "ro_view12"
181 DETAIL:  Views that do not select from a single table or view are not automatically updatable.
182 HINT:  To enable updating the view, provide an INSTEAD OF UPDATE trigger or an unconditional ON UPDATE DO INSTEAD rule.
183 INSERT INTO ro_view13 VALUES (3, 'Row 3');
184 ERROR:  cannot insert into view "ro_view13"
185 DETAIL:  Views that do not select from a single table or view are not automatically updatable.
186 HINT:  To enable inserting into the view, provide an INSTEAD OF INSERT trigger or an unconditional ON INSERT DO INSTEAD rule.
187 -- Partially updatable view
188 INSERT INTO rw_view14 VALUES (null, 3, 'Row 3'); -- should fail
189 ERROR:  cannot insert into column "ctid" of view "rw_view14"
190 DETAIL:  View columns that refer to system columns are not updatable.
191 INSERT INTO rw_view14 (a, b) VALUES (3, 'Row 3'); -- should be OK
192 UPDATE rw_view14 SET ctid=null WHERE a=3; -- should fail
193 ERROR:  cannot update column "ctid" of view "rw_view14"
194 DETAIL:  View columns that refer to system columns are not updatable.
195 UPDATE rw_view14 SET b='ROW 3' WHERE a=3; -- should be OK
196 SELECT * FROM base_tbl;
197  a  |   b    
198 ----+--------
199  -2 | Row -2
200  -1 | Row -1
201   0 | Row 0
202   1 | Row 1
203   2 | Row 2
204   3 | ROW 3
205 (6 rows)
206
207 DELETE FROM rw_view14 WHERE a=3; -- should be OK
208 -- Partially updatable view
209 INSERT INTO rw_view15 VALUES (3, 'ROW 3'); -- should fail
210 ERROR:  cannot insert into column "upper" of view "rw_view15"
211 DETAIL:  View columns that are not columns of their base relation are not updatable.
212 INSERT INTO rw_view15 (a) VALUES (3); -- should be OK
213 INSERT INTO rw_view15 (a) VALUES (3) ON CONFLICT DO NOTHING; -- succeeds
214 SELECT * FROM rw_view15;
215  a  |    upper    
216 ----+-------------
217  -2 | ROW -2
218  -1 | ROW -1
219   0 | ROW 0
220   1 | ROW 1
221   2 | ROW 2
222   3 | UNSPECIFIED
223 (6 rows)
224
225 INSERT INTO rw_view15 (a) VALUES (3) ON CONFLICT (a) DO NOTHING; -- succeeds
226 SELECT * FROM rw_view15;
227  a  |    upper    
228 ----+-------------
229  -2 | ROW -2
230  -1 | ROW -1
231   0 | ROW 0
232   1 | ROW 1
233   2 | ROW 2
234   3 | UNSPECIFIED
235 (6 rows)
236
237 INSERT INTO rw_view15 (a) VALUES (3) ON CONFLICT (a) DO UPDATE set a = excluded.a; -- succeeds
238 SELECT * FROM rw_view15;
239  a  |    upper    
240 ----+-------------
241  -2 | ROW -2
242  -1 | ROW -1
243   0 | ROW 0
244   1 | ROW 1
245   2 | ROW 2
246   3 | UNSPECIFIED
247 (6 rows)
248
249 INSERT INTO rw_view15 (a) VALUES (3) ON CONFLICT (a) DO UPDATE set upper = 'blarg'; -- fails
250 ERROR:  cannot insert into column "upper" of view "rw_view15"
251 DETAIL:  View columns that are not columns of their base relation are not updatable.
252 SELECT * FROM rw_view15;
253  a  |    upper    
254 ----+-------------
255  -2 | ROW -2
256  -1 | ROW -1
257   0 | ROW 0
258   1 | ROW 1
259   2 | ROW 2
260   3 | UNSPECIFIED
261 (6 rows)
262
263 SELECT * FROM rw_view15;
264  a  |    upper    
265 ----+-------------
266  -2 | ROW -2
267  -1 | ROW -1
268   0 | ROW 0
269   1 | ROW 1
270   2 | ROW 2
271   3 | UNSPECIFIED
272 (6 rows)
273
274 ALTER VIEW rw_view15 ALTER COLUMN upper SET DEFAULT 'NOT SET';
275 INSERT INTO rw_view15 (a) VALUES (4); -- should fail
276 ERROR:  cannot insert into column "upper" of view "rw_view15"
277 DETAIL:  View columns that are not columns of their base relation are not updatable.
278 UPDATE rw_view15 SET upper='ROW 3' WHERE a=3; -- should fail
279 ERROR:  cannot update column "upper" of view "rw_view15"
280 DETAIL:  View columns that are not columns of their base relation are not updatable.
281 UPDATE rw_view15 SET upper=DEFAULT WHERE a=3; -- should fail
282 ERROR:  cannot update column "upper" of view "rw_view15"
283 DETAIL:  View columns that are not columns of their base relation are not updatable.
284 UPDATE rw_view15 SET a=4 WHERE a=3; -- should be OK
285 SELECT * FROM base_tbl;
286  a  |      b      
287 ----+-------------
288  -2 | Row -2
289  -1 | Row -1
290   0 | Row 0
291   1 | Row 1
292   2 | Row 2
293   4 | Unspecified
294 (6 rows)
295
296 DELETE FROM rw_view15 WHERE a=4; -- should be OK
297 -- Partially updatable view
298 INSERT INTO rw_view16 VALUES (3, 'Row 3', 3); -- should fail
299 ERROR:  multiple assignments to same column "a"
300 INSERT INTO rw_view16 (a, b) VALUES (3, 'Row 3'); -- should be OK
301 UPDATE rw_view16 SET a=3, aa=-3 WHERE a=3; -- should fail
302 ERROR:  multiple assignments to same column "a"
303 UPDATE rw_view16 SET aa=-3 WHERE a=3; -- should be OK
304 SELECT * FROM base_tbl;
305  a  |   b    
306 ----+--------
307  -2 | Row -2
308  -1 | Row -1
309   0 | Row 0
310   1 | Row 1
311   2 | Row 2
312  -3 | Row 3
313 (6 rows)
314
315 DELETE FROM rw_view16 WHERE a=-3; -- should be OK
316 -- Read-only views
317 INSERT INTO ro_view17 VALUES (3, 'ROW 3');
318 ERROR:  cannot insert into view "ro_view1"
319 DETAIL:  Views containing DISTINCT are not automatically updatable.
320 HINT:  To enable inserting into the view, provide an INSTEAD OF INSERT trigger or an unconditional ON INSERT DO INSTEAD rule.
321 DELETE FROM ro_view18;
322 ERROR:  cannot delete from view "ro_view18"
323 DETAIL:  Views that do not select from a single table or view are not automatically updatable.
324 HINT:  To enable deleting from the view, provide an INSTEAD OF DELETE trigger or an unconditional ON DELETE DO INSTEAD rule.
325 UPDATE ro_view19 SET last_value=1000;
326 ERROR:  cannot update view "ro_view19"
327 DETAIL:  Views that do not select from a single table or view are not automatically updatable.
328 HINT:  To enable updating the view, provide an INSTEAD OF UPDATE trigger or an unconditional ON UPDATE DO INSTEAD rule.
329 UPDATE ro_view20 SET b=upper(b);
330 ERROR:  cannot update view "ro_view20"
331 DETAIL:  Views that return set-returning functions are not automatically updatable.
332 HINT:  To enable updating the view, provide an INSTEAD OF UPDATE trigger or an unconditional ON UPDATE DO INSTEAD rule.
333 DROP TABLE base_tbl CASCADE;
334 NOTICE:  drop cascades to 16 other objects
335 DETAIL:  drop cascades to view ro_view1
336 drop cascades to view ro_view17
337 drop cascades to view ro_view2
338 drop cascades to view ro_view3
339 drop cascades to view ro_view4
340 drop cascades to view ro_view5
341 drop cascades to view ro_view6
342 drop cascades to view ro_view7
343 drop cascades to view ro_view8
344 drop cascades to view ro_view9
345 drop cascades to view ro_view11
346 drop cascades to view ro_view13
347 drop cascades to view rw_view14
348 drop cascades to view rw_view15
349 drop cascades to view rw_view16
350 drop cascades to view ro_view20
351 DROP VIEW ro_view10, ro_view12, ro_view18;
352 DROP SEQUENCE uv_seq CASCADE;
353 NOTICE:  drop cascades to view ro_view19
354 -- simple updatable view
355 CREATE TABLE base_tbl (a int PRIMARY KEY, b text DEFAULT 'Unspecified');
356 INSERT INTO base_tbl SELECT i, 'Row ' || i FROM generate_series(-2, 2) g(i);
357 CREATE VIEW rw_view1 AS SELECT * FROM base_tbl WHERE a>0;
358 SELECT table_name, is_insertable_into
359   FROM information_schema.tables
360  WHERE table_name = 'rw_view1';
361  table_name | is_insertable_into 
362 ------------+--------------------
363  rw_view1   | YES
364 (1 row)
365
366 SELECT table_name, is_updatable, is_insertable_into
367   FROM information_schema.views
368  WHERE table_name = 'rw_view1';
369  table_name | is_updatable | is_insertable_into 
370 ------------+--------------+--------------------
371  rw_view1   | YES          | YES
372 (1 row)
373
374 SELECT table_name, column_name, is_updatable
375   FROM information_schema.columns
376  WHERE table_name = 'rw_view1'
377  ORDER BY ordinal_position;
378  table_name | column_name | is_updatable 
379 ------------+-------------+--------------
380  rw_view1   | a           | YES
381  rw_view1   | b           | YES
382 (2 rows)
383
384 INSERT INTO rw_view1 VALUES (3, 'Row 3');
385 INSERT INTO rw_view1 (a) VALUES (4);
386 UPDATE rw_view1 SET a=5 WHERE a=4;
387 DELETE FROM rw_view1 WHERE b='Row 2';
388 SELECT * FROM base_tbl;
389  a  |      b      
390 ----+-------------
391  -2 | Row -2
392  -1 | Row -1
393   0 | Row 0
394   1 | Row 1
395   3 | Row 3
396   5 | Unspecified
397 (6 rows)
398
399 EXPLAIN (costs off) UPDATE rw_view1 SET a=6 WHERE a=5;
400                     QUERY PLAN                    
401 --------------------------------------------------
402  Update on base_tbl
403    ->  Index Scan using base_tbl_pkey on base_tbl
404          Index Cond: ((a > 0) AND (a = 5))
405 (3 rows)
406
407 EXPLAIN (costs off) DELETE FROM rw_view1 WHERE a=5;
408                     QUERY PLAN                    
409 --------------------------------------------------
410  Delete on base_tbl
411    ->  Index Scan using base_tbl_pkey on base_tbl
412          Index Cond: ((a > 0) AND (a = 5))
413 (3 rows)
414
415 DROP TABLE base_tbl CASCADE;
416 NOTICE:  drop cascades to view rw_view1
417 -- view on top of view
418 CREATE TABLE base_tbl (a int PRIMARY KEY, b text DEFAULT 'Unspecified');
419 INSERT INTO base_tbl SELECT i, 'Row ' || i FROM generate_series(-2, 2) g(i);
420 CREATE VIEW rw_view1 AS SELECT b AS bb, a AS aa FROM base_tbl WHERE a>0;
421 CREATE VIEW rw_view2 AS SELECT aa AS aaa, bb AS bbb FROM rw_view1 WHERE aa<10;
422 SELECT table_name, is_insertable_into
423   FROM information_schema.tables
424  WHERE table_name = 'rw_view2';
425  table_name | is_insertable_into 
426 ------------+--------------------
427  rw_view2   | YES
428 (1 row)
429
430 SELECT table_name, is_updatable, is_insertable_into
431   FROM information_schema.views
432  WHERE table_name = 'rw_view2';
433  table_name | is_updatable | is_insertable_into 
434 ------------+--------------+--------------------
435  rw_view2   | YES          | YES
436 (1 row)
437
438 SELECT table_name, column_name, is_updatable
439   FROM information_schema.columns
440  WHERE table_name = 'rw_view2'
441  ORDER BY ordinal_position;
442  table_name | column_name | is_updatable 
443 ------------+-------------+--------------
444  rw_view2   | aaa         | YES
445  rw_view2   | bbb         | YES
446 (2 rows)
447
448 INSERT INTO rw_view2 VALUES (3, 'Row 3');
449 INSERT INTO rw_view2 (aaa) VALUES (4);
450 SELECT * FROM rw_view2;
451  aaa |     bbb     
452 -----+-------------
453    1 | Row 1
454    2 | Row 2
455    3 | Row 3
456    4 | Unspecified
457 (4 rows)
458
459 UPDATE rw_view2 SET bbb='Row 4' WHERE aaa=4;
460 DELETE FROM rw_view2 WHERE aaa=2;
461 SELECT * FROM rw_view2;
462  aaa |  bbb  
463 -----+-------
464    1 | Row 1
465    3 | Row 3
466    4 | Row 4
467 (3 rows)
468
469 EXPLAIN (costs off) UPDATE rw_view2 SET aaa=5 WHERE aaa=4;
470                        QUERY PLAN                       
471 --------------------------------------------------------
472  Update on base_tbl
473    ->  Index Scan using base_tbl_pkey on base_tbl
474          Index Cond: ((a < 10) AND (a > 0) AND (a = 4))
475 (3 rows)
476
477 EXPLAIN (costs off) DELETE FROM rw_view2 WHERE aaa=4;
478                        QUERY PLAN                       
479 --------------------------------------------------------
480  Delete on base_tbl
481    ->  Index Scan using base_tbl_pkey on base_tbl
482          Index Cond: ((a < 10) AND (a > 0) AND (a = 4))
483 (3 rows)
484
485 DROP TABLE base_tbl CASCADE;
486 NOTICE:  drop cascades to 2 other objects
487 DETAIL:  drop cascades to view rw_view1
488 drop cascades to view rw_view2
489 -- view on top of view with rules
490 CREATE TABLE base_tbl (a int PRIMARY KEY, b text DEFAULT 'Unspecified');
491 INSERT INTO base_tbl SELECT i, 'Row ' || i FROM generate_series(-2, 2) g(i);
492 CREATE VIEW rw_view1 AS SELECT * FROM base_tbl WHERE a>0 OFFSET 0; -- not updatable without rules/triggers
493 CREATE VIEW rw_view2 AS SELECT * FROM rw_view1 WHERE a<10;
494 SELECT table_name, is_insertable_into
495   FROM information_schema.tables
496  WHERE table_name LIKE 'rw_view%'
497  ORDER BY table_name;
498  table_name | is_insertable_into 
499 ------------+--------------------
500  rw_view1   | NO
501  rw_view2   | NO
502 (2 rows)
503
504 SELECT table_name, is_updatable, is_insertable_into
505   FROM information_schema.views
506  WHERE table_name LIKE 'rw_view%'
507  ORDER BY table_name;
508  table_name | is_updatable | is_insertable_into 
509 ------------+--------------+--------------------
510  rw_view1   | NO           | NO
511  rw_view2   | NO           | NO
512 (2 rows)
513
514 SELECT table_name, column_name, is_updatable
515   FROM information_schema.columns
516  WHERE table_name LIKE 'rw_view%'
517  ORDER BY table_name, ordinal_position;
518  table_name | column_name | is_updatable 
519 ------------+-------------+--------------
520  rw_view1   | a           | NO
521  rw_view1   | b           | NO
522  rw_view2   | a           | NO
523  rw_view2   | b           | NO
524 (4 rows)
525
526 CREATE RULE rw_view1_ins_rule AS ON INSERT TO rw_view1
527   DO INSTEAD INSERT INTO base_tbl VALUES (NEW.a, NEW.b) RETURNING *;
528 SELECT table_name, is_insertable_into
529   FROM information_schema.tables
530  WHERE table_name LIKE 'rw_view%'
531  ORDER BY table_name;
532  table_name | is_insertable_into 
533 ------------+--------------------
534  rw_view1   | YES
535  rw_view2   | YES
536 (2 rows)
537
538 SELECT table_name, is_updatable, is_insertable_into
539   FROM information_schema.views
540  WHERE table_name LIKE 'rw_view%'
541  ORDER BY table_name;
542  table_name | is_updatable | is_insertable_into 
543 ------------+--------------+--------------------
544  rw_view1   | NO           | YES
545  rw_view2   | NO           | YES
546 (2 rows)
547
548 SELECT table_name, column_name, is_updatable
549   FROM information_schema.columns
550  WHERE table_name LIKE 'rw_view%'
551  ORDER BY table_name, ordinal_position;
552  table_name | column_name | is_updatable 
553 ------------+-------------+--------------
554  rw_view1   | a           | NO
555  rw_view1   | b           | NO
556  rw_view2   | a           | NO
557  rw_view2   | b           | NO
558 (4 rows)
559
560 CREATE RULE rw_view1_upd_rule AS ON UPDATE TO rw_view1
561   DO INSTEAD UPDATE base_tbl SET b=NEW.b WHERE a=OLD.a RETURNING NEW.*;
562 SELECT table_name, is_insertable_into
563   FROM information_schema.tables
564  WHERE table_name LIKE 'rw_view%'
565  ORDER BY table_name;
566  table_name | is_insertable_into 
567 ------------+--------------------
568  rw_view1   | YES
569  rw_view2   | YES
570 (2 rows)
571
572 SELECT table_name, is_updatable, is_insertable_into
573   FROM information_schema.views
574  WHERE table_name LIKE 'rw_view%'
575  ORDER BY table_name;
576  table_name | is_updatable | is_insertable_into 
577 ------------+--------------+--------------------
578  rw_view1   | NO           | YES
579  rw_view2   | NO           | YES
580 (2 rows)
581
582 SELECT table_name, column_name, is_updatable
583   FROM information_schema.columns
584  WHERE table_name LIKE 'rw_view%'
585  ORDER BY table_name, ordinal_position;
586  table_name | column_name | is_updatable 
587 ------------+-------------+--------------
588  rw_view1   | a           | NO
589  rw_view1   | b           | NO
590  rw_view2   | a           | NO
591  rw_view2   | b           | NO
592 (4 rows)
593
594 CREATE RULE rw_view1_del_rule AS ON DELETE TO rw_view1
595   DO INSTEAD DELETE FROM base_tbl WHERE a=OLD.a RETURNING OLD.*;
596 SELECT table_name, is_insertable_into
597   FROM information_schema.tables
598  WHERE table_name LIKE 'rw_view%'
599  ORDER BY table_name;
600  table_name | is_insertable_into 
601 ------------+--------------------
602  rw_view1   | YES
603  rw_view2   | YES
604 (2 rows)
605
606 SELECT table_name, is_updatable, is_insertable_into
607   FROM information_schema.views
608  WHERE table_name LIKE 'rw_view%'
609  ORDER BY table_name;
610  table_name | is_updatable | is_insertable_into 
611 ------------+--------------+--------------------
612  rw_view1   | YES          | YES
613  rw_view2   | YES          | YES
614 (2 rows)
615
616 SELECT table_name, column_name, is_updatable
617   FROM information_schema.columns
618  WHERE table_name LIKE 'rw_view%'
619  ORDER BY table_name, ordinal_position;
620  table_name | column_name | is_updatable 
621 ------------+-------------+--------------
622  rw_view1   | a           | YES
623  rw_view1   | b           | YES
624  rw_view2   | a           | YES
625  rw_view2   | b           | YES
626 (4 rows)
627
628 INSERT INTO rw_view2 VALUES (3, 'Row 3') RETURNING *;
629  a |   b   
630 ---+-------
631  3 | Row 3
632 (1 row)
633
634 UPDATE rw_view2 SET b='Row three' WHERE a=3 RETURNING *;
635  a |     b     
636 ---+-----------
637  3 | Row three
638 (1 row)
639
640 SELECT * FROM rw_view2;
641  a |     b     
642 ---+-----------
643  1 | Row 1
644  2 | Row 2
645  3 | Row three
646 (3 rows)
647
648 DELETE FROM rw_view2 WHERE a=3 RETURNING *;
649  a |     b     
650 ---+-----------
651  3 | Row three
652 (1 row)
653
654 SELECT * FROM rw_view2;
655  a |   b   
656 ---+-------
657  1 | Row 1
658  2 | Row 2
659 (2 rows)
660
661 EXPLAIN (costs off) UPDATE rw_view2 SET a=3 WHERE a=2;
662                            QUERY PLAN                           
663 ----------------------------------------------------------------
664  Update on base_tbl
665    ->  Nested Loop
666          ->  Index Scan using base_tbl_pkey on base_tbl
667                Index Cond: (a = 2)
668          ->  Subquery Scan on rw_view1
669                Filter: ((rw_view1.a < 10) AND (rw_view1.a = 2))
670                ->  Bitmap Heap Scan on base_tbl base_tbl_1
671                      Recheck Cond: (a > 0)
672                      ->  Bitmap Index Scan on base_tbl_pkey
673                            Index Cond: (a > 0)
674 (10 rows)
675
676 EXPLAIN (costs off) DELETE FROM rw_view2 WHERE a=2;
677                            QUERY PLAN                           
678 ----------------------------------------------------------------
679  Delete on base_tbl
680    ->  Nested Loop
681          ->  Index Scan using base_tbl_pkey on base_tbl
682                Index Cond: (a = 2)
683          ->  Subquery Scan on rw_view1
684                Filter: ((rw_view1.a < 10) AND (rw_view1.a = 2))
685                ->  Bitmap Heap Scan on base_tbl base_tbl_1
686                      Recheck Cond: (a > 0)
687                      ->  Bitmap Index Scan on base_tbl_pkey
688                            Index Cond: (a > 0)
689 (10 rows)
690
691 DROP TABLE base_tbl CASCADE;
692 NOTICE:  drop cascades to 2 other objects
693 DETAIL:  drop cascades to view rw_view1
694 drop cascades to view rw_view2
695 -- view on top of view with triggers
696 CREATE TABLE base_tbl (a int PRIMARY KEY, b text DEFAULT 'Unspecified');
697 INSERT INTO base_tbl SELECT i, 'Row ' || i FROM generate_series(-2, 2) g(i);
698 CREATE VIEW rw_view1 AS SELECT * FROM base_tbl WHERE a>0 OFFSET 0; -- not updatable without rules/triggers
699 CREATE VIEW rw_view2 AS SELECT * FROM rw_view1 WHERE a<10;
700 SELECT table_name, is_insertable_into
701   FROM information_schema.tables
702  WHERE table_name LIKE 'rw_view%'
703  ORDER BY table_name;
704  table_name | is_insertable_into 
705 ------------+--------------------
706  rw_view1   | NO
707  rw_view2   | NO
708 (2 rows)
709
710 SELECT table_name, is_updatable, is_insertable_into,
711        is_trigger_updatable, is_trigger_deletable,
712        is_trigger_insertable_into
713   FROM information_schema.views
714  WHERE table_name LIKE 'rw_view%'
715  ORDER BY table_name;
716  table_name | is_updatable | is_insertable_into | is_trigger_updatable | is_trigger_deletable | is_trigger_insertable_into 
717 ------------+--------------+--------------------+----------------------+----------------------+----------------------------
718  rw_view1   | NO           | NO                 | NO                   | NO                   | NO
719  rw_view2   | NO           | NO                 | NO                   | NO                   | NO
720 (2 rows)
721
722 SELECT table_name, column_name, is_updatable
723   FROM information_schema.columns
724  WHERE table_name LIKE 'rw_view%'
725  ORDER BY table_name, ordinal_position;
726  table_name | column_name | is_updatable 
727 ------------+-------------+--------------
728  rw_view1   | a           | NO
729  rw_view1   | b           | NO
730  rw_view2   | a           | NO
731  rw_view2   | b           | NO
732 (4 rows)
733
734 CREATE FUNCTION rw_view1_trig_fn()
735 RETURNS trigger AS
736 $$
737 BEGIN
738   IF TG_OP = 'INSERT' THEN
739     INSERT INTO base_tbl VALUES (NEW.a, NEW.b);
740     RETURN NEW;
741   ELSIF TG_OP = 'UPDATE' THEN
742     UPDATE base_tbl SET b=NEW.b WHERE a=OLD.a;
743     RETURN NEW;
744   ELSIF TG_OP = 'DELETE' THEN
745     DELETE FROM base_tbl WHERE a=OLD.a;
746     RETURN OLD;
747   END IF;
748 END;
749 $$
750 LANGUAGE plpgsql;
751 CREATE TRIGGER rw_view1_ins_trig INSTEAD OF INSERT ON rw_view1
752   FOR EACH ROW EXECUTE PROCEDURE rw_view1_trig_fn();
753 SELECT table_name, is_insertable_into
754   FROM information_schema.tables
755  WHERE table_name LIKE 'rw_view%'
756  ORDER BY table_name;
757  table_name | is_insertable_into 
758 ------------+--------------------
759  rw_view1   | NO
760  rw_view2   | NO
761 (2 rows)
762
763 SELECT table_name, is_updatable, is_insertable_into,
764        is_trigger_updatable, is_trigger_deletable,
765        is_trigger_insertable_into
766   FROM information_schema.views
767  WHERE table_name LIKE 'rw_view%'
768  ORDER BY table_name;
769  table_name | is_updatable | is_insertable_into | is_trigger_updatable | is_trigger_deletable | is_trigger_insertable_into 
770 ------------+--------------+--------------------+----------------------+----------------------+----------------------------
771  rw_view1   | NO           | NO                 | NO                   | NO                   | YES
772  rw_view2   | NO           | NO                 | NO                   | NO                   | NO
773 (2 rows)
774
775 SELECT table_name, column_name, is_updatable
776   FROM information_schema.columns
777  WHERE table_name LIKE 'rw_view%'
778  ORDER BY table_name, ordinal_position;
779  table_name | column_name | is_updatable 
780 ------------+-------------+--------------
781  rw_view1   | a           | NO
782  rw_view1   | b           | NO
783  rw_view2   | a           | NO
784  rw_view2   | b           | NO
785 (4 rows)
786
787 CREATE TRIGGER rw_view1_upd_trig INSTEAD OF UPDATE ON rw_view1
788   FOR EACH ROW EXECUTE PROCEDURE rw_view1_trig_fn();
789 SELECT table_name, is_insertable_into
790   FROM information_schema.tables
791  WHERE table_name LIKE 'rw_view%'
792  ORDER BY table_name;
793  table_name | is_insertable_into 
794 ------------+--------------------
795  rw_view1   | NO
796  rw_view2   | NO
797 (2 rows)
798
799 SELECT table_name, is_updatable, is_insertable_into,
800        is_trigger_updatable, is_trigger_deletable,
801        is_trigger_insertable_into
802   FROM information_schema.views
803  WHERE table_name LIKE 'rw_view%'
804  ORDER BY table_name;
805  table_name | is_updatable | is_insertable_into | is_trigger_updatable | is_trigger_deletable | is_trigger_insertable_into 
806 ------------+--------------+--------------------+----------------------+----------------------+----------------------------
807  rw_view1   | NO           | NO                 | YES                  | NO                   | YES
808  rw_view2   | NO           | NO                 | NO                   | NO                   | NO
809 (2 rows)
810
811 SELECT table_name, column_name, is_updatable
812   FROM information_schema.columns
813  WHERE table_name LIKE 'rw_view%'
814  ORDER BY table_name, ordinal_position;
815  table_name | column_name | is_updatable 
816 ------------+-------------+--------------
817  rw_view1   | a           | NO
818  rw_view1   | b           | NO
819  rw_view2   | a           | NO
820  rw_view2   | b           | NO
821 (4 rows)
822
823 CREATE TRIGGER rw_view1_del_trig INSTEAD OF DELETE ON rw_view1
824   FOR EACH ROW EXECUTE PROCEDURE rw_view1_trig_fn();
825 SELECT table_name, is_insertable_into
826   FROM information_schema.tables
827  WHERE table_name LIKE 'rw_view%'
828  ORDER BY table_name;
829  table_name | is_insertable_into 
830 ------------+--------------------
831  rw_view1   | NO
832  rw_view2   | NO
833 (2 rows)
834
835 SELECT table_name, is_updatable, is_insertable_into,
836        is_trigger_updatable, is_trigger_deletable,
837        is_trigger_insertable_into
838   FROM information_schema.views
839  WHERE table_name LIKE 'rw_view%'
840  ORDER BY table_name;
841  table_name | is_updatable | is_insertable_into | is_trigger_updatable | is_trigger_deletable | is_trigger_insertable_into 
842 ------------+--------------+--------------------+----------------------+----------------------+----------------------------
843  rw_view1   | NO           | NO                 | YES                  | YES                  | YES
844  rw_view2   | NO           | NO                 | NO                   | NO                   | NO
845 (2 rows)
846
847 SELECT table_name, column_name, is_updatable
848   FROM information_schema.columns
849  WHERE table_name LIKE 'rw_view%'
850  ORDER BY table_name, ordinal_position;
851  table_name | column_name | is_updatable 
852 ------------+-------------+--------------
853  rw_view1   | a           | NO
854  rw_view1   | b           | NO
855  rw_view2   | a           | NO
856  rw_view2   | b           | NO
857 (4 rows)
858
859 INSERT INTO rw_view2 VALUES (3, 'Row 3') RETURNING *;
860  a |   b   
861 ---+-------
862  3 | Row 3
863 (1 row)
864
865 UPDATE rw_view2 SET b='Row three' WHERE a=3 RETURNING *;
866  a |     b     
867 ---+-----------
868  3 | Row three
869 (1 row)
870
871 SELECT * FROM rw_view2;
872  a |     b     
873 ---+-----------
874  1 | Row 1
875  2 | Row 2
876  3 | Row three
877 (3 rows)
878
879 DELETE FROM rw_view2 WHERE a=3 RETURNING *;
880  a |     b     
881 ---+-----------
882  3 | Row three
883 (1 row)
884
885 SELECT * FROM rw_view2;
886  a |   b   
887 ---+-------
888  1 | Row 1
889  2 | Row 2
890 (2 rows)
891
892 EXPLAIN (costs off) UPDATE rw_view2 SET a=3 WHERE a=2;
893                         QUERY PLAN                        
894 ----------------------------------------------------------
895  Update on rw_view1 rw_view1_1
896    ->  Subquery Scan on rw_view1
897          Filter: ((rw_view1.a < 10) AND (rw_view1.a = 2))
898          ->  Bitmap Heap Scan on base_tbl
899                Recheck Cond: (a > 0)
900                ->  Bitmap Index Scan on base_tbl_pkey
901                      Index Cond: (a > 0)
902 (7 rows)
903
904 EXPLAIN (costs off) DELETE FROM rw_view2 WHERE a=2;
905                         QUERY PLAN                        
906 ----------------------------------------------------------
907  Delete on rw_view1 rw_view1_1
908    ->  Subquery Scan on rw_view1
909          Filter: ((rw_view1.a < 10) AND (rw_view1.a = 2))
910          ->  Bitmap Heap Scan on base_tbl
911                Recheck Cond: (a > 0)
912                ->  Bitmap Index Scan on base_tbl_pkey
913                      Index Cond: (a > 0)
914 (7 rows)
915
916 DROP TABLE base_tbl CASCADE;
917 NOTICE:  drop cascades to 2 other objects
918 DETAIL:  drop cascades to view rw_view1
919 drop cascades to view rw_view2
920 DROP FUNCTION rw_view1_trig_fn();
921 -- update using whole row from view
922 CREATE TABLE base_tbl (a int PRIMARY KEY, b text DEFAULT 'Unspecified');
923 INSERT INTO base_tbl SELECT i, 'Row ' || i FROM generate_series(-2, 2) g(i);
924 CREATE VIEW rw_view1 AS SELECT b AS bb, a AS aa FROM base_tbl;
925 CREATE FUNCTION rw_view1_aa(x rw_view1)
926   RETURNS int AS $$ SELECT x.aa $$ LANGUAGE sql;
927 UPDATE rw_view1 v SET bb='Updated row 2' WHERE rw_view1_aa(v)=2
928   RETURNING rw_view1_aa(v), v.bb;
929  rw_view1_aa |      bb       
930 -------------+---------------
931            2 | Updated row 2
932 (1 row)
933
934 SELECT * FROM base_tbl;
935  a  |       b       
936 ----+---------------
937  -2 | Row -2
938  -1 | Row -1
939   0 | Row 0
940   1 | Row 1
941   2 | Updated row 2
942 (5 rows)
943
944 EXPLAIN (costs off)
945 UPDATE rw_view1 v SET bb='Updated row 2' WHERE rw_view1_aa(v)=2
946   RETURNING rw_view1_aa(v), v.bb;
947                     QUERY PLAN                    
948 --------------------------------------------------
949  Update on base_tbl
950    ->  Index Scan using base_tbl_pkey on base_tbl
951          Index Cond: (a = 2)
952 (3 rows)
953
954 DROP TABLE base_tbl CASCADE;
955 NOTICE:  drop cascades to 2 other objects
956 DETAIL:  drop cascades to view rw_view1
957 drop cascades to function rw_view1_aa(rw_view1)
958 -- permissions checks
959 CREATE USER regress_view_user1;
960 CREATE USER regress_view_user2;
961 SET SESSION AUTHORIZATION regress_view_user1;
962 CREATE TABLE base_tbl(a int, b text, c float);
963 INSERT INTO base_tbl VALUES (1, 'Row 1', 1.0);
964 CREATE VIEW rw_view1 AS SELECT b AS bb, c AS cc, a AS aa FROM base_tbl;
965 INSERT INTO rw_view1 VALUES ('Row 2', 2.0, 2);
966 GRANT SELECT ON base_tbl TO regress_view_user2;
967 GRANT SELECT ON rw_view1 TO regress_view_user2;
968 GRANT UPDATE (a,c) ON base_tbl TO regress_view_user2;
969 GRANT UPDATE (bb,cc) ON rw_view1 TO regress_view_user2;
970 RESET SESSION AUTHORIZATION;
971 SET SESSION AUTHORIZATION regress_view_user2;
972 CREATE VIEW rw_view2 AS SELECT b AS bb, c AS cc, a AS aa FROM base_tbl;
973 SELECT * FROM base_tbl; -- ok
974  a |   b   | c 
975 ---+-------+---
976  1 | Row 1 | 1
977  2 | Row 2 | 2
978 (2 rows)
979
980 SELECT * FROM rw_view1; -- ok
981   bb   | cc | aa 
982 -------+----+----
983  Row 1 |  1 |  1
984  Row 2 |  2 |  2
985 (2 rows)
986
987 SELECT * FROM rw_view2; -- ok
988   bb   | cc | aa 
989 -------+----+----
990  Row 1 |  1 |  1
991  Row 2 |  2 |  2
992 (2 rows)
993
994 INSERT INTO base_tbl VALUES (3, 'Row 3', 3.0); -- not allowed
995 ERROR:  permission denied for table base_tbl
996 INSERT INTO rw_view1 VALUES ('Row 3', 3.0, 3); -- not allowed
997 ERROR:  permission denied for view rw_view1
998 INSERT INTO rw_view2 VALUES ('Row 3', 3.0, 3); -- not allowed
999 ERROR:  permission denied for table base_tbl
1000 UPDATE base_tbl SET a=a, c=c; -- ok
1001 UPDATE base_tbl SET b=b; -- not allowed
1002 ERROR:  permission denied for table base_tbl
1003 UPDATE rw_view1 SET bb=bb, cc=cc; -- ok
1004 UPDATE rw_view1 SET aa=aa; -- not allowed
1005 ERROR:  permission denied for view rw_view1
1006 UPDATE rw_view2 SET aa=aa, cc=cc; -- ok
1007 UPDATE rw_view2 SET bb=bb; -- not allowed
1008 ERROR:  permission denied for table base_tbl
1009 DELETE FROM base_tbl; -- not allowed
1010 ERROR:  permission denied for table base_tbl
1011 DELETE FROM rw_view1; -- not allowed
1012 ERROR:  permission denied for view rw_view1
1013 DELETE FROM rw_view2; -- not allowed
1014 ERROR:  permission denied for table base_tbl
1015 RESET SESSION AUTHORIZATION;
1016 SET SESSION AUTHORIZATION regress_view_user1;
1017 GRANT INSERT, DELETE ON base_tbl TO regress_view_user2;
1018 RESET SESSION AUTHORIZATION;
1019 SET SESSION AUTHORIZATION regress_view_user2;
1020 INSERT INTO base_tbl VALUES (3, 'Row 3', 3.0); -- ok
1021 INSERT INTO rw_view1 VALUES ('Row 4', 4.0, 4); -- not allowed
1022 ERROR:  permission denied for view rw_view1
1023 INSERT INTO rw_view2 VALUES ('Row 4', 4.0, 4); -- ok
1024 DELETE FROM base_tbl WHERE a=1; -- ok
1025 DELETE FROM rw_view1 WHERE aa=2; -- not allowed
1026 ERROR:  permission denied for view rw_view1
1027 DELETE FROM rw_view2 WHERE aa=2; -- ok
1028 SELECT * FROM base_tbl;
1029  a |   b   | c 
1030 ---+-------+---
1031  3 | Row 3 | 3
1032  4 | Row 4 | 4
1033 (2 rows)
1034
1035 RESET SESSION AUTHORIZATION;
1036 SET SESSION AUTHORIZATION regress_view_user1;
1037 REVOKE INSERT, DELETE ON base_tbl FROM regress_view_user2;
1038 GRANT INSERT, DELETE ON rw_view1 TO regress_view_user2;
1039 RESET SESSION AUTHORIZATION;
1040 SET SESSION AUTHORIZATION regress_view_user2;
1041 INSERT INTO base_tbl VALUES (5, 'Row 5', 5.0); -- not allowed
1042 ERROR:  permission denied for table base_tbl
1043 INSERT INTO rw_view1 VALUES ('Row 5', 5.0, 5); -- ok
1044 INSERT INTO rw_view2 VALUES ('Row 6', 6.0, 6); -- not allowed
1045 ERROR:  permission denied for table base_tbl
1046 DELETE FROM base_tbl WHERE a=3; -- not allowed
1047 ERROR:  permission denied for table base_tbl
1048 DELETE FROM rw_view1 WHERE aa=3; -- ok
1049 DELETE FROM rw_view2 WHERE aa=4; -- not allowed
1050 ERROR:  permission denied for table base_tbl
1051 SELECT * FROM base_tbl;
1052  a |   b   | c 
1053 ---+-------+---
1054  4 | Row 4 | 4
1055  5 | Row 5 | 5
1056 (2 rows)
1057
1058 RESET SESSION AUTHORIZATION;
1059 DROP TABLE base_tbl CASCADE;
1060 NOTICE:  drop cascades to 2 other objects
1061 DETAIL:  drop cascades to view rw_view1
1062 drop cascades to view rw_view2
1063 -- nested-view permissions
1064 CREATE TABLE base_tbl(a int, b text, c float);
1065 INSERT INTO base_tbl VALUES (1, 'Row 1', 1.0);
1066 SET SESSION AUTHORIZATION regress_view_user1;
1067 CREATE VIEW rw_view1 AS SELECT * FROM base_tbl;
1068 SELECT * FROM rw_view1;  -- not allowed
1069 ERROR:  permission denied for table base_tbl
1070 SELECT * FROM rw_view1 FOR UPDATE;  -- not allowed
1071 ERROR:  permission denied for table base_tbl
1072 UPDATE rw_view1 SET b = 'foo' WHERE a = 1;  -- not allowed
1073 ERROR:  permission denied for table base_tbl
1074 SET SESSION AUTHORIZATION regress_view_user2;
1075 CREATE VIEW rw_view2 AS SELECT * FROM rw_view1;
1076 SELECT * FROM rw_view2;  -- not allowed
1077 ERROR:  permission denied for view rw_view1
1078 SELECT * FROM rw_view2 FOR UPDATE;  -- not allowed
1079 ERROR:  permission denied for view rw_view1
1080 UPDATE rw_view2 SET b = 'bar' WHERE a = 1;  -- not allowed
1081 ERROR:  permission denied for view rw_view1
1082 RESET SESSION AUTHORIZATION;
1083 GRANT SELECT ON base_tbl TO regress_view_user1;
1084 SET SESSION AUTHORIZATION regress_view_user1;
1085 SELECT * FROM rw_view1;
1086  a |   b   | c 
1087 ---+-------+---
1088  1 | Row 1 | 1
1089 (1 row)
1090
1091 SELECT * FROM rw_view1 FOR UPDATE;  -- not allowed
1092 ERROR:  permission denied for table base_tbl
1093 UPDATE rw_view1 SET b = 'foo' WHERE a = 1;  -- not allowed
1094 ERROR:  permission denied for table base_tbl
1095 SET SESSION AUTHORIZATION regress_view_user2;
1096 SELECT * FROM rw_view2;  -- not allowed
1097 ERROR:  permission denied for view rw_view1
1098 SELECT * FROM rw_view2 FOR UPDATE;  -- not allowed
1099 ERROR:  permission denied for view rw_view1
1100 UPDATE rw_view2 SET b = 'bar' WHERE a = 1;  -- not allowed
1101 ERROR:  permission denied for view rw_view1
1102 SET SESSION AUTHORIZATION regress_view_user1;
1103 GRANT SELECT ON rw_view1 TO regress_view_user2;
1104 SET SESSION AUTHORIZATION regress_view_user2;
1105 SELECT * FROM rw_view2;
1106  a |   b   | c 
1107 ---+-------+---
1108  1 | Row 1 | 1
1109 (1 row)
1110
1111 SELECT * FROM rw_view2 FOR UPDATE;  -- not allowed
1112 ERROR:  permission denied for view rw_view1
1113 UPDATE rw_view2 SET b = 'bar' WHERE a = 1;  -- not allowed
1114 ERROR:  permission denied for view rw_view1
1115 RESET SESSION AUTHORIZATION;
1116 GRANT UPDATE ON base_tbl TO regress_view_user1;
1117 SET SESSION AUTHORIZATION regress_view_user1;
1118 SELECT * FROM rw_view1;
1119  a |   b   | c 
1120 ---+-------+---
1121  1 | Row 1 | 1
1122 (1 row)
1123
1124 SELECT * FROM rw_view1 FOR UPDATE;
1125  a |   b   | c 
1126 ---+-------+---
1127  1 | Row 1 | 1
1128 (1 row)
1129
1130 UPDATE rw_view1 SET b = 'foo' WHERE a = 1;
1131 SET SESSION AUTHORIZATION regress_view_user2;
1132 SELECT * FROM rw_view2;
1133  a |  b  | c 
1134 ---+-----+---
1135  1 | foo | 1
1136 (1 row)
1137
1138 SELECT * FROM rw_view2 FOR UPDATE;  -- not allowed
1139 ERROR:  permission denied for view rw_view1
1140 UPDATE rw_view2 SET b = 'bar' WHERE a = 1;  -- not allowed
1141 ERROR:  permission denied for view rw_view1
1142 SET SESSION AUTHORIZATION regress_view_user1;
1143 GRANT UPDATE ON rw_view1 TO regress_view_user2;
1144 SET SESSION AUTHORIZATION regress_view_user2;
1145 SELECT * FROM rw_view2;
1146  a |  b  | c 
1147 ---+-----+---
1148  1 | foo | 1
1149 (1 row)
1150
1151 SELECT * FROM rw_view2 FOR UPDATE;
1152  a |  b  | c 
1153 ---+-----+---
1154  1 | foo | 1
1155 (1 row)
1156
1157 UPDATE rw_view2 SET b = 'bar' WHERE a = 1;
1158 RESET SESSION AUTHORIZATION;
1159 REVOKE UPDATE ON base_tbl FROM regress_view_user1;
1160 SET SESSION AUTHORIZATION regress_view_user1;
1161 SELECT * FROM rw_view1;
1162  a |  b  | c 
1163 ---+-----+---
1164  1 | bar | 1
1165 (1 row)
1166
1167 SELECT * FROM rw_view1 FOR UPDATE;  -- not allowed
1168 ERROR:  permission denied for table base_tbl
1169 UPDATE rw_view1 SET b = 'foo' WHERE a = 1;  -- not allowed
1170 ERROR:  permission denied for table base_tbl
1171 SET SESSION AUTHORIZATION regress_view_user2;
1172 SELECT * FROM rw_view2;
1173  a |  b  | c 
1174 ---+-----+---
1175  1 | bar | 1
1176 (1 row)
1177
1178 SELECT * FROM rw_view2 FOR UPDATE;  -- not allowed
1179 ERROR:  permission denied for table base_tbl
1180 UPDATE rw_view2 SET b = 'bar' WHERE a = 1;  -- not allowed
1181 ERROR:  permission denied for table base_tbl
1182 RESET SESSION AUTHORIZATION;
1183 DROP TABLE base_tbl CASCADE;
1184 NOTICE:  drop cascades to 2 other objects
1185 DETAIL:  drop cascades to view rw_view1
1186 drop cascades to view rw_view2
1187 DROP USER regress_view_user1;
1188 DROP USER regress_view_user2;
1189 -- column defaults
1190 CREATE TABLE base_tbl (a int PRIMARY KEY, b text DEFAULT 'Unspecified', c serial);
1191 INSERT INTO base_tbl VALUES (1, 'Row 1');
1192 INSERT INTO base_tbl VALUES (2, 'Row 2');
1193 INSERT INTO base_tbl VALUES (3);
1194 CREATE VIEW rw_view1 AS SELECT a AS aa, b AS bb FROM base_tbl;
1195 ALTER VIEW rw_view1 ALTER COLUMN bb SET DEFAULT 'View default';
1196 INSERT INTO rw_view1 VALUES (4, 'Row 4');
1197 INSERT INTO rw_view1 (aa) VALUES (5);
1198 SELECT * FROM base_tbl;
1199  a |      b       | c 
1200 ---+--------------+---
1201  1 | Row 1        | 1
1202  2 | Row 2        | 2
1203  3 | Unspecified  | 3
1204  4 | Row 4        | 4
1205  5 | View default | 5
1206 (5 rows)
1207
1208 DROP TABLE base_tbl CASCADE;
1209 NOTICE:  drop cascades to view rw_view1
1210 -- Table having triggers
1211 CREATE TABLE base_tbl (a int PRIMARY KEY, b text DEFAULT 'Unspecified');
1212 INSERT INTO base_tbl VALUES (1, 'Row 1');
1213 INSERT INTO base_tbl VALUES (2, 'Row 2');
1214 CREATE FUNCTION rw_view1_trig_fn()
1215 RETURNS trigger AS
1216 $$
1217 BEGIN
1218   IF TG_OP = 'INSERT' THEN
1219     UPDATE base_tbl SET b=NEW.b WHERE a=1;
1220     RETURN NULL;
1221   END IF;
1222   RETURN NULL;
1223 END;
1224 $$
1225 LANGUAGE plpgsql;
1226 CREATE TRIGGER rw_view1_ins_trig AFTER INSERT ON base_tbl
1227   FOR EACH ROW EXECUTE PROCEDURE rw_view1_trig_fn();
1228 CREATE VIEW rw_view1 AS SELECT a AS aa, b AS bb FROM base_tbl;
1229 INSERT INTO rw_view1 VALUES (3, 'Row 3');
1230 select * from base_tbl;
1231  a |   b   
1232 ---+-------
1233  2 | Row 2
1234  3 | Row 3
1235  1 | Row 3
1236 (3 rows)
1237
1238 DROP VIEW rw_view1;
1239 DROP TRIGGER rw_view1_ins_trig on base_tbl;
1240 DROP FUNCTION rw_view1_trig_fn();
1241 DROP TABLE base_tbl;
1242 -- view with ORDER BY
1243 CREATE TABLE base_tbl (a int, b int);
1244 INSERT INTO base_tbl VALUES (1,2), (4,5), (3,-3);
1245 CREATE VIEW rw_view1 AS SELECT * FROM base_tbl ORDER BY a+b;
1246 SELECT * FROM rw_view1;
1247  a | b  
1248 ---+----
1249  3 | -3
1250  1 |  2
1251  4 |  5
1252 (3 rows)
1253
1254 INSERT INTO rw_view1 VALUES (7,-8);
1255 SELECT * FROM rw_view1;
1256  a | b  
1257 ---+----
1258  7 | -8
1259  3 | -3
1260  1 |  2
1261  4 |  5
1262 (4 rows)
1263
1264 EXPLAIN (verbose, costs off) UPDATE rw_view1 SET b = b + 1 RETURNING *;
1265                          QUERY PLAN                          
1266 -------------------------------------------------------------
1267  Update on public.base_tbl
1268    Output: base_tbl.a, base_tbl.b
1269    ->  Seq Scan on public.base_tbl
1270          Output: base_tbl.a, (base_tbl.b + 1), base_tbl.ctid
1271 (4 rows)
1272
1273 UPDATE rw_view1 SET b = b + 1 RETURNING *;
1274  a | b  
1275 ---+----
1276  1 |  3
1277  4 |  6
1278  3 | -2
1279  7 | -7
1280 (4 rows)
1281
1282 SELECT * FROM rw_view1;
1283  a | b  
1284 ---+----
1285  7 | -7
1286  3 | -2
1287  1 |  3
1288  4 |  6
1289 (4 rows)
1290
1291 DROP TABLE base_tbl CASCADE;
1292 NOTICE:  drop cascades to view rw_view1
1293 -- multiple array-column updates
1294 CREATE TABLE base_tbl (a int, arr int[]);
1295 INSERT INTO base_tbl VALUES (1,ARRAY[2]), (3,ARRAY[4]);
1296 CREATE VIEW rw_view1 AS SELECT * FROM base_tbl;
1297 UPDATE rw_view1 SET arr[1] = 42, arr[2] = 77 WHERE a = 3;
1298 SELECT * FROM rw_view1;
1299  a |   arr   
1300 ---+---------
1301  1 | {2}
1302  3 | {42,77}
1303 (2 rows)
1304
1305 DROP TABLE base_tbl CASCADE;
1306 NOTICE:  drop cascades to view rw_view1
1307 -- views with updatable and non-updatable columns
1308 CREATE TABLE base_tbl(a float);
1309 INSERT INTO base_tbl SELECT i/10.0 FROM generate_series(1,10) g(i);
1310 CREATE VIEW rw_view1 AS
1311   SELECT ctid, sin(a) s, a, cos(a) c
1312   FROM base_tbl
1313   WHERE a != 0
1314   ORDER BY abs(a);
1315 INSERT INTO rw_view1 VALUES (null, null, 1.1, null); -- should fail
1316 ERROR:  cannot insert into column "ctid" of view "rw_view1"
1317 DETAIL:  View columns that refer to system columns are not updatable.
1318 INSERT INTO rw_view1 (s, c, a) VALUES (null, null, 1.1); -- should fail
1319 ERROR:  cannot insert into column "s" of view "rw_view1"
1320 DETAIL:  View columns that are not columns of their base relation are not updatable.
1321 INSERT INTO rw_view1 (a) VALUES (1.1) RETURNING a, s, c; -- OK
1322   a  |         s         |         c         
1323 -----+-------------------+-------------------
1324  1.1 | 0.891207360061435 | 0.453596121425577
1325 (1 row)
1326
1327 UPDATE rw_view1 SET s = s WHERE a = 1.1; -- should fail
1328 ERROR:  cannot update column "s" of view "rw_view1"
1329 DETAIL:  View columns that are not columns of their base relation are not updatable.
1330 UPDATE rw_view1 SET a = 1.05 WHERE a = 1.1 RETURNING s; -- OK
1331          s         
1332 -------------------
1333  0.867423225594017
1334 (1 row)
1335
1336 DELETE FROM rw_view1 WHERE a = 1.05; -- OK
1337 CREATE VIEW rw_view2 AS
1338   SELECT s, c, s/c t, a base_a, ctid
1339   FROM rw_view1;
1340 INSERT INTO rw_view2 VALUES (null, null, null, 1.1, null); -- should fail
1341 ERROR:  cannot insert into column "t" of view "rw_view2"
1342 DETAIL:  View columns that are not columns of their base relation are not updatable.
1343 INSERT INTO rw_view2(s, c, base_a) VALUES (null, null, 1.1); -- should fail
1344 ERROR:  cannot insert into column "s" of view "rw_view1"
1345 DETAIL:  View columns that are not columns of their base relation are not updatable.
1346 INSERT INTO rw_view2(base_a) VALUES (1.1) RETURNING t; -- OK
1347         t         
1348 ------------------
1349  1.96475965724865
1350 (1 row)
1351
1352 UPDATE rw_view2 SET s = s WHERE base_a = 1.1; -- should fail
1353 ERROR:  cannot update column "s" of view "rw_view1"
1354 DETAIL:  View columns that are not columns of their base relation are not updatable.
1355 UPDATE rw_view2 SET t = t WHERE base_a = 1.1; -- should fail
1356 ERROR:  cannot update column "t" of view "rw_view2"
1357 DETAIL:  View columns that are not columns of their base relation are not updatable.
1358 UPDATE rw_view2 SET base_a = 1.05 WHERE base_a = 1.1; -- OK
1359 DELETE FROM rw_view2 WHERE base_a = 1.05 RETURNING base_a, s, c, t; -- OK
1360  base_a |         s         |         c         |        t         
1361 --------+-------------------+-------------------+------------------
1362    1.05 | 0.867423225594017 | 0.497571047891727 | 1.74331530998317
1363 (1 row)
1364
1365 CREATE VIEW rw_view3 AS
1366   SELECT s, c, s/c t, ctid
1367   FROM rw_view1;
1368 INSERT INTO rw_view3 VALUES (null, null, null, null); -- should fail
1369 ERROR:  cannot insert into column "t" of view "rw_view3"
1370 DETAIL:  View columns that are not columns of their base relation are not updatable.
1371 INSERT INTO rw_view3(s) VALUES (null); -- should fail
1372 ERROR:  cannot insert into column "s" of view "rw_view1"
1373 DETAIL:  View columns that are not columns of their base relation are not updatable.
1374 UPDATE rw_view3 SET s = s; -- should fail
1375 ERROR:  cannot update column "s" of view "rw_view1"
1376 DETAIL:  View columns that are not columns of their base relation are not updatable.
1377 DELETE FROM rw_view3 WHERE s = sin(0.1); -- should be OK
1378 SELECT * FROM base_tbl ORDER BY a;
1379   a  
1380 -----
1381  0.2
1382  0.3
1383  0.4
1384  0.5
1385  0.6
1386  0.7
1387  0.8
1388  0.9
1389    1
1390 (9 rows)
1391
1392 SELECT table_name, is_insertable_into
1393   FROM information_schema.tables
1394  WHERE table_name LIKE E'r_\\_view%'
1395  ORDER BY table_name;
1396  table_name | is_insertable_into 
1397 ------------+--------------------
1398  rw_view1   | YES
1399  rw_view2   | YES
1400  rw_view3   | NO
1401 (3 rows)
1402
1403 SELECT table_name, is_updatable, is_insertable_into
1404   FROM information_schema.views
1405  WHERE table_name LIKE E'r_\\_view%'
1406  ORDER BY table_name;
1407  table_name | is_updatable | is_insertable_into 
1408 ------------+--------------+--------------------
1409  rw_view1   | YES          | YES
1410  rw_view2   | YES          | YES
1411  rw_view3   | NO           | NO
1412 (3 rows)
1413
1414 SELECT table_name, column_name, is_updatable
1415   FROM information_schema.columns
1416  WHERE table_name LIKE E'r_\\_view%'
1417  ORDER BY table_name, ordinal_position;
1418  table_name | column_name | is_updatable 
1419 ------------+-------------+--------------
1420  rw_view1   | ctid        | NO
1421  rw_view1   | s           | NO
1422  rw_view1   | a           | YES
1423  rw_view1   | c           | NO
1424  rw_view2   | s           | NO
1425  rw_view2   | c           | NO
1426  rw_view2   | t           | NO
1427  rw_view2   | base_a      | YES
1428  rw_view2   | ctid        | NO
1429  rw_view3   | s           | NO
1430  rw_view3   | c           | NO
1431  rw_view3   | t           | NO
1432  rw_view3   | ctid        | NO
1433 (13 rows)
1434
1435 SELECT events & 4 != 0 AS upd,
1436        events & 8 != 0 AS ins,
1437        events & 16 != 0 AS del
1438   FROM pg_catalog.pg_relation_is_updatable('rw_view3'::regclass, false) t(events);
1439  upd | ins | del 
1440 -----+-----+-----
1441  f   | f   | t
1442 (1 row)
1443
1444 DROP TABLE base_tbl CASCADE;
1445 NOTICE:  drop cascades to 3 other objects
1446 DETAIL:  drop cascades to view rw_view1
1447 drop cascades to view rw_view2
1448 drop cascades to view rw_view3
1449 -- inheritance tests
1450 CREATE TABLE base_tbl_parent (a int);
1451 CREATE TABLE base_tbl_child (CHECK (a > 0)) INHERITS (base_tbl_parent);
1452 INSERT INTO base_tbl_parent SELECT * FROM generate_series(-8, -1);
1453 INSERT INTO base_tbl_child SELECT * FROM generate_series(1, 8);
1454 CREATE VIEW rw_view1 AS SELECT * FROM base_tbl_parent;
1455 CREATE VIEW rw_view2 AS SELECT * FROM ONLY base_tbl_parent;
1456 SELECT * FROM rw_view1 ORDER BY a;
1457  a  
1458 ----
1459  -8
1460  -7
1461  -6
1462  -5
1463  -4
1464  -3
1465  -2
1466  -1
1467   1
1468   2
1469   3
1470   4
1471   5
1472   6
1473   7
1474   8
1475 (16 rows)
1476
1477 SELECT * FROM ONLY rw_view1 ORDER BY a;
1478  a  
1479 ----
1480  -8
1481  -7
1482  -6
1483  -5
1484  -4
1485  -3
1486  -2
1487  -1
1488   1
1489   2
1490   3
1491   4
1492   5
1493   6
1494   7
1495   8
1496 (16 rows)
1497
1498 SELECT * FROM rw_view2 ORDER BY a;
1499  a  
1500 ----
1501  -8
1502  -7
1503  -6
1504  -5
1505  -4
1506  -3
1507  -2
1508  -1
1509 (8 rows)
1510
1511 INSERT INTO rw_view1 VALUES (-100), (100);
1512 INSERT INTO rw_view2 VALUES (-200), (200);
1513 UPDATE rw_view1 SET a = a*10 WHERE a IN (-1, 1); -- Should produce -10 and 10
1514 UPDATE ONLY rw_view1 SET a = a*10 WHERE a IN (-2, 2); -- Should produce -20 and 20
1515 UPDATE rw_view2 SET a = a*10 WHERE a IN (-3, 3); -- Should produce -30 only
1516 UPDATE ONLY rw_view2 SET a = a*10 WHERE a IN (-4, 4); -- Should produce -40 only
1517 DELETE FROM rw_view1 WHERE a IN (-5, 5); -- Should delete -5 and 5
1518 DELETE FROM ONLY rw_view1 WHERE a IN (-6, 6); -- Should delete -6 and 6
1519 DELETE FROM rw_view2 WHERE a IN (-7, 7); -- Should delete -7 only
1520 DELETE FROM ONLY rw_view2 WHERE a IN (-8, 8); -- Should delete -8 only
1521 SELECT * FROM ONLY base_tbl_parent ORDER BY a;
1522   a   
1523 ------
1524  -200
1525  -100
1526   -40
1527   -30
1528   -20
1529   -10
1530   100
1531   200
1532 (8 rows)
1533
1534 SELECT * FROM base_tbl_child ORDER BY a;
1535  a  
1536 ----
1537   3
1538   4
1539   7
1540   8
1541  10
1542  20
1543 (6 rows)
1544
1545 CREATE TABLE other_tbl_parent (id int);
1546 CREATE TABLE other_tbl_child () INHERITS (other_tbl_parent);
1547 INSERT INTO other_tbl_parent VALUES (7),(200);
1548 INSERT INTO other_tbl_child VALUES (8),(100);
1549 EXPLAIN (costs off)
1550 UPDATE rw_view1 SET a = a + 1000 FROM other_tbl_parent WHERE a = id;
1551                           QUERY PLAN                          
1552 --------------------------------------------------------------
1553  Update on base_tbl_parent
1554    Update on base_tbl_parent
1555    Update on base_tbl_child
1556    ->  Hash Join
1557          Hash Cond: (other_tbl_parent.id = base_tbl_parent.a)
1558          ->  Append
1559                ->  Seq Scan on other_tbl_parent
1560                ->  Seq Scan on other_tbl_child
1561          ->  Hash
1562                ->  Seq Scan on base_tbl_parent
1563    ->  Merge Join
1564          Merge Cond: (base_tbl_child.a = other_tbl_parent.id)
1565          ->  Sort
1566                Sort Key: base_tbl_child.a
1567                ->  Seq Scan on base_tbl_child
1568          ->  Sort
1569                Sort Key: other_tbl_parent.id
1570                ->  Append
1571                      ->  Seq Scan on other_tbl_parent
1572                      ->  Seq Scan on other_tbl_child
1573 (20 rows)
1574
1575 UPDATE rw_view1 SET a = a + 1000 FROM other_tbl_parent WHERE a = id;
1576 SELECT * FROM ONLY base_tbl_parent ORDER BY a;
1577   a   
1578 ------
1579  -200
1580  -100
1581   -40
1582   -30
1583   -20
1584   -10
1585  1100
1586  1200
1587 (8 rows)
1588
1589 SELECT * FROM base_tbl_child ORDER BY a;
1590   a   
1591 ------
1592     3
1593     4
1594    10
1595    20
1596  1007
1597  1008
1598 (6 rows)
1599
1600 DROP TABLE base_tbl_parent, base_tbl_child CASCADE;
1601 NOTICE:  drop cascades to 2 other objects
1602 DETAIL:  drop cascades to view rw_view1
1603 drop cascades to view rw_view2
1604 DROP TABLE other_tbl_parent CASCADE;
1605 NOTICE:  drop cascades to table other_tbl_child
1606 -- simple WITH CHECK OPTION
1607 CREATE TABLE base_tbl (a int, b int DEFAULT 10);
1608 INSERT INTO base_tbl VALUES (1,2), (2,3), (1,-1);
1609 CREATE VIEW rw_view1 AS SELECT * FROM base_tbl WHERE a < b
1610   WITH LOCAL CHECK OPTION;
1611 \d+ rw_view1
1612                           View "public.rw_view1"
1613  Column |  Type   | Collation | Nullable | Default | Storage | Description 
1614 --------+---------+-----------+----------+---------+---------+-------------
1615  a      | integer |           |          |         | plain   | 
1616  b      | integer |           |          |         | plain   | 
1617 View definition:
1618  SELECT base_tbl.a,
1619     base_tbl.b
1620    FROM base_tbl
1621   WHERE base_tbl.a < base_tbl.b;
1622 Options: check_option=local
1623
1624 SELECT * FROM information_schema.views WHERE table_name = 'rw_view1';
1625  table_catalog | table_schema | table_name |          view_definition           | check_option | is_updatable | is_insertable_into | is_trigger_updatable | is_trigger_deletable | is_trigger_insertable_into 
1626 ---------------+--------------+------------+------------------------------------+--------------+--------------+--------------------+----------------------+----------------------+----------------------------
1627  regression    | public       | rw_view1   |  SELECT base_tbl.a,               +| LOCAL        | YES          | YES                | NO                   | NO                   | NO
1628                |              |            |     base_tbl.b                    +|              |              |                    |                      |                      | 
1629                |              |            |    FROM base_tbl                  +|              |              |                    |                      |                      | 
1630                |              |            |   WHERE (base_tbl.a < base_tbl.b); |              |              |                    |                      |                      | 
1631 (1 row)
1632
1633 INSERT INTO rw_view1 VALUES(3,4); -- ok
1634 INSERT INTO rw_view1 VALUES(4,3); -- should fail
1635 ERROR:  new row violates check option for view "rw_view1"
1636 DETAIL:  Failing row contains (4, 3).
1637 INSERT INTO rw_view1 VALUES(5,null); -- should fail
1638 ERROR:  new row violates check option for view "rw_view1"
1639 DETAIL:  Failing row contains (5, null).
1640 UPDATE rw_view1 SET b = 5 WHERE a = 3; -- ok
1641 UPDATE rw_view1 SET b = -5 WHERE a = 3; -- should fail
1642 ERROR:  new row violates check option for view "rw_view1"
1643 DETAIL:  Failing row contains (3, -5).
1644 INSERT INTO rw_view1(a) VALUES (9); -- ok
1645 INSERT INTO rw_view1(a) VALUES (10); -- should fail
1646 ERROR:  new row violates check option for view "rw_view1"
1647 DETAIL:  Failing row contains (10, 10).
1648 SELECT * FROM base_tbl;
1649  a | b  
1650 ---+----
1651  1 |  2
1652  2 |  3
1653  1 | -1
1654  3 |  5
1655  9 | 10
1656 (5 rows)
1657
1658 DROP TABLE base_tbl CASCADE;
1659 NOTICE:  drop cascades to view rw_view1
1660 -- WITH LOCAL/CASCADED CHECK OPTION
1661 CREATE TABLE base_tbl (a int);
1662 CREATE VIEW rw_view1 AS SELECT * FROM base_tbl WHERE a > 0;
1663 CREATE VIEW rw_view2 AS SELECT * FROM rw_view1 WHERE a < 10
1664   WITH CHECK OPTION; -- implicitly cascaded
1665 \d+ rw_view2
1666                           View "public.rw_view2"
1667  Column |  Type   | Collation | Nullable | Default | Storage | Description 
1668 --------+---------+-----------+----------+---------+---------+-------------
1669  a      | integer |           |          |         | plain   | 
1670 View definition:
1671  SELECT rw_view1.a
1672    FROM rw_view1
1673   WHERE rw_view1.a < 10;
1674 Options: check_option=cascaded
1675
1676 SELECT * FROM information_schema.views WHERE table_name = 'rw_view2';
1677  table_catalog | table_schema | table_name |      view_definition       | check_option | is_updatable | is_insertable_into | is_trigger_updatable | is_trigger_deletable | is_trigger_insertable_into 
1678 ---------------+--------------+------------+----------------------------+--------------+--------------+--------------------+----------------------+----------------------+----------------------------
1679  regression    | public       | rw_view2   |  SELECT rw_view1.a        +| CASCADED     | YES          | YES                | NO                   | NO                   | NO
1680                |              |            |    FROM rw_view1          +|              |              |                    |                      |                      | 
1681                |              |            |   WHERE (rw_view1.a < 10); |              |              |                    |                      |                      | 
1682 (1 row)
1683
1684 INSERT INTO rw_view2 VALUES (-5); -- should fail
1685 ERROR:  new row violates check option for view "rw_view1"
1686 DETAIL:  Failing row contains (-5).
1687 INSERT INTO rw_view2 VALUES (5); -- ok
1688 INSERT INTO rw_view2 VALUES (15); -- should fail
1689 ERROR:  new row violates check option for view "rw_view2"
1690 DETAIL:  Failing row contains (15).
1691 SELECT * FROM base_tbl;
1692  a 
1693 ---
1694  5
1695 (1 row)
1696
1697 UPDATE rw_view2 SET a = a - 10; -- should fail
1698 ERROR:  new row violates check option for view "rw_view1"
1699 DETAIL:  Failing row contains (-5).
1700 UPDATE rw_view2 SET a = a + 10; -- should fail
1701 ERROR:  new row violates check option for view "rw_view2"
1702 DETAIL:  Failing row contains (15).
1703 CREATE OR REPLACE VIEW rw_view2 AS SELECT * FROM rw_view1 WHERE a < 10
1704   WITH LOCAL CHECK OPTION;
1705 \d+ rw_view2
1706                           View "public.rw_view2"
1707  Column |  Type   | Collation | Nullable | Default | Storage | Description 
1708 --------+---------+-----------+----------+---------+---------+-------------
1709  a      | integer |           |          |         | plain   | 
1710 View definition:
1711  SELECT rw_view1.a
1712    FROM rw_view1
1713   WHERE rw_view1.a < 10;
1714 Options: check_option=local
1715
1716 SELECT * FROM information_schema.views WHERE table_name = 'rw_view2';
1717  table_catalog | table_schema | table_name |      view_definition       | check_option | is_updatable | is_insertable_into | is_trigger_updatable | is_trigger_deletable | is_trigger_insertable_into 
1718 ---------------+--------------+------------+----------------------------+--------------+--------------+--------------------+----------------------+----------------------+----------------------------
1719  regression    | public       | rw_view2   |  SELECT rw_view1.a        +| LOCAL        | YES          | YES                | NO                   | NO                   | NO
1720                |              |            |    FROM rw_view1          +|              |              |                    |                      |                      | 
1721                |              |            |   WHERE (rw_view1.a < 10); |              |              |                    |                      |                      | 
1722 (1 row)
1723
1724 INSERT INTO rw_view2 VALUES (-10); -- ok, but not in view
1725 INSERT INTO rw_view2 VALUES (20); -- should fail
1726 ERROR:  new row violates check option for view "rw_view2"
1727 DETAIL:  Failing row contains (20).
1728 SELECT * FROM base_tbl;
1729   a  
1730 -----
1731    5
1732  -10
1733 (2 rows)
1734
1735 ALTER VIEW rw_view1 SET (check_option=here); -- invalid
1736 ERROR:  invalid value for "check_option" option
1737 DETAIL:  Valid values are "local" and "cascaded".
1738 ALTER VIEW rw_view1 SET (check_option=local);
1739 INSERT INTO rw_view2 VALUES (-20); -- should fail
1740 ERROR:  new row violates check option for view "rw_view1"
1741 DETAIL:  Failing row contains (-20).
1742 INSERT INTO rw_view2 VALUES (30); -- should fail
1743 ERROR:  new row violates check option for view "rw_view2"
1744 DETAIL:  Failing row contains (30).
1745 ALTER VIEW rw_view2 RESET (check_option);
1746 \d+ rw_view2
1747                           View "public.rw_view2"
1748  Column |  Type   | Collation | Nullable | Default | Storage | Description 
1749 --------+---------+-----------+----------+---------+---------+-------------
1750  a      | integer |           |          |         | plain   | 
1751 View definition:
1752  SELECT rw_view1.a
1753    FROM rw_view1
1754   WHERE rw_view1.a < 10;
1755
1756 SELECT * FROM information_schema.views WHERE table_name = 'rw_view2';
1757  table_catalog | table_schema | table_name |      view_definition       | check_option | is_updatable | is_insertable_into | is_trigger_updatable | is_trigger_deletable | is_trigger_insertable_into 
1758 ---------------+--------------+------------+----------------------------+--------------+--------------+--------------------+----------------------+----------------------+----------------------------
1759  regression    | public       | rw_view2   |  SELECT rw_view1.a        +| NONE         | YES          | YES                | NO                   | NO                   | NO
1760                |              |            |    FROM rw_view1          +|              |              |                    |                      |                      | 
1761                |              |            |   WHERE (rw_view1.a < 10); |              |              |                    |                      |                      | 
1762 (1 row)
1763
1764 INSERT INTO rw_view2 VALUES (30); -- ok, but not in view
1765 SELECT * FROM base_tbl;
1766   a  
1767 -----
1768    5
1769  -10
1770   30
1771 (3 rows)
1772
1773 DROP TABLE base_tbl CASCADE;
1774 NOTICE:  drop cascades to 2 other objects
1775 DETAIL:  drop cascades to view rw_view1
1776 drop cascades to view rw_view2
1777 -- WITH CHECK OPTION with no local view qual
1778 CREATE TABLE base_tbl (a int);
1779 CREATE VIEW rw_view1 AS SELECT * FROM base_tbl WITH CHECK OPTION;
1780 CREATE VIEW rw_view2 AS SELECT * FROM rw_view1 WHERE a > 0;
1781 CREATE VIEW rw_view3 AS SELECT * FROM rw_view2 WITH CHECK OPTION;
1782 SELECT * FROM information_schema.views WHERE table_name LIKE E'rw\\_view_' ORDER BY table_name;
1783  table_catalog | table_schema | table_name |      view_definition      | check_option | is_updatable | is_insertable_into | is_trigger_updatable | is_trigger_deletable | is_trigger_insertable_into 
1784 ---------------+--------------+------------+---------------------------+--------------+--------------+--------------------+----------------------+----------------------+----------------------------
1785  regression    | public       | rw_view1   |  SELECT base_tbl.a       +| CASCADED     | YES          | YES                | NO                   | NO                   | NO
1786                |              |            |    FROM base_tbl;         |              |              |                    |                      |                      | 
1787  regression    | public       | rw_view2   |  SELECT rw_view1.a       +| NONE         | YES          | YES                | NO                   | NO                   | NO
1788                |              |            |    FROM rw_view1         +|              |              |                    |                      |                      | 
1789                |              |            |   WHERE (rw_view1.a > 0); |              |              |                    |                      |                      | 
1790  regression    | public       | rw_view3   |  SELECT rw_view2.a       +| CASCADED     | YES          | YES                | NO                   | NO                   | NO
1791                |              |            |    FROM rw_view2;         |              |              |                    |                      |                      | 
1792 (3 rows)
1793
1794 INSERT INTO rw_view1 VALUES (-1); -- ok
1795 INSERT INTO rw_view1 VALUES (1); -- ok
1796 INSERT INTO rw_view2 VALUES (-2); -- ok, but not in view
1797 INSERT INTO rw_view2 VALUES (2); -- ok
1798 INSERT INTO rw_view3 VALUES (-3); -- should fail
1799 ERROR:  new row violates check option for view "rw_view2"
1800 DETAIL:  Failing row contains (-3).
1801 INSERT INTO rw_view3 VALUES (3); -- ok
1802 DROP TABLE base_tbl CASCADE;
1803 NOTICE:  drop cascades to 3 other objects
1804 DETAIL:  drop cascades to view rw_view1
1805 drop cascades to view rw_view2
1806 drop cascades to view rw_view3
1807 -- WITH CHECK OPTION with scalar array ops
1808 CREATE TABLE base_tbl (a int, b int[]);
1809 CREATE VIEW rw_view1 AS SELECT * FROM base_tbl WHERE a = ANY (b)
1810   WITH CHECK OPTION;
1811 INSERT INTO rw_view1 VALUES (1, ARRAY[1,2,3]); -- ok
1812 INSERT INTO rw_view1 VALUES (10, ARRAY[4,5]); -- should fail
1813 ERROR:  new row violates check option for view "rw_view1"
1814 DETAIL:  Failing row contains (10, {4,5}).
1815 UPDATE rw_view1 SET b[2] = -b[2] WHERE a = 1; -- ok
1816 UPDATE rw_view1 SET b[1] = -b[1] WHERE a = 1; -- should fail
1817 ERROR:  new row violates check option for view "rw_view1"
1818 DETAIL:  Failing row contains (1, {-1,-2,3}).
1819 PREPARE ins(int, int[]) AS INSERT INTO rw_view1 VALUES($1, $2);
1820 EXECUTE ins(2, ARRAY[1,2,3]); -- ok
1821 EXECUTE ins(10, ARRAY[4,5]); -- should fail
1822 ERROR:  new row violates check option for view "rw_view1"
1823 DETAIL:  Failing row contains (10, {4,5}).
1824 DEALLOCATE PREPARE ins;
1825 DROP TABLE base_tbl CASCADE;
1826 NOTICE:  drop cascades to view rw_view1
1827 -- WITH CHECK OPTION with subquery
1828 CREATE TABLE base_tbl (a int);
1829 CREATE TABLE ref_tbl (a int PRIMARY KEY);
1830 INSERT INTO ref_tbl SELECT * FROM generate_series(1,10);
1831 CREATE VIEW rw_view1 AS
1832   SELECT * FROM base_tbl b
1833   WHERE EXISTS(SELECT 1 FROM ref_tbl r WHERE r.a = b.a)
1834   WITH CHECK OPTION;
1835 INSERT INTO rw_view1 VALUES (5); -- ok
1836 INSERT INTO rw_view1 VALUES (15); -- should fail
1837 ERROR:  new row violates check option for view "rw_view1"
1838 DETAIL:  Failing row contains (15).
1839 UPDATE rw_view1 SET a = a + 5; -- ok
1840 UPDATE rw_view1 SET a = a + 5; -- should fail
1841 ERROR:  new row violates check option for view "rw_view1"
1842 DETAIL:  Failing row contains (15).
1843 EXPLAIN (costs off) INSERT INTO rw_view1 VALUES (5);
1844                        QUERY PLAN                        
1845 ---------------------------------------------------------
1846  Insert on base_tbl b
1847    ->  Result
1848    SubPlan 1
1849      ->  Index Only Scan using ref_tbl_pkey on ref_tbl r
1850            Index Cond: (a = b.a)
1851    SubPlan 2
1852      ->  Seq Scan on ref_tbl r_1
1853 (7 rows)
1854
1855 EXPLAIN (costs off) UPDATE rw_view1 SET a = a + 5;
1856                         QUERY PLAN                         
1857 -----------------------------------------------------------
1858  Update on base_tbl b
1859    ->  Hash Join
1860          Hash Cond: (b.a = r.a)
1861          ->  Seq Scan on base_tbl b
1862          ->  Hash
1863                ->  Seq Scan on ref_tbl r
1864    SubPlan 1
1865      ->  Index Only Scan using ref_tbl_pkey on ref_tbl r_1
1866            Index Cond: (a = b.a)
1867    SubPlan 2
1868      ->  Seq Scan on ref_tbl r_2
1869 (11 rows)
1870
1871 DROP TABLE base_tbl, ref_tbl CASCADE;
1872 NOTICE:  drop cascades to view rw_view1
1873 -- WITH CHECK OPTION with BEFORE trigger on base table
1874 CREATE TABLE base_tbl (a int, b int);
1875 CREATE FUNCTION base_tbl_trig_fn()
1876 RETURNS trigger AS
1877 $$
1878 BEGIN
1879   NEW.b := 10;
1880   RETURN NEW;
1881 END;
1882 $$
1883 LANGUAGE plpgsql;
1884 CREATE TRIGGER base_tbl_trig BEFORE INSERT OR UPDATE ON base_tbl
1885   FOR EACH ROW EXECUTE PROCEDURE base_tbl_trig_fn();
1886 CREATE VIEW rw_view1 AS SELECT * FROM base_tbl WHERE a < b WITH CHECK OPTION;
1887 INSERT INTO rw_view1 VALUES (5,0); -- ok
1888 INSERT INTO rw_view1 VALUES (15, 20); -- should fail
1889 ERROR:  new row violates check option for view "rw_view1"
1890 DETAIL:  Failing row contains (15, 10).
1891 UPDATE rw_view1 SET a = 20, b = 30; -- should fail
1892 ERROR:  new row violates check option for view "rw_view1"
1893 DETAIL:  Failing row contains (20, 10).
1894 DROP TABLE base_tbl CASCADE;
1895 NOTICE:  drop cascades to view rw_view1
1896 DROP FUNCTION base_tbl_trig_fn();
1897 -- WITH LOCAL CHECK OPTION with INSTEAD OF trigger on base view
1898 CREATE TABLE base_tbl (a int, b int);
1899 CREATE VIEW rw_view1 AS SELECT a FROM base_tbl WHERE a < b;
1900 CREATE FUNCTION rw_view1_trig_fn()
1901 RETURNS trigger AS
1902 $$
1903 BEGIN
1904   IF TG_OP = 'INSERT' THEN
1905     INSERT INTO base_tbl VALUES (NEW.a, 10);
1906     RETURN NEW;
1907   ELSIF TG_OP = 'UPDATE' THEN
1908     UPDATE base_tbl SET a=NEW.a WHERE a=OLD.a;
1909     RETURN NEW;
1910   ELSIF TG_OP = 'DELETE' THEN
1911     DELETE FROM base_tbl WHERE a=OLD.a;
1912     RETURN OLD;
1913   END IF;
1914 END;
1915 $$
1916 LANGUAGE plpgsql;
1917 CREATE TRIGGER rw_view1_trig
1918   INSTEAD OF INSERT OR UPDATE OR DELETE ON rw_view1
1919   FOR EACH ROW EXECUTE PROCEDURE rw_view1_trig_fn();
1920 CREATE VIEW rw_view2 AS
1921   SELECT * FROM rw_view1 WHERE a > 0 WITH LOCAL CHECK OPTION;
1922 INSERT INTO rw_view2 VALUES (-5); -- should fail
1923 ERROR:  new row violates check option for view "rw_view2"
1924 DETAIL:  Failing row contains (-5).
1925 INSERT INTO rw_view2 VALUES (5); -- ok
1926 INSERT INTO rw_view2 VALUES (50); -- ok, but not in view
1927 UPDATE rw_view2 SET a = a - 10; -- should fail
1928 ERROR:  new row violates check option for view "rw_view2"
1929 DETAIL:  Failing row contains (-5).
1930 SELECT * FROM base_tbl;
1931  a  | b  
1932 ----+----
1933   5 | 10
1934  50 | 10
1935 (2 rows)
1936
1937 -- Check option won't cascade down to base view with INSTEAD OF triggers
1938 ALTER VIEW rw_view2 SET (check_option=cascaded);
1939 INSERT INTO rw_view2 VALUES (100); -- ok, but not in view (doesn't fail rw_view1's check)
1940 UPDATE rw_view2 SET a = 200 WHERE a = 5; -- ok, but not in view (doesn't fail rw_view1's check)
1941 SELECT * FROM base_tbl;
1942   a  | b  
1943 -----+----
1944   50 | 10
1945  100 | 10
1946  200 | 10
1947 (3 rows)
1948
1949 -- Neither local nor cascaded check options work with INSTEAD rules
1950 DROP TRIGGER rw_view1_trig ON rw_view1;
1951 CREATE RULE rw_view1_ins_rule AS ON INSERT TO rw_view1
1952   DO INSTEAD INSERT INTO base_tbl VALUES (NEW.a, 10);
1953 CREATE RULE rw_view1_upd_rule AS ON UPDATE TO rw_view1
1954   DO INSTEAD UPDATE base_tbl SET a=NEW.a WHERE a=OLD.a;
1955 INSERT INTO rw_view2 VALUES (-10); -- ok, but not in view (doesn't fail rw_view2's check)
1956 INSERT INTO rw_view2 VALUES (5); -- ok
1957 INSERT INTO rw_view2 VALUES (20); -- ok, but not in view (doesn't fail rw_view1's check)
1958 UPDATE rw_view2 SET a = 30 WHERE a = 5; -- ok, but not in view (doesn't fail rw_view1's check)
1959 INSERT INTO rw_view2 VALUES (5); -- ok
1960 UPDATE rw_view2 SET a = -5 WHERE a = 5; -- ok, but not in view (doesn't fail rw_view2's check)
1961 SELECT * FROM base_tbl;
1962   a  | b  
1963 -----+----
1964   50 | 10
1965  100 | 10
1966  200 | 10
1967  -10 | 10
1968   20 | 10
1969   30 | 10
1970   -5 | 10
1971 (7 rows)
1972
1973 DROP TABLE base_tbl CASCADE;
1974 NOTICE:  drop cascades to 2 other objects
1975 DETAIL:  drop cascades to view rw_view1
1976 drop cascades to view rw_view2
1977 DROP FUNCTION rw_view1_trig_fn();
1978 CREATE TABLE base_tbl (a int);
1979 CREATE VIEW rw_view1 AS SELECT a,10 AS b FROM base_tbl;
1980 CREATE RULE rw_view1_ins_rule AS ON INSERT TO rw_view1
1981   DO INSTEAD INSERT INTO base_tbl VALUES (NEW.a);
1982 CREATE VIEW rw_view2 AS
1983   SELECT * FROM rw_view1 WHERE a > b WITH LOCAL CHECK OPTION;
1984 INSERT INTO rw_view2 VALUES (2,3); -- ok, but not in view (doesn't fail rw_view2's check)
1985 DROP TABLE base_tbl CASCADE;
1986 NOTICE:  drop cascades to 2 other objects
1987 DETAIL:  drop cascades to view rw_view1
1988 drop cascades to view rw_view2
1989 -- security barrier view
1990 CREATE TABLE base_tbl (person text, visibility text);
1991 INSERT INTO base_tbl VALUES ('Tom', 'public'),
1992                             ('Dick', 'private'),
1993                             ('Harry', 'public');
1994 CREATE VIEW rw_view1 AS
1995   SELECT person FROM base_tbl WHERE visibility = 'public';
1996 CREATE FUNCTION snoop(anyelement)
1997 RETURNS boolean AS
1998 $$
1999 BEGIN
2000   RAISE NOTICE 'snooped value: %', $1;
2001   RETURN true;
2002 END;
2003 $$
2004 LANGUAGE plpgsql COST 0.000001;
2005 CREATE OR REPLACE FUNCTION leakproof(anyelement)
2006 RETURNS boolean AS
2007 $$
2008 BEGIN
2009   RETURN true;
2010 END;
2011 $$
2012 LANGUAGE plpgsql STRICT IMMUTABLE LEAKPROOF;
2013 SELECT * FROM rw_view1 WHERE snoop(person);
2014 NOTICE:  snooped value: Tom
2015 NOTICE:  snooped value: Dick
2016 NOTICE:  snooped value: Harry
2017  person 
2018 --------
2019  Tom
2020  Harry
2021 (2 rows)
2022
2023 UPDATE rw_view1 SET person=person WHERE snoop(person);
2024 NOTICE:  snooped value: Tom
2025 NOTICE:  snooped value: Dick
2026 NOTICE:  snooped value: Harry
2027 DELETE FROM rw_view1 WHERE NOT snoop(person);
2028 NOTICE:  snooped value: Dick
2029 NOTICE:  snooped value: Tom
2030 NOTICE:  snooped value: Harry
2031 ALTER VIEW rw_view1 SET (security_barrier = true);
2032 SELECT table_name, is_insertable_into
2033   FROM information_schema.tables
2034  WHERE table_name = 'rw_view1';
2035  table_name | is_insertable_into 
2036 ------------+--------------------
2037  rw_view1   | YES
2038 (1 row)
2039
2040 SELECT table_name, is_updatable, is_insertable_into
2041   FROM information_schema.views
2042  WHERE table_name = 'rw_view1';
2043  table_name | is_updatable | is_insertable_into 
2044 ------------+--------------+--------------------
2045  rw_view1   | YES          | YES
2046 (1 row)
2047
2048 SELECT table_name, column_name, is_updatable
2049   FROM information_schema.columns
2050  WHERE table_name = 'rw_view1'
2051  ORDER BY ordinal_position;
2052  table_name | column_name | is_updatable 
2053 ------------+-------------+--------------
2054  rw_view1   | person      | YES
2055 (1 row)
2056
2057 SELECT * FROM rw_view1 WHERE snoop(person);
2058 NOTICE:  snooped value: Tom
2059 NOTICE:  snooped value: Harry
2060  person 
2061 --------
2062  Tom
2063  Harry
2064 (2 rows)
2065
2066 UPDATE rw_view1 SET person=person WHERE snoop(person);
2067 NOTICE:  snooped value: Tom
2068 NOTICE:  snooped value: Harry
2069 DELETE FROM rw_view1 WHERE NOT snoop(person);
2070 NOTICE:  snooped value: Tom
2071 NOTICE:  snooped value: Harry
2072 EXPLAIN (costs off) SELECT * FROM rw_view1 WHERE snoop(person);
2073                   QUERY PLAN                   
2074 -----------------------------------------------
2075  Subquery Scan on rw_view1
2076    Filter: snoop(rw_view1.person)
2077    ->  Seq Scan on base_tbl
2078          Filter: (visibility = 'public'::text)
2079 (4 rows)
2080
2081 EXPLAIN (costs off) UPDATE rw_view1 SET person=person WHERE snoop(person);
2082                             QUERY PLAN                             
2083 -------------------------------------------------------------------
2084  Update on base_tbl
2085    ->  Seq Scan on base_tbl
2086          Filter: ((visibility = 'public'::text) AND snoop(person))
2087 (3 rows)
2088
2089 EXPLAIN (costs off) DELETE FROM rw_view1 WHERE NOT snoop(person);
2090                                QUERY PLAN                                
2091 -------------------------------------------------------------------------
2092  Delete on base_tbl
2093    ->  Seq Scan on base_tbl
2094          Filter: ((visibility = 'public'::text) AND (NOT snoop(person)))
2095 (3 rows)
2096
2097 -- security barrier view on top of security barrier view
2098 CREATE VIEW rw_view2 WITH (security_barrier = true) AS
2099   SELECT * FROM rw_view1 WHERE snoop(person);
2100 SELECT table_name, is_insertable_into
2101   FROM information_schema.tables
2102  WHERE table_name = 'rw_view2';
2103  table_name | is_insertable_into 
2104 ------------+--------------------
2105  rw_view2   | YES
2106 (1 row)
2107
2108 SELECT table_name, is_updatable, is_insertable_into
2109   FROM information_schema.views
2110  WHERE table_name = 'rw_view2';
2111  table_name | is_updatable | is_insertable_into 
2112 ------------+--------------+--------------------
2113  rw_view2   | YES          | YES
2114 (1 row)
2115
2116 SELECT table_name, column_name, is_updatable
2117   FROM information_schema.columns
2118  WHERE table_name = 'rw_view2'
2119  ORDER BY ordinal_position;
2120  table_name | column_name | is_updatable 
2121 ------------+-------------+--------------
2122  rw_view2   | person      | YES
2123 (1 row)
2124
2125 SELECT * FROM rw_view2 WHERE snoop(person);
2126 NOTICE:  snooped value: Tom
2127 NOTICE:  snooped value: Tom
2128 NOTICE:  snooped value: Harry
2129 NOTICE:  snooped value: Harry
2130  person 
2131 --------
2132  Tom
2133  Harry
2134 (2 rows)
2135
2136 UPDATE rw_view2 SET person=person WHERE snoop(person);
2137 NOTICE:  snooped value: Tom
2138 NOTICE:  snooped value: Tom
2139 NOTICE:  snooped value: Harry
2140 NOTICE:  snooped value: Harry
2141 DELETE FROM rw_view2 WHERE NOT snoop(person);
2142 NOTICE:  snooped value: Tom
2143 NOTICE:  snooped value: Tom
2144 NOTICE:  snooped value: Harry
2145 NOTICE:  snooped value: Harry
2146 EXPLAIN (costs off) SELECT * FROM rw_view2 WHERE snoop(person);
2147                      QUERY PLAN                      
2148 -----------------------------------------------------
2149  Subquery Scan on rw_view2
2150    Filter: snoop(rw_view2.person)
2151    ->  Subquery Scan on rw_view1
2152          Filter: snoop(rw_view1.person)
2153          ->  Seq Scan on base_tbl
2154                Filter: (visibility = 'public'::text)
2155 (6 rows)
2156
2157 EXPLAIN (costs off) UPDATE rw_view2 SET person=person WHERE snoop(person);
2158                                      QUERY PLAN                                      
2159 -------------------------------------------------------------------------------------
2160  Update on base_tbl
2161    ->  Seq Scan on base_tbl
2162          Filter: ((visibility = 'public'::text) AND snoop(person) AND snoop(person))
2163 (3 rows)
2164
2165 EXPLAIN (costs off) DELETE FROM rw_view2 WHERE NOT snoop(person);
2166                                         QUERY PLAN                                         
2167 -------------------------------------------------------------------------------------------
2168  Delete on base_tbl
2169    ->  Seq Scan on base_tbl
2170          Filter: ((visibility = 'public'::text) AND snoop(person) AND (NOT snoop(person)))
2171 (3 rows)
2172
2173 DROP TABLE base_tbl CASCADE;
2174 NOTICE:  drop cascades to 2 other objects
2175 DETAIL:  drop cascades to view rw_view1
2176 drop cascades to view rw_view2
2177 -- security barrier view on top of table with rules
2178 CREATE TABLE base_tbl(id int PRIMARY KEY, data text, deleted boolean);
2179 INSERT INTO base_tbl VALUES (1, 'Row 1', false), (2, 'Row 2', true);
2180 CREATE RULE base_tbl_ins_rule AS ON INSERT TO base_tbl
2181   WHERE EXISTS (SELECT 1 FROM base_tbl t WHERE t.id = new.id)
2182   DO INSTEAD
2183     UPDATE base_tbl SET data = new.data, deleted = false WHERE id = new.id;
2184 CREATE RULE base_tbl_del_rule AS ON DELETE TO base_tbl
2185   DO INSTEAD
2186     UPDATE base_tbl SET deleted = true WHERE id = old.id;
2187 CREATE VIEW rw_view1 WITH (security_barrier=true) AS
2188   SELECT id, data FROM base_tbl WHERE NOT deleted;
2189 SELECT * FROM rw_view1;
2190  id | data  
2191 ----+-------
2192   1 | Row 1
2193 (1 row)
2194
2195 EXPLAIN (costs off) DELETE FROM rw_view1 WHERE id = 1 AND snoop(data);
2196                             QUERY PLAN                             
2197 -------------------------------------------------------------------
2198  Update on base_tbl base_tbl_1
2199    ->  Nested Loop
2200          ->  Index Scan using base_tbl_pkey on base_tbl base_tbl_1
2201                Index Cond: (id = 1)
2202          ->  Index Scan using base_tbl_pkey on base_tbl
2203                Index Cond: (id = 1)
2204                Filter: ((NOT deleted) AND snoop(data))
2205 (7 rows)
2206
2207 DELETE FROM rw_view1 WHERE id = 1 AND snoop(data);
2208 NOTICE:  snooped value: Row 1
2209 EXPLAIN (costs off) INSERT INTO rw_view1 VALUES (2, 'New row 2');
2210                         QUERY PLAN                         
2211 -----------------------------------------------------------
2212  Insert on base_tbl
2213    InitPlan 1 (returns $0)
2214      ->  Index Only Scan using base_tbl_pkey on base_tbl t
2215            Index Cond: (id = 2)
2216    ->  Result
2217          One-Time Filter: ($0 IS NOT TRUE)
2218  
2219  Update on base_tbl
2220    InitPlan 1 (returns $0)
2221      ->  Index Only Scan using base_tbl_pkey on base_tbl t
2222            Index Cond: (id = 2)
2223    ->  Result
2224          One-Time Filter: $0
2225          ->  Index Scan using base_tbl_pkey on base_tbl
2226                Index Cond: (id = 2)
2227 (15 rows)
2228
2229 INSERT INTO rw_view1 VALUES (2, 'New row 2');
2230 SELECT * FROM base_tbl;
2231  id |   data    | deleted 
2232 ----+-----------+---------
2233   1 | Row 1     | t
2234   2 | New row 2 | f
2235 (2 rows)
2236
2237 DROP TABLE base_tbl CASCADE;
2238 NOTICE:  drop cascades to view rw_view1
2239 -- security barrier view based on inheritance set
2240 CREATE TABLE t1 (a int, b float, c text);
2241 CREATE INDEX t1_a_idx ON t1(a);
2242 INSERT INTO t1
2243 SELECT i,i,'t1' FROM generate_series(1,10) g(i);
2244 ANALYZE t1;
2245 CREATE TABLE t11 (d text) INHERITS (t1);
2246 CREATE INDEX t11_a_idx ON t11(a);
2247 INSERT INTO t11
2248 SELECT i,i,'t11','t11d' FROM generate_series(1,10) g(i);
2249 ANALYZE t11;
2250 CREATE TABLE t12 (e int[]) INHERITS (t1);
2251 CREATE INDEX t12_a_idx ON t12(a);
2252 INSERT INTO t12
2253 SELECT i,i,'t12','{1,2}'::int[] FROM generate_series(1,10) g(i);
2254 ANALYZE t12;
2255 CREATE TABLE t111 () INHERITS (t11, t12);
2256 NOTICE:  merging multiple inherited definitions of column "a"
2257 NOTICE:  merging multiple inherited definitions of column "b"
2258 NOTICE:  merging multiple inherited definitions of column "c"
2259 CREATE INDEX t111_a_idx ON t111(a);
2260 INSERT INTO t111
2261 SELECT i,i,'t111','t111d','{1,1,1}'::int[] FROM generate_series(1,10) g(i);
2262 ANALYZE t111;
2263 CREATE VIEW v1 WITH (security_barrier=true) AS
2264 SELECT *, (SELECT d FROM t11 WHERE t11.a = t1.a LIMIT 1) AS d
2265 FROM t1
2266 WHERE a > 5 AND EXISTS(SELECT 1 FROM t12 WHERE t12.a = t1.a);
2267 SELECT * FROM v1 WHERE a=3; -- should not see anything
2268  a | b | c | d 
2269 ---+---+---+---
2270 (0 rows)
2271
2272 SELECT * FROM v1 WHERE a=8;
2273  a | b |  c   |  d   
2274 ---+---+------+------
2275  8 | 8 | t1   | t11d
2276  8 | 8 | t11  | t11d
2277  8 | 8 | t12  | t11d
2278  8 | 8 | t111 | t11d
2279 (4 rows)
2280
2281 EXPLAIN (VERBOSE, COSTS OFF)
2282 UPDATE v1 SET a=100 WHERE snoop(a) AND leakproof(a) AND a < 7 AND a != 6;
2283                                                         QUERY PLAN                                                         
2284 ---------------------------------------------------------------------------------------------------------------------------
2285  Update on public.t1
2286    Update on public.t1
2287    Update on public.t11
2288    Update on public.t12
2289    Update on public.t111
2290    ->  Index Scan using t1_a_idx on public.t1
2291          Output: 100, t1.b, t1.c, t1.ctid
2292          Index Cond: ((t1.a > 5) AND (t1.a < 7))
2293          Filter: ((t1.a <> 6) AND (alternatives: SubPlan 1 or hashed SubPlan 2) AND snoop(t1.a) AND leakproof(t1.a))
2294          SubPlan 1
2295            ->  Append
2296                  ->  Seq Scan on public.t12 t12_1
2297                        Filter: (t12_1.a = t1.a)
2298                  ->  Seq Scan on public.t111 t111_1
2299                        Filter: (t111_1.a = t1.a)
2300          SubPlan 2
2301            ->  Append
2302                  ->  Seq Scan on public.t12 t12_2
2303                        Output: t12_2.a
2304                  ->  Seq Scan on public.t111 t111_2
2305                        Output: t111_2.a
2306    ->  Index Scan using t11_a_idx on public.t11
2307          Output: 100, t11.b, t11.c, t11.d, t11.ctid
2308          Index Cond: ((t11.a > 5) AND (t11.a < 7))
2309          Filter: ((t11.a <> 6) AND (alternatives: SubPlan 1 or hashed SubPlan 2) AND snoop(t11.a) AND leakproof(t11.a))
2310    ->  Index Scan using t12_a_idx on public.t12
2311          Output: 100, t12.b, t12.c, t12.e, t12.ctid
2312          Index Cond: ((t12.a > 5) AND (t12.a < 7))
2313          Filter: ((t12.a <> 6) AND (alternatives: SubPlan 1 or hashed SubPlan 2) AND snoop(t12.a) AND leakproof(t12.a))
2314    ->  Index Scan using t111_a_idx on public.t111
2315          Output: 100, t111.b, t111.c, t111.d, t111.e, t111.ctid
2316          Index Cond: ((t111.a > 5) AND (t111.a < 7))
2317          Filter: ((t111.a <> 6) AND (alternatives: SubPlan 1 or hashed SubPlan 2) AND snoop(t111.a) AND leakproof(t111.a))
2318 (33 rows)
2319
2320 UPDATE v1 SET a=100 WHERE snoop(a) AND leakproof(a) AND a < 7 AND a != 6;
2321 SELECT * FROM v1 WHERE a=100; -- Nothing should have been changed to 100
2322  a | b | c | d 
2323 ---+---+---+---
2324 (0 rows)
2325
2326 SELECT * FROM t1 WHERE a=100; -- Nothing should have been changed to 100
2327  a | b | c 
2328 ---+---+---
2329 (0 rows)
2330
2331 EXPLAIN (VERBOSE, COSTS OFF)
2332 UPDATE v1 SET a=a+1 WHERE snoop(a) AND leakproof(a) AND a = 8;
2333                                                QUERY PLAN                                                
2334 ---------------------------------------------------------------------------------------------------------
2335  Update on public.t1
2336    Update on public.t1
2337    Update on public.t11
2338    Update on public.t12
2339    Update on public.t111
2340    ->  Index Scan using t1_a_idx on public.t1
2341          Output: (t1.a + 1), t1.b, t1.c, t1.ctid
2342          Index Cond: ((t1.a > 5) AND (t1.a = 8))
2343          Filter: ((alternatives: SubPlan 1 or hashed SubPlan 2) AND snoop(t1.a) AND leakproof(t1.a))
2344          SubPlan 1
2345            ->  Append
2346                  ->  Seq Scan on public.t12 t12_1
2347                        Filter: (t12_1.a = t1.a)
2348                  ->  Seq Scan on public.t111 t111_1
2349                        Filter: (t111_1.a = t1.a)
2350          SubPlan 2
2351            ->  Append
2352                  ->  Seq Scan on public.t12 t12_2
2353                        Output: t12_2.a
2354                  ->  Seq Scan on public.t111 t111_2
2355                        Output: t111_2.a
2356    ->  Index Scan using t11_a_idx on public.t11
2357          Output: (t11.a + 1), t11.b, t11.c, t11.d, t11.ctid
2358          Index Cond: ((t11.a > 5) AND (t11.a = 8))
2359          Filter: ((alternatives: SubPlan 1 or hashed SubPlan 2) AND snoop(t11.a) AND leakproof(t11.a))
2360    ->  Index Scan using t12_a_idx on public.t12
2361          Output: (t12.a + 1), t12.b, t12.c, t12.e, t12.ctid
2362          Index Cond: ((t12.a > 5) AND (t12.a = 8))
2363          Filter: ((alternatives: SubPlan 1 or hashed SubPlan 2) AND snoop(t12.a) AND leakproof(t12.a))
2364    ->  Index Scan using t111_a_idx on public.t111
2365          Output: (t111.a + 1), t111.b, t111.c, t111.d, t111.e, t111.ctid
2366          Index Cond: ((t111.a > 5) AND (t111.a = 8))
2367          Filter: ((alternatives: SubPlan 1 or hashed SubPlan 2) AND snoop(t111.a) AND leakproof(t111.a))
2368 (33 rows)
2369
2370 UPDATE v1 SET a=a+1 WHERE snoop(a) AND leakproof(a) AND a = 8;
2371 NOTICE:  snooped value: 8
2372 NOTICE:  snooped value: 8
2373 NOTICE:  snooped value: 8
2374 NOTICE:  snooped value: 8
2375 SELECT * FROM v1 WHERE b=8;
2376  a | b |  c   |  d   
2377 ---+---+------+------
2378  9 | 8 | t1   | t11d
2379  9 | 8 | t11  | t11d
2380  9 | 8 | t12  | t11d
2381  9 | 8 | t111 | t11d
2382 (4 rows)
2383
2384 DELETE FROM v1 WHERE snoop(a) AND leakproof(a); -- should not delete everything, just where a>5
2385 NOTICE:  snooped value: 6
2386 NOTICE:  snooped value: 7
2387 NOTICE:  snooped value: 9
2388 NOTICE:  snooped value: 10
2389 NOTICE:  snooped value: 9
2390 NOTICE:  snooped value: 6
2391 NOTICE:  snooped value: 7
2392 NOTICE:  snooped value: 9
2393 NOTICE:  snooped value: 10
2394 NOTICE:  snooped value: 9
2395 NOTICE:  snooped value: 6
2396 NOTICE:  snooped value: 7
2397 NOTICE:  snooped value: 9
2398 NOTICE:  snooped value: 10
2399 NOTICE:  snooped value: 9
2400 NOTICE:  snooped value: 6
2401 NOTICE:  snooped value: 7
2402 NOTICE:  snooped value: 9
2403 NOTICE:  snooped value: 10
2404 NOTICE:  snooped value: 9
2405 TABLE t1; -- verify all a<=5 are intact
2406  a | b |  c   
2407 ---+---+------
2408  1 | 1 | t1
2409  2 | 2 | t1
2410  3 | 3 | t1
2411  4 | 4 | t1
2412  5 | 5 | t1
2413  1 | 1 | t11
2414  2 | 2 | t11
2415  3 | 3 | t11
2416  4 | 4 | t11
2417  5 | 5 | t11
2418  1 | 1 | t12
2419  2 | 2 | t12
2420  3 | 3 | t12
2421  4 | 4 | t12
2422  5 | 5 | t12
2423  1 | 1 | t111
2424  2 | 2 | t111
2425  3 | 3 | t111
2426  4 | 4 | t111
2427  5 | 5 | t111
2428 (20 rows)
2429
2430 DROP TABLE t1, t11, t12, t111 CASCADE;
2431 NOTICE:  drop cascades to view v1
2432 DROP FUNCTION snoop(anyelement);
2433 DROP FUNCTION leakproof(anyelement);
2434 CREATE TABLE tx1 (a integer);
2435 CREATE TABLE tx2 (b integer);
2436 CREATE TABLE tx3 (c integer);
2437 CREATE VIEW vx1 AS SELECT a FROM tx1 WHERE EXISTS(SELECT 1 FROM tx2 JOIN tx3 ON b=c);
2438 INSERT INTO vx1 values (1);
2439 SELECT * FROM tx1;
2440  a 
2441 ---
2442  1
2443 (1 row)
2444
2445 SELECT * FROM vx1;
2446  a 
2447 ---
2448 (0 rows)
2449
2450 DROP VIEW vx1;
2451 DROP TABLE tx1;
2452 DROP TABLE tx2;
2453 DROP TABLE tx3;
2454 CREATE TABLE tx1 (a integer);
2455 CREATE TABLE tx2 (b integer);
2456 CREATE TABLE tx3 (c integer);
2457 CREATE VIEW vx1 AS SELECT a FROM tx1 WHERE EXISTS(SELECT 1 FROM tx2 JOIN tx3 ON b=c);
2458 INSERT INTO vx1 VALUES (1);
2459 INSERT INTO vx1 VALUES (1);
2460 SELECT * FROM tx1;
2461  a 
2462 ---
2463  1
2464  1
2465 (2 rows)
2466
2467 SELECT * FROM vx1;
2468  a 
2469 ---
2470 (0 rows)
2471
2472 DROP VIEW vx1;
2473 DROP TABLE tx1;
2474 DROP TABLE tx2;
2475 DROP TABLE tx3;
2476 CREATE TABLE tx1 (a integer, b integer);
2477 CREATE TABLE tx2 (b integer, c integer);
2478 CREATE TABLE tx3 (c integer, d integer);
2479 ALTER TABLE tx1 DROP COLUMN b;
2480 ALTER TABLE tx2 DROP COLUMN c;
2481 ALTER TABLE tx3 DROP COLUMN d;
2482 CREATE VIEW vx1 AS SELECT a FROM tx1 WHERE EXISTS(SELECT 1 FROM tx2 JOIN tx3 ON b=c);
2483 INSERT INTO vx1 VALUES (1);
2484 INSERT INTO vx1 VALUES (1);
2485 SELECT * FROM tx1;
2486  a 
2487 ---
2488  1
2489  1
2490 (2 rows)
2491
2492 SELECT * FROM vx1;
2493  a 
2494 ---
2495 (0 rows)
2496
2497 DROP VIEW vx1;
2498 DROP TABLE tx1;
2499 DROP TABLE tx2;
2500 DROP TABLE tx3;
2501 --
2502 -- Test handling of vars from correlated subqueries in quals from outer
2503 -- security barrier views, per bug #13988
2504 --
2505 CREATE TABLE t1 (a int, b text, c int);
2506 INSERT INTO t1 VALUES (1, 'one', 10);
2507 CREATE TABLE t2 (cc int);
2508 INSERT INTO t2 VALUES (10), (20);
2509 CREATE VIEW v1 WITH (security_barrier = true) AS
2510   SELECT * FROM t1 WHERE (a > 0)
2511   WITH CHECK OPTION;
2512 CREATE VIEW v2 WITH (security_barrier = true) AS
2513   SELECT * FROM v1 WHERE EXISTS (SELECT 1 FROM t2 WHERE t2.cc = v1.c)
2514   WITH CHECK OPTION;
2515 INSERT INTO v2 VALUES (2, 'two', 20); -- ok
2516 INSERT INTO v2 VALUES (-2, 'minus two', 20); -- not allowed
2517 ERROR:  new row violates check option for view "v1"
2518 DETAIL:  Failing row contains (-2, minus two, 20).
2519 INSERT INTO v2 VALUES (3, 'three', 30); -- not allowed
2520 ERROR:  new row violates check option for view "v2"
2521 DETAIL:  Failing row contains (3, three, 30).
2522 UPDATE v2 SET b = 'ONE' WHERE a = 1; -- ok
2523 UPDATE v2 SET a = -1 WHERE a = 1; -- not allowed
2524 ERROR:  new row violates check option for view "v1"
2525 DETAIL:  Failing row contains (-1, ONE, 10).
2526 UPDATE v2 SET c = 30 WHERE a = 1; -- not allowed
2527 ERROR:  new row violates check option for view "v2"
2528 DETAIL:  Failing row contains (1, ONE, 30).
2529 DELETE FROM v2 WHERE a = 2; -- ok
2530 SELECT * FROM v2;
2531  a |  b  | c  
2532 ---+-----+----
2533  1 | ONE | 10
2534 (1 row)
2535
2536 DROP VIEW v2;
2537 DROP VIEW v1;
2538 DROP TABLE t2;
2539 DROP TABLE t1;
2540 --
2541 -- Test CREATE OR REPLACE VIEW turning a non-updatable view into an
2542 -- auto-updatable view and adding check options in a single step
2543 --
2544 CREATE TABLE t1 (a int, b text);
2545 CREATE VIEW v1 AS SELECT null::int AS a;
2546 CREATE OR REPLACE VIEW v1 AS SELECT * FROM t1 WHERE a > 0 WITH CHECK OPTION;
2547 INSERT INTO v1 VALUES (1, 'ok'); -- ok
2548 INSERT INTO v1 VALUES (-1, 'invalid'); -- should fail
2549 ERROR:  new row violates check option for view "v1"
2550 DETAIL:  Failing row contains (-1, invalid).
2551 DROP VIEW v1;
2552 DROP TABLE t1;
2553 -- check that an auto-updatable view on a partitioned table works correctly
2554 create table uv_pt (a int, b int, v varchar) partition by range (a, b);
2555 create table uv_pt1 (b int not null, v varchar, a int not null) partition by range (b);
2556 create table uv_pt11 (like uv_pt1);
2557 alter table uv_pt11 drop a;
2558 alter table uv_pt11 add a int;
2559 alter table uv_pt11 drop a;
2560 alter table uv_pt11 add a int not null;
2561 alter table uv_pt1 attach partition uv_pt11 for values from (2) to (5);
2562 alter table uv_pt attach partition uv_pt1 for values from (1, 2) to (1, 10);
2563 create view uv_ptv as select * from uv_pt;
2564 select events & 4 != 0 AS upd,
2565        events & 8 != 0 AS ins,
2566        events & 16 != 0 AS del
2567   from pg_catalog.pg_relation_is_updatable('uv_pt'::regclass, false) t(events);
2568  upd | ins | del 
2569 -----+-----+-----
2570  t   | t   | t
2571 (1 row)
2572
2573 select pg_catalog.pg_column_is_updatable('uv_pt'::regclass, 1::smallint, false);
2574  pg_column_is_updatable 
2575 ------------------------
2576  t
2577 (1 row)
2578
2579 select pg_catalog.pg_column_is_updatable('uv_pt'::regclass, 2::smallint, false);
2580  pg_column_is_updatable 
2581 ------------------------
2582  t
2583 (1 row)
2584
2585 select table_name, is_updatable, is_insertable_into
2586   from information_schema.views where table_name = 'uv_ptv';
2587  table_name | is_updatable | is_insertable_into 
2588 ------------+--------------+--------------------
2589  uv_ptv     | YES          | YES
2590 (1 row)
2591
2592 select table_name, column_name, is_updatable
2593   from information_schema.columns where table_name = 'uv_ptv' order by column_name;
2594  table_name | column_name | is_updatable 
2595 ------------+-------------+--------------
2596  uv_ptv     | a           | YES
2597  uv_ptv     | b           | YES
2598  uv_ptv     | v           | YES
2599 (3 rows)
2600
2601 insert into uv_ptv values (1, 2);
2602 select tableoid::regclass, * from uv_pt;
2603  tableoid | a | b | v 
2604 ----------+---+---+---
2605  uv_pt11  | 1 | 2 | 
2606 (1 row)
2607
2608 create view uv_ptv_wco as select * from uv_pt where a = 0 with check option;
2609 insert into uv_ptv_wco values (1, 2);
2610 ERROR:  new row violates check option for view "uv_ptv_wco"
2611 DETAIL:  Failing row contains (1, 2, null).
2612 drop view uv_ptv, uv_ptv_wco;
2613 drop table uv_pt, uv_pt1, uv_pt11;
2614 -- check that wholerow vars appearing in WITH CHECK OPTION constraint expressions
2615 -- work fine with partitioned tables
2616 create table wcowrtest (a int) partition by list (a);
2617 create table wcowrtest1 partition of wcowrtest for values in (1);
2618 create view wcowrtest_v as select * from wcowrtest where wcowrtest = '(2)'::wcowrtest with check option;
2619 insert into wcowrtest_v values (1);
2620 ERROR:  new row violates check option for view "wcowrtest_v"
2621 DETAIL:  Failing row contains (1).
2622 alter table wcowrtest add b text;
2623 create table wcowrtest2 (b text, c int, a int);
2624 alter table wcowrtest2 drop c;
2625 alter table wcowrtest attach partition wcowrtest2 for values in (2);
2626 create table sometable (a int, b text);
2627 insert into sometable values (1, 'a'), (2, 'b');
2628 create view wcowrtest_v2 as
2629     select *
2630       from wcowrtest r
2631       where r in (select s from sometable s where r.a = s.a)
2632 with check option;
2633 -- WITH CHECK qual will be processed with wcowrtest2's
2634 -- rowtype after tuple-routing
2635 insert into wcowrtest_v2 values (2, 'no such row in sometable');
2636 ERROR:  new row violates check option for view "wcowrtest_v2"
2637 DETAIL:  Failing row contains (2, no such row in sometable).
2638 drop view wcowrtest_v, wcowrtest_v2;
2639 drop table wcowrtest, sometable;
2640 -- Check INSERT .. ON CONFLICT DO UPDATE works correctly when the view's
2641 -- columns are named and ordered differently than the underlying table's.
2642 create table uv_iocu_tab (a text unique, b float);
2643 insert into uv_iocu_tab values ('xyxyxy', 0);
2644 create view uv_iocu_view as
2645    select b, b+1 as c, a, '2.0'::text as two from uv_iocu_tab;
2646 insert into uv_iocu_view (a, b) values ('xyxyxy', 1)
2647    on conflict (a) do update set b = uv_iocu_view.b;
2648 select * from uv_iocu_tab;
2649    a    | b 
2650 --------+---
2651  xyxyxy | 0
2652 (1 row)
2653
2654 insert into uv_iocu_view (a, b) values ('xyxyxy', 1)
2655    on conflict (a) do update set b = excluded.b;
2656 select * from uv_iocu_tab;
2657    a    | b 
2658 --------+---
2659  xyxyxy | 1
2660 (1 row)
2661
2662 -- OK to access view columns that are not present in underlying base
2663 -- relation in the ON CONFLICT portion of the query
2664 insert into uv_iocu_view (a, b) values ('xyxyxy', 3)
2665    on conflict (a) do update set b = cast(excluded.two as float);
2666 select * from uv_iocu_tab;
2667    a    | b 
2668 --------+---
2669  xyxyxy | 2
2670 (1 row)
2671
2672 explain (costs off)
2673 insert into uv_iocu_view (a, b) values ('xyxyxy', 3)
2674    on conflict (a) do update set b = excluded.b where excluded.c > 0;
2675                                     QUERY PLAN                                     
2676 -----------------------------------------------------------------------------------
2677  Insert on uv_iocu_tab
2678    Conflict Resolution: UPDATE
2679    Conflict Arbiter Indexes: uv_iocu_tab_a_key
2680    Conflict Filter: ((excluded.b + '1'::double precision) > '0'::double precision)
2681    ->  Result
2682 (5 rows)
2683
2684 insert into uv_iocu_view (a, b) values ('xyxyxy', 3)
2685    on conflict (a) do update set b = excluded.b where excluded.c > 0;
2686 select * from uv_iocu_tab;
2687    a    | b 
2688 --------+---
2689  xyxyxy | 3
2690 (1 row)
2691
2692 drop view uv_iocu_view;
2693 drop table uv_iocu_tab;
2694 -- Test whole-row references to the view
2695 create table uv_iocu_tab (a int unique, b text);
2696 create view uv_iocu_view as
2697     select b as bb, a as aa, uv_iocu_tab::text as cc from uv_iocu_tab;
2698 insert into uv_iocu_view (aa,bb) values (1,'x');
2699 explain (costs off)
2700 insert into uv_iocu_view (aa,bb) values (1,'y')
2701    on conflict (aa) do update set bb = 'Rejected: '||excluded.*
2702    where excluded.aa > 0
2703    and excluded.bb != ''
2704    and excluded.cc is not null;
2705                                                QUERY PLAN                                                
2706 ---------------------------------------------------------------------------------------------------------
2707  Insert on uv_iocu_tab
2708    Conflict Resolution: UPDATE
2709    Conflict Arbiter Indexes: uv_iocu_tab_a_key
2710    Conflict Filter: ((excluded.a > 0) AND (excluded.b <> ''::text) AND ((excluded.*)::text IS NOT NULL))
2711    ->  Result
2712 (5 rows)
2713
2714 insert into uv_iocu_view (aa,bb) values (1,'y')
2715    on conflict (aa) do update set bb = 'Rejected: '||excluded.*
2716    where excluded.aa > 0
2717    and excluded.bb != ''
2718    and excluded.cc is not null;
2719 select * from uv_iocu_view;
2720            bb            | aa |               cc                
2721 -------------------------+----+---------------------------------
2722  Rejected: (y,1,"(1,y)") |  1 | (1,"Rejected: (y,1,""(1,y)"")")
2723 (1 row)
2724
2725 -- Test omitting a column of the base relation
2726 delete from uv_iocu_view;
2727 insert into uv_iocu_view (aa,bb) values (1,'x');
2728 insert into uv_iocu_view (aa) values (1)
2729    on conflict (aa) do update set bb = 'Rejected: '||excluded.*;
2730 select * from uv_iocu_view;
2731           bb           | aa |              cc               
2732 -----------------------+----+-------------------------------
2733  Rejected: (,1,"(1,)") |  1 | (1,"Rejected: (,1,""(1,)"")")
2734 (1 row)
2735
2736 alter table uv_iocu_tab alter column b set default 'table default';
2737 insert into uv_iocu_view (aa) values (1)
2738    on conflict (aa) do update set bb = 'Rejected: '||excluded.*;
2739 select * from uv_iocu_view;
2740                           bb                           | aa |                                 cc                                  
2741 -------------------------------------------------------+----+---------------------------------------------------------------------
2742  Rejected: ("table default",1,"(1,""table default"")") |  1 | (1,"Rejected: (""table default"",1,""(1,""""table default"""")"")")
2743 (1 row)
2744
2745 alter view uv_iocu_view alter column bb set default 'view default';
2746 insert into uv_iocu_view (aa) values (1)
2747    on conflict (aa) do update set bb = 'Rejected: '||excluded.*;
2748 select * from uv_iocu_view;
2749                          bb                          | aa |                                cc                                 
2750 -----------------------------------------------------+----+-------------------------------------------------------------------
2751  Rejected: ("view default",1,"(1,""view default"")") |  1 | (1,"Rejected: (""view default"",1,""(1,""""view default"""")"")")
2752 (1 row)
2753
2754 -- Should fail to update non-updatable columns
2755 insert into uv_iocu_view (aa) values (1)
2756    on conflict (aa) do update set cc = 'XXX';
2757 ERROR:  cannot insert into column "cc" of view "uv_iocu_view"
2758 DETAIL:  View columns that are not columns of their base relation are not updatable.
2759 drop view uv_iocu_view;
2760 drop table uv_iocu_tab;
2761 -- ON CONFLICT DO UPDATE permissions checks
2762 create user regress_view_user1;
2763 create user regress_view_user2;
2764 set session authorization regress_view_user1;
2765 create table base_tbl(a int unique, b text, c float);
2766 insert into base_tbl values (1,'xxx',1.0);
2767 create view rw_view1 as select b as bb, c as cc, a as aa from base_tbl;
2768 grant select (aa,bb) on rw_view1 to regress_view_user2;
2769 grant insert on rw_view1 to regress_view_user2;
2770 grant update (bb) on rw_view1 to regress_view_user2;
2771 set session authorization regress_view_user2;
2772 insert into rw_view1 values ('yyy',2.0,1)
2773   on conflict (aa) do update set bb = excluded.cc; -- Not allowed
2774 ERROR:  permission denied for view rw_view1
2775 insert into rw_view1 values ('yyy',2.0,1)
2776   on conflict (aa) do update set bb = rw_view1.cc; -- Not allowed
2777 ERROR:  permission denied for view rw_view1
2778 insert into rw_view1 values ('yyy',2.0,1)
2779   on conflict (aa) do update set bb = excluded.bb; -- OK
2780 insert into rw_view1 values ('zzz',2.0,1)
2781   on conflict (aa) do update set bb = rw_view1.bb||'xxx'; -- OK
2782 insert into rw_view1 values ('zzz',2.0,1)
2783   on conflict (aa) do update set cc = 3.0; -- Not allowed
2784 ERROR:  permission denied for view rw_view1
2785 reset session authorization;
2786 select * from base_tbl;
2787  a |   b    | c 
2788 ---+--------+---
2789  1 | yyyxxx | 1
2790 (1 row)
2791
2792 set session authorization regress_view_user1;
2793 grant select (a,b) on base_tbl to regress_view_user2;
2794 grant insert (a,b) on base_tbl to regress_view_user2;
2795 grant update (a,b) on base_tbl to regress_view_user2;
2796 set session authorization regress_view_user2;
2797 create view rw_view2 as select b as bb, c as cc, a as aa from base_tbl;
2798 insert into rw_view2 (aa,bb) values (1,'xxx')
2799   on conflict (aa) do update set bb = excluded.bb; -- Not allowed
2800 ERROR:  permission denied for table base_tbl
2801 create view rw_view3 as select b as bb, a as aa from base_tbl;
2802 insert into rw_view3 (aa,bb) values (1,'xxx')
2803   on conflict (aa) do update set bb = excluded.bb; -- OK
2804 reset session authorization;
2805 select * from base_tbl;
2806  a |  b  | c 
2807 ---+-----+---
2808  1 | xxx | 1
2809 (1 row)
2810
2811 set session authorization regress_view_user2;
2812 create view rw_view4 as select aa, bb, cc FROM rw_view1;
2813 insert into rw_view4 (aa,bb) values (1,'yyy')
2814   on conflict (aa) do update set bb = excluded.bb; -- Not allowed
2815 ERROR:  permission denied for view rw_view1
2816 create view rw_view5 as select aa, bb FROM rw_view1;
2817 insert into rw_view5 (aa,bb) values (1,'yyy')
2818   on conflict (aa) do update set bb = excluded.bb; -- OK
2819 reset session authorization;
2820 select * from base_tbl;
2821  a |  b  | c 
2822 ---+-----+---
2823  1 | yyy | 1
2824 (1 row)
2825
2826 drop view rw_view5;
2827 drop view rw_view4;
2828 drop view rw_view3;
2829 drop view rw_view2;
2830 drop view rw_view1;
2831 drop table base_tbl;
2832 drop user regress_view_user1;
2833 drop user regress_view_user2;
2834 -- Test single- and multi-row inserts with table and view defaults.
2835 -- Table defaults should be used, unless overridden by view defaults.
2836 create table base_tab_def (a int, b text default 'Table default',
2837                            c text default 'Table default', d text, e text);
2838 create view base_tab_def_view as select * from base_tab_def;
2839 alter view base_tab_def_view alter b set default 'View default';
2840 alter view base_tab_def_view alter d set default 'View default';
2841 insert into base_tab_def values (1);
2842 insert into base_tab_def values (2), (3);
2843 insert into base_tab_def values (4, default, default, default, default);
2844 insert into base_tab_def values (5, default, default, default, default),
2845                                 (6, default, default, default, default);
2846 insert into base_tab_def_view values (11);
2847 insert into base_tab_def_view values (12), (13);
2848 insert into base_tab_def_view values (14, default, default, default, default);
2849 insert into base_tab_def_view values (15, default, default, default, default),
2850                                      (16, default, default, default, default);
2851 insert into base_tab_def_view values (17), (default);
2852 select * from base_tab_def order by a;
2853  a  |       b       |       c       |      d       | e 
2854 ----+---------------+---------------+--------------+---
2855   1 | Table default | Table default |              | 
2856   2 | Table default | Table default |              | 
2857   3 | Table default | Table default |              | 
2858   4 | Table default | Table default |              | 
2859   5 | Table default | Table default |              | 
2860   6 | Table default | Table default |              | 
2861  11 | View default  | Table default | View default | 
2862  12 | View default  | Table default | View default | 
2863  13 | View default  | Table default | View default | 
2864  14 | View default  | Table default | View default | 
2865  15 | View default  | Table default | View default | 
2866  16 | View default  | Table default | View default | 
2867  17 | View default  | Table default | View default | 
2868     | View default  | Table default | View default | 
2869 (14 rows)
2870
2871 -- Adding an INSTEAD OF trigger should cause NULLs to be inserted instead of
2872 -- table defaults, where there are no view defaults.
2873 create function base_tab_def_view_instrig_func() returns trigger
2874 as
2875 $$
2876 begin
2877   insert into base_tab_def values (new.a, new.b, new.c, new.d, new.e);
2878   return new;
2879 end;
2880 $$
2881 language plpgsql;
2882 create trigger base_tab_def_view_instrig instead of insert on base_tab_def_view
2883   for each row execute function base_tab_def_view_instrig_func();
2884 truncate base_tab_def;
2885 insert into base_tab_def values (1);
2886 insert into base_tab_def values (2), (3);
2887 insert into base_tab_def values (4, default, default, default, default);
2888 insert into base_tab_def values (5, default, default, default, default),
2889                                 (6, default, default, default, default);
2890 insert into base_tab_def_view values (11);
2891 insert into base_tab_def_view values (12), (13);
2892 insert into base_tab_def_view values (14, default, default, default, default);
2893 insert into base_tab_def_view values (15, default, default, default, default),
2894                                      (16, default, default, default, default);
2895 insert into base_tab_def_view values (17), (default);
2896 select * from base_tab_def order by a;
2897  a  |       b       |       c       |      d       | e 
2898 ----+---------------+---------------+--------------+---
2899   1 | Table default | Table default |              | 
2900   2 | Table default | Table default |              | 
2901   3 | Table default | Table default |              | 
2902   4 | Table default | Table default |              | 
2903   5 | Table default | Table default |              | 
2904   6 | Table default | Table default |              | 
2905  11 | View default  |               | View default | 
2906  12 | View default  |               | View default | 
2907  13 | View default  |               | View default | 
2908  14 | View default  |               | View default | 
2909  15 | View default  |               | View default | 
2910  16 | View default  |               | View default | 
2911  17 | View default  |               | View default | 
2912     | View default  |               | View default | 
2913 (14 rows)
2914
2915 -- Using an unconditional DO INSTEAD rule should also cause NULLs to be
2916 -- inserted where there are no view defaults.
2917 drop trigger base_tab_def_view_instrig on base_tab_def_view;
2918 drop function base_tab_def_view_instrig_func;
2919 create rule base_tab_def_view_ins_rule as on insert to base_tab_def_view
2920   do instead insert into base_tab_def values (new.a, new.b, new.c, new.d, new.e);
2921 truncate base_tab_def;
2922 insert into base_tab_def values (1);
2923 insert into base_tab_def values (2), (3);
2924 insert into base_tab_def values (4, default, default, default, default);
2925 insert into base_tab_def values (5, default, default, default, default),
2926                                 (6, default, default, default, default);
2927 insert into base_tab_def_view values (11);
2928 insert into base_tab_def_view values (12), (13);
2929 insert into base_tab_def_view values (14, default, default, default, default);
2930 insert into base_tab_def_view values (15, default, default, default, default),
2931                                      (16, default, default, default, default);
2932 insert into base_tab_def_view values (17), (default);
2933 select * from base_tab_def order by a;
2934  a  |       b       |       c       |      d       | e 
2935 ----+---------------+---------------+--------------+---
2936   1 | Table default | Table default |              | 
2937   2 | Table default | Table default |              | 
2938   3 | Table default | Table default |              | 
2939   4 | Table default | Table default |              | 
2940   5 | Table default | Table default |              | 
2941   6 | Table default | Table default |              | 
2942  11 | View default  |               | View default | 
2943  12 | View default  |               | View default | 
2944  13 | View default  |               | View default | 
2945  14 | View default  |               | View default | 
2946  15 | View default  |               | View default | 
2947  16 | View default  |               | View default | 
2948  17 | View default  |               | View default | 
2949     | View default  |               | View default | 
2950 (14 rows)
2951
2952 -- A DO ALSO rule should cause each row to be inserted twice. The first
2953 -- insert should behave the same as an auto-updatable view (using table
2954 -- defaults, unless overridden by view defaults). The second insert should
2955 -- behave the same as a rule-updatable view (inserting NULLs where there are
2956 -- no view defaults).
2957 drop rule base_tab_def_view_ins_rule on base_tab_def_view;
2958 create rule base_tab_def_view_ins_rule as on insert to base_tab_def_view
2959   do also insert into base_tab_def values (new.a, new.b, new.c, new.d, new.e);
2960 truncate base_tab_def;
2961 insert into base_tab_def values (1);
2962 insert into base_tab_def values (2), (3);
2963 insert into base_tab_def values (4, default, default, default, default);
2964 insert into base_tab_def values (5, default, default, default, default),
2965                                 (6, default, default, default, default);
2966 insert into base_tab_def_view values (11);
2967 insert into base_tab_def_view values (12), (13);
2968 insert into base_tab_def_view values (14, default, default, default, default);
2969 insert into base_tab_def_view values (15, default, default, default, default),
2970                                      (16, default, default, default, default);
2971 insert into base_tab_def_view values (17), (default);
2972 select * from base_tab_def order by a, c NULLS LAST;
2973  a  |       b       |       c       |      d       | e 
2974 ----+---------------+---------------+--------------+---
2975   1 | Table default | Table default |              | 
2976   2 | Table default | Table default |              | 
2977   3 | Table default | Table default |              | 
2978   4 | Table default | Table default |              | 
2979   5 | Table default | Table default |              | 
2980   6 | Table default | Table default |              | 
2981  11 | View default  | Table default | View default | 
2982  11 | View default  |               | View default | 
2983  12 | View default  | Table default | View default | 
2984  12 | View default  |               | View default | 
2985  13 | View default  | Table default | View default | 
2986  13 | View default  |               | View default | 
2987  14 | View default  | Table default | View default | 
2988  14 | View default  |               | View default | 
2989  15 | View default  | Table default | View default | 
2990  15 | View default  |               | View default | 
2991  16 | View default  | Table default | View default | 
2992  16 | View default  |               | View default | 
2993  17 | View default  | Table default | View default | 
2994  17 | View default  |               | View default | 
2995     | View default  | Table default | View default | 
2996     | View default  |               | View default | 
2997 (22 rows)
2998
2999 drop view base_tab_def_view;
3000 drop table base_tab_def;
3001 -- Test defaults with array assignments
3002 create table base_tab (a serial, b int[], c text, d text default 'Table default');
3003 create view base_tab_view as select c, a, b from base_tab;
3004 alter view base_tab_view alter column c set default 'View default';
3005 insert into base_tab_view (b[1], b[2], c, b[5], b[4], a, b[3])
3006 values (1, 2, default, 5, 4, default, 3), (10, 11, 'C value', 14, 13, 100, 12);
3007 select * from base_tab order by a;
3008   a  |        b         |      c       |       d       
3009 -----+------------------+--------------+---------------
3010    1 | {1,2,3,4,5}      | View default | Table default
3011  100 | {10,11,12,13,14} | C value      | Table default
3012 (2 rows)
3013
3014 drop view base_tab_view;
3015 drop table base_tab;