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