OLD | NEW |
| (Empty) |
1 # The author disclaims copyright to this source code. In place of | |
2 # a legal notice, here is a blessing: | |
3 # | |
4 # May you do good and not evil. | |
5 # May you find forgiveness for yourself and forgive others. | |
6 # May you share freely, never taking more than you give. | |
7 # | |
8 #*********************************************************************** | |
9 # | |
10 # Regression testing of FOR EACH ROW table triggers | |
11 # | |
12 # 1. Trigger execution order tests. | |
13 # These tests ensure that BEFORE and AFTER triggers are fired at the correct | |
14 # times relative to each other and the triggering statement. | |
15 # | |
16 # trigger2-1.1.*: ON UPDATE trigger execution model. | |
17 # trigger2-1.2.*: DELETE trigger execution model. | |
18 # trigger2-1.3.*: INSERT trigger execution model. | |
19 # | |
20 # 2. Trigger program execution tests. | |
21 # These tests ensure that trigger programs execute correctly (ie. that a | |
22 # trigger program can correctly execute INSERT, UPDATE, DELETE * SELECT | |
23 # statements, and combinations thereof). | |
24 # | |
25 # 3. Selective trigger execution | |
26 # This tests that conditional triggers (ie. UPDATE OF triggers and triggers | |
27 # with WHEN clauses) are fired only fired when they are supposed to be. | |
28 # | |
29 # trigger2-3.1: UPDATE OF triggers | |
30 # trigger2-3.2: WHEN clause | |
31 # | |
32 # 4. Cascaded trigger execution | |
33 # Tests that trigger-programs may cause other triggers to fire. Also that a | |
34 # trigger-program is never executed recursively. | |
35 # | |
36 # trigger2-4.1: Trivial cascading trigger | |
37 # trigger2-4.2: Trivial recursive trigger handling | |
38 # | |
39 # 5. Count changes behaviour. | |
40 # Verify that rows altered by triggers are not included in the return value | |
41 # of the "count changes" interface. | |
42 # | |
43 # 6. ON CONFLICT clause handling | |
44 # trigger2-6.1[a-f]: INSERT statements | |
45 # trigger2-6.2[a-f]: UPDATE statements | |
46 # | |
47 # 7. & 8. Triggers on views fire correctly. | |
48 # | |
49 | |
50 set testdir [file dirname $argv0] | |
51 source $testdir/tester.tcl | |
52 ifcapable {!trigger} { | |
53 finish_test | |
54 return | |
55 } | |
56 | |
57 # The tests in this file were written before SQLite supported recursive | |
58 # trigger invocation, and some tests depend on that to pass. So disable | |
59 # recursive triggers for this file. | |
60 catchsql { pragma recursive_triggers = off } | |
61 | |
62 # 1. | |
63 ifcapable subquery { | |
64 set ii 0 | |
65 set tbl_definitions [list \ | |
66 {CREATE TABLE tbl (a, b);} \ | |
67 {CREATE TABLE tbl (a INTEGER PRIMARY KEY, b);} \ | |
68 {CREATE TABLE tbl (a, b PRIMARY KEY);} \ | |
69 {CREATE TABLE tbl (a, b); CREATE INDEX tbl_idx ON tbl(b);} \ | |
70 ] | |
71 ifcapable tempdb { | |
72 lappend tbl_definitions \ | |
73 {CREATE TEMP TABLE tbl (a, b); CREATE INDEX tbl_idx ON tbl(b);} | |
74 lappend tbl_definitions {CREATE TEMP TABLE tbl (a, b);} | |
75 lappend tbl_definitions \ | |
76 {CREATE TEMPORARY TABLE tbl (a INTEGER PRIMARY KEY, b);} | |
77 } | |
78 foreach tbl_defn $tbl_definitions { | |
79 incr ii | |
80 catchsql { DROP INDEX tbl_idx; } | |
81 catchsql { | |
82 DROP TABLE rlog; | |
83 DROP TABLE clog; | |
84 DROP TABLE tbl; | |
85 DROP TABLE other_tbl; | |
86 } | |
87 | |
88 execsql $tbl_defn | |
89 | |
90 execsql { | |
91 INSERT INTO tbl VALUES(1, 2); | |
92 INSERT INTO tbl VALUES(3, 4); | |
93 | |
94 CREATE TABLE rlog (idx, old_a, old_b, db_sum_a, db_sum_b, new_a, new_b); | |
95 CREATE TABLE clog (idx, old_a, old_b, db_sum_a, db_sum_b, new_a, new_b); | |
96 | |
97 CREATE TRIGGER before_update_row BEFORE UPDATE ON tbl FOR EACH ROW | |
98 BEGIN | |
99 INSERT INTO rlog VALUES ( (SELECT coalesce(max(idx),0) + 1 FROM rlog), | |
100 old.a, old.b, | |
101 (SELECT coalesce(sum(a),0) FROM tbl), | |
102 (SELECT coalesce(sum(b),0) FROM tbl), | |
103 new.a, new.b); | |
104 END; | |
105 | |
106 CREATE TRIGGER after_update_row AFTER UPDATE ON tbl FOR EACH ROW | |
107 BEGIN | |
108 INSERT INTO rlog VALUES ( (SELECT coalesce(max(idx),0) + 1 FROM rlog), | |
109 old.a, old.b, | |
110 (SELECT coalesce(sum(a),0) FROM tbl), | |
111 (SELECT coalesce(sum(b),0) FROM tbl), | |
112 new.a, new.b); | |
113 END; | |
114 | |
115 CREATE TRIGGER conditional_update_row AFTER UPDATE ON tbl FOR EACH ROW | |
116 WHEN old.a = 1 | |
117 BEGIN | |
118 INSERT INTO clog VALUES ( (SELECT coalesce(max(idx),0) + 1 FROM clog), | |
119 old.a, old.b, | |
120 (SELECT coalesce(sum(a),0) FROM tbl), | |
121 (SELECT coalesce(sum(b),0) FROM tbl), | |
122 new.a, new.b); | |
123 END; | |
124 } | |
125 | |
126 do_test trigger2-1.$ii.1 { | |
127 set r {} | |
128 foreach v [execsql { | |
129 UPDATE tbl SET a = a * 10, b = b * 10; | |
130 SELECT * FROM rlog ORDER BY idx; | |
131 SELECT * FROM clog ORDER BY idx; | |
132 }] { | |
133 lappend r [expr {int($v)}] | |
134 } | |
135 set r | |
136 } [list 1 1 2 4 6 10 20 \ | |
137 2 1 2 13 24 10 20 \ | |
138 3 3 4 13 24 30 40 \ | |
139 4 3 4 40 60 30 40 \ | |
140 1 1 2 13 24 10 20 ] | |
141 | |
142 execsql { | |
143 DELETE FROM rlog; | |
144 DELETE FROM tbl; | |
145 INSERT INTO tbl VALUES (100, 100); | |
146 INSERT INTO tbl VALUES (300, 200); | |
147 CREATE TRIGGER delete_before_row BEFORE DELETE ON tbl FOR EACH ROW | |
148 BEGIN | |
149 INSERT INTO rlog VALUES ( (SELECT coalesce(max(idx),0) + 1 FROM rlog), | |
150 old.a, old.b, | |
151 (SELECT coalesce(sum(a),0) FROM tbl), | |
152 (SELECT coalesce(sum(b),0) FROM tbl), | |
153 0, 0); | |
154 END; | |
155 | |
156 CREATE TRIGGER delete_after_row AFTER DELETE ON tbl FOR EACH ROW | |
157 BEGIN | |
158 INSERT INTO rlog VALUES ( (SELECT coalesce(max(idx),0) + 1 FROM rlog), | |
159 old.a, old.b, | |
160 (SELECT coalesce(sum(a),0) FROM tbl), | |
161 (SELECT coalesce(sum(b),0) FROM tbl), | |
162 0, 0); | |
163 END; | |
164 } | |
165 do_test trigger2-1.$ii.2 { | |
166 set r {} | |
167 foreach v [execsql { | |
168 DELETE FROM tbl; | |
169 SELECT * FROM rlog; | |
170 }] { | |
171 lappend r [expr {int($v)}] | |
172 } | |
173 set r | |
174 } [list 1 100 100 400 300 0 0 \ | |
175 2 100 100 300 200 0 0 \ | |
176 3 300 200 300 200 0 0 \ | |
177 4 300 200 0 0 0 0 ] | |
178 | |
179 execsql { | |
180 DELETE FROM rlog; | |
181 CREATE TRIGGER insert_before_row BEFORE INSERT ON tbl FOR EACH ROW | |
182 BEGIN | |
183 INSERT INTO rlog VALUES ( (SELECT coalesce(max(idx),0) + 1 FROM rlog), | |
184 0, 0, | |
185 (SELECT coalesce(sum(a),0) FROM tbl), | |
186 (SELECT coalesce(sum(b),0) FROM tbl), | |
187 new.a, new.b); | |
188 END; | |
189 | |
190 CREATE TRIGGER insert_after_row AFTER INSERT ON tbl FOR EACH ROW | |
191 BEGIN | |
192 INSERT INTO rlog VALUES ( (SELECT coalesce(max(idx),0) + 1 FROM rlog), | |
193 0, 0, | |
194 (SELECT coalesce(sum(a),0) FROM tbl), | |
195 (SELECT coalesce(sum(b),0) FROM tbl), | |
196 new.a, new.b); | |
197 END; | |
198 } | |
199 do_test trigger2-1.$ii.3 { | |
200 execsql { | |
201 | |
202 CREATE TABLE other_tbl(a, b); | |
203 INSERT INTO other_tbl VALUES(1, 2); | |
204 INSERT INTO other_tbl VALUES(3, 4); | |
205 -- INSERT INTO tbl SELECT * FROM other_tbl; | |
206 INSERT INTO tbl VALUES(5, 6); | |
207 DROP TABLE other_tbl; | |
208 | |
209 SELECT * FROM rlog; | |
210 } | |
211 } [list 1 0 0 0 0 5 6 \ | |
212 2 0 0 5 6 5 6 ] | |
213 | |
214 integrity_check trigger2-1.$ii.4 | |
215 } | |
216 catchsql { | |
217 DROP TABLE rlog; | |
218 DROP TABLE clog; | |
219 DROP TABLE tbl; | |
220 DROP TABLE other_tbl; | |
221 } | |
222 } | |
223 | |
224 # 2. | |
225 set ii 0 | |
226 foreach tr_program { | |
227 {UPDATE tbl SET b = old.b;} | |
228 {INSERT INTO log VALUES(new.c, 2, 3);} | |
229 {DELETE FROM log WHERE a = 1;} | |
230 {INSERT INTO tbl VALUES(500, new.b * 10, 700); | |
231 UPDATE tbl SET c = old.c; | |
232 DELETE FROM log;} | |
233 {INSERT INTO log select * from tbl;} | |
234 } { | |
235 foreach test_varset [ list \ | |
236 { | |
237 set statement {UPDATE tbl SET c = 10 WHERE a = 1;} | |
238 set prep {INSERT INTO tbl VALUES(1, 2, 3);} | |
239 set newC 10 | |
240 set newB 2 | |
241 set newA 1 | |
242 set oldA 1 | |
243 set oldB 2 | |
244 set oldC 3 | |
245 } \ | |
246 { | |
247 set statement {DELETE FROM tbl WHERE a = 1;} | |
248 set prep {INSERT INTO tbl VALUES(1, 2, 3);} | |
249 set oldA 1 | |
250 set oldB 2 | |
251 set oldC 3 | |
252 } \ | |
253 { | |
254 set statement {INSERT INTO tbl VALUES(1, 2, 3);} | |
255 set newA 1 | |
256 set newB 2 | |
257 set newC 3 | |
258 } | |
259 ] \ | |
260 { | |
261 set statement {} | |
262 set prep {} | |
263 set newA {''} | |
264 set newB {''} | |
265 set newC {''} | |
266 set oldA {''} | |
267 set oldB {''} | |
268 set oldC {''} | |
269 | |
270 incr ii | |
271 | |
272 eval $test_varset | |
273 | |
274 set statement_type [string range $statement 0 5] | |
275 set tr_program_fixed $tr_program | |
276 if {$statement_type == "DELETE"} { | |
277 regsub -all new\.a $tr_program_fixed {''} tr_program_fixed | |
278 regsub -all new\.b $tr_program_fixed {''} tr_program_fixed | |
279 regsub -all new\.c $tr_program_fixed {''} tr_program_fixed | |
280 } | |
281 if {$statement_type == "INSERT"} { | |
282 regsub -all old\.a $tr_program_fixed {''} tr_program_fixed | |
283 regsub -all old\.b $tr_program_fixed {''} tr_program_fixed | |
284 regsub -all old\.c $tr_program_fixed {''} tr_program_fixed | |
285 } | |
286 | |
287 | |
288 set tr_program_cooked $tr_program | |
289 regsub -all new\.a $tr_program_cooked $newA tr_program_cooked | |
290 regsub -all new\.b $tr_program_cooked $newB tr_program_cooked | |
291 regsub -all new\.c $tr_program_cooked $newC tr_program_cooked | |
292 regsub -all old\.a $tr_program_cooked $oldA tr_program_cooked | |
293 regsub -all old\.b $tr_program_cooked $oldB tr_program_cooked | |
294 regsub -all old\.c $tr_program_cooked $oldC tr_program_cooked | |
295 | |
296 catchsql { | |
297 DROP TABLE tbl; | |
298 DROP TABLE log; | |
299 } | |
300 | |
301 execsql { | |
302 CREATE TABLE tbl(a PRIMARY KEY, b, c); | |
303 CREATE TABLE log(a, b, c); | |
304 } | |
305 | |
306 set query {SELECT * FROM tbl; SELECT * FROM log;} | |
307 set prep "$prep; INSERT INTO log VALUES(1, 2, 3);\ | |
308 INSERT INTO log VALUES(10, 20, 30);" | |
309 | |
310 # Check execution of BEFORE programs: | |
311 | |
312 set before_data [ execsql "$prep $tr_program_cooked $statement $query" ] | |
313 | |
314 execsql "DELETE FROM tbl; DELETE FROM log; $prep"; | |
315 execsql "CREATE TRIGGER the_trigger BEFORE [string range $statement 0 6]\ | |
316 ON tbl BEGIN $tr_program_fixed END;" | |
317 | |
318 do_test trigger2-2.$ii-before "execsql {$statement $query}" $before_data | |
319 | |
320 execsql "DROP TRIGGER the_trigger;" | |
321 execsql "DELETE FROM tbl; DELETE FROM log;" | |
322 | |
323 # Check execution of AFTER programs | |
324 set after_data [ execsql "$prep $statement $tr_program_cooked $query" ] | |
325 | |
326 execsql "DELETE FROM tbl; DELETE FROM log; $prep"; | |
327 execsql "CREATE TRIGGER the_trigger AFTER [string range $statement 0 6]\ | |
328 ON tbl BEGIN $tr_program_fixed END;" | |
329 | |
330 do_test trigger2-2.$ii-after "execsql {$statement $query}" $after_data | |
331 execsql "DROP TRIGGER the_trigger;" | |
332 | |
333 integrity_check trigger2-2.$ii-integrity | |
334 } | |
335 } | |
336 catchsql { | |
337 DROP TABLE tbl; | |
338 DROP TABLE log; | |
339 } | |
340 | |
341 # 3. | |
342 | |
343 # trigger2-3.1: UPDATE OF triggers | |
344 execsql { | |
345 CREATE TABLE tbl (a, b, c, d); | |
346 CREATE TABLE log (a); | |
347 INSERT INTO log VALUES (0); | |
348 INSERT INTO tbl VALUES (0, 0, 0, 0); | |
349 INSERT INTO tbl VALUES (1, 0, 0, 0); | |
350 CREATE TRIGGER tbl_after_update_cd BEFORE UPDATE OF c, d ON tbl | |
351 BEGIN | |
352 UPDATE log SET a = a + 1; | |
353 END; | |
354 } | |
355 do_test trigger2-3.1 { | |
356 execsql { | |
357 UPDATE tbl SET b = 1, c = 10; -- 2 | |
358 UPDATE tbl SET b = 10; -- 0 | |
359 UPDATE tbl SET d = 4 WHERE a = 0; --1 | |
360 UPDATE tbl SET a = 4, b = 10; --0 | |
361 SELECT * FROM log; | |
362 } | |
363 } {3} | |
364 execsql { | |
365 DROP TABLE tbl; | |
366 DROP TABLE log; | |
367 } | |
368 | |
369 # trigger2-3.2: WHEN clause | |
370 set when_triggers [list {t1 BEFORE INSERT ON tbl WHEN new.a > 20}] | |
371 ifcapable subquery { | |
372 lappend when_triggers \ | |
373 {t2 BEFORE INSERT ON tbl WHEN (SELECT count(*) FROM tbl) = 0} | |
374 } | |
375 | |
376 execsql { | |
377 CREATE TABLE tbl (a, b, c, d); | |
378 CREATE TABLE log (a); | |
379 INSERT INTO log VALUES (0); | |
380 } | |
381 | |
382 foreach trig $when_triggers { | |
383 execsql "CREATE TRIGGER $trig BEGIN UPDATE log set a = a + 1; END;" | |
384 } | |
385 | |
386 ifcapable subquery { | |
387 set t232 {1 0 1} | |
388 } else { | |
389 set t232 {0 0 1} | |
390 } | |
391 do_test trigger2-3.2 { | |
392 execsql { | |
393 | |
394 INSERT INTO tbl VALUES(0, 0, 0, 0); -- 1 (ifcapable subquery) | |
395 SELECT * FROM log; | |
396 UPDATE log SET a = 0; | |
397 | |
398 INSERT INTO tbl VALUES(0, 0, 0, 0); -- 0 | |
399 SELECT * FROM log; | |
400 UPDATE log SET a = 0; | |
401 | |
402 INSERT INTO tbl VALUES(200, 0, 0, 0); -- 1 | |
403 SELECT * FROM log; | |
404 UPDATE log SET a = 0; | |
405 } | |
406 } $t232 | |
407 execsql { | |
408 DROP TABLE tbl; | |
409 DROP TABLE log; | |
410 } | |
411 integrity_check trigger2-3.3 | |
412 | |
413 # Simple cascaded trigger | |
414 execsql { | |
415 CREATE TABLE tblA(a, b); | |
416 CREATE TABLE tblB(a, b); | |
417 CREATE TABLE tblC(a, b); | |
418 | |
419 CREATE TRIGGER tr1 BEFORE INSERT ON tblA BEGIN | |
420 INSERT INTO tblB values(new.a, new.b); | |
421 END; | |
422 | |
423 CREATE TRIGGER tr2 BEFORE INSERT ON tblB BEGIN | |
424 INSERT INTO tblC values(new.a, new.b); | |
425 END; | |
426 } | |
427 do_test trigger2-4.1 { | |
428 execsql { | |
429 INSERT INTO tblA values(1, 2); | |
430 SELECT * FROM tblA; | |
431 SELECT * FROM tblB; | |
432 SELECT * FROM tblC; | |
433 } | |
434 } {1 2 1 2 1 2} | |
435 execsql { | |
436 DROP TABLE tblA; | |
437 DROP TABLE tblB; | |
438 DROP TABLE tblC; | |
439 } | |
440 | |
441 # Simple recursive trigger | |
442 execsql { | |
443 CREATE TABLE tbl(a, b, c); | |
444 CREATE TRIGGER tbl_trig BEFORE INSERT ON tbl | |
445 BEGIN | |
446 INSERT INTO tbl VALUES (new.a, new.b, new.c); | |
447 END; | |
448 } | |
449 do_test trigger2-4.2 { | |
450 execsql { | |
451 INSERT INTO tbl VALUES (1, 2, 3); | |
452 select * from tbl; | |
453 } | |
454 } {1 2 3 1 2 3} | |
455 execsql { | |
456 DROP TABLE tbl; | |
457 } | |
458 | |
459 # 5. | |
460 execsql { | |
461 CREATE TABLE tbl(a, b, c); | |
462 CREATE TRIGGER tbl_trig BEFORE INSERT ON tbl | |
463 BEGIN | |
464 INSERT INTO tbl VALUES (1, 2, 3); | |
465 INSERT INTO tbl VALUES (2, 2, 3); | |
466 UPDATE tbl set b = 10 WHERE a = 1; | |
467 DELETE FROM tbl WHERE a = 1; | |
468 DELETE FROM tbl; | |
469 END; | |
470 } | |
471 do_test trigger2-5 { | |
472 execsql { | |
473 INSERT INTO tbl VALUES(100, 200, 300); | |
474 } | |
475 db changes | |
476 } {1} | |
477 execsql { | |
478 DROP TABLE tbl; | |
479 } | |
480 | |
481 ifcapable conflict { | |
482 # Handling of ON CONFLICT by INSERT statements inside triggers | |
483 execsql { | |
484 CREATE TABLE tbl (a primary key, b, c); | |
485 CREATE TRIGGER ai_tbl AFTER INSERT ON tbl BEGIN | |
486 INSERT OR IGNORE INTO tbl values (new.a, 0, 0); | |
487 END; | |
488 } | |
489 do_test trigger2-6.1a { | |
490 execsql { | |
491 BEGIN; | |
492 INSERT INTO tbl values (1, 2, 3); | |
493 SELECT * from tbl; | |
494 } | |
495 } {1 2 3} | |
496 do_test trigger2-6.1b { | |
497 catchsql { | |
498 INSERT OR ABORT INTO tbl values (2, 2, 3); | |
499 } | |
500 } {1 {UNIQUE constraint failed: tbl.a}} | |
501 do_test trigger2-6.1c { | |
502 execsql { | |
503 SELECT * from tbl; | |
504 } | |
505 } {1 2 3} | |
506 do_test trigger2-6.1d { | |
507 catchsql { | |
508 INSERT OR FAIL INTO tbl values (2, 2, 3); | |
509 } | |
510 } {1 {UNIQUE constraint failed: tbl.a}} | |
511 do_test trigger2-6.1e { | |
512 execsql { | |
513 SELECT * from tbl; | |
514 } | |
515 } {1 2 3 2 2 3} | |
516 do_test trigger2-6.1f { | |
517 execsql { | |
518 INSERT OR REPLACE INTO tbl values (2, 2, 3); | |
519 SELECT * from tbl; | |
520 } | |
521 } {1 2 3 2 0 0} | |
522 do_test trigger2-6.1g { | |
523 catchsql { | |
524 INSERT OR ROLLBACK INTO tbl values (3, 2, 3); | |
525 } | |
526 } {1 {UNIQUE constraint failed: tbl.a}} | |
527 do_test trigger2-6.1h { | |
528 execsql { | |
529 SELECT * from tbl; | |
530 } | |
531 } {} | |
532 execsql {DELETE FROM tbl} | |
533 | |
534 | |
535 # Handling of ON CONFLICT by UPDATE statements inside triggers | |
536 execsql { | |
537 INSERT INTO tbl values (4, 2, 3); | |
538 INSERT INTO tbl values (6, 3, 4); | |
539 CREATE TRIGGER au_tbl AFTER UPDATE ON tbl BEGIN | |
540 UPDATE OR IGNORE tbl SET a = new.a, c = 10; | |
541 END; | |
542 } | |
543 do_test trigger2-6.2a { | |
544 execsql { | |
545 BEGIN; | |
546 UPDATE tbl SET a = 1 WHERE a = 4; | |
547 SELECT * from tbl; | |
548 } | |
549 } {1 2 10 6 3 4} | |
550 do_test trigger2-6.2b { | |
551 catchsql { | |
552 UPDATE OR ABORT tbl SET a = 4 WHERE a = 1; | |
553 } | |
554 } {1 {UNIQUE constraint failed: tbl.a}} | |
555 do_test trigger2-6.2c { | |
556 execsql { | |
557 SELECT * from tbl; | |
558 } | |
559 } {1 2 10 6 3 4} | |
560 do_test trigger2-6.2d { | |
561 catchsql { | |
562 UPDATE OR FAIL tbl SET a = 4 WHERE a = 1; | |
563 } | |
564 } {1 {UNIQUE constraint failed: tbl.a}} | |
565 do_test trigger2-6.2e { | |
566 execsql { | |
567 SELECT * from tbl; | |
568 } | |
569 } {4 2 10 6 3 4} | |
570 do_test trigger2-6.2f.1 { | |
571 execsql { | |
572 UPDATE OR REPLACE tbl SET a = 1 WHERE a = 4; | |
573 SELECT * from tbl; | |
574 } | |
575 } {1 3 10} | |
576 do_test trigger2-6.2f.2 { | |
577 execsql { | |
578 INSERT INTO tbl VALUES (2, 3, 4); | |
579 SELECT * FROM tbl; | |
580 } | |
581 } {1 3 10 2 3 4} | |
582 do_test trigger2-6.2g { | |
583 catchsql { | |
584 UPDATE OR ROLLBACK tbl SET a = 4 WHERE a = 1; | |
585 } | |
586 } {1 {UNIQUE constraint failed: tbl.a}} | |
587 do_test trigger2-6.2h { | |
588 execsql { | |
589 SELECT * from tbl; | |
590 } | |
591 } {4 2 3 6 3 4} | |
592 execsql { | |
593 DROP TABLE tbl; | |
594 } | |
595 } ; # ifcapable conflict | |
596 | |
597 # 7. Triggers on views | |
598 ifcapable view { | |
599 | |
600 do_test trigger2-7.1 { | |
601 execsql { | |
602 CREATE TABLE ab(a, b); | |
603 CREATE TABLE cd(c, d); | |
604 INSERT INTO ab VALUES (1, 2); | |
605 INSERT INTO ab VALUES (0, 0); | |
606 INSERT INTO cd VALUES (3, 4); | |
607 | |
608 CREATE TABLE tlog(ii INTEGER PRIMARY KEY, | |
609 olda, oldb, oldc, oldd, newa, newb, newc, newd); | |
610 | |
611 CREATE VIEW abcd AS SELECT a, b, c, d FROM ab, cd; | |
612 | |
613 CREATE TRIGGER before_update INSTEAD OF UPDATE ON abcd BEGIN | |
614 INSERT INTO tlog VALUES(NULL, | |
615 old.a, old.b, old.c, old.d, new.a, new.b, new.c, new.d); | |
616 END; | |
617 CREATE TRIGGER after_update INSTEAD OF UPDATE ON abcd BEGIN | |
618 INSERT INTO tlog VALUES(NULL, | |
619 old.a, old.b, old.c, old.d, new.a, new.b, new.c, new.d); | |
620 END; | |
621 | |
622 CREATE TRIGGER before_delete INSTEAD OF DELETE ON abcd BEGIN | |
623 INSERT INTO tlog VALUES(NULL, | |
624 old.a, old.b, old.c, old.d, 0, 0, 0, 0); | |
625 END; | |
626 CREATE TRIGGER after_delete INSTEAD OF DELETE ON abcd BEGIN | |
627 INSERT INTO tlog VALUES(NULL, | |
628 old.a, old.b, old.c, old.d, 0, 0, 0, 0); | |
629 END; | |
630 | |
631 CREATE TRIGGER before_insert INSTEAD OF INSERT ON abcd BEGIN | |
632 INSERT INTO tlog VALUES(NULL, | |
633 0, 0, 0, 0, new.a, new.b, new.c, new.d); | |
634 END; | |
635 CREATE TRIGGER after_insert INSTEAD OF INSERT ON abcd BEGIN | |
636 INSERT INTO tlog VALUES(NULL, | |
637 0, 0, 0, 0, new.a, new.b, new.c, new.d); | |
638 END; | |
639 } | |
640 } {}; | |
641 | |
642 do_test trigger2-7.2 { | |
643 execsql { | |
644 UPDATE abcd SET a = 100, b = 5*5 WHERE a = 1; | |
645 DELETE FROM abcd WHERE a = 1; | |
646 INSERT INTO abcd VALUES(10, 20, 30, 40); | |
647 SELECT * FROM tlog; | |
648 } | |
649 } [ list 1 1 2 3 4 100 25 3 4 \ | |
650 2 1 2 3 4 100 25 3 4 \ | |
651 3 1 2 3 4 0 0 0 0 \ | |
652 4 1 2 3 4 0 0 0 0 \ | |
653 5 0 0 0 0 10 20 30 40 \ | |
654 6 0 0 0 0 10 20 30 40 ] | |
655 | |
656 do_test trigger2-7.3 { | |
657 execsql { | |
658 DELETE FROM tlog; | |
659 INSERT INTO abcd VALUES(10, 20, 30, 40); | |
660 UPDATE abcd SET a = 100, b = 5*5 WHERE a = 1; | |
661 DELETE FROM abcd WHERE a = 1; | |
662 SELECT * FROM tlog; | |
663 } | |
664 } [ list \ | |
665 1 0 0 0 0 10 20 30 40 \ | |
666 2 0 0 0 0 10 20 30 40 \ | |
667 3 1 2 3 4 100 25 3 4 \ | |
668 4 1 2 3 4 100 25 3 4 \ | |
669 5 1 2 3 4 0 0 0 0 \ | |
670 6 1 2 3 4 0 0 0 0 \ | |
671 ] | |
672 do_test trigger2-7.4 { | |
673 execsql { | |
674 DELETE FROM tlog; | |
675 DELETE FROM abcd WHERE a = 1; | |
676 INSERT INTO abcd VALUES(10, 20, 30, 40); | |
677 UPDATE abcd SET a = 100, b = 5*5 WHERE a = 1; | |
678 SELECT * FROM tlog; | |
679 } | |
680 } [ list \ | |
681 1 1 2 3 4 0 0 0 0 \ | |
682 2 1 2 3 4 0 0 0 0 \ | |
683 3 0 0 0 0 10 20 30 40 \ | |
684 4 0 0 0 0 10 20 30 40 \ | |
685 5 1 2 3 4 100 25 3 4 \ | |
686 6 1 2 3 4 100 25 3 4 \ | |
687 ] | |
688 | |
689 do_test trigger2-8.1 { | |
690 execsql { | |
691 CREATE TABLE t1(a,b,c); | |
692 INSERT INTO t1 VALUES(1,2,3); | |
693 CREATE VIEW v1 AS | |
694 SELECT a+b AS x, b+c AS y, a+c AS z FROM t1; | |
695 SELECT * FROM v1; | |
696 } | |
697 } {3 5 4} | |
698 do_test trigger2-8.2 { | |
699 execsql { | |
700 CREATE TABLE v1log(a,b,c,d,e,f); | |
701 CREATE TRIGGER r1 INSTEAD OF DELETE ON v1 BEGIN | |
702 INSERT INTO v1log VALUES(OLD.x,NULL,OLD.y,NULL,OLD.z,NULL); | |
703 END; | |
704 DELETE FROM v1 WHERE x=1; | |
705 SELECT * FROM v1log; | |
706 } | |
707 } {} | |
708 do_test trigger2-8.3 { | |
709 execsql { | |
710 DELETE FROM v1 WHERE x=3; | |
711 SELECT * FROM v1log; | |
712 } | |
713 } {3 {} 5 {} 4 {}} | |
714 do_test trigger2-8.4 { | |
715 execsql { | |
716 INSERT INTO t1 VALUES(4,5,6); | |
717 DELETE FROM v1log; | |
718 DELETE FROM v1 WHERE y=11; | |
719 SELECT * FROM v1log; | |
720 } | |
721 } {9 {} 11 {} 10 {}} | |
722 do_test trigger2-8.5 { | |
723 execsql { | |
724 CREATE TRIGGER r2 INSTEAD OF INSERT ON v1 BEGIN | |
725 INSERT INTO v1log VALUES(NULL,NEW.x,NULL,NEW.y,NULL,NEW.z); | |
726 END; | |
727 DELETE FROM v1log; | |
728 INSERT INTO v1 VALUES(1,2,3); | |
729 SELECT * FROM v1log; | |
730 } | |
731 } {{} 1 {} 2 {} 3} | |
732 do_test trigger2-8.6 { | |
733 execsql { | |
734 CREATE TRIGGER r3 INSTEAD OF UPDATE ON v1 BEGIN | |
735 INSERT INTO v1log VALUES(OLD.x,NEW.x,OLD.y,NEW.y,OLD.z,NEW.z); | |
736 END; | |
737 DELETE FROM v1log; | |
738 UPDATE v1 SET x=x+100, y=y+200, z=z+300; | |
739 SELECT * FROM v1log; | |
740 } | |
741 } {3 103 5 205 4 304 9 109 11 211 10 310} | |
742 | |
743 # At one point the following was causing a segfault. | |
744 do_test trigger2-9.1 { | |
745 execsql { | |
746 CREATE TABLE t3(a TEXT, b TEXT); | |
747 CREATE VIEW v3 AS SELECT t3.a FROM t3; | |
748 CREATE TRIGGER trig1 INSTEAD OF DELETE ON v3 BEGIN | |
749 SELECT 1; | |
750 END; | |
751 DELETE FROM v3 WHERE a = 1; | |
752 } | |
753 } {} | |
754 | |
755 } ;# ifcapable view | |
756 | |
757 integrity_check trigger2-9.9 | |
758 | |
759 finish_test | |
OLD | NEW |