xref: /sqlite-3.40.0/test/triggerC.test (revision fda06bef)
1436355a0Sdan# 2009 August 24
2436355a0Sdan#
3436355a0Sdan# The author disclaims copyright to this source code.  In place of
4436355a0Sdan# a legal notice', here is a blessing:
5436355a0Sdan#
6436355a0Sdan#    May you do good and not evil.
7436355a0Sdan#    May you find forgiveness for yourself and forgive others.
8436355a0Sdan#    May you share freely, never taking more than you give.
9436355a0Sdan#
10436355a0Sdan#***********************************************************************
11436355a0Sdan#
12436355a0Sdan
13436355a0Sdanset testdir [file dirname $argv0]
14436355a0Sdansource $testdir/tester.tcl
15436355a0Sdanifcapable {!trigger} {
16436355a0Sdan  finish_test
17436355a0Sdan  return
18436355a0Sdan}
19436355a0Sdan
202283d46cSdan#-------------------------------------------------------------------------
212283d46cSdan# Test organization:
222283d46cSdan#
232283d46cSdan# triggerC-1.*: Haphazardly designed trigger related tests that were useful
242283d46cSdan#               during an upgrade of the triggers sub-system.
252283d46cSdan#
262283d46cSdan# triggerC-2.*:
272283d46cSdan#
282283d46cSdan# triggerC-3.*:
292283d46cSdan#
302283d46cSdan# triggerC-4.*:
312283d46cSdan#
322283d46cSdan# triggerC-5.*: Test that when recursive triggers are enabled DELETE
332283d46cSdan#               triggers are fired when rows are deleted as part of OR
342283d46cSdan#               REPLACE conflict resolution. And that they are not fired
352283d46cSdan#               if recursive triggers are not enabled.
362283d46cSdan#
37e0af83acSdan# triggerC-6.*: Test that the recursive_triggers pragma returns correct
38e0af83acSdan#               results when invoked without an argument.
39e0af83acSdan#
402283d46cSdan
41436355a0Sdan# Enable recursive triggers for this file.
42436355a0Sdan#
435bde73c4Sdanexecsql { PRAGMA recursive_triggers = on }
44436355a0Sdan
45436355a0Sdan#sqlite3_db_config_lookaside db 0 0 0
46436355a0Sdan
47436355a0Sdan#-------------------------------------------------------------------------
48436355a0Sdan# This block of tests, triggerC-1.*, are not aimed at any specific
49436355a0Sdan# property of the triggers sub-system. They were created to debug
50436355a0Sdan# specific problems while modifying SQLite to support recursive
51436355a0Sdan# triggers. They are left here in case they can help debug the
52436355a0Sdan# same problems again.
53436355a0Sdan#
54436355a0Sdando_test triggerC-1.1 {
55436355a0Sdan  execsql {
56436355a0Sdan    CREATE TABLE t1(a, b, c);
57436355a0Sdan    CREATE TABLE log(t, a1, b1, c1, a2, b2, c2);
58436355a0Sdan    CREATE TRIGGER trig1 BEFORE INSERT ON t1 BEGIN
59436355a0Sdan      INSERT INTO log VALUES('before', NULL, NULL, NULL, new.a, new.b, new.c);
60436355a0Sdan    END;
61436355a0Sdan    CREATE TRIGGER trig2 AFTER INSERT ON t1 BEGIN
62436355a0Sdan      INSERT INTO log VALUES('after', NULL, NULL, NULL, new.a, new.b, new.c);
63436355a0Sdan    END;
64436355a0Sdan    CREATE TRIGGER trig3 BEFORE UPDATE ON t1 BEGIN
65436355a0Sdan      INSERT INTO log VALUES('before', old.a,old.b,old.c, new.a,new.b,new.c);
66436355a0Sdan    END;
67436355a0Sdan    CREATE TRIGGER trig4 AFTER UPDATE ON t1 BEGIN
68436355a0Sdan      INSERT INTO log VALUES('after', old.a,old.b,old.c, new.a,new.b,new.c);
69436355a0Sdan    END;
70436355a0Sdan
71436355a0Sdan    CREATE TRIGGER trig5 BEFORE DELETE ON t1 BEGIN
72436355a0Sdan      INSERT INTO log VALUES('before', old.a,old.b,old.c, NULL,NULL,NULL);
73436355a0Sdan    END;
74436355a0Sdan    CREATE TRIGGER trig6 AFTER DELETE ON t1 BEGIN
75436355a0Sdan      INSERT INTO log VALUES('after', old.a,old.b,old.c, NULL,NULL,NULL);
76436355a0Sdan    END;
77436355a0Sdan  }
78436355a0Sdan} {}
79436355a0Sdando_test triggerC-1.2 {
80436355a0Sdan  execsql {
81436355a0Sdan    INSERT INTO t1 VALUES('A', 'B', 'C');
82436355a0Sdan    SELECT * FROM log;
83436355a0Sdan  }
84436355a0Sdan} {before {} {} {} A B C after {} {} {} A B C}
85436355a0Sdando_test triggerC-1.3 {
86436355a0Sdan  execsql { SELECT * FROM t1 }
87436355a0Sdan} {A B C}
88436355a0Sdando_test triggerC-1.4 {
89436355a0Sdan  execsql {
90436355a0Sdan    DELETE FROM log;
91436355a0Sdan    UPDATE t1 SET a = 'a';
92436355a0Sdan    SELECT * FROM log;
93436355a0Sdan  }
94436355a0Sdan} {before A B C a B C after A B C a B C}
95436355a0Sdando_test triggerC-1.5 {
96436355a0Sdan  execsql { SELECT * FROM t1 }
97436355a0Sdan} {a B C}
98436355a0Sdando_test triggerC-1.6 {
99436355a0Sdan  execsql {
100436355a0Sdan    DELETE FROM log;
101436355a0Sdan    DELETE FROM t1;
102436355a0Sdan    SELECT * FROM log;
103436355a0Sdan  }
104436355a0Sdan} {before a B C {} {} {} after a B C {} {} {}}
105436355a0Sdando_test triggerC-1.7 {
106436355a0Sdan  execsql { SELECT * FROM t1 }
107436355a0Sdan} {}
108436355a0Sdando_test triggerC-1.8 {
109436355a0Sdan  execsql {
110436355a0Sdan    CREATE TABLE t4(a, b);
111436355a0Sdan    CREATE TRIGGER t4t AFTER DELETE ON t4 BEGIN
112436355a0Sdan      SELECT RAISE(ABORT, 'delete is not supported');
113436355a0Sdan    END;
114436355a0Sdan  }
115436355a0Sdan} {}
116436355a0Sdando_test triggerC-1.9 {
117436355a0Sdan  execsql { INSERT INTO t4 VALUES(1, 2) }
118436355a0Sdan  catchsql { DELETE FROM t4 }
119436355a0Sdan} {1 {delete is not supported}}
120436355a0Sdando_test triggerC-1.10 {
121436355a0Sdan  execsql { SELECT * FROM t4 }
122436355a0Sdan} {1 2}
123436355a0Sdando_test triggerC-1.11 {
124436355a0Sdan  execsql {
125436355a0Sdan    CREATE TABLE t5 (a primary key, b, c);
126436355a0Sdan    INSERT INTO t5 values (1, 2, 3);
127436355a0Sdan    CREATE TRIGGER au_tbl AFTER UPDATE ON t5 BEGIN
128436355a0Sdan      UPDATE OR IGNORE t5 SET a = new.a, c = 10;
129436355a0Sdan    END;
130436355a0Sdan  }
131436355a0Sdan} {}
132436355a0Sdando_test triggerC-1.12 {
133436355a0Sdan  catchsql { UPDATE OR REPLACE t5 SET a = 4 WHERE a = 1 }
134436355a0Sdan} {1 {too many levels of trigger recursion}}
135436355a0Sdando_test triggerC-1.13 {
136436355a0Sdan  execsql {
137436355a0Sdan    CREATE TABLE t6(a INTEGER PRIMARY KEY, b);
138436355a0Sdan    INSERT INTO t6 VALUES(1, 2);
139436355a0Sdan    create trigger r1 after update on t6 for each row begin
140436355a0Sdan      SELECT 1;
141436355a0Sdan    end;
142436355a0Sdan    UPDATE t6 SET a=a;
143436355a0Sdan  }
144436355a0Sdan} {}
145436355a0Sdando_test triggerC-1.14 {
146436355a0Sdan  execsql {
147436355a0Sdan    DROP TABLE t1;
148436355a0Sdan    CREATE TABLE cnt(n);
149436355a0Sdan    INSERT INTO cnt VALUES(0);
150436355a0Sdan    CREATE TABLE t1(a INTEGER PRIMARY KEY, b UNIQUE, c, d, e);
151436355a0Sdan    CREATE INDEX t1cd ON t1(c,d);
152436355a0Sdan    CREATE TRIGGER t1r1 AFTER UPDATE ON t1 BEGIN UPDATE cnt SET n=n+1; END;
153436355a0Sdan    INSERT INTO t1 VALUES(1,2,3,4,5);
154436355a0Sdan    INSERT INTO t1 VALUES(6,7,8,9,10);
155436355a0Sdan    INSERT INTO t1 VALUES(11,12,13,14,15);
156436355a0Sdan  }
157436355a0Sdan} {}
158436355a0Sdando_test triggerC-1.15 {
159436355a0Sdan  catchsql { UPDATE OR ROLLBACK t1 SET a=100 }
160436355a0Sdan} {1 {PRIMARY KEY must be unique}}
161436355a0Sdan
162436355a0Sdan
163436355a0Sdan#-------------------------------------------------------------------------
164436355a0Sdan# This block of tests, triggerC-2.*, tests that recursive trigger
165436355a0Sdan# programs (triggers that fire themselves) work. More specifically,
166436355a0Sdan# this block focuses on recursive INSERT triggers.
167436355a0Sdan#
168436355a0Sdando_test triggerC-2.1.0 {
169436355a0Sdan  execsql {
170436355a0Sdan    CREATE TABLE t2(a PRIMARY KEY);
171436355a0Sdan  }
172436355a0Sdan} {}
173436355a0Sdan
174436355a0Sdanforeach {n tdefn rc} {
175436355a0Sdan  1 {
176436355a0Sdan    CREATE TRIGGER t2_trig AFTER INSERT ON t2 WHEN (new.a>0) BEGIN
177436355a0Sdan      INSERT INTO t2 VALUES(new.a - 1);
178436355a0Sdan    END;
179436355a0Sdan  } {0 {10 9 8 7 6 5 4 3 2 1 0}}
180436355a0Sdan
181436355a0Sdan  2 {
182436355a0Sdan    CREATE TRIGGER t2_trig AFTER INSERT ON t2 BEGIN
183436355a0Sdan      SELECT CASE WHEN new.a==2 THEN RAISE(IGNORE) ELSE NULL END;
184436355a0Sdan      INSERT INTO t2 VALUES(new.a - 1);
185436355a0Sdan    END;
186436355a0Sdan  } {0 {10 9 8 7 6 5 4 3 2}}
187436355a0Sdan
188436355a0Sdan  3 {
189436355a0Sdan    CREATE TRIGGER t2_trig BEFORE INSERT ON t2 WHEN (new.a>0) BEGIN
190436355a0Sdan      INSERT INTO t2 VALUES(new.a - 1);
191436355a0Sdan    END;
192436355a0Sdan  } {0 {0 1 2 3 4 5 6 7 8 9 10}}
193436355a0Sdan
194436355a0Sdan  4 {
195436355a0Sdan    CREATE TRIGGER t2_trig BEFORE INSERT ON t2 BEGIN
196436355a0Sdan      SELECT CASE WHEN new.a==2 THEN RAISE(IGNORE) ELSE NULL END;
197436355a0Sdan      INSERT INTO t2 VALUES(new.a - 1);
198436355a0Sdan    END;
199436355a0Sdan  } {0 {3 4 5 6 7 8 9 10}}
200436355a0Sdan
201436355a0Sdan  5 {
202436355a0Sdan    CREATE TRIGGER t2_trig BEFORE INSERT ON t2 BEGIN
203436355a0Sdan      INSERT INTO t2 VALUES(new.a - 1);
204436355a0Sdan    END;
205436355a0Sdan  } {1 {too many levels of trigger recursion}}
206436355a0Sdan
207436355a0Sdan  6 {
208436355a0Sdan    CREATE TRIGGER t2_trig AFTER INSERT ON t2 WHEN (new.a>0) BEGIN
209436355a0Sdan      INSERT OR IGNORE INTO t2 VALUES(new.a);
210436355a0Sdan    END;
211436355a0Sdan  } {0 10}
212436355a0Sdan
213436355a0Sdan  7 {
214436355a0Sdan    CREATE TRIGGER t2_trig BEFORE INSERT ON t2 WHEN (new.a>0) BEGIN
215436355a0Sdan      INSERT OR IGNORE INTO t2 VALUES(new.a);
216436355a0Sdan    END;
217436355a0Sdan  } {1 {too many levels of trigger recursion}}
218436355a0Sdan} {
219436355a0Sdan  do_test triggerC-2.1.$n {
220436355a0Sdan    catchsql { DROP TRIGGER t2_trig }
221436355a0Sdan    execsql  { DELETE FROM t2 }
222436355a0Sdan    execsql  $tdefn
223436355a0Sdan    catchsql {
224436355a0Sdan      INSERT INTO t2 VALUES(10);
225436355a0Sdan      SELECT * FROM t2;
226436355a0Sdan    }
227436355a0Sdan  } $rc
228436355a0Sdan}
229436355a0Sdan
230436355a0Sdando_test triggerC-2.2 {
231f9032cbcSshaneh  execsql "
232436355a0Sdan    CREATE TABLE t22(x);
233436355a0Sdan
234436355a0Sdan    CREATE TRIGGER t22a AFTER INSERT ON t22 BEGIN
235436355a0Sdan      INSERT INTO t22 SELECT x + (SELECT max(x) FROM t22) FROM t22;
236436355a0Sdan    END;
237436355a0Sdan    CREATE TRIGGER t22b BEFORE INSERT ON t22 BEGIN
238f9032cbcSshaneh      SELECT CASE WHEN (SELECT count(*) FROM t22) >= [expr $SQLITE_MAX_TRIGGER_DEPTH / 2]
239436355a0Sdan                  THEN RAISE(IGNORE)
240436355a0Sdan                  ELSE NULL END;
241436355a0Sdan    END;
242436355a0Sdan
243436355a0Sdan    INSERT INTO t22 VALUES(1);
244436355a0Sdan    SELECT count(*) FROM t22;
245f9032cbcSshaneh  "
246f9032cbcSshaneh} [list [expr $SQLITE_MAX_TRIGGER_DEPTH / 2]]
247436355a0Sdan
248436355a0Sdando_test triggerC-2.3 {
24935913a49Sshaneh  execsql "
250436355a0Sdan    CREATE TABLE t23(x PRIMARY KEY);
251436355a0Sdan
252436355a0Sdan    CREATE TRIGGER t23a AFTER INSERT ON t23 BEGIN
253436355a0Sdan      INSERT INTO t23 VALUES(new.x + 1);
254436355a0Sdan    END;
255436355a0Sdan
256436355a0Sdan    CREATE TRIGGER t23b BEFORE INSERT ON t23 BEGIN
25735913a49Sshaneh      SELECT CASE WHEN new.x>[expr $SQLITE_MAX_TRIGGER_DEPTH / 2]
258436355a0Sdan                  THEN RAISE(IGNORE)
259436355a0Sdan                  ELSE NULL END;
260436355a0Sdan    END;
261436355a0Sdan
262436355a0Sdan    INSERT INTO t23 VALUES(1);
263436355a0Sdan    SELECT count(*) FROM t23;
26435913a49Sshaneh  "
26535913a49Sshaneh} [list [expr $SQLITE_MAX_TRIGGER_DEPTH / 2]]
266436355a0Sdan
267436355a0Sdan
268436355a0Sdan#-----------------------------------------------------------------------
269436355a0Sdan# This block of tests, triggerC-3.*, test that SQLite throws an exception
270436355a0Sdan# when it detects excessive recursion.
271436355a0Sdan#
272436355a0Sdando_test triggerC-3.1.1 {
273436355a0Sdan  execsql {
274436355a0Sdan    CREATE TABLE t3(a, b);
275436355a0Sdan    CREATE TRIGGER t3i AFTER INSERT ON t3 BEGIN
276436355a0Sdan      DELETE FROM t3 WHERE rowid = new.rowid;
277436355a0Sdan    END;
278436355a0Sdan    CREATE TRIGGER t3d AFTER DELETE ON t3 BEGIN
279436355a0Sdan      INSERT INTO t3 VALUES(old.a, old.b);
280436355a0Sdan    END;
281436355a0Sdan  }
282436355a0Sdan} {}
283436355a0Sdando_test triggerC-3.1.2 {
284436355a0Sdan  catchsql { INSERT INTO t3 VALUES(0,0) }
285436355a0Sdan} {1 {too many levels of trigger recursion}}
286436355a0Sdando_test triggerC-3.1.3 {
287436355a0Sdan  execsql { SELECT * FROM t3 }
288436355a0Sdan} {}
289436355a0Sdan
290417168adSdrhdo_test triggerC-3.2.1 {
29135913a49Sshaneh  execsql "
292417168adSdrh    CREATE TABLE t3b(x);
29335913a49Sshaneh    CREATE TRIGGER t3bi AFTER INSERT ON t3b WHEN new.x<[expr $SQLITE_MAX_TRIGGER_DEPTH * 2] BEGIN
294417168adSdrh      INSERT INTO t3b VALUES(new.x+1);
295417168adSdrh    END;
29635913a49Sshaneh  "
297417168adSdrh  catchsql {
298417168adSdrh    INSERT INTO t3b VALUES(1);
299417168adSdrh  }
300417168adSdrh} {1 {too many levels of trigger recursion}}
301417168adSdrhdo_test triggerC-3.2.2 {
302417168adSdrh  db eval {SELECT * FROM t3b}
303417168adSdrh} {}
304417168adSdrh
305417168adSdrhdo_test triggerC-3.3.1 {
30635913a49Sshaneh  catchsql "
30735913a49Sshaneh    INSERT INTO t3b VALUES([expr $SQLITE_MAX_TRIGGER_DEPTH + 1]);
30835913a49Sshaneh  "
309417168adSdrh} {0 {}}
310417168adSdrhdo_test triggerC-3.3.2 {
311417168adSdrh  db eval {SELECT count(*), max(x), min(x) FROM t3b}
31235913a49Sshaneh} [list $SQLITE_MAX_TRIGGER_DEPTH [expr $SQLITE_MAX_TRIGGER_DEPTH * 2] [expr $SQLITE_MAX_TRIGGER_DEPTH + 1]]
313417168adSdrh
314417168adSdrhdo_test triggerC-3.4.1 {
31535913a49Sshaneh  catchsql "
316417168adSdrh    DELETE FROM t3b;
31735913a49Sshaneh    INSERT INTO t3b VALUES([expr $SQLITE_MAX_TRIGGER_DEPTH - 1]);
31835913a49Sshaneh  "
319417168adSdrh} {1 {too many levels of trigger recursion}}
320417168adSdrhdo_test triggerC-3.4.2 {
321417168adSdrh  db eval {SELECT count(*), max(x), min(x) FROM t3b}
322417168adSdrh} {0 {} {}}
323417168adSdrh
324417168adSdrhdo_test triggerC-3.5.1 {
32535913a49Sshaneh  sqlite3_limit db SQLITE_LIMIT_TRIGGER_DEPTH  [expr $SQLITE_MAX_TRIGGER_DEPTH / 10]
32635913a49Sshaneh  catchsql "
32735913a49Sshaneh    INSERT INTO t3b VALUES([expr ($SQLITE_MAX_TRIGGER_DEPTH * 2) - ($SQLITE_MAX_TRIGGER_DEPTH / 10) + 1]);
32835913a49Sshaneh  "
329417168adSdrh} {0 {}}
330417168adSdrhdo_test triggerC-3.5.2 {
331417168adSdrh  db eval {SELECT count(*), max(x), min(x) FROM t3b}
33235913a49Sshaneh} [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]]
333417168adSdrh
334417168adSdrhdo_test triggerC-3.5.3 {
33535913a49Sshaneh  catchsql "
336417168adSdrh    DELETE FROM t3b;
33735913a49Sshaneh    INSERT INTO t3b VALUES([expr ($SQLITE_MAX_TRIGGER_DEPTH * 2) - ($SQLITE_MAX_TRIGGER_DEPTH / 10)]);
33835913a49Sshaneh  "
339417168adSdrh} {1 {too many levels of trigger recursion}}
340417168adSdrhdo_test triggerC-3.5.4 {
341417168adSdrh  db eval {SELECT count(*), max(x), min(x) FROM t3b}
342417168adSdrh} {0 {} {}}
343417168adSdrh
344417168adSdrhdo_test triggerC-3.6.1 {
345417168adSdrh  sqlite3_limit db SQLITE_LIMIT_TRIGGER_DEPTH 1
34635913a49Sshaneh  catchsql "
34735913a49Sshaneh    INSERT INTO t3b VALUES([expr $SQLITE_MAX_TRIGGER_DEPTH * 2]);
34835913a49Sshaneh  "
349417168adSdrh} {0 {}}
350417168adSdrhdo_test triggerC-3.6.2 {
351417168adSdrh  db eval {SELECT count(*), max(x), min(x) FROM t3b}
35235913a49Sshaneh} [list 1 [expr $SQLITE_MAX_TRIGGER_DEPTH * 2] [expr $SQLITE_MAX_TRIGGER_DEPTH * 2]]
353417168adSdrh
354417168adSdrhdo_test triggerC-3.6.3 {
35535913a49Sshaneh  catchsql "
356417168adSdrh    DELETE FROM t3b;
35735913a49Sshaneh    INSERT INTO t3b VALUES([expr ($SQLITE_MAX_TRIGGER_DEPTH * 2) - 1]);
35835913a49Sshaneh  "
359417168adSdrh} {1 {too many levels of trigger recursion}}
360417168adSdrhdo_test triggerC-3.6.4 {
361417168adSdrh  db eval {SELECT count(*), max(x), min(x) FROM t3b}
362417168adSdrh} {0 {} {}}
36335913a49Sshanehsqlite3_limit db SQLITE_LIMIT_TRIGGER_DEPTH $SQLITE_MAX_TRIGGER_DEPTH
364417168adSdrh
365417168adSdrh
366436355a0Sdan#-----------------------------------------------------------------------
367436355a0Sdan# This next block of tests, triggerC-4.*, checks that affinity
368436355a0Sdan# transformations and constraint processing is performed at the correct
369436355a0Sdan# times relative to BEFORE and AFTER triggers.
370436355a0Sdan#
371436355a0Sdan# For an INSERT statement, for each row to be inserted:
372436355a0Sdan#
373436355a0Sdan#   1. Apply affinities to non-rowid values to be inserted.
374436355a0Sdan#   2. Fire BEFORE triggers.
375436355a0Sdan#   3. Process constraints.
376436355a0Sdan#   4. Insert new record.
377436355a0Sdan#   5. Fire AFTER triggers.
378436355a0Sdan#
379436355a0Sdan# If the value of the rowid field is to be automatically assigned, it is
380436355a0Sdan# set to -1 in the new.* record. Even if it is explicitly set to NULL
381436355a0Sdan# by the INSERT statement.
382436355a0Sdan#
383436355a0Sdan# For an UPDATE statement, for each row to be deleted:
384436355a0Sdan#
385436355a0Sdan#   1. Apply affinities to non-rowid values to be inserted.
386436355a0Sdan#   2. Fire BEFORE triggers.
387436355a0Sdan#   3. Process constraints.
388436355a0Sdan#   4. Insert new record.
389436355a0Sdan#   5. Fire AFTER triggers.
390436355a0Sdan#
391436355a0Sdan# For a DELETE statement, for each row to be deleted:
392436355a0Sdan#
393436355a0Sdan#   1. Fire BEFORE triggers.
394436355a0Sdan#   2. Remove database record.
395436355a0Sdan#   3. Fire AFTER triggers.
396436355a0Sdan#
397436355a0Sdan# When a numeric value that as an exact integer representation is stored
398436355a0Sdan# in a column with REAL affinity, it is actually stored as an integer.
399436355a0Sdan# These tests check that the typeof() such values is always 'real',
400436355a0Sdan# not 'integer'.
401436355a0Sdan#
402436355a0Sdan# triggerC-4.1.*: Check that affinity transformations are made before
403436355a0Sdan#                 triggers are invoked.
404436355a0Sdan#
405436355a0Sdando_test triggerC-4.1.1 {
406436355a0Sdan  catchsql { DROP TABLE log }
407436355a0Sdan  catchsql { DROP TABLE t4 }
408436355a0Sdan  execsql {
409436355a0Sdan    CREATE TABLE log(t);
410436355a0Sdan    CREATE TABLE t4(a TEXT,b INTEGER,c REAL);
411436355a0Sdan    CREATE TRIGGER t4bi BEFORE INSERT ON t4 BEGIN
412436355a0Sdan      INSERT INTO log VALUES(new.rowid || ' ' || typeof(new.rowid) || ' ' ||
413436355a0Sdan                             new.a     || ' ' || typeof(new.a)     || ' ' ||
414436355a0Sdan                             new.b     || ' ' || typeof(new.b)     || ' ' ||
415436355a0Sdan                             new.c     || ' ' || typeof(new.c)
416436355a0Sdan      );
417436355a0Sdan    END;
418436355a0Sdan    CREATE TRIGGER t4ai AFTER INSERT ON t4 BEGIN
419436355a0Sdan      INSERT INTO log VALUES(new.rowid || ' ' || typeof(new.rowid) || ' ' ||
420436355a0Sdan                             new.a     || ' ' || typeof(new.a)     || ' ' ||
421436355a0Sdan                             new.b     || ' ' || typeof(new.b)     || ' ' ||
422436355a0Sdan                             new.c     || ' ' || typeof(new.c)
423436355a0Sdan      );
424436355a0Sdan    END;
425436355a0Sdan    CREATE TRIGGER t4bd BEFORE DELETE ON t4 BEGIN
426436355a0Sdan      INSERT INTO log VALUES(old.rowid || ' ' || typeof(old.rowid) || ' ' ||
427436355a0Sdan                             old.a     || ' ' || typeof(old.a)     || ' ' ||
428436355a0Sdan                             old.b     || ' ' || typeof(old.b)     || ' ' ||
429436355a0Sdan                             old.c     || ' ' || typeof(old.c)
430436355a0Sdan      );
431436355a0Sdan    END;
432436355a0Sdan    CREATE TRIGGER t4ad AFTER DELETE ON t4 BEGIN
433436355a0Sdan      INSERT INTO log VALUES(old.rowid || ' ' || typeof(old.rowid) || ' ' ||
434436355a0Sdan                             old.a     || ' ' || typeof(old.a)     || ' ' ||
435436355a0Sdan                             old.b     || ' ' || typeof(old.b)     || ' ' ||
436436355a0Sdan                             old.c     || ' ' || typeof(old.c)
437436355a0Sdan      );
438436355a0Sdan    END;
439436355a0Sdan    CREATE TRIGGER t4bu BEFORE UPDATE ON t4 BEGIN
440436355a0Sdan      INSERT INTO log VALUES(old.rowid || ' ' || typeof(old.rowid) || ' ' ||
441436355a0Sdan                             old.a     || ' ' || typeof(old.a)     || ' ' ||
442436355a0Sdan                             old.b     || ' ' || typeof(old.b)     || ' ' ||
443436355a0Sdan                             old.c     || ' ' || typeof(old.c)
444436355a0Sdan      );
445436355a0Sdan      INSERT INTO log VALUES(new.rowid || ' ' || typeof(new.rowid) || ' ' ||
446436355a0Sdan                             new.a     || ' ' || typeof(new.a)     || ' ' ||
447436355a0Sdan                             new.b     || ' ' || typeof(new.b)     || ' ' ||
448436355a0Sdan                             new.c     || ' ' || typeof(new.c)
449436355a0Sdan      );
450436355a0Sdan    END;
451436355a0Sdan    CREATE TRIGGER t4au AFTER UPDATE ON t4 BEGIN
452436355a0Sdan      INSERT INTO log VALUES(old.rowid || ' ' || typeof(old.rowid) || ' ' ||
453436355a0Sdan                             old.a     || ' ' || typeof(old.a)     || ' ' ||
454436355a0Sdan                             old.b     || ' ' || typeof(old.b)     || ' ' ||
455436355a0Sdan                             old.c     || ' ' || typeof(old.c)
456436355a0Sdan      );
457436355a0Sdan      INSERT INTO log VALUES(new.rowid || ' ' || typeof(new.rowid) || ' ' ||
458436355a0Sdan                             new.a     || ' ' || typeof(new.a)     || ' ' ||
459436355a0Sdan                             new.b     || ' ' || typeof(new.b)     || ' ' ||
460436355a0Sdan                             new.c     || ' ' || typeof(new.c)
461436355a0Sdan      );
462436355a0Sdan    END;
463436355a0Sdan  }
464436355a0Sdan} {}
465436355a0Sdanforeach {n insert log} {
466436355a0Sdan
467436355a0Sdan  2 {
468436355a0Sdan   INSERT INTO t4 VALUES('1', '1', '1');
469436355a0Sdan   DELETE FROM t4;
470436355a0Sdan  } {
471436355a0Sdan    -1 integer 1 text 1 integer 1.0 real
472436355a0Sdan     1 integer 1 text 1 integer 1.0 real
473436355a0Sdan     1 integer 1 text 1 integer 1.0 real
474436355a0Sdan     1 integer 1 text 1 integer 1.0 real
475436355a0Sdan  }
476436355a0Sdan
477436355a0Sdan  3 {
478436355a0Sdan   INSERT INTO t4(rowid,a,b,c) VALUES(45, 45, 45, 45);
479436355a0Sdan   DELETE FROM t4;
480436355a0Sdan  } {
481436355a0Sdan    45 integer 45 text 45 integer 45.0 real
482436355a0Sdan    45 integer 45 text 45 integer 45.0 real
483436355a0Sdan    45 integer 45 text 45 integer 45.0 real
484436355a0Sdan    45 integer 45 text 45 integer 45.0 real
485436355a0Sdan  }
486436355a0Sdan
487436355a0Sdan  4 {
488436355a0Sdan   INSERT INTO t4(rowid,a,b,c) VALUES(-42.0, -42.0, -42.0, -42.0);
489436355a0Sdan   DELETE FROM t4;
490436355a0Sdan  } {
491436355a0Sdan    -42 integer -42.0 text -42 integer -42.0 real
492436355a0Sdan    -42 integer -42.0 text -42 integer -42.0 real
493436355a0Sdan    -42 integer -42.0 text -42 integer -42.0 real
494436355a0Sdan    -42 integer -42.0 text -42 integer -42.0 real
495436355a0Sdan  }
496436355a0Sdan
497436355a0Sdan  5 {
498436355a0Sdan   INSERT INTO t4(rowid,a,b,c) VALUES(NULL, -42.4, -42.4, -42.4);
499436355a0Sdan   DELETE FROM t4;
500436355a0Sdan  } {
501436355a0Sdan    -1 integer -42.4 text -42.4 real -42.4 real
502436355a0Sdan     1 integer -42.4 text -42.4 real -42.4 real
503436355a0Sdan     1 integer -42.4 text -42.4 real -42.4 real
504436355a0Sdan     1 integer -42.4 text -42.4 real -42.4 real
505436355a0Sdan  }
506436355a0Sdan
507436355a0Sdan  6 {
508436355a0Sdan   INSERT INTO t4 VALUES(7, 7, 7);
509436355a0Sdan   UPDATE t4 SET a=8, b=8, c=8;
510436355a0Sdan  } {
511436355a0Sdan    -1 integer 7 text 7 integer 7.0 real
512436355a0Sdan     1 integer 7 text 7 integer 7.0 real
513436355a0Sdan     1 integer 7 text 7 integer 7.0 real
514436355a0Sdan     1 integer 8 text 8 integer 8.0 real
515436355a0Sdan     1 integer 7 text 7 integer 7.0 real
516436355a0Sdan     1 integer 8 text 8 integer 8.0 real
517436355a0Sdan  }
518436355a0Sdan
519436355a0Sdan  7 {
520436355a0Sdan   UPDATE t4 SET rowid=2;
521436355a0Sdan  } {
522436355a0Sdan     1 integer 8 text 8 integer 8.0 real
523436355a0Sdan     2 integer 8 text 8 integer 8.0 real
524436355a0Sdan     1 integer 8 text 8 integer 8.0 real
525436355a0Sdan     2 integer 8 text 8 integer 8.0 real
526436355a0Sdan  }
527436355a0Sdan
528436355a0Sdan  8 {
529436355a0Sdan   UPDATE t4 SET a='9', b='9', c='9';
530436355a0Sdan  } {
531436355a0Sdan     2 integer 8 text 8 integer 8.0 real
532436355a0Sdan     2 integer 9 text 9 integer 9.0 real
533436355a0Sdan     2 integer 8 text 8 integer 8.0 real
534436355a0Sdan     2 integer 9 text 9 integer 9.0 real
535436355a0Sdan  }
536436355a0Sdan
537436355a0Sdan  9 {
538436355a0Sdan   UPDATE t4 SET a='9.1', b='9.1', c='9.1';
539436355a0Sdan  } {
540436355a0Sdan     2 integer 9   text 9   integer 9.0 real
541436355a0Sdan     2 integer 9.1 text 9.1 real    9.1 real
542436355a0Sdan     2 integer 9   text 9   integer 9.0 real
543436355a0Sdan     2 integer 9.1 text 9.1 real    9.1 real
544436355a0Sdan  }
545436355a0Sdan} {
546436355a0Sdan  do_test triggerC-4.1.$n {
547436355a0Sdan    eval concat [execsql "
548436355a0Sdan      DELETE FROM log;
549436355a0Sdan      $insert ;
550436355a0Sdan      SELECT * FROM log;
551436355a0Sdan    "]
552436355a0Sdan  } [join $log " "]
553436355a0Sdan}
554436355a0Sdan
5552283d46cSdan#-------------------------------------------------------------------------
5562283d46cSdan# This block of tests, triggerC-5.*, test that DELETE triggers are fired
5572283d46cSdan# if a row is deleted as a result of OR REPLACE conflict resolution.
5582283d46cSdan#
5592283d46cSdando_test triggerC-5.1.0 {
5602283d46cSdan  execsql {
5612283d46cSdan    DROP TABLE IF EXISTS t5;
5622283d46cSdan    CREATE TABLE t5(a INTEGER PRIMARY KEY, b);
5632283d46cSdan    CREATE UNIQUE INDEX t5i ON t5(b);
5642283d46cSdan    INSERT INTO t5 VALUES(1, 'a');
5652283d46cSdan    INSERT INTO t5 VALUES(2, 'b');
5662283d46cSdan    INSERT INTO t5 VALUES(3, 'c');
5672283d46cSdan
5682283d46cSdan    CREATE TABLE t5g(a, b, c);
5692283d46cSdan    CREATE TRIGGER t5t BEFORE DELETE ON t5 BEGIN
5702283d46cSdan      INSERT INTO t5g VALUES(old.a, old.b, (SELECT count(*) FROM t5));
5712283d46cSdan    END;
5722283d46cSdan  }
5732283d46cSdan} {}
5742283d46cSdanforeach {n dml t5g t5} {
5752283d46cSdan  1 "DELETE FROM t5 WHERE a=2"                        {2 b 3} {1 a 3 c}
5762283d46cSdan  2 "INSERT OR REPLACE INTO t5 VALUES(2, 'd')"        {2 b 3} {1 a 2 d 3 c}
5772283d46cSdan  3 "UPDATE OR REPLACE t5 SET a = 2 WHERE a = 3"      {2 b 3} {1 a 2 c}
5782283d46cSdan  4 "INSERT OR REPLACE INTO t5 VALUES(4, 'b')"        {2 b 3} {1 a 3 c 4 b}
5792283d46cSdan  5 "UPDATE OR REPLACE t5 SET b = 'b' WHERE b = 'c'"  {2 b 3} {1 a 3 b}
5802283d46cSdan  6 "INSERT OR REPLACE INTO t5 VALUES(2, 'c')"        {2 b 3 3 c 2} {1 a 2 c}
5812283d46cSdan  7 "UPDATE OR REPLACE t5 SET a=1, b='b' WHERE a = 3" {1 a 3 2 b 2} {1 b}
5822283d46cSdan} {
5832283d46cSdan  do_test triggerC-5.1.$n {
5842283d46cSdan    execsql "
5852283d46cSdan      BEGIN;
5862283d46cSdan        $dml ;
5872283d46cSdan        SELECT * FROM t5g;
5882283d46cSdan        SELECT * FROM t5;
5892283d46cSdan      ROLLBACK;
5902283d46cSdan    "
5912283d46cSdan  } [concat $t5g $t5]
5922283d46cSdan}
5932283d46cSdando_test triggerC-5.2.0 {
5942283d46cSdan  execsql {
5952283d46cSdan    DROP TRIGGER t5t;
5962283d46cSdan    CREATE TRIGGER t5t AFTER DELETE ON t5 BEGIN
5972283d46cSdan      INSERT INTO t5g VALUES(old.a, old.b, (SELECT count(*) FROM t5));
5982283d46cSdan    END;
5992283d46cSdan  }
6002283d46cSdan} {}
6012283d46cSdanforeach {n dml t5g t5} {
6022283d46cSdan  1 "DELETE FROM t5 WHERE a=2"                        {2 b 2} {1 a 3 c}
6032283d46cSdan  2 "INSERT OR REPLACE INTO t5 VALUES(2, 'd')"        {2 b 2} {1 a 2 d 3 c}
6042283d46cSdan  3 "UPDATE OR REPLACE t5 SET a = 2 WHERE a = 3"      {2 b 2} {1 a 2 c}
6052283d46cSdan  4 "INSERT OR REPLACE INTO t5 VALUES(4, 'b')"        {2 b 2} {1 a 3 c 4 b}
6062283d46cSdan  5 "UPDATE OR REPLACE t5 SET b = 'b' WHERE b = 'c'"  {2 b 2} {1 a 3 b}
6072283d46cSdan  6 "INSERT OR REPLACE INTO t5 VALUES(2, 'c')"        {2 b 2 3 c 1} {1 a 2 c}
6082283d46cSdan  7 "UPDATE OR REPLACE t5 SET a=1, b='b' WHERE a = 3" {1 a 2 2 b 1} {1 b}
6092283d46cSdan} {
6102283d46cSdan  do_test triggerC-5.2.$n {
6112283d46cSdan    execsql "
6122283d46cSdan      BEGIN;
6132283d46cSdan        $dml ;
6142283d46cSdan        SELECT * FROM t5g;
6152283d46cSdan        SELECT * FROM t5;
6162283d46cSdan      ROLLBACK;
6172283d46cSdan    "
6182283d46cSdan  } [concat $t5g $t5]
6192283d46cSdan}
6202283d46cSdando_test triggerC-5.3.0 {
6212283d46cSdan  execsql { PRAGMA recursive_triggers = off }
6222283d46cSdan} {}
6232283d46cSdanforeach {n dml t5g t5} {
6242283d46cSdan  1 "DELETE FROM t5 WHERE a=2"                        {2 b 2} {1 a 3 c}
6252283d46cSdan  2 "INSERT OR REPLACE INTO t5 VALUES(2, 'd')"        {} {1 a 2 d 3 c}
6262283d46cSdan  3 "UPDATE OR REPLACE t5 SET a = 2 WHERE a = 3"      {} {1 a 2 c}
6272283d46cSdan  4 "INSERT OR REPLACE INTO t5 VALUES(4, 'b')"        {} {1 a 3 c 4 b}
6282283d46cSdan  5 "UPDATE OR REPLACE t5 SET b = 'b' WHERE b = 'c'"  {} {1 a 3 b}
6292283d46cSdan  6 "INSERT OR REPLACE INTO t5 VALUES(2, 'c')"        {} {1 a 2 c}
6302283d46cSdan  7 "UPDATE OR REPLACE t5 SET a=1, b='b' WHERE a = 3" {} {1 b}
6312283d46cSdan} {
6322283d46cSdan  do_test triggerC-5.3.$n {
6332283d46cSdan    execsql "
6342283d46cSdan      BEGIN;
6352283d46cSdan        $dml ;
6362283d46cSdan        SELECT * FROM t5g;
6372283d46cSdan        SELECT * FROM t5;
6382283d46cSdan      ROLLBACK;
6392283d46cSdan    "
6402283d46cSdan  } [concat $t5g $t5]
6412283d46cSdan}
6422283d46cSdando_test triggerC-5.3.8 {
6432283d46cSdan  execsql { PRAGMA recursive_triggers = on }
6442283d46cSdan} {}
6452283d46cSdan
6462283d46cSdan#-------------------------------------------------------------------------
6472283d46cSdan# This block of tests, triggerC-6.*, tests that "PRAGMA recursive_triggers"
6482283d46cSdan# statements return the current value of the recursive triggers flag.
6492283d46cSdan#
6502283d46cSdando_test triggerC-6.1 {
6512283d46cSdan  execsql { PRAGMA recursive_triggers }
6522283d46cSdan} {1}
6532283d46cSdando_test triggerC-6.2 {
6542283d46cSdan  execsql {
6552283d46cSdan    PRAGMA recursive_triggers = off;
6562283d46cSdan    PRAGMA recursive_triggers;
6572283d46cSdan  }
6582283d46cSdan} {0}
6592283d46cSdando_test triggerC-6.3 {
6602283d46cSdan  execsql {
6612283d46cSdan    PRAGMA recursive_triggers = on;
6622283d46cSdan    PRAGMA recursive_triggers;
6632283d46cSdan  }
6642283d46cSdan} {1}
6652283d46cSdan
666e0af83acSdan#-------------------------------------------------------------------------
667e0af83acSdan# Test some of the "undefined behaviour" associated with triggers. The
668e0af83acSdan# undefined behaviour occurs when a row being updated or deleted is
669e0af83acSdan# manipulated by a BEFORE trigger.
670e0af83acSdan#
671ae0931edSdando_test triggerC-7.1 {
672ae0931edSdan  execsql {
673ae0931edSdan    CREATE TABLE t8(x);
674ae0931edSdan    CREATE TABLE t7(a, b);
675ae0931edSdan    INSERT INTO t7 VALUES(1, 2);
676ae0931edSdan    INSERT INTO t7 VALUES(3, 4);
677ae0931edSdan    INSERT INTO t7 VALUES(5, 6);
678ae0931edSdan    CREATE TRIGGER t7t BEFORE UPDATE ON t7 BEGIN
679ae0931edSdan      DELETE FROM t7 WHERE a = 1;
680ae0931edSdan    END;
681ae0931edSdan    CREATE TRIGGER t7ta AFTER UPDATE ON t7 BEGIN
682ae0931edSdan      INSERT INTO t8 VALUES('after fired ' || old.rowid || '->' || new.rowid);
683ae0931edSdan    END;
684ae0931edSdan  }
685ae0931edSdan} {}
686ae0931edSdando_test triggerC-7.2 {
687ae0931edSdan  execsql {
688ae0931edSdan    BEGIN;
689ae0931edSdan      UPDATE t7 SET b=7 WHERE a = 5;
690ae0931edSdan      SELECT * FROM t7;
691ae0931edSdan      SELECT * FROM t8;
692ae0931edSdan    ROLLBACK;
693ae0931edSdan  }
694ae0931edSdan} {3 4 5 7 {after fired 3->3}}
695ae0931edSdando_test triggerC-7.3 {
696ae0931edSdan  execsql {
697ae0931edSdan    BEGIN;
698ae0931edSdan      UPDATE t7 SET b=7 WHERE a = 1;
699ae0931edSdan      SELECT * FROM t7;
700ae0931edSdan      SELECT * FROM t8;
701ae0931edSdan    ROLLBACK;
702ae0931edSdan  }
703ae0931edSdan} {3 4 5 6}
704ae0931edSdan
705ae0931edSdando_test triggerC-7.4 {
706ae0931edSdan  execsql {
707ae0931edSdan    DROP TRIGGER t7t;
708ae0931edSdan    CREATE TRIGGER t7t BEFORE UPDATE ON t7 WHEN (old.rowid!=1 OR new.rowid!=8)
709ae0931edSdan    BEGIN
710ae0931edSdan      UPDATE t7 set rowid = 8 WHERE rowid=1;
711ae0931edSdan    END;
712ae0931edSdan  }
713ae0931edSdan} {}
714ae0931edSdando_test triggerC-7.5 {
715ae0931edSdan  execsql {
716ae0931edSdan    BEGIN;
717ae0931edSdan      UPDATE t7 SET b=7 WHERE a = 5;
718ae0931edSdan      SELECT rowid, * FROM t7;
719ae0931edSdan      SELECT * FROM t8;
720ae0931edSdan    ROLLBACK;
721ae0931edSdan  }
722ae0931edSdan} {2 3 4 3 5 7 8 1 2 {after fired 1->8} {after fired 3->3}}
723ae0931edSdando_test triggerC-7.6 {
724ae0931edSdan  execsql {
725ae0931edSdan    BEGIN;
726ae0931edSdan      UPDATE t7 SET b=7 WHERE a = 1;
727ae0931edSdan      SELECT rowid, * FROM t7;
728ae0931edSdan      SELECT * FROM t8;
729ae0931edSdan    ROLLBACK;
730ae0931edSdan  }
731ae0931edSdan} {2 3 4 3 5 6 8 1 2 {after fired 1->8}}
732ae0931edSdan
733ae0931edSdando_test triggerC-7.7 {
734ae0931edSdan  execsql {
735ae0931edSdan    DROP TRIGGER t7t;
736ae0931edSdan    DROP TRIGGER t7ta;
737ae0931edSdan    CREATE TRIGGER t7t BEFORE DELETE ON t7 BEGIN
738ae0931edSdan      UPDATE t7 set rowid = 8 WHERE rowid=1;
739ae0931edSdan    END;
740ae0931edSdan    CREATE TRIGGER t7ta AFTER DELETE ON t7 BEGIN
741ae0931edSdan      INSERT INTO t8 VALUES('after fired ' || old.rowid);
742ae0931edSdan    END;
743ae0931edSdan  }
744ae0931edSdan} {}
745ae0931edSdando_test triggerC-7.8 {
746ae0931edSdan  execsql {
747ae0931edSdan    BEGIN;
748ae0931edSdan      DELETE FROM t7 WHERE a = 3;
749ae0931edSdan      SELECT rowid, * FROM t7;
750ae0931edSdan      SELECT * FROM t8;
751ae0931edSdan    ROLLBACK;
752ae0931edSdan  }
753ae0931edSdan} {3 5 6 8 1 2 {after fired 2}}
754ae0931edSdando_test triggerC-7.9 {
755ae0931edSdan  execsql {
756ae0931edSdan    BEGIN;
757ae0931edSdan      DELETE FROM t7 WHERE a = 1;
758ae0931edSdan      SELECT rowid, * FROM t7;
759ae0931edSdan      SELECT * FROM t8;
760ae0931edSdan    ROLLBACK;
761ae0931edSdan  }
762ae0931edSdan} {2 3 4 3 5 6 8 1 2}
763e0af83acSdan
7643991bb0dSdrh# Ticket [e25d9ea771febc9c311928c1c01c3163dcb26643]
7653991bb0dSdrh#
7663991bb0dSdrhdo_test triggerC-9.1 {
7673991bb0dSdrh  execsql {
7683991bb0dSdrh    CREATE TABLE t9(a,b);
7693991bb0dSdrh    CREATE INDEX t9b ON t9(b);
7703991bb0dSdrh    INSERT INTO t9 VALUES(1,0);
7713991bb0dSdrh    INSERT INTO t9 VALUES(2,1);
7723991bb0dSdrh    INSERT INTO t9 VALUES(3,2);
7733991bb0dSdrh    INSERT INTO t9 SELECT a+3, a+2 FROM t9;
7743991bb0dSdrh    INSERT INTO t9 SELECT a+6, a+5 FROM t9;
7753991bb0dSdrh    SELECT a FROM t9 ORDER BY a;
7763991bb0dSdrh  }
7773991bb0dSdrh} {1 2 3 4 5 6 7 8 9 10 11 12}
7783991bb0dSdrhdo_test triggerC-9.2 {
7793991bb0dSdrh  execsql {
7803991bb0dSdrh    CREATE TRIGGER t9r1 AFTER DELETE ON t9 BEGIN
7813991bb0dSdrh      DELETE FROM t9 WHERE b=old.a;
7823991bb0dSdrh    END;
7833991bb0dSdrh    DELETE FROM t9 WHERE b=4;
7843991bb0dSdrh    SELECT a FROM t9 ORDER BY a;
7853991bb0dSdrh  }
7863991bb0dSdrh} {1 2 3 4}
7873991bb0dSdrh
788bb5f168fSdan# At one point (between versions 3.6.18 and 3.6.20 inclusive), an UPDATE
789bb5f168fSdan# that fired a BEFORE trigger that itself updated the same row as the
790bb5f168fSdan# statement causing it to fire was causing a strange side-effect: The
791bb5f168fSdan# values updated by the statement within the trigger were being overwritten
792bb5f168fSdan# by the values in the new.* array, even if those values were not
793bb5f168fSdan# themselves written by the parent UPDATE statement.
794bb5f168fSdan#
795bb5f168fSdan# Technically speaking this was not a bug. The SQLite documentation says
796bb5f168fSdan# that if a BEFORE UPDATE or BEFORE DELETE trigger modifies or deletes the
797bb5f168fSdan# row that the parent statement is operating on the results are undefined.
798bb5f168fSdan# But as of 3.6.21 behaviour is restored to the way it was in versions
799bb5f168fSdan# 3.6.17 and earlier to avoid causing unnecessary difficulties.
800bb5f168fSdan#
801bb5f168fSdando_test triggerC-10.1 {
802bb5f168fSdan  execsql {
803bb5f168fSdan    CREATE TABLE t10(a, updatecnt DEFAULT 0);
804bb5f168fSdan    CREATE TRIGGER t10_bu BEFORE UPDATE OF a ON t10 BEGIN
805bb5f168fSdan      UPDATE t10 SET updatecnt = updatecnt+1 WHERE rowid = old.rowid;
806bb5f168fSdan    END;
807bb5f168fSdan    INSERT INTO t10(a) VALUES('hello');
808bb5f168fSdan  }
8093991bb0dSdrh
810bb5f168fSdan  # Before the problem was fixed, table t10 would contain the tuple
811bb5f168fSdan  # (world, 0) after running the following script (because the value
812bb5f168fSdan  # 1 written to column "updatecnt" was clobbered by the old value 0).
813bb5f168fSdan  #
814bb5f168fSdan  execsql {
815bb5f168fSdan    UPDATE t10 SET a = 'world';
816bb5f168fSdan    SELECT * FROM t10;
817bb5f168fSdan  }
818bb5f168fSdan} {world 1}
819bb5f168fSdan
820bb5f168fSdando_test triggerC-10.2 {
821bb5f168fSdan  execsql {
822bb5f168fSdan    UPDATE t10 SET a = 'tcl', updatecnt = 5;
823bb5f168fSdan    SELECT * FROM t10;
824bb5f168fSdan  }
825bb5f168fSdan} {tcl 5}
826bb5f168fSdan
827bb5f168fSdando_test triggerC-10.3 {
828bb5f168fSdan  execsql {
829bb5f168fSdan    CREATE TABLE t11(
830bb5f168fSdan      c1,   c2,  c3,  c4,  c5,  c6,  c7,  c8,  c9, c10,
831bb5f168fSdan      c11, c12, c13, c14, c15, c16, c17, c18, c19, c20,
832bb5f168fSdan      c21, c22, c23, c24, c25, c26, c27, c28, c29, c30,
833bb5f168fSdan      c31, c32, c33, c34, c35, c36, c37, c38, c39, c40
834bb5f168fSdan    );
835bb5f168fSdan
836bb5f168fSdan    CREATE TRIGGER t11_bu BEFORE UPDATE OF c1 ON t11 BEGIN
837bb5f168fSdan      UPDATE t11 SET c31 = c31+1, c32=c32+1 WHERE rowid = old.rowid;
838bb5f168fSdan    END;
839bb5f168fSdan
840bb5f168fSdan    INSERT INTO t11 VALUES(
841bb5f168fSdan      1,   2,  3,  4,  5,  6,  7,  8,  9, 10,
842bb5f168fSdan      11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
843bb5f168fSdan      21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
844bb5f168fSdan      31, 32, 33, 34, 35, 36, 37, 38, 39, 40
845bb5f168fSdan    );
846bb5f168fSdan  }
847bb5f168fSdan
848bb5f168fSdan  # Before the problem was fixed, table t10 would contain the tuple
849bb5f168fSdan  # (world, 0) after running the following script (because the value
850bb5f168fSdan  # 1 written to column "updatecnt" was clobbered by the old value 0).
851bb5f168fSdan  #
852bb5f168fSdan  execsql {
853bb5f168fSdan    UPDATE t11 SET c4=35, c33=22, c1=5;
854bb5f168fSdan    SELECT * FROM t11;
855bb5f168fSdan  }
856bb5f168fSdan} {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}
8573991bb0dSdrh
8587ba45971Sdan#-------------------------------------------------------------------------
8597ba45971Sdan# Test that bug [371bab5d65] has been fixed. BEFORE INSERT and INSTEAD OF
8607ba45971Sdan# INSERT triggers with the DEFAULT VALUES INSERT syntax.
8617ba45971Sdan#
8627ba45971Sdando_test triggerC-11.0 {
8637ba45971Sdan  catchsql { DROP TABLE log }
8647ba45971Sdan  execsql  { CREATE TABLE log(a, b) }
8657ba45971Sdan} {}
8667ba45971Sdan
8677ba45971Sdanforeach {testno tbl defaults} {
8687ba45971Sdan  1 "CREATE TABLE t1(a, b)"                          {{} {}}
8697ba45971Sdan  2 "CREATE TABLE t1(a DEFAULT 1, b DEFAULT 'abc')"  {1 abc}
8707ba45971Sdan  3 "CREATE TABLE t1(a, b DEFAULT 4.5)"              {{} 4.5}
8717ba45971Sdan} {
8727ba45971Sdan  do_test triggerC-11.$testno.1 {
8737ba45971Sdan    catchsql { DROP TABLE t1 }
8747ba45971Sdan    execsql { DELETE FROM log }
8757ba45971Sdan    execsql $tbl
8767ba45971Sdan    execsql {
8777ba45971Sdan      CREATE TRIGGER tt1 BEFORE INSERT ON t1 BEGIN
8787ba45971Sdan        INSERT INTO log VALUES(new.a, new.b);
8797ba45971Sdan      END;
8807ba45971Sdan      INSERT INTO t1 DEFAULT VALUES;
8817ba45971Sdan      SELECT * FROM log;
8827ba45971Sdan    }
8837ba45971Sdan  } $defaults
8847ba45971Sdan
8857ba45971Sdan  do_test triggerC-11.$testno.2 {
8867ba45971Sdan    execsql { DELETE FROM log }
8877ba45971Sdan    execsql {
8887ba45971Sdan      CREATE TRIGGER tt2 AFTER INSERT ON t1 BEGIN
8897ba45971Sdan        INSERT INTO log VALUES(new.a, new.b);
8907ba45971Sdan      END;
8917ba45971Sdan      INSERT INTO t1 DEFAULT VALUES;
8927ba45971Sdan      SELECT * FROM log;
8937ba45971Sdan    }
8947ba45971Sdan  } [concat $defaults $defaults]
8957ba45971Sdan
8967ba45971Sdan  do_test triggerC-11.$testno.3 {
8977ba45971Sdan    execsql { DROP TRIGGER tt1 }
8987ba45971Sdan    execsql { DELETE FROM log }
8997ba45971Sdan    execsql {
9007ba45971Sdan      INSERT INTO t1 DEFAULT VALUES;
9017ba45971Sdan      SELECT * FROM log;
9027ba45971Sdan    }
9037ba45971Sdan  } $defaults
9047ba45971Sdan}
9057ba45971Sdando_test triggerC-11.4 {
9067ba45971Sdan  catchsql { DROP TABLE t2 }
9077ba45971Sdan  execsql {
9087ba45971Sdan    DELETE FROM log;
9097ba45971Sdan    CREATE TABLE t2(a, b);
9107ba45971Sdan    CREATE VIEW v2 AS SELECT * FROM t2;
9117ba45971Sdan    CREATE TRIGGER tv2 INSTEAD OF INSERT ON v2 BEGIN
9127ba45971Sdan      INSERT INTO log VALUES(new.a, new.b);
9137ba45971Sdan    END;
9147ba45971Sdan    INSERT INTO v2 DEFAULT VALUES;
9157ba45971Sdan    SELECT a, b, a IS NULL, b IS NULL FROM log;
9167ba45971Sdan  }
9177ba45971Sdan} {{} {} 1 1}
9187ba45971Sdan
91998530cacSdando_test triggerC-12.1 {
92098530cacSdan  db close
921*fda06befSmistachkin  forcedelete test.db
92298530cacSdan  sqlite3 db test.db
92398530cacSdan
92498530cacSdan  execsql {
92598530cacSdan    CREATE TABLE t1(a, b);
92698530cacSdan    INSERT INTO t1 VALUES(1, 2);
92798530cacSdan    INSERT INTO t1 VALUES(3, 4);
92898530cacSdan    INSERT INTO t1 VALUES(5, 6);
92998530cacSdan    CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN SELECT 1 ; END ;
93098530cacSdan    SELECT count(*) FROM sqlite_master;
93198530cacSdan  }
93298530cacSdan} {2}
93398530cacSdando_test triggerC-12.2 {
93498530cacSdan  db eval { SELECT * FROM t1 } {
93598530cacSdan    if {$a == 3} { execsql { DROP TRIGGER tr1 } }
93698530cacSdan  }
93798530cacSdan  execsql { SELECT count(*) FROM sqlite_master }
93898530cacSdan} {1}
93998530cacSdan
94027106570Sdando_execsql_test triggerC-13.1 {
94127106570Sdan  PRAGMA recursive_triggers = ON;
94227106570Sdan  CREATE TABLE t12(a, b);
94327106570Sdan  INSERT INTO t12 VALUES(1, 2);
94427106570Sdan  CREATE TRIGGER tr12 AFTER UPDATE ON t12 BEGIN
94527106570Sdan    UPDATE t12 SET a=new.a+1, b=new.b+1;
94627106570Sdan  END;
94727106570Sdan} {}
94827106570Sdando_catchsql_test triggerC-13.2 {
94927106570Sdan  UPDATE t12 SET a=a+1, b=b+1;
95027106570Sdan} {1 {too many levels of trigger recursion}}
95127106570Sdan
9527ba45971Sdan
9532283d46cSdan
954436355a0Sdanfinish_test
955