1--
2-- RULES
3-- From Jan's original setup_ruletest.sql and run_ruletest.sql
4-- - thomas 1998-09-13
5--
6
7--
8-- Tables and rules for the view test
9--
10create table rtest_t1 (a int4, b int4);
11create table rtest_t2 (a int4, b int4);
12create table rtest_t3 (a int4, b int4);
13
14create view rtest_v1 as select * from rtest_t1;
15create rule rtest_v1_ins as on insert to rtest_v1 do instead
16	insert into rtest_t1 values (new.a, new.b);
17create rule rtest_v1_upd as on update to rtest_v1 do instead
18	update rtest_t1 set a = new.a, b = new.b
19	where a = old.a;
20create rule rtest_v1_del as on delete to rtest_v1 do instead
21	delete from rtest_t1 where a = old.a;
22-- Test comments
23COMMENT ON RULE rtest_v1_bad ON rtest_v1 IS 'bad rule';
24COMMENT ON RULE rtest_v1_del ON rtest_v1 IS 'delete rule';
25COMMENT ON RULE rtest_v1_del ON rtest_v1 IS NULL;
26--
27-- Tables and rules for the constraint update/delete test
28--
29-- Note:
30-- 	Now that we have multiple action rule support, we check
31-- 	both possible syntaxes to define them (The last action
32--  can but must not have a semicolon at the end).
33--
34create table rtest_system (sysname text, sysdesc text);
35create table rtest_interface (sysname text, ifname text);
36create table rtest_person (pname text, pdesc text);
37create table rtest_admin (pname text, sysname text);
38
39create rule rtest_sys_upd as on update to rtest_system do also (
40	update rtest_interface set sysname = new.sysname
41		where sysname = old.sysname;
42	update rtest_admin set sysname = new.sysname
43		where sysname = old.sysname
44	);
45
46create rule rtest_sys_del as on delete to rtest_system do also (
47	delete from rtest_interface where sysname = old.sysname;
48	delete from rtest_admin where sysname = old.sysname;
49	);
50
51create rule rtest_pers_upd as on update to rtest_person do also
52	update rtest_admin set pname = new.pname where pname = old.pname;
53
54create rule rtest_pers_del as on delete to rtest_person do also
55	delete from rtest_admin where pname = old.pname;
56
57--
58-- Tables and rules for the logging test
59--
60create table rtest_emp (ename char(20), salary money);
61create table rtest_emplog (ename char(20), who name, action char(10), newsal money, oldsal money);
62create table rtest_empmass (ename char(20), salary money);
63
64create rule rtest_emp_ins as on insert to rtest_emp do
65	insert into rtest_emplog values (new.ename, current_user,
66			'hired', new.salary, '0.00');
67
68create rule rtest_emp_upd as on update to rtest_emp where new.salary != old.salary do
69	insert into rtest_emplog values (new.ename, current_user,
70			'honored', new.salary, old.salary);
71
72create rule rtest_emp_del as on delete to rtest_emp do
73	insert into rtest_emplog values (old.ename, current_user,
74			'fired', '0.00', old.salary);
75
76--
77-- Tables and rules for the multiple cascaded qualified instead
78-- rule test
79--
80create table rtest_t4 (a int4, b text);
81create table rtest_t5 (a int4, b text);
82create table rtest_t6 (a int4, b text);
83create table rtest_t7 (a int4, b text);
84create table rtest_t8 (a int4, b text);
85create table rtest_t9 (a int4, b text);
86
87create rule rtest_t4_ins1 as on insert to rtest_t4
88		where new.a >= 10 and new.a < 20 do instead
89	insert into rtest_t5 values (new.a, new.b);
90
91create rule rtest_t4_ins2 as on insert to rtest_t4
92		where new.a >= 20 and new.a < 30 do
93	insert into rtest_t6 values (new.a, new.b);
94
95create rule rtest_t5_ins as on insert to rtest_t5
96		where new.a > 15 do
97	insert into rtest_t7 values (new.a, new.b);
98
99create rule rtest_t6_ins as on insert to rtest_t6
100		where new.a > 25 do instead
101	insert into rtest_t8 values (new.a, new.b);
102
103--
104-- Tables and rules for the rule fire order test
105--
106-- As of PG 7.3, the rules should fire in order by name, regardless
107-- of INSTEAD attributes or creation order.
108--
109create table rtest_order1 (a int4);
110create table rtest_order2 (a int4, b int4, c text);
111
112create sequence rtest_seq;
113
114create rule rtest_order_r3 as on insert to rtest_order1 do instead
115	insert into rtest_order2 values (new.a, nextval('rtest_seq'),
116		'rule 3 - this should run 3rd');
117
118create rule rtest_order_r4 as on insert to rtest_order1
119		where a < 100 do instead
120	insert into rtest_order2 values (new.a, nextval('rtest_seq'),
121		'rule 4 - this should run 4th');
122
123create rule rtest_order_r2 as on insert to rtest_order1 do
124	insert into rtest_order2 values (new.a, nextval('rtest_seq'),
125		'rule 2 - this should run 2nd');
126
127create rule rtest_order_r1 as on insert to rtest_order1 do instead
128	insert into rtest_order2 values (new.a, nextval('rtest_seq'),
129		'rule 1 - this should run 1st');
130
131--
132-- Tables and rules for the instead nothing test
133--
134create table rtest_nothn1 (a int4, b text);
135create table rtest_nothn2 (a int4, b text);
136create table rtest_nothn3 (a int4, b text);
137create table rtest_nothn4 (a int4, b text);
138
139create rule rtest_nothn_r1 as on insert to rtest_nothn1
140	where new.a >= 10 and new.a < 20 do instead nothing;
141
142create rule rtest_nothn_r2 as on insert to rtest_nothn1
143	where new.a >= 30 and new.a < 40 do instead nothing;
144
145create rule rtest_nothn_r3 as on insert to rtest_nothn2
146	where new.a >= 100 do instead
147	insert into rtest_nothn3 values (new.a, new.b);
148
149create rule rtest_nothn_r4 as on insert to rtest_nothn2
150	do instead nothing;
151
152--
153-- Tests on a view that is select * of a table
154-- and has insert/update/delete instead rules to
155-- behave close like the real table.
156--
157
158--
159-- We need test date later
160--
161insert into rtest_t2 values (1, 21);
162insert into rtest_t2 values (2, 22);
163insert into rtest_t2 values (3, 23);
164
165insert into rtest_t3 values (1, 31);
166insert into rtest_t3 values (2, 32);
167insert into rtest_t3 values (3, 33);
168insert into rtest_t3 values (4, 34);
169insert into rtest_t3 values (5, 35);
170
171-- insert values
172insert into rtest_v1 values (1, 11);
173insert into rtest_v1 values (2, 12);
174select * from rtest_v1;
175
176-- delete with constant expression
177delete from rtest_v1 where a = 1;
178select * from rtest_v1;
179insert into rtest_v1 values (1, 11);
180delete from rtest_v1 where b = 12;
181select * from rtest_v1;
182insert into rtest_v1 values (2, 12);
183insert into rtest_v1 values (2, 13);
184select * from rtest_v1;
185** Remember the delete rule on rtest_v1: It says
186** DO INSTEAD DELETE FROM rtest_t1 WHERE a = old.a
187** So this time both rows with a = 2 must get deleted
188\p
189\r
190delete from rtest_v1 where b = 12;
191select * from rtest_v1;
192delete from rtest_v1;
193
194-- insert select
195insert into rtest_v1 select * from rtest_t2;
196select * from rtest_v1;
197delete from rtest_v1;
198
199-- same with swapped targetlist
200insert into rtest_v1 (b, a) select b, a from rtest_t2;
201select * from rtest_v1;
202
203-- now with only one target attribute
204insert into rtest_v1 (a) select a from rtest_t3;
205select * from rtest_v1;
206select * from rtest_v1 where b isnull;
207
208-- let attribute a differ (must be done on rtest_t1 - see above)
209update rtest_t1 set a = a + 10 where b isnull;
210delete from rtest_v1 where b isnull;
211select * from rtest_v1;
212
213-- now updates with constant expression
214update rtest_v1 set b = 42 where a = 2;
215select * from rtest_v1;
216update rtest_v1 set b = 99 where b = 42;
217select * from rtest_v1;
218update rtest_v1 set b = 88 where b < 50;
219select * from rtest_v1;
220delete from rtest_v1;
221insert into rtest_v1 select rtest_t2.a, rtest_t3.b
222    from rtest_t2, rtest_t3
223    where rtest_t2.a = rtest_t3.a;
224select * from rtest_v1;
225
226-- updates in a mergejoin
227update rtest_v1 set b = rtest_t2.b from rtest_t2 where rtest_v1.a = rtest_t2.a;
228select * from rtest_v1;
229insert into rtest_v1 select * from rtest_t3;
230select * from rtest_v1;
231update rtest_t1 set a = a + 10 where b > 30;
232select * from rtest_v1;
233update rtest_v1 set a = rtest_t3.a + 20 from rtest_t3 where rtest_v1.b = rtest_t3.b;
234select * from rtest_v1;
235
236--
237-- Test for constraint updates/deletes
238--
239insert into rtest_system values ('orion', 'Linux Jan Wieck');
240insert into rtest_system values ('notjw', 'WinNT Jan Wieck (notebook)');
241insert into rtest_system values ('neptun', 'Fileserver');
242
243insert into rtest_interface values ('orion', 'eth0');
244insert into rtest_interface values ('orion', 'eth1');
245insert into rtest_interface values ('notjw', 'eth0');
246insert into rtest_interface values ('neptun', 'eth0');
247
248insert into rtest_person values ('jw', 'Jan Wieck');
249insert into rtest_person values ('bm', 'Bruce Momjian');
250
251insert into rtest_admin values ('jw', 'orion');
252insert into rtest_admin values ('jw', 'notjw');
253insert into rtest_admin values ('bm', 'neptun');
254
255update rtest_system set sysname = 'pluto' where sysname = 'neptun';
256
257select * from rtest_interface;
258select * from rtest_admin;
259
260update rtest_person set pname = 'jwieck' where pdesc = 'Jan Wieck';
261
262-- Note: use ORDER BY here to ensure consistent output across all systems.
263-- The above UPDATE affects two rows with equal keys, so they could be
264-- updated in either order depending on the whim of the local qsort().
265
266select * from rtest_admin order by pname, sysname;
267
268delete from rtest_system where sysname = 'orion';
269
270select * from rtest_interface;
271select * from rtest_admin;
272
273--
274-- Rule qualification test
275--
276insert into rtest_emp values ('wiecc', '5000.00');
277insert into rtest_emp values ('gates', '80000.00');
278update rtest_emp set ename = 'wiecx' where ename = 'wiecc';
279update rtest_emp set ename = 'wieck', salary = '6000.00' where ename = 'wiecx';
280update rtest_emp set salary = '7000.00' where ename = 'wieck';
281delete from rtest_emp where ename = 'gates';
282
283select ename, who = current_user as "matches user", action, newsal, oldsal from rtest_emplog order by ename, action, newsal;
284insert into rtest_empmass values ('meyer', '4000.00');
285insert into rtest_empmass values ('maier', '5000.00');
286insert into rtest_empmass values ('mayr', '6000.00');
287insert into rtest_emp select * from rtest_empmass;
288select ename, who = current_user as "matches user", action, newsal, oldsal from rtest_emplog order by ename, action, newsal;
289update rtest_empmass set salary = salary + '1000.00';
290update rtest_emp set salary = rtest_empmass.salary from rtest_empmass where rtest_emp.ename = rtest_empmass.ename;
291select ename, who = current_user as "matches user", action, newsal, oldsal from rtest_emplog order by ename, action, newsal;
292delete from rtest_emp using rtest_empmass where rtest_emp.ename = rtest_empmass.ename;
293select ename, who = current_user as "matches user", action, newsal, oldsal from rtest_emplog order by ename, action, newsal;
294
295--
296-- Multiple cascaded qualified instead rule test
297--
298insert into rtest_t4 values (1, 'Record should go to rtest_t4');
299insert into rtest_t4 values (2, 'Record should go to rtest_t4');
300insert into rtest_t4 values (10, 'Record should go to rtest_t5');
301insert into rtest_t4 values (15, 'Record should go to rtest_t5');
302insert into rtest_t4 values (19, 'Record should go to rtest_t5 and t7');
303insert into rtest_t4 values (20, 'Record should go to rtest_t4 and t6');
304insert into rtest_t4 values (26, 'Record should go to rtest_t4 and t8');
305insert into rtest_t4 values (28, 'Record should go to rtest_t4 and t8');
306insert into rtest_t4 values (30, 'Record should go to rtest_t4');
307insert into rtest_t4 values (40, 'Record should go to rtest_t4');
308
309select * from rtest_t4;
310select * from rtest_t5;
311select * from rtest_t6;
312select * from rtest_t7;
313select * from rtest_t8;
314
315delete from rtest_t4;
316delete from rtest_t5;
317delete from rtest_t6;
318delete from rtest_t7;
319delete from rtest_t8;
320
321insert into rtest_t9 values (1, 'Record should go to rtest_t4');
322insert into rtest_t9 values (2, 'Record should go to rtest_t4');
323insert into rtest_t9 values (10, 'Record should go to rtest_t5');
324insert into rtest_t9 values (15, 'Record should go to rtest_t5');
325insert into rtest_t9 values (19, 'Record should go to rtest_t5 and t7');
326insert into rtest_t9 values (20, 'Record should go to rtest_t4 and t6');
327insert into rtest_t9 values (26, 'Record should go to rtest_t4 and t8');
328insert into rtest_t9 values (28, 'Record should go to rtest_t4 and t8');
329insert into rtest_t9 values (30, 'Record should go to rtest_t4');
330insert into rtest_t9 values (40, 'Record should go to rtest_t4');
331
332insert into rtest_t4 select * from rtest_t9 where a < 20;
333
334select * from rtest_t4;
335select * from rtest_t5;
336select * from rtest_t6;
337select * from rtest_t7;
338select * from rtest_t8;
339
340insert into rtest_t4 select * from rtest_t9 where b ~ 'and t8';
341
342select * from rtest_t4;
343select * from rtest_t5;
344select * from rtest_t6;
345select * from rtest_t7;
346select * from rtest_t8;
347
348insert into rtest_t4 select a + 1, b from rtest_t9 where a in (20, 30, 40);
349
350select * from rtest_t4;
351select * from rtest_t5;
352select * from rtest_t6;
353select * from rtest_t7;
354select * from rtest_t8;
355
356--
357-- Check that the ordering of rules fired is correct
358--
359insert into rtest_order1 values (1);
360select * from rtest_order2;
361
362--
363-- Check if instead nothing w/without qualification works
364--
365insert into rtest_nothn1 values (1, 'want this');
366insert into rtest_nothn1 values (2, 'want this');
367insert into rtest_nothn1 values (10, 'don''t want this');
368insert into rtest_nothn1 values (19, 'don''t want this');
369insert into rtest_nothn1 values (20, 'want this');
370insert into rtest_nothn1 values (29, 'want this');
371insert into rtest_nothn1 values (30, 'don''t want this');
372insert into rtest_nothn1 values (39, 'don''t want this');
373insert into rtest_nothn1 values (40, 'want this');
374insert into rtest_nothn1 values (50, 'want this');
375insert into rtest_nothn1 values (60, 'want this');
376
377select * from rtest_nothn1;
378
379insert into rtest_nothn2 values (10, 'too small');
380insert into rtest_nothn2 values (50, 'too small');
381insert into rtest_nothn2 values (100, 'OK');
382insert into rtest_nothn2 values (200, 'OK');
383
384select * from rtest_nothn2;
385select * from rtest_nothn3;
386
387delete from rtest_nothn1;
388delete from rtest_nothn2;
389delete from rtest_nothn3;
390
391insert into rtest_nothn4 values (1, 'want this');
392insert into rtest_nothn4 values (2, 'want this');
393insert into rtest_nothn4 values (10, 'don''t want this');
394insert into rtest_nothn4 values (19, 'don''t want this');
395insert into rtest_nothn4 values (20, 'want this');
396insert into rtest_nothn4 values (29, 'want this');
397insert into rtest_nothn4 values (30, 'don''t want this');
398insert into rtest_nothn4 values (39, 'don''t want this');
399insert into rtest_nothn4 values (40, 'want this');
400insert into rtest_nothn4 values (50, 'want this');
401insert into rtest_nothn4 values (60, 'want this');
402
403insert into rtest_nothn1 select * from rtest_nothn4;
404
405select * from rtest_nothn1;
406
407delete from rtest_nothn4;
408
409insert into rtest_nothn4 values (10, 'too small');
410insert into rtest_nothn4 values (50, 'too small');
411insert into rtest_nothn4 values (100, 'OK');
412insert into rtest_nothn4 values (200, 'OK');
413
414insert into rtest_nothn2 select * from rtest_nothn4;
415
416select * from rtest_nothn2;
417select * from rtest_nothn3;
418
419create table rtest_view1 (a int4, b text, v bool);
420create table rtest_view2 (a int4);
421create table rtest_view3 (a int4, b text);
422create table rtest_view4 (a int4, b text, c int4);
423create view rtest_vview1 as select a, b from rtest_view1 X
424	where 0 < (select count(*) from rtest_view2 Y where Y.a = X.a);
425create view rtest_vview2 as select a, b from rtest_view1 where v;
426create view rtest_vview3 as select a, b from rtest_vview2 X
427	where 0 < (select count(*) from rtest_view2 Y where Y.a = X.a);
428create view rtest_vview4 as select X.a, X.b, count(Y.a) as refcount
429	from rtest_view1 X, rtest_view2 Y
430	where X.a = Y.a
431	group by X.a, X.b;
432create function rtest_viewfunc1(int4) returns int4 as
433	'select count(*)::int4 from rtest_view2 where a = $1'
434	language sql;
435create view rtest_vview5 as select a, b, rtest_viewfunc1(a) as refcount
436	from rtest_view1;
437
438insert into rtest_view1 values (1, 'item 1', 't');
439insert into rtest_view1 values (2, 'item 2', 't');
440insert into rtest_view1 values (3, 'item 3', 't');
441insert into rtest_view1 values (4, 'item 4', 'f');
442insert into rtest_view1 values (5, 'item 5', 't');
443insert into rtest_view1 values (6, 'item 6', 'f');
444insert into rtest_view1 values (7, 'item 7', 't');
445insert into rtest_view1 values (8, 'item 8', 't');
446
447insert into rtest_view2 values (2);
448insert into rtest_view2 values (2);
449insert into rtest_view2 values (4);
450insert into rtest_view2 values (5);
451insert into rtest_view2 values (7);
452insert into rtest_view2 values (7);
453insert into rtest_view2 values (7);
454insert into rtest_view2 values (7);
455
456select * from rtest_vview1;
457select * from rtest_vview2;
458select * from rtest_vview3;
459select * from rtest_vview4 order by a, b;
460select * from rtest_vview5;
461
462insert into rtest_view3 select * from rtest_vview1 where a < 7;
463select * from rtest_view3;
464delete from rtest_view3;
465
466insert into rtest_view3 select * from rtest_vview2 where a != 5 and b !~ '2';
467select * from rtest_view3;
468delete from rtest_view3;
469
470insert into rtest_view3 select * from rtest_vview3;
471select * from rtest_view3;
472delete from rtest_view3;
473
474insert into rtest_view4 select * from rtest_vview4 where 3 > refcount;
475select * from rtest_view4 order by a, b;
476delete from rtest_view4;
477
478insert into rtest_view4 select * from rtest_vview5 where a > 2 and refcount = 0;
479select * from rtest_view4;
480delete from rtest_view4;
481--
482-- Test for computations in views
483--
484create table rtest_comp (
485	part	text,
486	unit	char(4),
487	size	float
488);
489
490
491create table rtest_unitfact (
492	unit	char(4),
493	factor	float
494);
495
496create view rtest_vcomp as
497	select X.part, (X.size * Y.factor) as size_in_cm
498			from rtest_comp X, rtest_unitfact Y
499			where X.unit = Y.unit;
500
501
502insert into rtest_unitfact values ('m', 100.0);
503insert into rtest_unitfact values ('cm', 1.0);
504insert into rtest_unitfact values ('inch', 2.54);
505
506insert into rtest_comp values ('p1', 'm', 5.0);
507insert into rtest_comp values ('p2', 'm', 3.0);
508insert into rtest_comp values ('p3', 'cm', 5.0);
509insert into rtest_comp values ('p4', 'cm', 15.0);
510insert into rtest_comp values ('p5', 'inch', 7.0);
511insert into rtest_comp values ('p6', 'inch', 4.4);
512
513select * from rtest_vcomp order by part;
514
515select * from rtest_vcomp where size_in_cm > 10.0 order by size_in_cm using >;
516
517--
518-- In addition run the (slightly modified) queries from the
519-- programmers manual section on the rule system.
520--
521CREATE TABLE shoe_data (
522	shoename   char(10),      -- primary key
523	sh_avail   integer,       -- available # of pairs
524	slcolor    char(10),      -- preferred shoelace color
525	slminlen   float,         -- minimum shoelace length
526	slmaxlen   float,         -- maximum shoelace length
527	slunit     char(8)        -- length unit
528);
529
530CREATE TABLE shoelace_data (
531	sl_name    char(10),      -- primary key
532	sl_avail   integer,       -- available # of pairs
533	sl_color   char(10),      -- shoelace color
534	sl_len     float,         -- shoelace length
535	sl_unit    char(8)        -- length unit
536);
537
538CREATE TABLE unit (
539	un_name    char(8),       -- the primary key
540	un_fact    float          -- factor to transform to cm
541);
542
543CREATE VIEW shoe AS
544	SELECT sh.shoename,
545		   sh.sh_avail,
546		   sh.slcolor,
547		   sh.slminlen,
548		   sh.slminlen * un.un_fact AS slminlen_cm,
549		   sh.slmaxlen,
550		   sh.slmaxlen * un.un_fact AS slmaxlen_cm,
551		   sh.slunit
552	  FROM shoe_data sh, unit un
553	 WHERE sh.slunit = un.un_name;
554
555CREATE VIEW shoelace AS
556	SELECT s.sl_name,
557		   s.sl_avail,
558		   s.sl_color,
559		   s.sl_len,
560		   s.sl_unit,
561		   s.sl_len * u.un_fact AS sl_len_cm
562	  FROM shoelace_data s, unit u
563	 WHERE s.sl_unit = u.un_name;
564
565CREATE VIEW shoe_ready AS
566	SELECT rsh.shoename,
567		   rsh.sh_avail,
568		   rsl.sl_name,
569		   rsl.sl_avail,
570		   int4smaller(rsh.sh_avail, rsl.sl_avail) AS total_avail
571	  FROM shoe rsh, shoelace rsl
572	 WHERE rsl.sl_color = rsh.slcolor
573	   AND rsl.sl_len_cm >= rsh.slminlen_cm
574	   AND rsl.sl_len_cm <= rsh.slmaxlen_cm;
575
576INSERT INTO unit VALUES ('cm', 1.0);
577INSERT INTO unit VALUES ('m', 100.0);
578INSERT INTO unit VALUES ('inch', 2.54);
579
580INSERT INTO shoe_data VALUES ('sh1', 2, 'black', 70.0, 90.0, 'cm');
581INSERT INTO shoe_data VALUES ('sh2', 0, 'black', 30.0, 40.0, 'inch');
582INSERT INTO shoe_data VALUES ('sh3', 4, 'brown', 50.0, 65.0, 'cm');
583INSERT INTO shoe_data VALUES ('sh4', 3, 'brown', 40.0, 50.0, 'inch');
584
585INSERT INTO shoelace_data VALUES ('sl1', 5, 'black', 80.0, 'cm');
586INSERT INTO shoelace_data VALUES ('sl2', 6, 'black', 100.0, 'cm');
587INSERT INTO shoelace_data VALUES ('sl3', 0, 'black', 35.0 , 'inch');
588INSERT INTO shoelace_data VALUES ('sl4', 8, 'black', 40.0 , 'inch');
589INSERT INTO shoelace_data VALUES ('sl5', 4, 'brown', 1.0 , 'm');
590INSERT INTO shoelace_data VALUES ('sl6', 0, 'brown', 0.9 , 'm');
591INSERT INTO shoelace_data VALUES ('sl7', 7, 'brown', 60 , 'cm');
592INSERT INTO shoelace_data VALUES ('sl8', 1, 'brown', 40 , 'inch');
593
594-- SELECTs in doc
595SELECT * FROM shoelace ORDER BY sl_name;
596SELECT * FROM shoe_ready WHERE total_avail >= 2 ORDER BY 1;
597
598    CREATE TABLE shoelace_log (
599        sl_name    char(10),      -- shoelace changed
600        sl_avail   integer,       -- new available value
601        log_who    name,          -- who did it
602        log_when   timestamp      -- when
603    );
604
605-- Want "log_who" to be CURRENT_USER,
606-- but that is non-portable for the regression test
607-- - thomas 1999-02-21
608
609    CREATE RULE log_shoelace AS ON UPDATE TO shoelace_data
610        WHERE NEW.sl_avail != OLD.sl_avail
611        DO INSERT INTO shoelace_log VALUES (
612                                        NEW.sl_name,
613                                        NEW.sl_avail,
614                                        'Al Bundy',
615                                        'epoch'
616                                    );
617
618UPDATE shoelace_data SET sl_avail = 6 WHERE  sl_name = 'sl7';
619
620SELECT * FROM shoelace_log;
621
622    CREATE RULE shoelace_ins AS ON INSERT TO shoelace
623        DO INSTEAD
624        INSERT INTO shoelace_data VALUES (
625               NEW.sl_name,
626               NEW.sl_avail,
627               NEW.sl_color,
628               NEW.sl_len,
629               NEW.sl_unit);
630
631    CREATE RULE shoelace_upd AS ON UPDATE TO shoelace
632        DO INSTEAD
633        UPDATE shoelace_data SET
634               sl_name = NEW.sl_name,
635               sl_avail = NEW.sl_avail,
636               sl_color = NEW.sl_color,
637               sl_len = NEW.sl_len,
638               sl_unit = NEW.sl_unit
639         WHERE sl_name = OLD.sl_name;
640
641    CREATE RULE shoelace_del AS ON DELETE TO shoelace
642        DO INSTEAD
643        DELETE FROM shoelace_data
644         WHERE sl_name = OLD.sl_name;
645
646    CREATE TABLE shoelace_arrive (
647        arr_name    char(10),
648        arr_quant   integer
649    );
650
651    CREATE TABLE shoelace_ok (
652        ok_name     char(10),
653        ok_quant    integer
654    );
655
656    CREATE RULE shoelace_ok_ins AS ON INSERT TO shoelace_ok
657        DO INSTEAD
658        UPDATE shoelace SET
659               sl_avail = sl_avail + NEW.ok_quant
660         WHERE sl_name = NEW.ok_name;
661
662INSERT INTO shoelace_arrive VALUES ('sl3', 10);
663INSERT INTO shoelace_arrive VALUES ('sl6', 20);
664INSERT INTO shoelace_arrive VALUES ('sl8', 20);
665
666SELECT * FROM shoelace ORDER BY sl_name;
667
668insert into shoelace_ok select * from shoelace_arrive;
669
670SELECT * FROM shoelace ORDER BY sl_name;
671
672SELECT * FROM shoelace_log ORDER BY sl_name;
673
674    CREATE VIEW shoelace_obsolete AS
675	SELECT * FROM shoelace WHERE NOT EXISTS
676	    (SELECT shoename FROM shoe WHERE slcolor = sl_color);
677
678    CREATE VIEW shoelace_candelete AS
679	SELECT * FROM shoelace_obsolete WHERE sl_avail = 0;
680
681insert into shoelace values ('sl9', 0, 'pink', 35.0, 'inch', 0.0);
682insert into shoelace values ('sl10', 1000, 'magenta', 40.0, 'inch', 0.0);
683-- Unsupported (even though a similar updatable view construct is)
684insert into shoelace values ('sl10', 1000, 'magenta', 40.0, 'inch', 0.0)
685  on conflict do nothing;
686
687SELECT * FROM shoelace_obsolete ORDER BY sl_len_cm;
688SELECT * FROM shoelace_candelete;
689
690DELETE FROM shoelace WHERE EXISTS
691    (SELECT * FROM shoelace_candelete
692             WHERE sl_name = shoelace.sl_name);
693
694SELECT * FROM shoelace ORDER BY sl_name;
695
696SELECT * FROM shoe ORDER BY shoename;
697SELECT count(*) FROM shoe;
698
699
700--
701-- Simple test of qualified ON INSERT ... this did not work in 7.0 ...
702--
703create table rules_foo (f1 int);
704create table rules_foo2 (f1 int);
705
706create rule rules_foorule as on insert to rules_foo where f1 < 100
707do instead nothing;
708
709insert into rules_foo values(1);
710insert into rules_foo values(1001);
711select * from rules_foo;
712
713drop rule rules_foorule on rules_foo;
714
715-- this should fail because f1 is not exposed for unqualified reference:
716create rule rules_foorule as on insert to rules_foo where f1 < 100
717do instead insert into rules_foo2 values (f1);
718-- this is the correct way:
719create rule rules_foorule as on insert to rules_foo where f1 < 100
720do instead insert into rules_foo2 values (new.f1);
721
722insert into rules_foo values(2);
723insert into rules_foo values(100);
724
725select * from rules_foo;
726select * from rules_foo2;
727
728drop rule rules_foorule on rules_foo;
729drop table rules_foo;
730drop table rules_foo2;
731
732
733--
734-- Test rules containing INSERT ... SELECT, which is a very ugly special
735-- case as of 7.1.  Example is based on bug report from Joel Burton.
736--
737create table pparent (pid int, txt text);
738insert into pparent values (1,'parent1');
739insert into pparent values (2,'parent2');
740
741create table cchild (pid int, descrip text);
742insert into cchild values (1,'descrip1');
743
744create view vview as
745  select pparent.pid, txt, descrip from
746    pparent left join cchild using (pid);
747
748create rule rrule as
749  on update to vview do instead
750(
751  insert into cchild (pid, descrip)
752    select old.pid, new.descrip where old.descrip isnull;
753  update cchild set descrip = new.descrip where cchild.pid = old.pid;
754);
755
756select * from vview;
757update vview set descrip='test1' where pid=1;
758select * from vview;
759update vview set descrip='test2' where pid=2;
760select * from vview;
761update vview set descrip='test3' where pid=3;
762select * from vview;
763select * from cchild;
764
765drop rule rrule on vview;
766drop view vview;
767drop table pparent;
768drop table cchild;
769
770
771--
772-- Check that ruleutils are working
773--
774
775-- temporarily disable fancy output, so view changes create less diff noise
776\a\t
777
778SELECT viewname, definition FROM pg_views
779WHERE schemaname IN ('pg_catalog', 'public')
780ORDER BY viewname;
781
782SELECT tablename, rulename, definition FROM pg_rules
783WHERE schemaname IN ('pg_catalog', 'public')
784ORDER BY tablename, rulename;
785
786-- restore normal output mode
787\a\t
788
789--
790-- CREATE OR REPLACE RULE
791--
792
793CREATE TABLE ruletest_tbl (a int, b int);
794CREATE TABLE ruletest_tbl2 (a int, b int);
795
796CREATE OR REPLACE RULE myrule AS ON INSERT TO ruletest_tbl
797	DO INSTEAD INSERT INTO ruletest_tbl2 VALUES (10, 10);
798
799INSERT INTO ruletest_tbl VALUES (99, 99);
800
801CREATE OR REPLACE RULE myrule AS ON INSERT TO ruletest_tbl
802	DO INSTEAD INSERT INTO ruletest_tbl2 VALUES (1000, 1000);
803
804INSERT INTO ruletest_tbl VALUES (99, 99);
805
806SELECT * FROM ruletest_tbl2;
807
808-- Check that rewrite rules splitting one INSERT into multiple
809-- conditional statements does not disable FK checking.
810create table rule_and_refint_t1 (
811	id1a integer,
812	id1b integer,
813
814	primary key (id1a, id1b)
815);
816
817create table rule_and_refint_t2 (
818	id2a integer,
819	id2c integer,
820
821	primary key (id2a, id2c)
822);
823
824create table rule_and_refint_t3 (
825	id3a integer,
826	id3b integer,
827	id3c integer,
828	data text,
829
830	primary key (id3a, id3b, id3c),
831
832	foreign key (id3a, id3b) references rule_and_refint_t1 (id1a, id1b),
833	foreign key (id3a, id3c) references rule_and_refint_t2 (id2a, id2c)
834);
835
836
837insert into rule_and_refint_t1 values (1, 11);
838insert into rule_and_refint_t1 values (1, 12);
839insert into rule_and_refint_t1 values (2, 21);
840insert into rule_and_refint_t1 values (2, 22);
841
842insert into rule_and_refint_t2 values (1, 11);
843insert into rule_and_refint_t2 values (1, 12);
844insert into rule_and_refint_t2 values (2, 21);
845insert into rule_and_refint_t2 values (2, 22);
846
847insert into rule_and_refint_t3 values (1, 11, 11, 'row1');
848insert into rule_and_refint_t3 values (1, 11, 12, 'row2');
849insert into rule_and_refint_t3 values (1, 12, 11, 'row3');
850insert into rule_and_refint_t3 values (1, 12, 12, 'row4');
851insert into rule_and_refint_t3 values (1, 11, 13, 'row5');
852insert into rule_and_refint_t3 values (1, 13, 11, 'row6');
853-- Ordinary table
854insert into rule_and_refint_t3 values (1, 13, 11, 'row6')
855  on conflict do nothing;
856-- rule not fired, so fk violation
857insert into rule_and_refint_t3 values (1, 13, 11, 'row6')
858  on conflict (id3a, id3b, id3c) do update
859  set id3b = excluded.id3b;
860-- rule fired, so unsupported
861insert into shoelace values ('sl9', 0, 'pink', 35.0, 'inch', 0.0)
862  on conflict (sl_name) do update
863  set sl_avail = excluded.sl_avail;
864
865create rule rule_and_refint_t3_ins as on insert to rule_and_refint_t3
866	where (exists (select 1 from rule_and_refint_t3
867			where (((rule_and_refint_t3.id3a = new.id3a)
868			and (rule_and_refint_t3.id3b = new.id3b))
869			and (rule_and_refint_t3.id3c = new.id3c))))
870	do instead update rule_and_refint_t3 set data = new.data
871	where (((rule_and_refint_t3.id3a = new.id3a)
872	and (rule_and_refint_t3.id3b = new.id3b))
873	and (rule_and_refint_t3.id3c = new.id3c));
874
875insert into rule_and_refint_t3 values (1, 11, 13, 'row7');
876insert into rule_and_refint_t3 values (1, 13, 11, 'row8');
877
878--
879-- disallow dropping a view's rule (bug #5072)
880--
881
882create view rules_fooview as select 'rules_foo'::text;
883drop rule "_RETURN" on rules_fooview;
884drop view rules_fooview;
885
886--
887-- test conversion of table to view (needed to load some pg_dump files)
888--
889
890create table rules_fooview (x int, y text);
891select xmin, * from rules_fooview;
892
893create rule "_RETURN" as on select to rules_fooview do instead
894  select 1 as x, 'aaa'::text as y;
895
896select * from rules_fooview;
897select xmin, * from rules_fooview;  -- fail, views don't have such a column
898
899select reltoastrelid, relkind, relfrozenxid
900  from pg_class where oid = 'rules_fooview'::regclass;
901
902drop view rules_fooview;
903
904-- cannot convert an inheritance parent or child to a view, though
905create table rules_fooview (x int, y text);
906create table rules_fooview_child () inherits (rules_fooview);
907
908create rule "_RETURN" as on select to rules_fooview do instead
909  select 1 as x, 'aaa'::text as y;
910create rule "_RETURN" as on select to rules_fooview_child do instead
911  select 1 as x, 'aaa'::text as y;
912
913drop table rules_fooview cascade;
914
915-- likewise, converting a partitioned table or partition to view is not allowed
916create table rules_fooview (x int, y text) partition by list (x);
917create rule "_RETURN" as on select to rules_fooview do instead
918  select 1 as x, 'aaa'::text as y;
919
920create table rules_fooview_part partition of rules_fooview for values in (1);
921create rule "_RETURN" as on select to rules_fooview_part do instead
922  select 1 as x, 'aaa'::text as y;
923
924drop table rules_fooview;
925
926--
927-- check for planner problems with complex inherited UPDATES
928--
929
930create table id (id serial primary key, name text);
931-- currently, must respecify PKEY for each inherited subtable
932create table test_1 (id integer primary key) inherits (id);
933create table test_2 (id integer primary key) inherits (id);
934create table test_3 (id integer primary key) inherits (id);
935
936insert into test_1 (name) values ('Test 1');
937insert into test_1 (name) values ('Test 2');
938insert into test_2 (name) values ('Test 3');
939insert into test_2 (name) values ('Test 4');
940insert into test_3 (name) values ('Test 5');
941insert into test_3 (name) values ('Test 6');
942
943create view id_ordered as select * from id order by id;
944
945create rule update_id_ordered as on update to id_ordered
946	do instead update id set name = new.name where id = old.id;
947
948select * from id_ordered;
949update id_ordered set name = 'update 2' where id = 2;
950update id_ordered set name = 'update 4' where id = 4;
951update id_ordered set name = 'update 5' where id = 5;
952select * from id_ordered;
953
954drop table id cascade;
955
956--
957-- check corner case where an entirely-dummy subplan is created by
958-- constraint exclusion
959--
960
961create temp table t1 (a integer primary key);
962
963create temp table t1_1 (check (a >= 0 and a < 10)) inherits (t1);
964create temp table t1_2 (check (a >= 10 and a < 20)) inherits (t1);
965
966create rule t1_ins_1 as on insert to t1
967	where new.a >= 0 and new.a < 10
968	do instead
969	insert into t1_1 values (new.a);
970create rule t1_ins_2 as on insert to t1
971	where new.a >= 10 and new.a < 20
972	do instead
973	insert into t1_2 values (new.a);
974
975create rule t1_upd_1 as on update to t1
976	where old.a >= 0 and old.a < 10
977	do instead
978	update t1_1 set a = new.a where a = old.a;
979create rule t1_upd_2 as on update to t1
980	where old.a >= 10 and old.a < 20
981	do instead
982	update t1_2 set a = new.a where a = old.a;
983
984set constraint_exclusion = on;
985
986insert into t1 select * from generate_series(5,19,1) g;
987update t1 set a = 4 where a = 5;
988
989select * from only t1;
990select * from only t1_1;
991select * from only t1_2;
992
993reset constraint_exclusion;
994
995-- test FOR UPDATE in rules
996
997create table rules_base(f1 int, f2 int);
998insert into rules_base values(1,2), (11,12);
999create rule r1 as on update to rules_base do instead
1000  select * from rules_base where f1 = 1 for update;
1001update rules_base set f2 = f2 + 1;
1002create or replace rule r1 as on update to rules_base do instead
1003  select * from rules_base where f1 = 11 for update of rules_base;
1004update rules_base set f2 = f2 + 1;
1005create or replace rule r1 as on update to rules_base do instead
1006  select * from rules_base where f1 = 11 for update of old; -- error
1007drop table rules_base;
1008
1009-- test various flavors of pg_get_viewdef()
1010
1011select pg_get_viewdef('shoe'::regclass) as unpretty;
1012select pg_get_viewdef('shoe'::regclass,true) as pretty;
1013select pg_get_viewdef('shoe'::regclass,0) as prettier;
1014
1015--
1016-- check multi-row VALUES in rules
1017--
1018
1019create table rules_src(f1 int, f2 int);
1020create table rules_log(f1 int, f2 int, tag text);
1021insert into rules_src values(1,2), (11,12);
1022create rule r1 as on update to rules_src do also
1023  insert into rules_log values(old.*, 'old'), (new.*, 'new');
1024update rules_src set f2 = f2 + 1;
1025update rules_src set f2 = f2 * 10;
1026select * from rules_src;
1027select * from rules_log;
1028create rule r2 as on update to rules_src do also
1029  values(old.*, 'old'), (new.*, 'new');
1030update rules_src set f2 = f2 / 10;
1031select * from rules_src;
1032select * from rules_log;
1033create rule r3 as on delete to rules_src do notify rules_src_deletion;
1034\d+ rules_src
1035
1036--
1037-- Ensure an aliased target relation for insert is correctly deparsed.
1038--
1039create rule r4 as on insert to rules_src do instead insert into rules_log AS trgt SELECT NEW.* RETURNING trgt.f1, trgt.f2;
1040create rule r5 as on update to rules_src do instead UPDATE rules_log AS trgt SET tag = 'updated' WHERE trgt.f1 = new.f1;
1041\d+ rules_src
1042
1043--
1044-- Also check multiassignment deparsing.
1045--
1046create table rule_t1(f1 int, f2 int);
1047create table rule_dest(f1 int, f2 int[], tag text);
1048create rule rr as on update to rule_t1 do instead UPDATE rule_dest trgt
1049  SET (f2[1], f1, tag) = (SELECT new.f2, new.f1, 'updated'::varchar)
1050  WHERE trgt.f1 = new.f1 RETURNING new.*;
1051\d+ rule_t1
1052drop table rule_t1, rule_dest;
1053
1054--
1055-- check alter rename rule
1056--
1057CREATE TABLE rule_t1 (a INT);
1058CREATE VIEW rule_v1 AS SELECT * FROM rule_t1;
1059
1060CREATE RULE InsertRule AS
1061    ON INSERT TO rule_v1
1062    DO INSTEAD
1063        INSERT INTO rule_t1 VALUES(new.a);
1064
1065ALTER RULE InsertRule ON rule_v1 RENAME to NewInsertRule;
1066
1067INSERT INTO rule_v1 VALUES(1);
1068SELECT * FROM rule_v1;
1069
1070\d+ rule_v1
1071
1072--
1073-- error conditions for alter rename rule
1074--
1075ALTER RULE InsertRule ON rule_v1 RENAME TO NewInsertRule; -- doesn't exist
1076ALTER RULE NewInsertRule ON rule_v1 RENAME TO "_RETURN"; -- already exists
1077ALTER RULE "_RETURN" ON rule_v1 RENAME TO abc; -- ON SELECT rule cannot be renamed
1078
1079DROP VIEW rule_v1;
1080DROP TABLE rule_t1;
1081
1082--
1083-- check display of VALUES in view definitions
1084--
1085create view rule_v1 as values(1,2);
1086\d+ rule_v1
1087alter table rule_v1 rename column column2 to q2;
1088\d+ rule_v1
1089drop view rule_v1;
1090create view rule_v1(x) as values(1,2);
1091\d+ rule_v1
1092drop view rule_v1;
1093create view rule_v1(x) as select * from (values(1,2)) v;
1094\d+ rule_v1
1095drop view rule_v1;
1096create view rule_v1(x) as select * from (values(1,2)) v(q,w);
1097\d+ rule_v1
1098drop view rule_v1;
1099
1100--
1101-- Check DO INSTEAD rules with ON CONFLICT
1102--
1103CREATE TABLE hats (
1104	hat_name    char(10) primary key,
1105	hat_color   char(10)      -- hat color
1106);
1107
1108CREATE TABLE hat_data (
1109	hat_name    char(10),
1110	hat_color   char(10)      -- hat color
1111);
1112create unique index hat_data_unique_idx
1113  on hat_data (hat_name COLLATE "C" bpchar_pattern_ops);
1114
1115-- DO NOTHING with ON CONFLICT
1116CREATE RULE hat_nosert AS ON INSERT TO hats
1117    DO INSTEAD
1118    INSERT INTO hat_data VALUES (
1119           NEW.hat_name,
1120           NEW.hat_color)
1121        ON CONFLICT (hat_name COLLATE "C" bpchar_pattern_ops) WHERE hat_color = 'green'
1122        DO NOTHING
1123        RETURNING *;
1124SELECT definition FROM pg_rules WHERE tablename = 'hats' ORDER BY rulename;
1125
1126-- Works (projects row)
1127INSERT INTO hats VALUES ('h7', 'black') RETURNING *;
1128-- Works (does nothing)
1129INSERT INTO hats VALUES ('h7', 'black') RETURNING *;
1130SELECT tablename, rulename, definition FROM pg_rules
1131	WHERE tablename = 'hats';
1132DROP RULE hat_nosert ON hats;
1133
1134-- DO NOTHING without ON CONFLICT
1135CREATE RULE hat_nosert_all AS ON INSERT TO hats
1136    DO INSTEAD
1137    INSERT INTO hat_data VALUES (
1138           NEW.hat_name,
1139           NEW.hat_color)
1140        ON CONFLICT
1141        DO NOTHING
1142        RETURNING *;
1143SELECT definition FROM pg_rules WHERE tablename = 'hats' ORDER BY rulename;
1144DROP RULE hat_nosert_all ON hats;
1145
1146-- Works (does nothing)
1147INSERT INTO hats VALUES ('h7', 'black') RETURNING *;
1148
1149-- DO UPDATE with a WHERE clause
1150CREATE RULE hat_upsert AS ON INSERT TO hats
1151    DO INSTEAD
1152    INSERT INTO hat_data VALUES (
1153           NEW.hat_name,
1154           NEW.hat_color)
1155        ON CONFLICT (hat_name)
1156        DO UPDATE
1157           SET hat_name = hat_data.hat_name, hat_color = excluded.hat_color
1158           WHERE excluded.hat_color <>  'forbidden' AND hat_data.* != excluded.*
1159        RETURNING *;
1160SELECT definition FROM pg_rules WHERE tablename = 'hats' ORDER BY rulename;
1161
1162-- Works (does upsert)
1163INSERT INTO hats VALUES ('h8', 'black') RETURNING *;
1164SELECT * FROM hat_data WHERE hat_name = 'h8';
1165INSERT INTO hats VALUES ('h8', 'white') RETURNING *;
1166SELECT * FROM hat_data WHERE hat_name = 'h8';
1167INSERT INTO hats VALUES ('h8', 'forbidden') RETURNING *;
1168SELECT * FROM hat_data WHERE hat_name = 'h8';
1169SELECT tablename, rulename, definition FROM pg_rules
1170	WHERE tablename = 'hats';
1171-- ensure explain works for on insert conflict rules
1172explain (costs off) INSERT INTO hats VALUES ('h8', 'forbidden') RETURNING *;
1173
1174-- ensure upserting into a rule, with a CTE (different offsets!) works
1175WITH data(hat_name, hat_color) AS MATERIALIZED (
1176    VALUES ('h8', 'green'),
1177        ('h9', 'blue'),
1178        ('h7', 'forbidden')
1179)
1180INSERT INTO hats
1181    SELECT * FROM data
1182RETURNING *;
1183EXPLAIN (costs off)
1184WITH data(hat_name, hat_color) AS MATERIALIZED (
1185    VALUES ('h8', 'green'),
1186        ('h9', 'blue'),
1187        ('h7', 'forbidden')
1188)
1189INSERT INTO hats
1190    SELECT * FROM data
1191RETURNING *;
1192SELECT * FROM hat_data WHERE hat_name IN ('h8', 'h9', 'h7') ORDER BY hat_name;
1193
1194DROP RULE hat_upsert ON hats;
1195
1196drop table hats;
1197drop table hat_data;
1198
1199-- test for pg_get_functiondef properly regurgitating SET parameters
1200-- Note that the function is kept around to stress pg_dump.
1201CREATE FUNCTION func_with_set_params() RETURNS integer
1202    AS 'select 1;'
1203    LANGUAGE SQL
1204    SET search_path TO PG_CATALOG
1205    SET extra_float_digits TO 2
1206    SET work_mem TO '4MB'
1207    SET datestyle to iso, mdy
1208    SET local_preload_libraries TO "Mixed/Case", 'c:/''a"/path', '', '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789'
1209    IMMUTABLE STRICT;
1210SELECT pg_get_functiondef('func_with_set_params()'::regprocedure);
1211
1212-- tests for pg_get_*def with invalid objects
1213SELECT pg_get_constraintdef(0);
1214SELECT pg_get_functiondef(0);
1215SELECT pg_get_indexdef(0);
1216SELECT pg_get_ruledef(0);
1217SELECT pg_get_statisticsobjdef(0);
1218SELECT pg_get_triggerdef(0);
1219SELECT pg_get_viewdef(0);
1220SELECT pg_get_function_arguments(0);
1221SELECT pg_get_function_identity_arguments(0);
1222SELECT pg_get_function_result(0);
1223SELECT pg_get_function_arg_default(0, 0);
1224SELECT pg_get_function_arg_default('pg_class'::regclass, 0);
1225SELECT pg_get_partkeydef(0);
1226
1227-- test rename for a rule defined on a partitioned table
1228CREATE TABLE rules_parted_table (a int) PARTITION BY LIST (a);
1229CREATE TABLE rules_parted_table_1 PARTITION OF rules_parted_table FOR VALUES IN (1);
1230CREATE RULE rules_parted_table_insert AS ON INSERT to rules_parted_table
1231    DO INSTEAD INSERT INTO rules_parted_table_1 VALUES (NEW.*);
1232ALTER RULE rules_parted_table_insert ON rules_parted_table RENAME TO rules_parted_table_insert_redirect;
1233DROP TABLE rules_parted_table;
1234
1235--
1236-- Test enabling/disabling
1237--
1238CREATE TABLE ruletest1 (a int);
1239CREATE TABLE ruletest2 (b int);
1240
1241CREATE RULE rule1 AS ON INSERT TO ruletest1
1242    DO INSTEAD INSERT INTO ruletest2 VALUES (NEW.*);
1243
1244INSERT INTO ruletest1 VALUES (1);
1245ALTER TABLE ruletest1 DISABLE RULE rule1;
1246INSERT INTO ruletest1 VALUES (2);
1247ALTER TABLE ruletest1 ENABLE RULE rule1;
1248SET session_replication_role = replica;
1249INSERT INTO ruletest1 VALUES (3);
1250ALTER TABLE ruletest1 ENABLE REPLICA RULE rule1;
1251INSERT INTO ruletest1 VALUES (4);
1252RESET session_replication_role;
1253INSERT INTO ruletest1 VALUES (5);
1254
1255SELECT * FROM ruletest1;
1256SELECT * FROM ruletest2;
1257
1258DROP TABLE ruletest1;
1259DROP TABLE ruletest2;
1260