Small performance optimization in sqlite3VdbeRecordCompareWithSkip() for
[sqlite.git] / test / triggerC.test
blob3e47521fd11c71ddbf63b7507addedea33082da8
1 # 2009 August 24
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 set testprefix triggerC
16 ifcapable {!trigger} {
17   finish_test
18   return
21 #-------------------------------------------------------------------------
22 # Test organization:
24 # triggerC-1.*: Haphazardly designed trigger related tests that were useful
25 #               during an upgrade of the triggers sub-system.
26
27 # triggerC-2.*:
29 # triggerC-3.*:
31 # triggerC-4.*:
33 # triggerC-5.*: Test that when recursive triggers are enabled DELETE 
34 #               triggers are fired when rows are deleted as part of OR
35 #               REPLACE conflict resolution. And that they are not fired
36 #               if recursive triggers are not enabled.
38 # triggerC-6.*: Test that the recursive_triggers pragma returns correct
39 #               results when invoked without an argument.
42 # Enable recursive triggers for this file.
44 execsql { PRAGMA recursive_triggers = on }
46 #sqlite3_db_config_lookaside db 0 0 0
48 #-------------------------------------------------------------------------
49 # This block of tests, triggerC-1.*, are not aimed at any specific
50 # property of the triggers sub-system. They were created to debug
51 # specific problems while modifying SQLite to support recursive
52 # triggers. They are left here in case they can help debug the
53 # same problems again.
55 do_test triggerC-1.1 {
56   execsql {
57     CREATE TABLE t1(a, b, c);
58     CREATE TABLE log(t, a1, b1, c1, a2, b2, c2);
59     CREATE TRIGGER trig1 BEFORE INSERT ON t1 BEGIN
60       INSERT INTO log VALUES('before', NULL, NULL, NULL, new.a, new.b, new.c);
61     END;
62     CREATE TRIGGER trig2 AFTER INSERT ON t1 BEGIN
63       INSERT INTO log VALUES('after', NULL, NULL, NULL, new.a, new.b, new.c);
64     END;
65     CREATE TRIGGER trig3 BEFORE UPDATE ON t1 BEGIN
66       INSERT INTO log VALUES('before', old.a,old.b,old.c, new.a,new.b,new.c);
67     END;
68     CREATE TRIGGER trig4 AFTER UPDATE ON t1 BEGIN
69       INSERT INTO log VALUES('after', old.a,old.b,old.c, new.a,new.b,new.c);
70     END;
72     CREATE TRIGGER trig5 BEFORE DELETE ON t1 BEGIN
73       INSERT INTO log VALUES('before', old.a,old.b,old.c, NULL,NULL,NULL);
74     END;
75     CREATE TRIGGER trig6 AFTER DELETE ON t1 BEGIN
76       INSERT INTO log VALUES('after', old.a,old.b,old.c, NULL,NULL,NULL);
77     END;
78   }
79 } {}
80 do_test triggerC-1.2 {
81   execsql {
82     INSERT INTO t1 VALUES('A', 'B', 'C');
83     SELECT * FROM log;
84   }
85 } {before {} {} {} A B C after {} {} {} A B C}
86 do_test triggerC-1.3 {
87   execsql { SELECT * FROM t1 }
88 } {A B C}
89 do_test triggerC-1.4 {
90   execsql {
91     DELETE FROM log;
92     UPDATE t1 SET a = 'a';
93     SELECT * FROM log;
94   }
95 } {before A B C a B C after A B C a B C}
96 do_test triggerC-1.5 {
97   execsql { SELECT * FROM t1 }
98 } {a B C}
99 do_test triggerC-1.6 {
100   execsql {
101     DELETE FROM log;
102     DELETE FROM t1;
103     SELECT * FROM log;
104   }
105 } {before a B C {} {} {} after a B C {} {} {}}
106 do_test triggerC-1.7 {
107   execsql { SELECT * FROM t1 }
108 } {}
109 do_test triggerC-1.8 {
110   execsql {
111     CREATE TABLE t4(a, b);
112     CREATE TRIGGER t4t AFTER DELETE ON t4 BEGIN
113       SELECT RAISE(ABORT, 'delete is not supported');
114     END;
115   }
116 } {}
117 do_test triggerC-1.9 {
118   execsql { INSERT INTO t4 VALUES(1, 2) }
119   catchsql { DELETE FROM t4 }
120 } {1 {delete is not supported}}
121 do_test triggerC-1.10 {
122   execsql { SELECT * FROM t4 }
123 } {1 2}
124 do_test triggerC-1.11 {
125   execsql {
126     CREATE TABLE t5 (a primary key, b, c);
127     INSERT INTO t5 values (1, 2, 3);
128     CREATE TRIGGER au_tbl AFTER UPDATE ON t5 BEGIN
129       UPDATE OR IGNORE t5 SET a = new.a, c = 10;
130     END;
131   }
132 } {}
133 do_test triggerC-1.12 {
134   catchsql { UPDATE OR REPLACE t5 SET a = 4 WHERE a = 1 }
135 } {1 {too many levels of trigger recursion}}
136 do_test triggerC-1.13 {
137   execsql {
138     CREATE TABLE t6(a INTEGER PRIMARY KEY, b);
139     INSERT INTO t6 VALUES(1, 2);
140     create trigger r1 after update on t6 for each row begin
141       SELECT 1;
142     end;
143     UPDATE t6 SET a=a; 
144   }
145 } {}
146 do_test triggerC-1.14 {
147   execsql {
148     DROP TABLE t1;
149     CREATE TABLE cnt(n);
150     INSERT INTO cnt VALUES(0);
151     CREATE TABLE t1(a INTEGER PRIMARY KEY, b UNIQUE, c, d, e);
152     CREATE INDEX t1cd ON t1(c,d);
153     CREATE TRIGGER t1r1 AFTER UPDATE ON t1 BEGIN UPDATE cnt SET n=n+1; END;
154     INSERT INTO t1 VALUES(1,2,3,4,5);
155     INSERT INTO t1 VALUES(6,7,8,9,10);
156     INSERT INTO t1 VALUES(11,12,13,14,15);
157   }
158 } {}
159 do_test triggerC-1.15 {
160   catchsql { UPDATE OR ROLLBACK t1 SET a=100 }
161 } {1 {UNIQUE constraint failed: t1.a}}
164 #-------------------------------------------------------------------------
165 # This block of tests, triggerC-2.*, tests that recursive trigger
166 # programs (triggers that fire themselves) work. More specifically,
167 # this block focuses on recursive INSERT triggers.
169 do_test triggerC-2.1.0 {
170   execsql {
171     CREATE TABLE t2(a PRIMARY KEY);
172   }
173 } {}
175 foreach {n tdefn rc} {
176   1 { 
177     CREATE TRIGGER t2_trig AFTER INSERT ON t2 WHEN (new.a>0) BEGIN
178       INSERT INTO t2 VALUES(new.a - 1);
179     END; 
180   } {0 {10 9 8 7 6 5 4 3 2 1 0}}
182   2 {
183     CREATE TRIGGER t2_trig AFTER INSERT ON t2 BEGIN
184       SELECT CASE WHEN new.a==2 THEN RAISE(IGNORE) ELSE NULL END;
185       INSERT INTO t2 VALUES(new.a - 1);
186     END;
187   } {0 {10 9 8 7 6 5 4 3 2}}
189   3 { 
190     CREATE TRIGGER t2_trig BEFORE INSERT ON t2 WHEN (new.a>0) BEGIN
191       INSERT INTO t2 VALUES(new.a - 1);
192     END; 
193   } {0 {0 1 2 3 4 5 6 7 8 9 10}}
195   4 { 
196     CREATE TRIGGER t2_trig BEFORE INSERT ON t2 BEGIN
197       SELECT CASE WHEN new.a==2 THEN RAISE(IGNORE) ELSE NULL END;
198       INSERT INTO t2 VALUES(new.a - 1);
199     END;
200   } {0 {3 4 5 6 7 8 9 10}}
202   5 { 
203     CREATE TRIGGER t2_trig BEFORE INSERT ON t2 BEGIN
204       INSERT INTO t2 VALUES(new.a - 1);
205     END;
206   } {1 {too many levels of trigger recursion}}
208   6 { 
209     CREATE TRIGGER t2_trig AFTER INSERT ON t2 WHEN (new.a>0) BEGIN
210       INSERT OR IGNORE INTO t2 VALUES(new.a);
211     END;
212   } {0 10}
214   7 { 
215     CREATE TRIGGER t2_trig BEFORE INSERT ON t2 WHEN (new.a>0) BEGIN
216       INSERT OR IGNORE INTO t2 VALUES(new.a);
217     END;
218   } {1 {too many levels of trigger recursion}}
219 } {
220   do_test triggerC-2.1.$n {
221     catchsql { DROP TRIGGER t2_trig }
222     execsql  { DELETE FROM t2 }
223     execsql  $tdefn
224     catchsql {
225       INSERT INTO t2 VALUES(10);
226       SELECT * FROM t2 ORDER BY rowid;
227     }
228   } $rc
231 do_test triggerC-2.2 {
232   execsql "
233     CREATE TABLE t22(x);
235     CREATE TRIGGER t22a AFTER INSERT ON t22 BEGIN
236       INSERT INTO t22 SELECT x + (SELECT max(x) FROM t22) FROM t22;
237     END;
238     CREATE TRIGGER t22b BEFORE INSERT ON t22 BEGIN
239       SELECT CASE WHEN (SELECT count(*) FROM t22) >= [expr $SQLITE_MAX_TRIGGER_DEPTH / 2]
240                   THEN RAISE(IGNORE)
241                   ELSE NULL END;
242     END;
244     INSERT INTO t22 VALUES(1);
245     SELECT count(*) FROM t22;
246   "
247 } [list [expr $SQLITE_MAX_TRIGGER_DEPTH / 2]]
249 do_test triggerC-2.3 {
250   execsql "
251     CREATE TABLE t23(x PRIMARY KEY);
253     CREATE TRIGGER t23a AFTER INSERT ON t23 BEGIN
254       INSERT INTO t23 VALUES(new.x + 1);
255     END;
257     CREATE TRIGGER t23b BEFORE INSERT ON t23 BEGIN
258       SELECT CASE WHEN new.x>[expr $SQLITE_MAX_TRIGGER_DEPTH / 2]
259                   THEN RAISE(IGNORE)
260                   ELSE NULL END;
261     END;
263     INSERT INTO t23 VALUES(1);
264     SELECT count(*) FROM t23;
265   "
266 } [list [expr $SQLITE_MAX_TRIGGER_DEPTH / 2]]
269 #-----------------------------------------------------------------------
270 # This block of tests, triggerC-3.*, test that SQLite throws an exception
271 # when it detects excessive recursion.
273 do_test triggerC-3.1.1 {
274   execsql {
275     CREATE TABLE t3(a, b);
276     CREATE TRIGGER t3i AFTER INSERT ON t3 BEGIN
277       DELETE FROM t3 WHERE rowid = new.rowid;
278     END;
279     CREATE TRIGGER t3d AFTER DELETE ON t3 BEGIN
280       INSERT INTO t3 VALUES(old.a, old.b);
281     END;
282   }
283 } {}
284 do_test triggerC-3.1.2 {
285   catchsql { INSERT INTO t3 VALUES(0,0) }
286 } {1 {too many levels of trigger recursion}}
287 do_test triggerC-3.1.3 {
288   execsql { SELECT * FROM t3 }
289 } {}
291 do_test triggerC-3.2.1 {
292   execsql "
293     CREATE TABLE t3b(x);
294     CREATE TRIGGER t3bi AFTER INSERT ON t3b WHEN new.x<[expr $SQLITE_MAX_TRIGGER_DEPTH * 2] BEGIN
295       INSERT INTO t3b VALUES(new.x+1);
296     END;
297   "
298   catchsql {
299     INSERT INTO t3b VALUES(1);
300   }
301 } {1 {too many levels of trigger recursion}}
302 do_test triggerC-3.2.2 {
303   db eval {SELECT * FROM t3b}
304 } {}
306 do_test triggerC-3.3.1 {
307   catchsql "
308     INSERT INTO t3b VALUES([expr $SQLITE_MAX_TRIGGER_DEPTH + 1]);
309   "
310 } {0 {}}
311 do_test triggerC-3.3.2 {
312   db eval {SELECT count(*), max(x), min(x) FROM t3b}
313 } [list $SQLITE_MAX_TRIGGER_DEPTH [expr $SQLITE_MAX_TRIGGER_DEPTH * 2] [expr $SQLITE_MAX_TRIGGER_DEPTH + 1]]
315 do_test triggerC-3.4.1 {
316   catchsql "
317     DELETE FROM t3b;
318     INSERT INTO t3b VALUES([expr $SQLITE_MAX_TRIGGER_DEPTH - 1]);
319   "
320 } {1 {too many levels of trigger recursion}}
321 do_test triggerC-3.4.2 {
322   db eval {SELECT count(*), max(x), min(x) FROM t3b}
323 } {0 {} {}}
325 do_test triggerC-3.5.1 {
326   sqlite3_limit db SQLITE_LIMIT_TRIGGER_DEPTH  [expr $SQLITE_MAX_TRIGGER_DEPTH / 10]
327   catchsql "
328     INSERT INTO t3b VALUES([expr ($SQLITE_MAX_TRIGGER_DEPTH * 2) - ($SQLITE_MAX_TRIGGER_DEPTH / 10) + 1]);
329   "
330 } {0 {}}
331 do_test triggerC-3.5.2 {
332   db eval {SELECT count(*), max(x), min(x) FROM t3b}
333 } [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]]
335 do_test triggerC-3.5.3 {
336   catchsql "
337     DELETE FROM t3b;
338     INSERT INTO t3b VALUES([expr ($SQLITE_MAX_TRIGGER_DEPTH * 2) - ($SQLITE_MAX_TRIGGER_DEPTH / 10)]);
339   "
340 } {1 {too many levels of trigger recursion}}
341 do_test triggerC-3.5.4 {
342   db eval {SELECT count(*), max(x), min(x) FROM t3b}
343 } {0 {} {}}
345 do_test triggerC-3.6.1 {
346   sqlite3_limit db SQLITE_LIMIT_TRIGGER_DEPTH 1
347   catchsql "
348     INSERT INTO t3b VALUES([expr $SQLITE_MAX_TRIGGER_DEPTH * 2]);
349   "
350 } {0 {}}
351 do_test triggerC-3.6.2 {
352   db eval {SELECT count(*), max(x), min(x) FROM t3b}
353 } [list 1 [expr $SQLITE_MAX_TRIGGER_DEPTH * 2] [expr $SQLITE_MAX_TRIGGER_DEPTH * 2]]
355 do_test triggerC-3.6.3 {
356   catchsql "
357     DELETE FROM t3b;
358     INSERT INTO t3b VALUES([expr ($SQLITE_MAX_TRIGGER_DEPTH * 2) - 1]);
359   "
360 } {1 {too many levels of trigger recursion}}
361 do_test triggerC-3.6.4 {
362   db eval {SELECT count(*), max(x), min(x) FROM t3b}
363 } {0 {} {}}
364 sqlite3_limit db SQLITE_LIMIT_TRIGGER_DEPTH $SQLITE_MAX_TRIGGER_DEPTH
367 #-----------------------------------------------------------------------
368 # This next block of tests, triggerC-4.*, checks that affinity 
369 # transformations and constraint processing is performed at the correct 
370 # times relative to BEFORE and AFTER triggers.
372 # For an INSERT statement, for each row to be inserted:
374 #   1. Apply affinities to non-rowid values to be inserted.
375 #   2. Fire BEFORE triggers.
376 #   3. Process constraints.
377 #   4. Insert new record.
378 #   5. Fire AFTER triggers.
380 # If the value of the rowid field is to be automatically assigned, it is
381 # set to -1 in the new.* record. Even if it is explicitly set to NULL
382 # by the INSERT statement.
384 # For an UPDATE statement, for each row to be deleted:
386 #   1. Apply affinities to non-rowid values to be inserted.
387 #   2. Fire BEFORE triggers.
388 #   3. Process constraints.
389 #   4. Insert new record.
390 #   5. Fire AFTER triggers.
392 # For a DELETE statement, for each row to be deleted:
394 #   1. Fire BEFORE triggers.
395 #   2. Remove database record.
396 #   3. Fire AFTER triggers.
398 # When a numeric value that as an exact integer representation is stored
399 # in a column with REAL affinity, it is actually stored as an integer.
400 # These tests check that the typeof() such values is always 'real',
401 # not 'integer'.
403 # triggerC-4.1.*: Check that affinity transformations are made before
404 #                 triggers are invoked.
406 do_test triggerC-4.1.1 {
407   catchsql { DROP TABLE log }
408   catchsql { DROP TABLE t4 }
409   execsql {
410     CREATE TABLE log(t);
411     CREATE TABLE t4(a TEXT,b INTEGER,c REAL);
412     CREATE TRIGGER t4bi BEFORE INSERT ON t4 BEGIN
413       INSERT INTO log VALUES(new.rowid || ' ' || typeof(new.rowid) || ' ' ||
414                              new.a     || ' ' || typeof(new.a)     || ' ' ||
415                              new.b     || ' ' || typeof(new.b)     || ' ' ||
416                              new.c     || ' ' || typeof(new.c)
417       );
418     END;
419     CREATE TRIGGER t4ai AFTER INSERT ON t4 BEGIN
420       INSERT INTO log VALUES(new.rowid || ' ' || typeof(new.rowid) || ' ' ||
421                              new.a     || ' ' || typeof(new.a)     || ' ' ||
422                              new.b     || ' ' || typeof(new.b)     || ' ' ||
423                              new.c     || ' ' || typeof(new.c)
424       );
425     END;
426     CREATE TRIGGER t4bd BEFORE DELETE ON t4 BEGIN
427       INSERT INTO log VALUES(old.rowid || ' ' || typeof(old.rowid) || ' ' ||
428                              old.a     || ' ' || typeof(old.a)     || ' ' ||
429                              old.b     || ' ' || typeof(old.b)     || ' ' ||
430                              old.c     || ' ' || typeof(old.c)
431       );
432     END;
433     CREATE TRIGGER t4ad AFTER DELETE ON t4 BEGIN
434       INSERT INTO log VALUES(old.rowid || ' ' || typeof(old.rowid) || ' ' ||
435                              old.a     || ' ' || typeof(old.a)     || ' ' ||
436                              old.b     || ' ' || typeof(old.b)     || ' ' ||
437                              old.c     || ' ' || typeof(old.c)
438       );
439     END;
440     CREATE TRIGGER t4bu BEFORE UPDATE ON t4 BEGIN
441       INSERT INTO log VALUES(old.rowid || ' ' || typeof(old.rowid) || ' ' ||
442                              old.a     || ' ' || typeof(old.a)     || ' ' ||
443                              old.b     || ' ' || typeof(old.b)     || ' ' ||
444                              old.c     || ' ' || typeof(old.c)
445       );
446       INSERT INTO log VALUES(new.rowid || ' ' || typeof(new.rowid) || ' ' ||
447                              new.a     || ' ' || typeof(new.a)     || ' ' ||
448                              new.b     || ' ' || typeof(new.b)     || ' ' ||
449                              new.c     || ' ' || typeof(new.c)
450       );
451     END;
452     CREATE TRIGGER t4au AFTER UPDATE ON t4 BEGIN
453       INSERT INTO log VALUES(old.rowid || ' ' || typeof(old.rowid) || ' ' ||
454                              old.a     || ' ' || typeof(old.a)     || ' ' ||
455                              old.b     || ' ' || typeof(old.b)     || ' ' ||
456                              old.c     || ' ' || typeof(old.c)
457       );
458       INSERT INTO log VALUES(new.rowid || ' ' || typeof(new.rowid) || ' ' ||
459                              new.a     || ' ' || typeof(new.a)     || ' ' ||
460                              new.b     || ' ' || typeof(new.b)     || ' ' ||
461                              new.c     || ' ' || typeof(new.c)
462       );
463     END;
464   }
465 } {}
466 foreach {n insert log} {
468   2 { 
469    INSERT INTO t4 VALUES('1', '1', '1');
470    DELETE FROM t4;
471   } {
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 
475      1 integer 1 text 1 integer 1.0 real
476   }
478   3 { 
479    INSERT INTO t4(rowid,a,b,c) VALUES(45, 45, 45, 45);
480    DELETE FROM t4;
481   } {
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
485     45 integer 45 text 45 integer 45.0 real
486   }
488   4 { 
489    INSERT INTO t4(rowid,a,b,c) VALUES(-42.0, -42.0, -42.0, -42.0);
490    DELETE FROM t4;
491   } {
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 
495     -42 integer -42.0 text -42 integer -42.0 real
496   }
498   5 { 
499    INSERT INTO t4(rowid,a,b,c) VALUES(NULL, -42.4, -42.4, -42.4);
500    DELETE FROM t4;
501   } {
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
505      1 integer -42.4 text -42.4 real -42.4 real
506   }
508   6 { 
509    INSERT INTO t4 VALUES(7, 7, 7);
510    UPDATE t4 SET a=8, b=8, c=8;
511   } {
512     -1 integer 7 text 7 integer 7.0 real
513      1 integer 7 text 7 integer 7.0 real
514      1 integer 7 text 7 integer 7.0 real
515      1 integer 8 text 8 integer 8.0 real
516      1 integer 7 text 7 integer 7.0 real
517      1 integer 8 text 8 integer 8.0 real
518   }
520   7 { 
521    UPDATE t4 SET rowid=2;
522   } {
523      1 integer 8 text 8 integer 8.0 real
524      2 integer 8 text 8 integer 8.0 real
525      1 integer 8 text 8 integer 8.0 real
526      2 integer 8 text 8 integer 8.0 real
527   }
529   8 { 
530    UPDATE t4 SET a='9', b='9', c='9';
531   } {
532      2 integer 8 text 8 integer 8.0 real
533      2 integer 9 text 9 integer 9.0 real
534      2 integer 8 text 8 integer 8.0 real
535      2 integer 9 text 9 integer 9.0 real
536   }
538   9 { 
539    UPDATE t4 SET a='9.1', b='9.1', c='9.1';
540   } {
541      2 integer 9   text 9   integer 9.0 real
542      2 integer 9.1 text 9.1 real    9.1 real
543      2 integer 9   text 9   integer 9.0 real
544      2 integer 9.1 text 9.1 real    9.1 real
545   }
546 } {
547   do_test triggerC-4.1.$n {
548     eval concat [execsql " 
549       DELETE FROM log;
550       $insert ; 
551       SELECT * FROM log ORDER BY rowid;
552     "]
553   } [join $log " "]
556 #-------------------------------------------------------------------------
557 # This block of tests, triggerC-5.*, test that DELETE triggers are fired
558 # if a row is deleted as a result of OR REPLACE conflict resolution.
560 do_test triggerC-5.1.0 {
561   execsql {
562     DROP TABLE IF EXISTS t5;
563     CREATE TABLE t5(a INTEGER PRIMARY KEY, b);
564     CREATE UNIQUE INDEX t5i ON t5(b);
565     INSERT INTO t5 VALUES(1, 'a');
566     INSERT INTO t5 VALUES(2, 'b');
567     INSERT INTO t5 VALUES(3, 'c');
569     CREATE TABLE t5g(a, b, c);
570     CREATE TRIGGER t5t BEFORE DELETE ON t5 BEGIN
571       INSERT INTO t5g VALUES(old.a, old.b, (SELECT count(*) FROM t5));
572     END;
573   }
574 } {}
575 foreach {n dml t5g t5} {
576   1 "DELETE FROM t5 WHERE a=2"                        {2 b 3} {1 a 3 c}
577   2 "INSERT OR REPLACE INTO t5 VALUES(2, 'd')"        {2 b 3} {1 a 2 d 3 c}
578   3 "UPDATE OR REPLACE t5 SET a = 2 WHERE a = 3"      {2 b 3} {1 a 2 c}
579   4 "INSERT OR REPLACE INTO t5 VALUES(4, 'b')"        {2 b 3} {1 a 3 c 4 b}
580   5 "UPDATE OR REPLACE t5 SET b = 'b' WHERE b = 'c'"  {2 b 3} {1 a 3 b}
581   6 "INSERT OR REPLACE INTO t5 VALUES(2, 'c')"        {2 b 3 3 c 2} {1 a 2 c}
582   7 "UPDATE OR REPLACE t5 SET a=1, b='b' WHERE a = 3" {1 a 3 2 b 2} {1 b}
583 } {
584   do_test triggerC-5.1.$n {
585     execsql "
586       BEGIN;
587         $dml ;
588         SELECT * FROM t5g ORDER BY rowid;
589         SELECT * FROM t5 ORDER BY rowid;
590       ROLLBACK;
591     "
592   } [concat $t5g $t5]
594 do_test triggerC-5.2.0 {
595   execsql {
596     DROP TRIGGER t5t;
597     CREATE TRIGGER t5t AFTER DELETE ON t5 BEGIN
598       INSERT INTO t5g VALUES(old.a, old.b, (SELECT count(*) FROM t5));
599     END;
600   }
601 } {}
602 foreach {n dml t5g t5} {
603   1 "DELETE FROM t5 WHERE a=2"                        {2 b 2} {1 a 3 c}
604   2 "INSERT OR REPLACE INTO t5 VALUES(2, 'd')"        {2 b 2} {1 a 2 d 3 c}
605   3 "UPDATE OR REPLACE t5 SET a = 2 WHERE a = 3"      {2 b 2} {1 a 2 c}
606   4 "INSERT OR REPLACE INTO t5 VALUES(4, 'b')"        {2 b 2} {1 a 3 c 4 b}
607   5 "UPDATE OR REPLACE t5 SET b = 'b' WHERE b = 'c'"  {2 b 2} {1 a 3 b}
608   6 "INSERT OR REPLACE INTO t5 VALUES(2, 'c')"        {2 b 2 3 c 1} {1 a 2 c}
609   7 "UPDATE OR REPLACE t5 SET a=1, b='b' WHERE a = 3" {1 a 2 2 b 1} {1 b}
610 } {
611   do_test triggerC-5.2.$n {
612     execsql "
613       BEGIN;
614         $dml ;
615         SELECT * FROM t5g ORDER BY rowid;
616         SELECT * FROM t5 ORDER BY rowid;
617       ROLLBACK;
618     "
619   } [concat $t5g $t5]
621 do_test triggerC-5.3.0 {
622   execsql { PRAGMA recursive_triggers = off }
623 } {}
624 foreach {n dml t5g t5} {
625   1 "DELETE FROM t5 WHERE a=2"                        {2 b 2} {1 a 3 c}
626   2 "INSERT OR REPLACE INTO t5 VALUES(2, 'd')"        {} {1 a 2 d 3 c}
627   3 "UPDATE OR REPLACE t5 SET a = 2 WHERE a = 3"      {} {1 a 2 c}
628   4 "INSERT OR REPLACE INTO t5 VALUES(4, 'b')"        {} {1 a 3 c 4 b}
629   5 "UPDATE OR REPLACE t5 SET b = 'b' WHERE b = 'c'"  {} {1 a 3 b}
630   6 "INSERT OR REPLACE INTO t5 VALUES(2, 'c')"        {} {1 a 2 c}
631   7 "UPDATE OR REPLACE t5 SET a=1, b='b' WHERE a = 3" {} {1 b}
632 } {
633   do_test triggerC-5.3.$n {
634     execsql "
635       BEGIN;
636         $dml ;
637         SELECT * FROM t5g ORDER BY rowid;
638         SELECT * FROM t5 ORDER BY rowid;
639       ROLLBACK;
640     "
641   } [concat $t5g $t5]
643 do_test triggerC-5.3.8 {
644   execsql { PRAGMA recursive_triggers = on }
645 } {}
647 #-------------------------------------------------------------------------
648 # This block of tests, triggerC-6.*, tests that "PRAGMA recursive_triggers"
649 # statements return the current value of the recursive triggers flag.
651 do_test triggerC-6.1 {
652   execsql { PRAGMA recursive_triggers }
653 } {1}
654 do_test triggerC-6.2 {
655   execsql { 
656     PRAGMA recursive_triggers = off;
657     PRAGMA recursive_triggers;
658   }
659 } {0}
660 do_test triggerC-6.3 {
661   execsql { 
662     PRAGMA recursive_triggers = on;
663     PRAGMA recursive_triggers;
664   }
665 } {1}
667 #-------------------------------------------------------------------------
668 # Test some of the "undefined behaviour" associated with triggers. The
669 # undefined behaviour occurs when a row being updated or deleted is 
670 # manipulated by a BEFORE trigger.
672 do_test triggerC-7.1 {
673   execsql {
674     CREATE TABLE t8(x);
675     CREATE TABLE t7(a, b);
676     INSERT INTO t7 VALUES(1, 2);
677     INSERT INTO t7 VALUES(3, 4);
678     INSERT INTO t7 VALUES(5, 6);
679     CREATE TRIGGER t7t BEFORE UPDATE ON t7 BEGIN
680       DELETE FROM t7 WHERE a = 1;
681     END;
682     CREATE TRIGGER t7ta AFTER UPDATE ON t7 BEGIN
683       INSERT INTO t8 VALUES('after fired ' || old.rowid || '->' || new.rowid);
684     END;
685   }
686 } {}
687 do_test triggerC-7.2 {
688   execsql {
689     BEGIN;
690       UPDATE t7 SET b=7 WHERE a = 5;
691       SELECT * FROM t7;
692       SELECT * FROM t8;
693     ROLLBACK;
694   }
695 } {3 4 5 7 {after fired 3->3}}
696 do_test triggerC-7.3 {
697   execsql {
698     BEGIN;
699       UPDATE t7 SET b=7 WHERE a = 1;
700       SELECT * FROM t7;
701       SELECT * FROM t8;
702     ROLLBACK;
703   }
704 } {3 4 5 6}
706 do_test triggerC-7.4 {
707   execsql {
708     DROP TRIGGER t7t;
709     CREATE TRIGGER t7t BEFORE UPDATE ON t7 WHEN (old.rowid!=1 OR new.rowid!=8)
710     BEGIN
711       UPDATE t7 set rowid = 8 WHERE rowid=1;
712     END;
713   }
714 } {}
715 do_test triggerC-7.5 {
716   execsql {
717     BEGIN;
718       UPDATE t7 SET b=7 WHERE a = 5;
719       SELECT rowid, * FROM t7;
720       SELECT * FROM t8;
721     ROLLBACK;
722   }
723 } {2 3 4 3 5 7 8 1 2 {after fired 1->8} {after fired 3->3}}
724 do_test triggerC-7.6 {
725   execsql {
726     BEGIN;
727       UPDATE t7 SET b=7 WHERE a = 1;
728       SELECT rowid, * FROM t7;
729       SELECT * FROM t8;
730     ROLLBACK;
731   }
732 } {2 3 4 3 5 6 8 1 2 {after fired 1->8}}
734 do_test triggerC-7.7 {
735   execsql {
736     DROP TRIGGER t7t;
737     DROP TRIGGER t7ta;
738     CREATE TRIGGER t7t BEFORE DELETE ON t7 BEGIN
739       UPDATE t7 set rowid = 8 WHERE rowid=1;
740     END;
741     CREATE TRIGGER t7ta AFTER DELETE ON t7 BEGIN
742       INSERT INTO t8 VALUES('after fired ' || old.rowid);
743     END;
744   }
745 } {}
746 do_test triggerC-7.8 {
747   execsql {
748     BEGIN;
749       DELETE FROM t7 WHERE a = 3;
750       SELECT rowid, * FROM t7;
751       SELECT * FROM t8;
752     ROLLBACK;
753   }
754 } {3 5 6 8 1 2 {after fired 2}}
755 do_test triggerC-7.9 {
756   execsql {
757     BEGIN;
758       DELETE FROM t7 WHERE a = 1;
759       SELECT rowid, * FROM t7;
760       SELECT * FROM t8;
761     ROLLBACK;
762   }
763 } {2 3 4 3 5 6 8 1 2}
765 # Ticket [e25d9ea771febc9c311928c1c01c3163dcb26643]
767 do_test triggerC-9.1 {
768   execsql {
769     CREATE TABLE t9(a,b);
770     CREATE INDEX t9b ON t9(b);
771     INSERT INTO t9 VALUES(1,0);
772     INSERT INTO t9 VALUES(2,1);
773     INSERT INTO t9 VALUES(3,2);
774     INSERT INTO t9 SELECT a+3, a+2 FROM t9;
775     INSERT INTO t9 SELECT a+6, a+5 FROM t9;
776     SELECT a FROM t9 ORDER BY a;
777   }
778 } {1 2 3 4 5 6 7 8 9 10 11 12}
779 do_test triggerC-9.2 {
780   execsql {
781     CREATE TRIGGER t9r1 AFTER DELETE ON t9 BEGIN
782       DELETE FROM t9 WHERE b=old.a;
783     END;
784     DELETE FROM t9 WHERE b=4;
785     SELECT a FROM t9 ORDER BY a;
786   }
787 } {1 2 3 4}
789 # At one point (between versions 3.6.18 and 3.6.20 inclusive), an UPDATE 
790 # that fired a BEFORE trigger that itself updated the same row as the 
791 # statement causing it to fire was causing a strange side-effect: The 
792 # values updated by the statement within the trigger were being overwritten 
793 # by the values in the new.* array, even if those values were not 
794 # themselves written by the parent UPDATE statement.
796 # Technically speaking this was not a bug. The SQLite documentation says
797 # that if a BEFORE UPDATE or BEFORE DELETE trigger modifies or deletes the
798 # row that the parent statement is operating on the results are undefined. 
799 # But as of 3.6.21 behaviour is restored to the way it was in versions
800 # 3.6.17 and earlier to avoid causing unnecessary difficulties.
802 do_test triggerC-10.1 {
803   execsql {
804     CREATE TABLE t10(a, updatecnt DEFAULT 0);
805     CREATE TRIGGER t10_bu BEFORE UPDATE OF a ON t10 BEGIN
806       UPDATE t10 SET updatecnt = updatecnt+1 WHERE rowid = old.rowid;
807     END;
808     INSERT INTO t10(a) VALUES('hello');
809   }
811   # Before the problem was fixed, table t10 would contain the tuple 
812   # (world, 0) after running the following script (because the value
813   # 1 written to column "updatecnt" was clobbered by the old value 0).
814   #
815   execsql {
816     UPDATE t10 SET a = 'world';
817     SELECT * FROM t10;
818   }
819 } {world 1}
821 do_test triggerC-10.2 {
822   execsql {
823     UPDATE t10 SET a = 'tcl', updatecnt = 5;
824     SELECT * FROM t10;
825   }
826 } {tcl 5}
828 do_test triggerC-10.3 {
829   execsql {
830     CREATE TABLE t11(
831       c1,   c2,  c3,  c4,  c5,  c6,  c7,  c8,  c9, c10,
832       c11, c12, c13, c14, c15, c16, c17, c18, c19, c20,
833       c21, c22, c23, c24, c25, c26, c27, c28, c29, c30,
834       c31, c32, c33, c34, c35, c36, c37, c38, c39, c40
835     );
837     CREATE TRIGGER t11_bu BEFORE UPDATE OF c1 ON t11 BEGIN
838       UPDATE t11 SET c31 = c31+1, c32=c32+1 WHERE rowid = old.rowid;
839     END;
841     INSERT INTO t11 VALUES(
842       1,   2,  3,  4,  5,  6,  7,  8,  9, 10,
843       11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
844       21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
845       31, 32, 33, 34, 35, 36, 37, 38, 39, 40
846     );
847   }
849   # Before the problem was fixed, table t10 would contain the tuple 
850   # (world, 0) after running the following script (because the value
851   # 1 written to column "updatecnt" was clobbered by the old value 0).
852   #
853   execsql {
854     UPDATE t11 SET c4=35, c33=22, c1=5;
855     SELECT * FROM t11;
856   } 
857 } {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}
859 #-------------------------------------------------------------------------
860 # Test that bug [371bab5d65] has been fixed. BEFORE INSERT and INSTEAD OF
861 # INSERT triggers with the DEFAULT VALUES INSERT syntax.
863 do_test triggerC-11.0 {
864   catchsql { DROP TABLE log }
865   execsql  { CREATE TABLE log(a, b) }
866 } {}
868 foreach {testno tbl defaults} {
869   1 "CREATE TABLE t1(a, b)"                          {{} {}}
870   2 "CREATE TABLE t1(a DEFAULT 1, b DEFAULT 'abc')"  {1 abc}
871   3 "CREATE TABLE t1(a, b DEFAULT 4.5)"              {{} 4.5}
872 } {
873   do_test triggerC-11.$testno.1 {
874     catchsql { DROP TABLE t1 }
875     execsql { DELETE FROM log }
876     execsql $tbl
877     execsql {
878       CREATE TRIGGER tt1 BEFORE INSERT ON t1 BEGIN 
879         INSERT INTO log VALUES(new.a, new.b);
880       END;
881       INSERT INTO t1 DEFAULT VALUES;
882       SELECT * FROM log;
883     }
884   } $defaults
886   do_test triggerC-11.$testno.2 {
887     execsql { DELETE FROM log }
888     execsql {
889       CREATE TRIGGER tt2 AFTER INSERT ON t1 BEGIN 
890         INSERT INTO log VALUES(new.a, new.b);
891       END;
892       INSERT INTO t1 DEFAULT VALUES;
893       SELECT * FROM log;
894     }
895   } [concat $defaults $defaults]
897   do_test triggerC-11.$testno.3 {
898     execsql { DROP TRIGGER tt1 }
899     execsql { DELETE FROM log }
900     execsql {
901       INSERT INTO t1 DEFAULT VALUES;
902       SELECT * FROM log;
903     }
904   } $defaults
906 do_test triggerC-11.4 {
907   catchsql { DROP TABLE t2 }
908   execsql {
909     DELETE FROM log;
910     CREATE TABLE t2(a, b);
911     CREATE VIEW v2 AS SELECT * FROM t2;
912     CREATE TRIGGER tv2 INSTEAD OF INSERT ON v2 BEGIN
913       INSERT INTO log VALUES(new.a, new.b);
914     END;
915     INSERT INTO v2 DEFAULT VALUES;
916     SELECT a, b, a IS NULL, b IS NULL FROM log;
917   }
918 } {{} {} 1 1}
920 do_test triggerC-12.1 {
921   db close
922   forcedelete test.db
923   sqlite3 db test.db
925   execsql {
926     CREATE TABLE t1(a, b);
927     INSERT INTO t1 VALUES(1, 2);
928     INSERT INTO t1 VALUES(3, 4);
929     INSERT INTO t1 VALUES(5, 6);
930     CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN SELECT 1 ; END ;
931     SELECT count(*) FROM sqlite_master;
932   }
933 } {2}
934 do_test triggerC-12.2 {
935   db eval { SELECT * FROM t1 } {
936     if {$a == 3} { execsql { DROP TRIGGER tr1 } }
937   }
938   execsql { SELECT count(*) FROM sqlite_master }
939 } {1}
941 do_execsql_test triggerC-13.1 {
942   PRAGMA recursive_triggers = ON;
943   CREATE TABLE t12(a, b);
944   INSERT INTO t12 VALUES(1, 2);
945   CREATE TRIGGER tr12 AFTER UPDATE ON t12 BEGIN
946     UPDATE t12 SET a=new.a+1, b=new.b+1;
947   END;
948 } {}
949 do_catchsql_test triggerC-13.2 {
950   UPDATE t12 SET a=a+1, b=b+1;
951 } {1 {too many levels of trigger recursion}}
953 #-------------------------------------------------------------------------
954 # The following tests seek to verify that constant values (i.e. literals)
955 # are not factored out of loops within trigger programs. SQLite does
956 # not factor constants out of loops within trigger programs as it may only
957 # do so in code generated before the first table or index is opened. And
958 # by the time a trigger program is coded, at least one table or index has
959 # always been opened.
961 # At one point, due to a bug allowing constant factoring within triggers,
962 # the following SQL would produce the wrong result.
964 set SQL {
965   CREATE TABLE t1(a, b, c);
966   CREATE INDEX i1 ON t1(a, c);
967   CREATE INDEX i2 ON t1(b, c);
968   INSERT INTO t1 VALUES(1, 2, 3);
970   CREATE TABLE t2(e, f);
971   CREATE INDEX i3 ON t2(e);
972   INSERT INTO t2 VALUES(1234567, 3);
974   CREATE TABLE empty(x);
975   CREATE TABLE not_empty(x);
976   INSERT INTO not_empty VALUES(2);
978   CREATE TABLE t4(x);
979   CREATE TABLE t5(g, h, i);
981   CREATE TRIGGER trig BEFORE INSERT ON t4 BEGIN
982     INSERT INTO t5 SELECT * FROM t1 WHERE 
983         (a IN (SELECT x FROM empty) OR b IN (SELECT x FROM not_empty)) 
984         AND c IN (SELECT f FROM t2 WHERE e=1234567);
985   END;
987   INSERT INTO t4 VALUES(0);
988   SELECT * FROM t5;
991 reset_db
992 do_execsql_test triggerC-14.1 $SQL {1 2 3}
993 reset_db
994 optimization_control db factor-constants 0
995 do_execsql_test triggerC-14.2 $SQL {1 2 3}
997 #-------------------------------------------------------------------------
998 # Check that table names used by trigger programs are dequoted exactly
999 # once.
1001 do_execsql_test 15.1.1 {
1002   PRAGMA recursive_triggers = 1;
1003   CREATE TABLE node(
1004       id int not null primary key, 
1005       pid int not null default 0 references node,
1006       key varchar not null, 
1007       path varchar default '',
1008       unique(pid, key)
1009       );
1010   CREATE TRIGGER node_delete_referencing AFTER DELETE ON "node"
1011     BEGIN
1012     DELETE FROM "node" WHERE pid = old."id";
1013   END;
1015 do_execsql_test 15.1.2 {
1016   INSERT INTO node(id, pid, key) VALUES(9, 0, 'test');
1017   INSERT INTO node(id, pid, key) VALUES(90, 9, 'test1');
1018   INSERT INTO node(id, pid, key) VALUES(900, 90, 'test2');
1019   DELETE FROM node WHERE id=9;
1020   SELECT * FROM node;
1023 do_execsql_test 15.2.1 {
1024   CREATE TABLE   x1  (x);
1026   CREATE TABLE   x2  (a, b);
1027   CREATE TABLE '"x2"'(a, b);
1029   INSERT INTO x2 VALUES(1, 2);
1030   INSERT INTO x2 VALUES(3, 4);
1031   INSERT INTO '"x2"' SELECT * FROM x2;
1033   CREATE TRIGGER x1ai AFTER INSERT ON x1 BEGIN
1034     INSERT INTO """x2""" VALUES('x', 'y');
1035     DELETE FROM """x2""" WHERE a=1;
1036     UPDATE """x2""" SET b = 11 WHERE a = 3;
1037   END;
1039   INSERT INTO x1 VALUES('go!');
1042 do_execsql_test 15.2.2 { SELECT * FROM x2;       } {1 2 3 4}
1043 do_execsql_test 15.2.3 { SELECT * FROM """x2"""; } {3 11 x y}
1045 finish_test