3 # The author disclaims copyright to this source code. In place of
4 # a legal notice', here is a blessing:
6 # May you do good and not evil.
7 # May you find forgiveness for yourself and forgive others.
8 # May you share freely, never taking more than you give.
10 #***********************************************************************
13 set testdir [file dirname $argv0]
14 source $testdir/tester.tcl
15 ifcapable {!trigger} {
20 #-------------------------------------------------------------------------
23 # triggerC-1.*: Haphazardly designed trigger related tests that were useful
24 # during an upgrade of the triggers sub-system.
32 # triggerC-5.*: Test that when recursive triggers are enabled DELETE
33 # triggers are fired when rows are deleted as part of OR
34 # REPLACE conflict resolution. And that they are not fired
35 # if recursive triggers are not enabled.
37 # triggerC-6.*: Test that the recursive_triggers pragma returns correct
38 # results when invoked without an argument.
41 # Enable recursive triggers for this file.
43 execsql { PRAGMA recursive_triggers = on }
45 #sqlite3_db_config_lookaside db 0 0 0
47 #-------------------------------------------------------------------------
48 # This block of tests, triggerC-1.*, are not aimed at any specific
49 # property of the triggers sub-system. They were created to debug
50 # specific problems while modifying SQLite to support recursive
51 # triggers. They are left here in case they can help debug the
52 # same problems again.
54 do_test triggerC-1.1 {
56 CREATE TABLE t1(a, b, c);
57 CREATE TABLE log(t, a1, b1, c1, a2, b2, c2);
58 CREATE TRIGGER trig1 BEFORE INSERT ON t1 BEGIN
59 INSERT INTO log VALUES('before', NULL, NULL, NULL, new.a, new.b, new.c);
61 CREATE TRIGGER trig2 AFTER INSERT ON t1 BEGIN
62 INSERT INTO log VALUES('after', NULL, NULL, NULL, new.a, new.b, new.c);
64 CREATE TRIGGER trig3 BEFORE UPDATE ON t1 BEGIN
65 INSERT INTO log VALUES('before', old.a,old.b,old.c, new.a,new.b,new.c);
67 CREATE TRIGGER trig4 AFTER UPDATE ON t1 BEGIN
68 INSERT INTO log VALUES('after', old.a,old.b,old.c, new.a,new.b,new.c);
71 CREATE TRIGGER trig5 BEFORE DELETE ON t1 BEGIN
72 INSERT INTO log VALUES('before', old.a,old.b,old.c, NULL,NULL,NULL);
74 CREATE TRIGGER trig6 AFTER DELETE ON t1 BEGIN
75 INSERT INTO log VALUES('after', old.a,old.b,old.c, NULL,NULL,NULL);
79 do_test triggerC-1.2 {
81 INSERT INTO t1 VALUES('A', 'B', 'C');
84 } {before {} {} {} A B C after {} {} {} A B C}
85 do_test triggerC-1.3 {
86 execsql { SELECT * FROM t1 }
88 do_test triggerC-1.4 {
91 UPDATE t1 SET a = 'a';
94 } {before A B C a B C after A B C a B C}
95 do_test triggerC-1.5 {
96 execsql { SELECT * FROM t1 }
98 do_test triggerC-1.6 {
104 } {before a B C {} {} {} after a B C {} {} {}}
105 do_test triggerC-1.7 {
106 execsql { SELECT * FROM t1 }
108 do_test triggerC-1.8 {
110 CREATE TABLE t4(a, b);
111 CREATE TRIGGER t4t AFTER DELETE ON t4 BEGIN
112 SELECT RAISE(ABORT, 'delete is not supported');
116 do_test triggerC-1.9 {
117 execsql { INSERT INTO t4 VALUES(1, 2) }
118 catchsql { DELETE FROM t4 }
119 } {1 {delete is not supported}}
120 do_test triggerC-1.10 {
121 execsql { SELECT * FROM t4 }
123 do_test triggerC-1.11 {
125 CREATE TABLE t5 (a primary key, b, c);
126 INSERT INTO t5 values (1, 2, 3);
127 CREATE TRIGGER au_tbl AFTER UPDATE ON t5 BEGIN
128 UPDATE OR IGNORE t5 SET a = new.a, c = 10;
132 do_test triggerC-1.12 {
133 catchsql { UPDATE OR REPLACE t5 SET a = 4 WHERE a = 1 }
134 } {1 {too many levels of trigger recursion}}
135 do_test triggerC-1.13 {
137 CREATE TABLE t6(a INTEGER PRIMARY KEY, b);
138 INSERT INTO t6 VALUES(1, 2);
139 create trigger r1 after update on t6 for each row begin
145 do_test triggerC-1.14 {
149 INSERT INTO cnt VALUES(0);
150 CREATE TABLE t1(a INTEGER PRIMARY KEY, b UNIQUE, c, d, e);
151 CREATE INDEX t1cd ON t1(c,d);
152 CREATE TRIGGER t1r1 AFTER UPDATE ON t1 BEGIN UPDATE cnt SET n=n+1; END;
153 INSERT INTO t1 VALUES(1,2,3,4,5);
154 INSERT INTO t1 VALUES(6,7,8,9,10);
155 INSERT INTO t1 VALUES(11,12,13,14,15);
158 do_test triggerC-1.15 {
159 catchsql { UPDATE OR ROLLBACK t1 SET a=100 }
160 } {1 {PRIMARY KEY must be unique}}
163 #-------------------------------------------------------------------------
164 # This block of tests, triggerC-2.*, tests that recursive trigger
165 # programs (triggers that fire themselves) work. More specifically,
166 # this block focuses on recursive INSERT triggers.
168 do_test triggerC-2.1.0 {
170 CREATE TABLE t2(a PRIMARY KEY);
174 foreach {n tdefn rc} {
176 CREATE TRIGGER t2_trig AFTER INSERT ON t2 WHEN (new.a>0) BEGIN
177 INSERT INTO t2 VALUES(new.a - 1);
179 } {0 {10 9 8 7 6 5 4 3 2 1 0}}
182 CREATE TRIGGER t2_trig AFTER INSERT ON t2 BEGIN
183 SELECT CASE WHEN new.a==2 THEN RAISE(IGNORE) ELSE NULL END;
184 INSERT INTO t2 VALUES(new.a - 1);
186 } {0 {10 9 8 7 6 5 4 3 2}}
189 CREATE TRIGGER t2_trig BEFORE INSERT ON t2 WHEN (new.a>0) BEGIN
190 INSERT INTO t2 VALUES(new.a - 1);
192 } {0 {0 1 2 3 4 5 6 7 8 9 10}}
195 CREATE TRIGGER t2_trig BEFORE INSERT ON t2 BEGIN
196 SELECT CASE WHEN new.a==2 THEN RAISE(IGNORE) ELSE NULL END;
197 INSERT INTO t2 VALUES(new.a - 1);
199 } {0 {3 4 5 6 7 8 9 10}}
202 CREATE TRIGGER t2_trig BEFORE INSERT ON t2 BEGIN
203 INSERT INTO t2 VALUES(new.a - 1);
205 } {1 {too many levels of trigger recursion}}
208 CREATE TRIGGER t2_trig AFTER INSERT ON t2 WHEN (new.a>0) BEGIN
209 INSERT OR IGNORE INTO t2 VALUES(new.a);
214 CREATE TRIGGER t2_trig BEFORE INSERT ON t2 WHEN (new.a>0) BEGIN
215 INSERT OR IGNORE INTO t2 VALUES(new.a);
217 } {1 {too many levels of trigger recursion}}
219 do_test triggerC-2.1.$n {
220 catchsql { DROP TRIGGER t2_trig }
221 execsql { DELETE FROM t2 }
224 INSERT INTO t2 VALUES(10);
230 do_test triggerC-2.2 {
234 CREATE TRIGGER t22a AFTER INSERT ON t22 BEGIN
235 INSERT INTO t22 SELECT x + (SELECT max(x) FROM t22) FROM t22;
237 CREATE TRIGGER t22b BEFORE INSERT ON t22 BEGIN
238 SELECT CASE WHEN (SELECT count(*) FROM t22) >= [expr $SQLITE_MAX_TRIGGER_DEPTH / 2]
243 INSERT INTO t22 VALUES(1);
244 SELECT count(*) FROM t22;
246 } [list [expr $SQLITE_MAX_TRIGGER_DEPTH / 2]]
248 do_test triggerC-2.3 {
250 CREATE TABLE t23(x PRIMARY KEY);
252 CREATE TRIGGER t23a AFTER INSERT ON t23 BEGIN
253 INSERT INTO t23 VALUES(new.x + 1);
256 CREATE TRIGGER t23b BEFORE INSERT ON t23 BEGIN
257 SELECT CASE WHEN new.x>[expr $SQLITE_MAX_TRIGGER_DEPTH / 2]
262 INSERT INTO t23 VALUES(1);
263 SELECT count(*) FROM t23;
265 } [list [expr $SQLITE_MAX_TRIGGER_DEPTH / 2]]
268 #-----------------------------------------------------------------------
269 # This block of tests, triggerC-3.*, test that SQLite throws an exception
270 # when it detects excessive recursion.
272 do_test triggerC-3.1.1 {
274 CREATE TABLE t3(a, b);
275 CREATE TRIGGER t3i AFTER INSERT ON t3 BEGIN
276 DELETE FROM t3 WHERE rowid = new.rowid;
278 CREATE TRIGGER t3d AFTER DELETE ON t3 BEGIN
279 INSERT INTO t3 VALUES(old.a, old.b);
283 do_test triggerC-3.1.2 {
284 catchsql { INSERT INTO t3 VALUES(0,0) }
285 } {1 {too many levels of trigger recursion}}
286 do_test triggerC-3.1.3 {
287 execsql { SELECT * FROM t3 }
290 do_test triggerC-3.2.1 {
293 CREATE TRIGGER t3bi AFTER INSERT ON t3b WHEN new.x<[expr $SQLITE_MAX_TRIGGER_DEPTH * 2] BEGIN
294 INSERT INTO t3b VALUES(new.x+1);
298 INSERT INTO t3b VALUES(1);
300 } {1 {too many levels of trigger recursion}}
301 do_test triggerC-3.2.2 {
302 db eval {SELECT * FROM t3b}
305 do_test triggerC-3.3.1 {
307 INSERT INTO t3b VALUES([expr $SQLITE_MAX_TRIGGER_DEPTH + 1]);
310 do_test triggerC-3.3.2 {
311 db eval {SELECT count(*), max(x), min(x) FROM t3b}
312 } [list $SQLITE_MAX_TRIGGER_DEPTH [expr $SQLITE_MAX_TRIGGER_DEPTH * 2] [expr $SQLITE_MAX_TRIGGER_DEPTH + 1]]
314 do_test triggerC-3.4.1 {
317 INSERT INTO t3b VALUES([expr $SQLITE_MAX_TRIGGER_DEPTH - 1]);
319 } {1 {too many levels of trigger recursion}}
320 do_test triggerC-3.4.2 {
321 db eval {SELECT count(*), max(x), min(x) FROM t3b}
324 do_test triggerC-3.5.1 {
325 sqlite3_limit db SQLITE_LIMIT_TRIGGER_DEPTH [expr $SQLITE_MAX_TRIGGER_DEPTH / 10]
327 INSERT INTO t3b VALUES([expr ($SQLITE_MAX_TRIGGER_DEPTH * 2) - ($SQLITE_MAX_TRIGGER_DEPTH / 10) + 1]);
330 do_test triggerC-3.5.2 {
331 db eval {SELECT count(*), max(x), min(x) FROM t3b}
332 } [list [expr $SQLITE_MAX_TRIGGER_DEPTH / 10] [expr $SQLITE_MAX_TRIGGER_DEPTH * 2] [expr ($SQLITE_MAX_TRIGGER_DEPTH * 2) - ($SQLITE_MAX_TRIGGER_DEPTH / 10) + 1]]
334 do_test triggerC-3.5.3 {
337 INSERT INTO t3b VALUES([expr ($SQLITE_MAX_TRIGGER_DEPTH * 2) - ($SQLITE_MAX_TRIGGER_DEPTH / 10)]);
339 } {1 {too many levels of trigger recursion}}
340 do_test triggerC-3.5.4 {
341 db eval {SELECT count(*), max(x), min(x) FROM t3b}
344 do_test triggerC-3.6.1 {
345 sqlite3_limit db SQLITE_LIMIT_TRIGGER_DEPTH 1
347 INSERT INTO t3b VALUES([expr $SQLITE_MAX_TRIGGER_DEPTH * 2]);
350 do_test triggerC-3.6.2 {
351 db eval {SELECT count(*), max(x), min(x) FROM t3b}
352 } [list 1 [expr $SQLITE_MAX_TRIGGER_DEPTH * 2] [expr $SQLITE_MAX_TRIGGER_DEPTH * 2]]
354 do_test triggerC-3.6.3 {
357 INSERT INTO t3b VALUES([expr ($SQLITE_MAX_TRIGGER_DEPTH * 2) - 1]);
359 } {1 {too many levels of trigger recursion}}
360 do_test triggerC-3.6.4 {
361 db eval {SELECT count(*), max(x), min(x) FROM t3b}
363 sqlite3_limit db SQLITE_LIMIT_TRIGGER_DEPTH $SQLITE_MAX_TRIGGER_DEPTH
366 #-----------------------------------------------------------------------
367 # This next block of tests, triggerC-4.*, checks that affinity
368 # transformations and constraint processing is performed at the correct
369 # times relative to BEFORE and AFTER triggers.
371 # For an INSERT statement, for each row to be inserted:
373 # 1. Apply affinities to non-rowid values to be inserted.
374 # 2. Fire BEFORE triggers.
375 # 3. Process constraints.
376 # 4. Insert new record.
377 # 5. Fire AFTER triggers.
379 # If the value of the rowid field is to be automatically assigned, it is
380 # set to -1 in the new.* record. Even if it is explicitly set to NULL
381 # by the INSERT statement.
383 # For an UPDATE statement, for each row to be deleted:
385 # 1. Apply affinities to non-rowid values to be inserted.
386 # 2. Fire BEFORE triggers.
387 # 3. Process constraints.
388 # 4. Insert new record.
389 # 5. Fire AFTER triggers.
391 # For a DELETE statement, for each row to be deleted:
393 # 1. Fire BEFORE triggers.
394 # 2. Remove database record.
395 # 3. Fire AFTER triggers.
397 # When a numeric value that as an exact integer representation is stored
398 # in a column with REAL affinity, it is actually stored as an integer.
399 # These tests check that the typeof() such values is always 'real',
402 # triggerC-4.1.*: Check that affinity transformations are made before
403 # triggers are invoked.
405 do_test triggerC-4.1.1 {
406 catchsql { DROP TABLE log }
407 catchsql { DROP TABLE t4 }
410 CREATE TABLE t4(a TEXT,b INTEGER,c REAL);
411 CREATE TRIGGER t4bi BEFORE INSERT ON t4 BEGIN
412 INSERT INTO log VALUES(new.rowid || ' ' || typeof(new.rowid) || ' ' ||
413 new.a || ' ' || typeof(new.a) || ' ' ||
414 new.b || ' ' || typeof(new.b) || ' ' ||
415 new.c || ' ' || typeof(new.c)
418 CREATE TRIGGER t4ai AFTER INSERT ON t4 BEGIN
419 INSERT INTO log VALUES(new.rowid || ' ' || typeof(new.rowid) || ' ' ||
420 new.a || ' ' || typeof(new.a) || ' ' ||
421 new.b || ' ' || typeof(new.b) || ' ' ||
422 new.c || ' ' || typeof(new.c)
425 CREATE TRIGGER t4bd BEFORE DELETE ON t4 BEGIN
426 INSERT INTO log VALUES(old.rowid || ' ' || typeof(old.rowid) || ' ' ||
427 old.a || ' ' || typeof(old.a) || ' ' ||
428 old.b || ' ' || typeof(old.b) || ' ' ||
429 old.c || ' ' || typeof(old.c)
432 CREATE TRIGGER t4ad AFTER DELETE ON t4 BEGIN
433 INSERT INTO log VALUES(old.rowid || ' ' || typeof(old.rowid) || ' ' ||
434 old.a || ' ' || typeof(old.a) || ' ' ||
435 old.b || ' ' || typeof(old.b) || ' ' ||
436 old.c || ' ' || typeof(old.c)
439 CREATE TRIGGER t4bu BEFORE UPDATE ON t4 BEGIN
440 INSERT INTO log VALUES(old.rowid || ' ' || typeof(old.rowid) || ' ' ||
441 old.a || ' ' || typeof(old.a) || ' ' ||
442 old.b || ' ' || typeof(old.b) || ' ' ||
443 old.c || ' ' || typeof(old.c)
445 INSERT INTO log VALUES(new.rowid || ' ' || typeof(new.rowid) || ' ' ||
446 new.a || ' ' || typeof(new.a) || ' ' ||
447 new.b || ' ' || typeof(new.b) || ' ' ||
448 new.c || ' ' || typeof(new.c)
451 CREATE TRIGGER t4au AFTER UPDATE ON t4 BEGIN
452 INSERT INTO log VALUES(old.rowid || ' ' || typeof(old.rowid) || ' ' ||
453 old.a || ' ' || typeof(old.a) || ' ' ||
454 old.b || ' ' || typeof(old.b) || ' ' ||
455 old.c || ' ' || typeof(old.c)
457 INSERT INTO log VALUES(new.rowid || ' ' || typeof(new.rowid) || ' ' ||
458 new.a || ' ' || typeof(new.a) || ' ' ||
459 new.b || ' ' || typeof(new.b) || ' ' ||
460 new.c || ' ' || typeof(new.c)
465 foreach {n insert log} {
468 INSERT INTO t4 VALUES('1', '1', '1');
471 -1 integer 1 text 1 integer 1.0 real
472 1 integer 1 text 1 integer 1.0 real
473 1 integer 1 text 1 integer 1.0 real
474 1 integer 1 text 1 integer 1.0 real
478 INSERT INTO t4(rowid,a,b,c) VALUES(45, 45, 45, 45);
481 45 integer 45 text 45 integer 45.0 real
482 45 integer 45 text 45 integer 45.0 real
483 45 integer 45 text 45 integer 45.0 real
484 45 integer 45 text 45 integer 45.0 real
488 INSERT INTO t4(rowid,a,b,c) VALUES(-42.0, -42.0, -42.0, -42.0);
491 -42 integer -42.0 text -42 integer -42.0 real
492 -42 integer -42.0 text -42 integer -42.0 real
493 -42 integer -42.0 text -42 integer -42.0 real
494 -42 integer -42.0 text -42 integer -42.0 real
498 INSERT INTO t4(rowid,a,b,c) VALUES(NULL, -42.4, -42.4, -42.4);
501 -1 integer -42.4 text -42.4 real -42.4 real
502 1 integer -42.4 text -42.4 real -42.4 real
503 1 integer -42.4 text -42.4 real -42.4 real
504 1 integer -42.4 text -42.4 real -42.4 real
508 INSERT INTO t4 VALUES(7, 7, 7);
509 UPDATE t4 SET a=8, b=8, c=8;
511 -1 integer 7 text 7 integer 7.0 real
512 1 integer 7 text 7 integer 7.0 real
513 1 integer 7 text 7 integer 7.0 real
514 1 integer 8 text 8 integer 8.0 real
515 1 integer 7 text 7 integer 7.0 real
516 1 integer 8 text 8 integer 8.0 real
520 UPDATE t4 SET rowid=2;
522 1 integer 8 text 8 integer 8.0 real
523 2 integer 8 text 8 integer 8.0 real
524 1 integer 8 text 8 integer 8.0 real
525 2 integer 8 text 8 integer 8.0 real
529 UPDATE t4 SET a='9', b='9', c='9';
531 2 integer 8 text 8 integer 8.0 real
532 2 integer 9 text 9 integer 9.0 real
533 2 integer 8 text 8 integer 8.0 real
534 2 integer 9 text 9 integer 9.0 real
538 UPDATE t4 SET a='9.1', b='9.1', c='9.1';
540 2 integer 9 text 9 integer 9.0 real
541 2 integer 9.1 text 9.1 real 9.1 real
542 2 integer 9 text 9 integer 9.0 real
543 2 integer 9.1 text 9.1 real 9.1 real
546 do_test triggerC-4.1.$n {
547 eval concat [execsql "
555 #-------------------------------------------------------------------------
556 # This block of tests, triggerC-5.*, test that DELETE triggers are fired
557 # if a row is deleted as a result of OR REPLACE conflict resolution.
559 do_test triggerC-5.1.0 {
561 DROP TABLE IF EXISTS t5;
562 CREATE TABLE t5(a INTEGER PRIMARY KEY, b);
563 CREATE UNIQUE INDEX t5i ON t5(b);
564 INSERT INTO t5 VALUES(1, 'a');
565 INSERT INTO t5 VALUES(2, 'b');
566 INSERT INTO t5 VALUES(3, 'c');
568 CREATE TABLE t5g(a, b, c);
569 CREATE TRIGGER t5t BEFORE DELETE ON t5 BEGIN
570 INSERT INTO t5g VALUES(old.a, old.b, (SELECT count(*) FROM t5));
574 foreach {n dml t5g t5} {
575 1 "DELETE FROM t5 WHERE a=2" {2 b 3} {1 a 3 c}
576 2 "INSERT OR REPLACE INTO t5 VALUES(2, 'd')" {2 b 3} {1 a 2 d 3 c}
577 3 "UPDATE OR REPLACE t5 SET a = 2 WHERE a = 3" {2 b 3} {1 a 2 c}
578 4 "INSERT OR REPLACE INTO t5 VALUES(4, 'b')" {2 b 3} {1 a 3 c 4 b}
579 5 "UPDATE OR REPLACE t5 SET b = 'b' WHERE b = 'c'" {2 b 3} {1 a 3 b}
580 6 "INSERT OR REPLACE INTO t5 VALUES(2, 'c')" {2 b 3 3 c 2} {1 a 2 c}
581 7 "UPDATE OR REPLACE t5 SET a=1, b='b' WHERE a = 3" {1 a 3 2 b 2} {1 b}
583 do_test triggerC-5.1.$n {
593 do_test triggerC-5.2.0 {
596 CREATE TRIGGER t5t AFTER DELETE ON t5 BEGIN
597 INSERT INTO t5g VALUES(old.a, old.b, (SELECT count(*) FROM t5));
601 foreach {n dml t5g t5} {
602 1 "DELETE FROM t5 WHERE a=2" {2 b 2} {1 a 3 c}
603 2 "INSERT OR REPLACE INTO t5 VALUES(2, 'd')" {2 b 2} {1 a 2 d 3 c}
604 3 "UPDATE OR REPLACE t5 SET a = 2 WHERE a = 3" {2 b 2} {1 a 2 c}
605 4 "INSERT OR REPLACE INTO t5 VALUES(4, 'b')" {2 b 2} {1 a 3 c 4 b}
606 5 "UPDATE OR REPLACE t5 SET b = 'b' WHERE b = 'c'" {2 b 2} {1 a 3 b}
607 6 "INSERT OR REPLACE INTO t5 VALUES(2, 'c')" {2 b 2 3 c 1} {1 a 2 c}
608 7 "UPDATE OR REPLACE t5 SET a=1, b='b' WHERE a = 3" {1 a 2 2 b 1} {1 b}
610 do_test triggerC-5.2.$n {
620 do_test triggerC-5.3.0 {
621 execsql { PRAGMA recursive_triggers = off }
623 foreach {n dml t5g t5} {
624 1 "DELETE FROM t5 WHERE a=2" {2 b 2} {1 a 3 c}
625 2 "INSERT OR REPLACE INTO t5 VALUES(2, 'd')" {} {1 a 2 d 3 c}
626 3 "UPDATE OR REPLACE t5 SET a = 2 WHERE a = 3" {} {1 a 2 c}
627 4 "INSERT OR REPLACE INTO t5 VALUES(4, 'b')" {} {1 a 3 c 4 b}
628 5 "UPDATE OR REPLACE t5 SET b = 'b' WHERE b = 'c'" {} {1 a 3 b}
629 6 "INSERT OR REPLACE INTO t5 VALUES(2, 'c')" {} {1 a 2 c}
630 7 "UPDATE OR REPLACE t5 SET a=1, b='b' WHERE a = 3" {} {1 b}
632 do_test triggerC-5.3.$n {
642 do_test triggerC-5.3.8 {
643 execsql { PRAGMA recursive_triggers = on }
646 #-------------------------------------------------------------------------
647 # This block of tests, triggerC-6.*, tests that "PRAGMA recursive_triggers"
648 # statements return the current value of the recursive triggers flag.
650 do_test triggerC-6.1 {
651 execsql { PRAGMA recursive_triggers }
653 do_test triggerC-6.2 {
655 PRAGMA recursive_triggers = off;
656 PRAGMA recursive_triggers;
659 do_test triggerC-6.3 {
661 PRAGMA recursive_triggers = on;
662 PRAGMA recursive_triggers;
666 #-------------------------------------------------------------------------
667 # Test some of the "undefined behaviour" associated with triggers. The
668 # undefined behaviour occurs when a row being updated or deleted is
669 # manipulated by a BEFORE trigger.
671 do_test triggerC-7.1 {
674 CREATE TABLE t7(a, b);
675 INSERT INTO t7 VALUES(1, 2);
676 INSERT INTO t7 VALUES(3, 4);
677 INSERT INTO t7 VALUES(5, 6);
678 CREATE TRIGGER t7t BEFORE UPDATE ON t7 BEGIN
679 DELETE FROM t7 WHERE a = 1;
681 CREATE TRIGGER t7ta AFTER UPDATE ON t7 BEGIN
682 INSERT INTO t8 VALUES('after fired ' || old.rowid || '->' || new.rowid);
686 do_test triggerC-7.2 {
689 UPDATE t7 SET b=7 WHERE a = 5;
694 } {3 4 5 7 {after fired 3->3}}
695 do_test triggerC-7.3 {
698 UPDATE t7 SET b=7 WHERE a = 1;
705 do_test triggerC-7.4 {
708 CREATE TRIGGER t7t BEFORE UPDATE ON t7 WHEN (old.rowid!=1 OR new.rowid!=8)
710 UPDATE t7 set rowid = 8 WHERE rowid=1;
714 do_test triggerC-7.5 {
717 UPDATE t7 SET b=7 WHERE a = 5;
718 SELECT rowid, * FROM t7;
722 } {2 3 4 3 5 7 8 1 2 {after fired 1->8} {after fired 3->3}}
723 do_test triggerC-7.6 {
726 UPDATE t7 SET b=7 WHERE a = 1;
727 SELECT rowid, * FROM t7;
731 } {2 3 4 3 5 6 8 1 2 {after fired 1->8}}
733 do_test triggerC-7.7 {
737 CREATE TRIGGER t7t BEFORE DELETE ON t7 BEGIN
738 UPDATE t7 set rowid = 8 WHERE rowid=1;
740 CREATE TRIGGER t7ta AFTER DELETE ON t7 BEGIN
741 INSERT INTO t8 VALUES('after fired ' || old.rowid);
745 do_test triggerC-7.8 {
748 DELETE FROM t7 WHERE a = 3;
749 SELECT rowid, * FROM t7;
753 } {3 5 6 8 1 2 {after fired 2}}
754 do_test triggerC-7.9 {
757 DELETE FROM t7 WHERE a = 1;
758 SELECT rowid, * FROM t7;
762 } {2 3 4 3 5 6 8 1 2}
764 # Ticket [e25d9ea771febc9c311928c1c01c3163dcb26643]
766 do_test triggerC-9.1 {
768 CREATE TABLE t9(a,b);
769 CREATE INDEX t9b ON t9(b);
770 INSERT INTO t9 VALUES(1,0);
771 INSERT INTO t9 VALUES(2,1);
772 INSERT INTO t9 VALUES(3,2);
773 INSERT INTO t9 SELECT a+3, a+2 FROM t9;
774 INSERT INTO t9 SELECT a+6, a+5 FROM t9;
775 SELECT a FROM t9 ORDER BY a;
777 } {1 2 3 4 5 6 7 8 9 10 11 12}
778 do_test triggerC-9.2 {
780 CREATE TRIGGER t9r1 AFTER DELETE ON t9 BEGIN
781 DELETE FROM t9 WHERE b=old.a;
783 DELETE FROM t9 WHERE b=4;
784 SELECT a FROM t9 ORDER BY a;
788 # At one point (between versions 3.6.18 and 3.6.20 inclusive), an UPDATE
789 # that fired a BEFORE trigger that itself updated the same row as the
790 # statement causing it to fire was causing a strange side-effect: The
791 # values updated by the statement within the trigger were being overwritten
792 # by the values in the new.* array, even if those values were not
793 # themselves written by the parent UPDATE statement.
795 # Technically speaking this was not a bug. The SQLite documentation says
796 # that if a BEFORE UPDATE or BEFORE DELETE trigger modifies or deletes the
797 # row that the parent statement is operating on the results are undefined.
798 # But as of 3.6.21 behaviour is restored to the way it was in versions
799 # 3.6.17 and earlier to avoid causing unnecessary difficulties.
801 do_test triggerC-10.1 {
803 CREATE TABLE t10(a, updatecnt DEFAULT 0);
804 CREATE TRIGGER t10_bu BEFORE UPDATE OF a ON t10 BEGIN
805 UPDATE t10 SET updatecnt = updatecnt+1 WHERE rowid = old.rowid;
807 INSERT INTO t10(a) VALUES('hello');
810 # Before the problem was fixed, table t10 would contain the tuple
811 # (world, 0) after running the following script (because the value
812 # 1 written to column "updatecnt" was clobbered by the old value 0).
815 UPDATE t10 SET a = 'world';
820 do_test triggerC-10.2 {
822 UPDATE t10 SET a = 'tcl', updatecnt = 5;
827 do_test triggerC-10.3 {
830 c1, c2, c3, c4, c5, c6, c7, c8, c9, c10,
831 c11, c12, c13, c14, c15, c16, c17, c18, c19, c20,
832 c21, c22, c23, c24, c25, c26, c27, c28, c29, c30,
833 c31, c32, c33, c34, c35, c36, c37, c38, c39, c40
836 CREATE TRIGGER t11_bu BEFORE UPDATE OF c1 ON t11 BEGIN
837 UPDATE t11 SET c31 = c31+1, c32=c32+1 WHERE rowid = old.rowid;
840 INSERT INTO t11 VALUES(
841 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
842 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
843 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
844 31, 32, 33, 34, 35, 36, 37, 38, 39, 40
848 # Before the problem was fixed, table t10 would contain the tuple
849 # (world, 0) after running the following script (because the value
850 # 1 written to column "updatecnt" was clobbered by the old value 0).
853 UPDATE t11 SET c4=35, c33=22, c1=5;
856 } {5 2 3 35 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 32 33 22 34 35 36 37 38 39 40}
858 #-------------------------------------------------------------------------
859 # Test that bug [371bab5d65] has been fixed. BEFORE INSERT and INSTEAD OF
860 # INSERT triggers with the DEFAULT VALUES INSERT syntax.
862 do_test triggerC-11.0 {
863 catchsql { DROP TABLE log }
864 execsql { CREATE TABLE log(a, b) }
867 foreach {testno tbl defaults} {
868 1 "CREATE TABLE t1(a, b)" {{} {}}
869 2 "CREATE TABLE t1(a DEFAULT 1, b DEFAULT 'abc')" {1 abc}
870 3 "CREATE TABLE t1(a, b DEFAULT 4.5)" {{} 4.5}
872 do_test triggerC-11.$testno.1 {
873 catchsql { DROP TABLE t1 }
874 execsql { DELETE FROM log }
877 CREATE TRIGGER tt1 BEFORE INSERT ON t1 BEGIN
878 INSERT INTO log VALUES(new.a, new.b);
880 INSERT INTO t1 DEFAULT VALUES;
885 do_test triggerC-11.$testno.2 {
886 execsql { DELETE FROM log }
888 CREATE TRIGGER tt2 AFTER INSERT ON t1 BEGIN
889 INSERT INTO log VALUES(new.a, new.b);
891 INSERT INTO t1 DEFAULT VALUES;
894 } [concat $defaults $defaults]
896 do_test triggerC-11.$testno.3 {
897 execsql { DROP TRIGGER tt1 }
898 execsql { DELETE FROM log }
900 INSERT INTO t1 DEFAULT VALUES;
905 do_test triggerC-11.4 {
906 catchsql { DROP TABLE t2 }
909 CREATE TABLE t2(a, b);
910 CREATE VIEW v2 AS SELECT * FROM t2;
911 CREATE TRIGGER tv2 INSTEAD OF INSERT ON v2 BEGIN
912 INSERT INTO log VALUES(new.a, new.b);
914 INSERT INTO v2 DEFAULT VALUES;
915 SELECT a, b, a IS NULL, b IS NULL FROM log;
919 do_test triggerC-12.1 {
925 CREATE TABLE t1(a, b);
926 INSERT INTO t1 VALUES(1, 2);
927 INSERT INTO t1 VALUES(3, 4);
928 INSERT INTO t1 VALUES(5, 6);
929 CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN SELECT 1 ; END ;
930 SELECT count(*) FROM sqlite_master;
933 do_test triggerC-12.2 {
934 db eval { SELECT * FROM t1 } {
935 if {$a == 3} { execsql { DROP TRIGGER tr1 } }
937 execsql { SELECT count(*) FROM sqlite_master }
940 do_execsql_test triggerC-13.1 {
941 PRAGMA recursive_triggers = ON;
942 CREATE TABLE t12(a, b);
943 INSERT INTO t12 VALUES(1, 2);
944 CREATE TRIGGER tr12 AFTER UPDATE ON t12 BEGIN
945 UPDATE t12 SET a=new.a+1, b=new.b+1;
948 do_catchsql_test triggerC-13.2 {
949 UPDATE t12 SET a=a+1, b=b+1;
950 } {1 {too many levels of trigger recursion}}