blob: 8d9848794ad65eef345157f71a0290b86117100f [file] [log] [blame]
dan436355a2009-09-01 16:19:19 +00001# 2009 August 24
2#
3# The author disclaims copyright to this source code. In place of
4# a legal notice', here is a blessing:
5#
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.
9#
10#***********************************************************************
11#
12
13set testdir [file dirname $argv0]
14source $testdir/tester.tcl
15ifcapable {!trigger} {
16 finish_test
17 return
18}
19
dan2283d462009-09-08 15:55:15 +000020#-------------------------------------------------------------------------
21# Test organization:
22#
23# triggerC-1.*: Haphazardly designed trigger related tests that were useful
24# during an upgrade of the triggers sub-system.
25#
26# triggerC-2.*:
27#
28# triggerC-3.*:
29#
30# triggerC-4.*:
31#
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.
36#
dane0af83a2009-09-08 19:15:01 +000037# triggerC-6.*: Test that the recursive_triggers pragma returns correct
38# results when invoked without an argument.
39#
dan2283d462009-09-08 15:55:15 +000040
dan436355a2009-09-01 16:19:19 +000041# Enable recursive triggers for this file.
42#
dan5bde73c2009-09-01 17:11:07 +000043execsql { PRAGMA recursive_triggers = on }
dan436355a2009-09-01 16:19:19 +000044
45#sqlite3_db_config_lookaside db 0 0 0
46
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.
53#
54do_test triggerC-1.1 {
55 execsql {
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);
60 END;
61 CREATE TRIGGER trig2 AFTER INSERT ON t1 BEGIN
62 INSERT INTO log VALUES('after', NULL, NULL, NULL, new.a, new.b, new.c);
63 END;
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);
66 END;
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);
69 END;
70
71 CREATE TRIGGER trig5 BEFORE DELETE ON t1 BEGIN
72 INSERT INTO log VALUES('before', old.a,old.b,old.c, NULL,NULL,NULL);
73 END;
74 CREATE TRIGGER trig6 AFTER DELETE ON t1 BEGIN
75 INSERT INTO log VALUES('after', old.a,old.b,old.c, NULL,NULL,NULL);
76 END;
77 }
78} {}
79do_test triggerC-1.2 {
80 execsql {
81 INSERT INTO t1 VALUES('A', 'B', 'C');
82 SELECT * FROM log;
83 }
84} {before {} {} {} A B C after {} {} {} A B C}
85do_test triggerC-1.3 {
86 execsql { SELECT * FROM t1 }
87} {A B C}
88do_test triggerC-1.4 {
89 execsql {
90 DELETE FROM log;
91 UPDATE t1 SET a = 'a';
92 SELECT * FROM log;
93 }
94} {before A B C a B C after A B C a B C}
95do_test triggerC-1.5 {
96 execsql { SELECT * FROM t1 }
97} {a B C}
98do_test triggerC-1.6 {
99 execsql {
100 DELETE FROM log;
101 DELETE FROM t1;
102 SELECT * FROM log;
103 }
104} {before a B C {} {} {} after a B C {} {} {}}
105do_test triggerC-1.7 {
106 execsql { SELECT * FROM t1 }
107} {}
108do_test triggerC-1.8 {
109 execsql {
110 CREATE TABLE t4(a, b);
111 CREATE TRIGGER t4t AFTER DELETE ON t4 BEGIN
112 SELECT RAISE(ABORT, 'delete is not supported');
113 END;
114 }
115} {}
116do_test triggerC-1.9 {
117 execsql { INSERT INTO t4 VALUES(1, 2) }
118 catchsql { DELETE FROM t4 }
119} {1 {delete is not supported}}
120do_test triggerC-1.10 {
121 execsql { SELECT * FROM t4 }
122} {1 2}
123do_test triggerC-1.11 {
124 execsql {
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;
129 END;
130 }
131} {}
132do_test triggerC-1.12 {
133 catchsql { UPDATE OR REPLACE t5 SET a = 4 WHERE a = 1 }
134} {1 {too many levels of trigger recursion}}
135do_test triggerC-1.13 {
136 execsql {
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
140 SELECT 1;
141 end;
142 UPDATE t6 SET a=a;
143 }
144} {}
145do_test triggerC-1.14 {
146 execsql {
147 DROP TABLE t1;
148 CREATE TABLE cnt(n);
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);
156 }
157} {}
158do_test triggerC-1.15 {
159 catchsql { UPDATE OR ROLLBACK t1 SET a=100 }
160} {1 {PRIMARY KEY must be unique}}
161
162
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.
167#
168do_test triggerC-2.1.0 {
169 execsql {
170 CREATE TABLE t2(a PRIMARY KEY);
171 }
172} {}
173
174foreach {n tdefn rc} {
175 1 {
176 CREATE TRIGGER t2_trig AFTER INSERT ON t2 WHEN (new.a>0) BEGIN
177 INSERT INTO t2 VALUES(new.a - 1);
178 END;
179 } {0 {10 9 8 7 6 5 4 3 2 1 0}}
180
181 2 {
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);
185 END;
186 } {0 {10 9 8 7 6 5 4 3 2}}
187
188 3 {
189 CREATE TRIGGER t2_trig BEFORE INSERT ON t2 WHEN (new.a>0) BEGIN
190 INSERT INTO t2 VALUES(new.a - 1);
191 END;
192 } {0 {0 1 2 3 4 5 6 7 8 9 10}}
193
194 4 {
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);
198 END;
199 } {0 {3 4 5 6 7 8 9 10}}
200
201 5 {
202 CREATE TRIGGER t2_trig BEFORE INSERT ON t2 BEGIN
203 INSERT INTO t2 VALUES(new.a - 1);
204 END;
205 } {1 {too many levels of trigger recursion}}
206
207 6 {
208 CREATE TRIGGER t2_trig AFTER INSERT ON t2 WHEN (new.a>0) BEGIN
209 INSERT OR IGNORE INTO t2 VALUES(new.a);
210 END;
211 } {0 10}
212
213 7 {
214 CREATE TRIGGER t2_trig BEFORE INSERT ON t2 WHEN (new.a>0) BEGIN
215 INSERT OR IGNORE INTO t2 VALUES(new.a);
216 END;
217 } {1 {too many levels of trigger recursion}}
218} {
219 do_test triggerC-2.1.$n {
220 catchsql { DROP TRIGGER t2_trig }
221 execsql { DELETE FROM t2 }
222 execsql $tdefn
223 catchsql {
224 INSERT INTO t2 VALUES(10);
drh3f4d1d12012-09-15 18:45:54 +0000225 SELECT * FROM t2 ORDER BY rowid;
dan436355a2009-09-01 16:19:19 +0000226 }
227 } $rc
228}
229
230do_test triggerC-2.2 {
shanehf9032cb2011-06-22 14:43:59 +0000231 execsql "
dan436355a2009-09-01 16:19:19 +0000232 CREATE TABLE t22(x);
233
234 CREATE TRIGGER t22a AFTER INSERT ON t22 BEGIN
235 INSERT INTO t22 SELECT x + (SELECT max(x) FROM t22) FROM t22;
236 END;
237 CREATE TRIGGER t22b BEFORE INSERT ON t22 BEGIN
shanehf9032cb2011-06-22 14:43:59 +0000238 SELECT CASE WHEN (SELECT count(*) FROM t22) >= [expr $SQLITE_MAX_TRIGGER_DEPTH / 2]
dan436355a2009-09-01 16:19:19 +0000239 THEN RAISE(IGNORE)
240 ELSE NULL END;
241 END;
242
243 INSERT INTO t22 VALUES(1);
244 SELECT count(*) FROM t22;
shanehf9032cb2011-06-22 14:43:59 +0000245 "
246} [list [expr $SQLITE_MAX_TRIGGER_DEPTH / 2]]
dan436355a2009-09-01 16:19:19 +0000247
248do_test triggerC-2.3 {
shaneh35913a42011-04-17 00:55:13 +0000249 execsql "
dan436355a2009-09-01 16:19:19 +0000250 CREATE TABLE t23(x PRIMARY KEY);
251
252 CREATE TRIGGER t23a AFTER INSERT ON t23 BEGIN
253 INSERT INTO t23 VALUES(new.x + 1);
254 END;
255
256 CREATE TRIGGER t23b BEFORE INSERT ON t23 BEGIN
shaneh35913a42011-04-17 00:55:13 +0000257 SELECT CASE WHEN new.x>[expr $SQLITE_MAX_TRIGGER_DEPTH / 2]
dan436355a2009-09-01 16:19:19 +0000258 THEN RAISE(IGNORE)
259 ELSE NULL END;
260 END;
261
262 INSERT INTO t23 VALUES(1);
263 SELECT count(*) FROM t23;
shaneh35913a42011-04-17 00:55:13 +0000264 "
265} [list [expr $SQLITE_MAX_TRIGGER_DEPTH / 2]]
dan436355a2009-09-01 16:19:19 +0000266
267
268#-----------------------------------------------------------------------
269# This block of tests, triggerC-3.*, test that SQLite throws an exception
270# when it detects excessive recursion.
271#
272do_test triggerC-3.1.1 {
273 execsql {
274 CREATE TABLE t3(a, b);
275 CREATE TRIGGER t3i AFTER INSERT ON t3 BEGIN
276 DELETE FROM t3 WHERE rowid = new.rowid;
277 END;
278 CREATE TRIGGER t3d AFTER DELETE ON t3 BEGIN
279 INSERT INTO t3 VALUES(old.a, old.b);
280 END;
281 }
282} {}
283do_test triggerC-3.1.2 {
284 catchsql { INSERT INTO t3 VALUES(0,0) }
285} {1 {too many levels of trigger recursion}}
286do_test triggerC-3.1.3 {
287 execsql { SELECT * FROM t3 }
288} {}
289
drh417168a2009-09-07 18:14:02 +0000290do_test triggerC-3.2.1 {
shaneh35913a42011-04-17 00:55:13 +0000291 execsql "
drh417168a2009-09-07 18:14:02 +0000292 CREATE TABLE t3b(x);
shaneh35913a42011-04-17 00:55:13 +0000293 CREATE TRIGGER t3bi AFTER INSERT ON t3b WHEN new.x<[expr $SQLITE_MAX_TRIGGER_DEPTH * 2] BEGIN
drh417168a2009-09-07 18:14:02 +0000294 INSERT INTO t3b VALUES(new.x+1);
295 END;
shaneh35913a42011-04-17 00:55:13 +0000296 "
drh417168a2009-09-07 18:14:02 +0000297 catchsql {
298 INSERT INTO t3b VALUES(1);
299 }
300} {1 {too many levels of trigger recursion}}
301do_test triggerC-3.2.2 {
302 db eval {SELECT * FROM t3b}
303} {}
304
305do_test triggerC-3.3.1 {
shaneh35913a42011-04-17 00:55:13 +0000306 catchsql "
307 INSERT INTO t3b VALUES([expr $SQLITE_MAX_TRIGGER_DEPTH + 1]);
308 "
drh417168a2009-09-07 18:14:02 +0000309} {0 {}}
310do_test triggerC-3.3.2 {
311 db eval {SELECT count(*), max(x), min(x) FROM t3b}
shaneh35913a42011-04-17 00:55:13 +0000312} [list $SQLITE_MAX_TRIGGER_DEPTH [expr $SQLITE_MAX_TRIGGER_DEPTH * 2] [expr $SQLITE_MAX_TRIGGER_DEPTH + 1]]
drh417168a2009-09-07 18:14:02 +0000313
314do_test triggerC-3.4.1 {
shaneh35913a42011-04-17 00:55:13 +0000315 catchsql "
drh417168a2009-09-07 18:14:02 +0000316 DELETE FROM t3b;
shaneh35913a42011-04-17 00:55:13 +0000317 INSERT INTO t3b VALUES([expr $SQLITE_MAX_TRIGGER_DEPTH - 1]);
318 "
drh417168a2009-09-07 18:14:02 +0000319} {1 {too many levels of trigger recursion}}
320do_test triggerC-3.4.2 {
321 db eval {SELECT count(*), max(x), min(x) FROM t3b}
322} {0 {} {}}
323
324do_test triggerC-3.5.1 {
shaneh35913a42011-04-17 00:55:13 +0000325 sqlite3_limit db SQLITE_LIMIT_TRIGGER_DEPTH [expr $SQLITE_MAX_TRIGGER_DEPTH / 10]
326 catchsql "
327 INSERT INTO t3b VALUES([expr ($SQLITE_MAX_TRIGGER_DEPTH * 2) - ($SQLITE_MAX_TRIGGER_DEPTH / 10) + 1]);
328 "
drh417168a2009-09-07 18:14:02 +0000329} {0 {}}
330do_test triggerC-3.5.2 {
331 db eval {SELECT count(*), max(x), min(x) FROM t3b}
shaneh35913a42011-04-17 00:55:13 +0000332} [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]]
drh417168a2009-09-07 18:14:02 +0000333
334do_test triggerC-3.5.3 {
shaneh35913a42011-04-17 00:55:13 +0000335 catchsql "
drh417168a2009-09-07 18:14:02 +0000336 DELETE FROM t3b;
shaneh35913a42011-04-17 00:55:13 +0000337 INSERT INTO t3b VALUES([expr ($SQLITE_MAX_TRIGGER_DEPTH * 2) - ($SQLITE_MAX_TRIGGER_DEPTH / 10)]);
338 "
drh417168a2009-09-07 18:14:02 +0000339} {1 {too many levels of trigger recursion}}
340do_test triggerC-3.5.4 {
341 db eval {SELECT count(*), max(x), min(x) FROM t3b}
342} {0 {} {}}
343
344do_test triggerC-3.6.1 {
345 sqlite3_limit db SQLITE_LIMIT_TRIGGER_DEPTH 1
shaneh35913a42011-04-17 00:55:13 +0000346 catchsql "
347 INSERT INTO t3b VALUES([expr $SQLITE_MAX_TRIGGER_DEPTH * 2]);
348 "
drh417168a2009-09-07 18:14:02 +0000349} {0 {}}
350do_test triggerC-3.6.2 {
351 db eval {SELECT count(*), max(x), min(x) FROM t3b}
shaneh35913a42011-04-17 00:55:13 +0000352} [list 1 [expr $SQLITE_MAX_TRIGGER_DEPTH * 2] [expr $SQLITE_MAX_TRIGGER_DEPTH * 2]]
drh417168a2009-09-07 18:14:02 +0000353
354do_test triggerC-3.6.3 {
shaneh35913a42011-04-17 00:55:13 +0000355 catchsql "
drh417168a2009-09-07 18:14:02 +0000356 DELETE FROM t3b;
shaneh35913a42011-04-17 00:55:13 +0000357 INSERT INTO t3b VALUES([expr ($SQLITE_MAX_TRIGGER_DEPTH * 2) - 1]);
358 "
drh417168a2009-09-07 18:14:02 +0000359} {1 {too many levels of trigger recursion}}
360do_test triggerC-3.6.4 {
361 db eval {SELECT count(*), max(x), min(x) FROM t3b}
362} {0 {} {}}
shaneh35913a42011-04-17 00:55:13 +0000363sqlite3_limit db SQLITE_LIMIT_TRIGGER_DEPTH $SQLITE_MAX_TRIGGER_DEPTH
364
drh417168a2009-09-07 18:14:02 +0000365
dan436355a2009-09-01 16:19:19 +0000366#-----------------------------------------------------------------------
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.
370#
371# For an INSERT statement, for each row to be inserted:
372#
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.
378#
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.
382#
383# For an UPDATE statement, for each row to be deleted:
384#
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.
390#
391# For a DELETE statement, for each row to be deleted:
392#
393# 1. Fire BEFORE triggers.
394# 2. Remove database record.
395# 3. Fire AFTER triggers.
396#
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',
400# not 'integer'.
401#
402# triggerC-4.1.*: Check that affinity transformations are made before
403# triggers are invoked.
404#
405do_test triggerC-4.1.1 {
406 catchsql { DROP TABLE log }
407 catchsql { DROP TABLE t4 }
408 execsql {
409 CREATE TABLE log(t);
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)
416 );
417 END;
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)
423 );
424 END;
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)
430 );
431 END;
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)
437 );
438 END;
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)
444 );
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)
449 );
450 END;
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)
456 );
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)
461 );
462 END;
463 }
464} {}
465foreach {n insert log} {
466
467 2 {
468 INSERT INTO t4 VALUES('1', '1', '1');
469 DELETE FROM t4;
470 } {
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
475 }
476
477 3 {
478 INSERT INTO t4(rowid,a,b,c) VALUES(45, 45, 45, 45);
479 DELETE FROM t4;
480 } {
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
485 }
486
487 4 {
488 INSERT INTO t4(rowid,a,b,c) VALUES(-42.0, -42.0, -42.0, -42.0);
489 DELETE FROM t4;
490 } {
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
495 }
496
497 5 {
498 INSERT INTO t4(rowid,a,b,c) VALUES(NULL, -42.4, -42.4, -42.4);
499 DELETE FROM t4;
500 } {
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
505 }
506
507 6 {
508 INSERT INTO t4 VALUES(7, 7, 7);
509 UPDATE t4 SET a=8, b=8, c=8;
510 } {
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
517 }
518
519 7 {
520 UPDATE t4 SET rowid=2;
521 } {
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
526 }
527
528 8 {
529 UPDATE t4 SET a='9', b='9', c='9';
530 } {
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
535 }
536
537 9 {
538 UPDATE t4 SET a='9.1', b='9.1', c='9.1';
539 } {
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
544 }
545} {
546 do_test triggerC-4.1.$n {
547 eval concat [execsql "
548 DELETE FROM log;
549 $insert ;
drh3f4d1d12012-09-15 18:45:54 +0000550 SELECT * FROM log ORDER BY rowid;
dan436355a2009-09-01 16:19:19 +0000551 "]
552 } [join $log " "]
553}
554
dan2283d462009-09-08 15:55:15 +0000555#-------------------------------------------------------------------------
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.
558#
559do_test triggerC-5.1.0 {
560 execsql {
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');
567
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));
571 END;
572 }
573} {}
574foreach {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}
582} {
583 do_test triggerC-5.1.$n {
584 execsql "
585 BEGIN;
586 $dml ;
drh3f4d1d12012-09-15 18:45:54 +0000587 SELECT * FROM t5g ORDER BY rowid;
588 SELECT * FROM t5 ORDER BY rowid;
dan2283d462009-09-08 15:55:15 +0000589 ROLLBACK;
590 "
591 } [concat $t5g $t5]
592}
593do_test triggerC-5.2.0 {
594 execsql {
595 DROP TRIGGER t5t;
596 CREATE TRIGGER t5t AFTER DELETE ON t5 BEGIN
597 INSERT INTO t5g VALUES(old.a, old.b, (SELECT count(*) FROM t5));
598 END;
599 }
600} {}
601foreach {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}
609} {
610 do_test triggerC-5.2.$n {
611 execsql "
612 BEGIN;
613 $dml ;
drh3f4d1d12012-09-15 18:45:54 +0000614 SELECT * FROM t5g ORDER BY rowid;
615 SELECT * FROM t5 ORDER BY rowid;
dan2283d462009-09-08 15:55:15 +0000616 ROLLBACK;
617 "
618 } [concat $t5g $t5]
619}
620do_test triggerC-5.3.0 {
621 execsql { PRAGMA recursive_triggers = off }
622} {}
623foreach {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}
631} {
632 do_test triggerC-5.3.$n {
633 execsql "
634 BEGIN;
635 $dml ;
drh3f4d1d12012-09-15 18:45:54 +0000636 SELECT * FROM t5g ORDER BY rowid;
637 SELECT * FROM t5 ORDER BY rowid;
dan2283d462009-09-08 15:55:15 +0000638 ROLLBACK;
639 "
640 } [concat $t5g $t5]
641}
642do_test triggerC-5.3.8 {
643 execsql { PRAGMA recursive_triggers = on }
644} {}
645
646#-------------------------------------------------------------------------
647# This block of tests, triggerC-6.*, tests that "PRAGMA recursive_triggers"
648# statements return the current value of the recursive triggers flag.
649#
650do_test triggerC-6.1 {
651 execsql { PRAGMA recursive_triggers }
652} {1}
653do_test triggerC-6.2 {
654 execsql {
655 PRAGMA recursive_triggers = off;
656 PRAGMA recursive_triggers;
657 }
658} {0}
659do_test triggerC-6.3 {
660 execsql {
661 PRAGMA recursive_triggers = on;
662 PRAGMA recursive_triggers;
663 }
664} {1}
665
dane0af83a2009-09-08 19:15:01 +0000666#-------------------------------------------------------------------------
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.
danae0931e2009-09-09 15:06:10 +0000670#
671do_test triggerC-7.1 {
672 execsql {
673 CREATE TABLE t8(x);
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;
680 END;
681 CREATE TRIGGER t7ta AFTER UPDATE ON t7 BEGIN
682 INSERT INTO t8 VALUES('after fired ' || old.rowid || '->' || new.rowid);
683 END;
684 }
685} {}
686do_test triggerC-7.2 {
687 execsql {
688 BEGIN;
689 UPDATE t7 SET b=7 WHERE a = 5;
690 SELECT * FROM t7;
691 SELECT * FROM t8;
692 ROLLBACK;
693 }
694} {3 4 5 7 {after fired 3->3}}
695do_test triggerC-7.3 {
696 execsql {
697 BEGIN;
698 UPDATE t7 SET b=7 WHERE a = 1;
699 SELECT * FROM t7;
700 SELECT * FROM t8;
701 ROLLBACK;
702 }
703} {3 4 5 6}
704
705do_test triggerC-7.4 {
706 execsql {
707 DROP TRIGGER t7t;
708 CREATE TRIGGER t7t BEFORE UPDATE ON t7 WHEN (old.rowid!=1 OR new.rowid!=8)
709 BEGIN
710 UPDATE t7 set rowid = 8 WHERE rowid=1;
711 END;
712 }
713} {}
714do_test triggerC-7.5 {
715 execsql {
716 BEGIN;
717 UPDATE t7 SET b=7 WHERE a = 5;
718 SELECT rowid, * FROM t7;
719 SELECT * FROM t8;
720 ROLLBACK;
721 }
722} {2 3 4 3 5 7 8 1 2 {after fired 1->8} {after fired 3->3}}
723do_test triggerC-7.6 {
724 execsql {
725 BEGIN;
726 UPDATE t7 SET b=7 WHERE a = 1;
727 SELECT rowid, * FROM t7;
728 SELECT * FROM t8;
729 ROLLBACK;
730 }
731} {2 3 4 3 5 6 8 1 2 {after fired 1->8}}
732
733do_test triggerC-7.7 {
734 execsql {
735 DROP TRIGGER t7t;
736 DROP TRIGGER t7ta;
737 CREATE TRIGGER t7t BEFORE DELETE ON t7 BEGIN
738 UPDATE t7 set rowid = 8 WHERE rowid=1;
739 END;
740 CREATE TRIGGER t7ta AFTER DELETE ON t7 BEGIN
741 INSERT INTO t8 VALUES('after fired ' || old.rowid);
742 END;
743 }
744} {}
745do_test triggerC-7.8 {
746 execsql {
747 BEGIN;
748 DELETE FROM t7 WHERE a = 3;
749 SELECT rowid, * FROM t7;
750 SELECT * FROM t8;
751 ROLLBACK;
752 }
753} {3 5 6 8 1 2 {after fired 2}}
754do_test triggerC-7.9 {
755 execsql {
756 BEGIN;
757 DELETE FROM t7 WHERE a = 1;
758 SELECT rowid, * FROM t7;
759 SELECT * FROM t8;
760 ROLLBACK;
761 }
762} {2 3 4 3 5 6 8 1 2}
dane0af83a2009-09-08 19:15:01 +0000763
drh3991bb02009-09-17 00:41:19 +0000764# Ticket [e25d9ea771febc9c311928c1c01c3163dcb26643]
765#
766do_test triggerC-9.1 {
767 execsql {
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;
776 }
777} {1 2 3 4 5 6 7 8 9 10 11 12}
778do_test triggerC-9.2 {
779 execsql {
780 CREATE TRIGGER t9r1 AFTER DELETE ON t9 BEGIN
781 DELETE FROM t9 WHERE b=old.a;
782 END;
783 DELETE FROM t9 WHERE b=4;
784 SELECT a FROM t9 ORDER BY a;
785 }
786} {1 2 3 4}
drh3991bb02009-09-17 00:41:19 +0000787
danbb5f1682009-11-27 12:12:34 +0000788# 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.
794#
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.
800#
801do_test triggerC-10.1 {
802 execsql {
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;
806 END;
807 INSERT INTO t10(a) VALUES('hello');
808 }
809
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).
813 #
814 execsql {
815 UPDATE t10 SET a = 'world';
816 SELECT * FROM t10;
817 }
818} {world 1}
819
820do_test triggerC-10.2 {
821 execsql {
822 UPDATE t10 SET a = 'tcl', updatecnt = 5;
823 SELECT * FROM t10;
824 }
825} {tcl 5}
826
827do_test triggerC-10.3 {
828 execsql {
829 CREATE TABLE t11(
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
834 );
835
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;
838 END;
839
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
845 );
846 }
847
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).
851 #
852 execsql {
853 UPDATE t11 SET c4=35, c33=22, c1=5;
854 SELECT * FROM t11;
855 }
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}
drh3991bb02009-09-17 00:41:19 +0000857
dan7ba45972010-03-30 12:40:32 +0000858#-------------------------------------------------------------------------
859# Test that bug [371bab5d65] has been fixed. BEFORE INSERT and INSTEAD OF
860# INSERT triggers with the DEFAULT VALUES INSERT syntax.
861#
862do_test triggerC-11.0 {
863 catchsql { DROP TABLE log }
864 execsql { CREATE TABLE log(a, b) }
865} {}
866
867foreach {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}
871} {
872 do_test triggerC-11.$testno.1 {
873 catchsql { DROP TABLE t1 }
874 execsql { DELETE FROM log }
875 execsql $tbl
876 execsql {
877 CREATE TRIGGER tt1 BEFORE INSERT ON t1 BEGIN
878 INSERT INTO log VALUES(new.a, new.b);
879 END;
880 INSERT INTO t1 DEFAULT VALUES;
881 SELECT * FROM log;
882 }
883 } $defaults
884
885 do_test triggerC-11.$testno.2 {
886 execsql { DELETE FROM log }
887 execsql {
888 CREATE TRIGGER tt2 AFTER INSERT ON t1 BEGIN
889 INSERT INTO log VALUES(new.a, new.b);
890 END;
891 INSERT INTO t1 DEFAULT VALUES;
892 SELECT * FROM log;
893 }
894 } [concat $defaults $defaults]
895
896 do_test triggerC-11.$testno.3 {
897 execsql { DROP TRIGGER tt1 }
898 execsql { DELETE FROM log }
899 execsql {
900 INSERT INTO t1 DEFAULT VALUES;
901 SELECT * FROM log;
902 }
903 } $defaults
904}
905do_test triggerC-11.4 {
906 catchsql { DROP TABLE t2 }
907 execsql {
908 DELETE FROM log;
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);
913 END;
914 INSERT INTO v2 DEFAULT VALUES;
915 SELECT a, b, a IS NULL, b IS NULL FROM log;
916 }
917} {{} {} 1 1}
918
dan98530ca2010-08-14 05:04:47 +0000919do_test triggerC-12.1 {
920 db close
mistachkinfda06be2011-08-02 00:57:34 +0000921 forcedelete test.db
dan98530ca2010-08-14 05:04:47 +0000922 sqlite3 db test.db
923
924 execsql {
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;
931 }
932} {2}
933do_test triggerC-12.2 {
934 db eval { SELECT * FROM t1 } {
935 if {$a == 3} { execsql { DROP TRIGGER tr1 } }
936 }
937 execsql { SELECT count(*) FROM sqlite_master }
938} {1}
939
dan27106572010-12-01 08:04:47 +0000940do_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;
946 END;
947} {}
948do_catchsql_test triggerC-13.2 {
949 UPDATE t12 SET a=a+1, b=b+1;
950} {1 {too many levels of trigger recursion}}
951
danf78baaf2012-12-06 19:37:22 +0000952#-------------------------------------------------------------------------
953# The following tests seek to verify that constant values (i.e. literals)
954# are not factored out of loops within trigger programs. SQLite does
955# not factor constants out of loops within trigger programs as it may only
956# do so in code generated before the first table or index is opened. And
957# by the time a trigger program is coded, at least one table or index has
958# always been opened.
959#
960# At one point, due to a bug allowing constant factoring within triggers,
961# the following SQL would produce the wrong result.
962#
963set SQL {
964 CREATE TABLE t1(a, b, c);
965 CREATE INDEX i1 ON t1(a, c);
966 CREATE INDEX i2 ON t1(b, c);
967 INSERT INTO t1 VALUES(1, 2, 3);
dan7ba45972010-03-30 12:40:32 +0000968
danf78baaf2012-12-06 19:37:22 +0000969 CREATE TABLE t2(e, f);
970 CREATE INDEX i3 ON t2(e);
971 INSERT INTO t2 VALUES(1234567, 3);
972
973 CREATE TABLE empty(x);
974 CREATE TABLE not_empty(x);
975 INSERT INTO not_empty VALUES(2);
976
977 CREATE TABLE t4(x);
978 CREATE TABLE t5(g, h, i);
979
980 CREATE TRIGGER trig BEFORE INSERT ON t4 BEGIN
981 INSERT INTO t5 SELECT * FROM t1 WHERE
982 (a IN (SELECT x FROM empty) OR b IN (SELECT x FROM not_empty))
983 AND c IN (SELECT f FROM t2 WHERE e=1234567);
984 END;
985
986 INSERT INTO t4 VALUES(0);
987 SELECT * FROM t5;
988}
989
990reset_db
991do_execsql_test triggerC-14.1 $SQL {1 2 3}
992reset_db
993optimization_control db factor-constants 0
994do_execsql_test triggerC-14.2 $SQL {1 2 3}
dan2283d462009-09-08 15:55:15 +0000995
dan436355a2009-09-01 16:19:19 +0000996finish_test