xref: /sqlite-3.40.0/test/e_changes.test (revision 37f3ac8f)
1c3da667bSdan# 2011 October 28
2c3da667bSdan#
3c3da667bSdan# The author disclaims copyright to this source code.  In place of
4c3da667bSdan# a legal notice, here is a blessing:
5c3da667bSdan#
6c3da667bSdan#    May you do good and not evil.
7c3da667bSdan#    May you find forgiveness for yourself and forgive others.
8c3da667bSdan#    May you share freely, never taking more than you give.
9c3da667bSdan#
10c3da667bSdan#***********************************************************************
11c3da667bSdan#
12c3da667bSdan
13c3da667bSdanset testdir [file dirname $argv0]
14c3da667bSdansource $testdir/tester.tcl
15c3da667bSdanset testprefix e_changes
16c3da667bSdan
17c3da667bSdan# Like [do_execsql_test], except it appends the value returned by
18c3da667bSdan# [db changes] to the result of executing the SQL script.
19c3da667bSdan#
20c3da667bSdanproc do_changes_test {tn sql res} {
21c3da667bSdan  uplevel [list \
22c3da667bSdan    do_test $tn "concat \[execsql {$sql}\] \[db changes\]" $res
23c3da667bSdan  ]
24c3da667bSdan}
25c3da667bSdan
26c3da667bSdan
27c3da667bSdan#--------------------------------------------------------------------------
28c0bd26a2Sdrh# EVIDENCE-OF: R-58361-29089 The changes() function returns the number
29c0bd26a2Sdrh# of database rows that were changed or inserted or deleted by the most
30c0bd26a2Sdrh# recently completed INSERT, DELETE, or UPDATE statement, exclusive of
31c0bd26a2Sdrh# statements in lower-level triggers.
32c3da667bSdan#
33c3da667bSdando_execsql_test 1.0 {
34c3da667bSdan  CREATE TABLE t1(a, b);
35c3da667bSdan  CREATE TABLE t2(x, y, PRIMARY KEY(x, y)) WITHOUT ROWID;
36c3da667bSdan  CREATE INDEX i1 ON t1(a);
37c3da667bSdan  CREATE INDEX i2 ON t2(y);
38c3da667bSdan}
39c3da667bSdanforeach {tn schema} {
40c3da667bSdan  1 {
41c3da667bSdan      CREATE TABLE t1(a, b);
42c3da667bSdan      CREATE INDEX i1 ON t1(b);
43c3da667bSdan  }
44c3da667bSdan  2 {
45c3da667bSdan      CREATE TABLE t1(a, b, PRIMARY KEY(a, b)) WITHOUT ROWID;
46c3da667bSdan      CREATE INDEX i1 ON t1(b);
47c3da667bSdan  }
48c3da667bSdan} {
49c3da667bSdan  reset_db
50c3da667bSdan  execsql $schema
51c3da667bSdan
52c3da667bSdan  # Insert 1 row.
53c3da667bSdan  do_changes_test 1.$tn.1 { INSERT INTO t1 VALUES(0, 0) } 1
54c3da667bSdan
55c3da667bSdan  # Insert 10 rows.
56c3da667bSdan  do_changes_test 1.$tn.2 {
57c3da667bSdan    WITH rows(i, j) AS (
58c3da667bSdan        SELECT 1, 1 UNION ALL SELECT i+1, j+i FROM rows WHERE i<10
59c3da667bSdan    )
60c3da667bSdan    INSERT INTO t1 SELECT * FROM rows
61c3da667bSdan  } 10
62c3da667bSdan
63c3da667bSdan  # Modify 5 rows.
64c3da667bSdan  do_changes_test 1.$tn.3 {
65c3da667bSdan    UPDATE t1 SET b=b+1 WHERE a<5;
66c3da667bSdan  } 5
67c3da667bSdan
68c3da667bSdan  # Delete 4 rows
69c3da667bSdan  do_changes_test 1.$tn.4 {
70c3da667bSdan    DELETE FROM t1 WHERE a>6
71c3da667bSdan  } 4
72c3da667bSdan
73c3da667bSdan  # Check the "on the database connecton specified" part of hte
74c3da667bSdan  # requirement - changes made by other connections do not show up in
75c3da667bSdan  # the return value of sqlite3_changes().
76c3da667bSdan  do_test 1.$tn.5 {
77c3da667bSdan    sqlite3 db2 test.db
78c3da667bSdan    execsql { INSERT INTO t1 VALUES(-1, -1) } db2
79c3da667bSdan    db2 changes
80c3da667bSdan  } 1
81c3da667bSdan  do_test 1.$tn.6 {
82c3da667bSdan    db changes
83c3da667bSdan  } 4
84c3da667bSdan  db2 close
85c3da667bSdan
86c3da667bSdan  # Test that statements that modify no rows because they hit UNIQUE
87c3da667bSdan  # constraints set the sqlite3_changes() value to 0. Regardless of
88c3da667bSdan  # whether or not they are executed inside an explicit transaction.
89c3da667bSdan  #
90c3da667bSdan  #   1.$tn.8-9: outside of a transaction
91c3da667bSdan  #   1.$tn.10-12: inside a transaction
92c3da667bSdan  #
93c3da667bSdan  do_changes_test 1.$tn.7 {
94c3da667bSdan    CREATE UNIQUE INDEX i2 ON t1(a);
95c3da667bSdan  } 4
96c3da667bSdan  do_catchsql_test 1.$tn.8 {
97c3da667bSdan    INSERT INTO t1 VALUES('a', 0), ('b', 0), ('c', 0), (0, 11);
98c3da667bSdan  } {1 {UNIQUE constraint failed: t1.a}}
99c3da667bSdan  do_test 1.$tn.9 { db changes } 0
100c3da667bSdan  do_catchsql_test 1.$tn.10 {
101c3da667bSdan    BEGIN;
102c3da667bSdan      INSERT INTO t1 VALUES('a', 0), ('b', 0), ('c', 0), (0, 11);
103c3da667bSdan  } {1 {UNIQUE constraint failed: t1.a}}
104c3da667bSdan  do_test 1.$tn.11 { db changes } 0
105c3da667bSdan  do_changes_test 1.$tn.12 COMMIT 0
106c3da667bSdan
107c3da667bSdan}
108c3da667bSdan
109c3da667bSdan
110c3da667bSdan#--------------------------------------------------------------------------
111c0bd26a2Sdrh# X-EVIDENCE-OF: R-44877-05564 Executing any other type of SQL statement
112c3da667bSdan# does not modify the value returned by this function.
113c3da667bSdan#
114c3da667bSdanreset_db
115c3da667bSdando_changes_test 2.1 { CREATE TABLE t1(x)          } 0
116c3da667bSdando_changes_test 2.2 {
117c3da667bSdan  WITH d(y) AS (SELECT 1 UNION ALL SELECT y+1 FROM d WHERE y<47)
118c3da667bSdan  INSERT INTO t1 SELECT y FROM d;
119c3da667bSdan} 47
120c3da667bSdan
121c3da667bSdan# The statement above set changes() to 47. Check that none of the following
122c3da667bSdan# modify this.
123c3da667bSdando_changes_test 2.3 { SELECT count(x) FROM t1 } {47 47}
124c3da667bSdando_changes_test 2.4 { DROP TABLE t1               } 47
125c3da667bSdando_changes_test 2.5 { CREATE TABLE t1(x)          } 47
126*37f3ac8fSdanifcapable altertable {
127c3da667bSdan  do_changes_test 2.6 { ALTER TABLE t1 ADD COLUMN b } 47
128*37f3ac8fSdan}
129c3da667bSdan
130c3da667bSdan
131c3da667bSdan#--------------------------------------------------------------------------
132c3da667bSdan# EVIDENCE-OF: R-53938-27527 Only changes made directly by the INSERT,
133c3da667bSdan# UPDATE or DELETE statement are considered - auxiliary changes caused
134c3da667bSdan# by triggers, foreign key actions or REPLACE constraint resolution are
135c3da667bSdan# not counted.
136c3da667bSdan#
137c3da667bSdan#   3.1.*: triggers
138c3da667bSdan#   3.2.*: foreign key actions
139c3da667bSdan#   3.3.*: replace constraints
140c3da667bSdan#
141c3da667bSdanreset_db
142c3da667bSdando_execsql_test 3.1.0 {
143c3da667bSdan  CREATE TABLE log(x);
144c3da667bSdan  CREATE TABLE p1(one PRIMARY KEY, two);
145c3da667bSdan
146c3da667bSdan  CREATE TRIGGER tr_ai AFTER INSERT ON p1 BEGIN
147c3da667bSdan    INSERT INTO log VALUES('insert');
148c3da667bSdan  END;
149c3da667bSdan  CREATE TRIGGER tr_bd BEFORE DELETE ON p1 BEGIN
150c3da667bSdan    INSERT INTO log VALUES('delete');
151c3da667bSdan  END;
152c3da667bSdan  CREATE TRIGGER tr_au AFTER UPDATE ON p1 BEGIN
153c3da667bSdan    INSERT INTO log VALUES('update');
154c3da667bSdan  END;
155c3da667bSdan
156c3da667bSdan}
157c3da667bSdan
158c3da667bSdando_changes_test 3.1.1 {
159c3da667bSdan  INSERT INTO p1 VALUES('a', 'A'), ('b', 'B'), ('c', 'C');
160c3da667bSdan} 3
161c3da667bSdando_changes_test 3.1.2 {
162c3da667bSdan  UPDATE p1 SET two = two||two;
163c3da667bSdan} 3
164c3da667bSdando_changes_test 3.1.3 {
165c3da667bSdan  DELETE FROM p1 WHERE one IN ('a', 'c');
166c3da667bSdan} 2
167c3da667bSdando_execsql_test 3.1.4 {
168c3da667bSdan  -- None of the inserts on table log were counted.
169c3da667bSdan  SELECT count(*) FROM log
170c3da667bSdan} 8
171c3da667bSdan
172c3da667bSdando_execsql_test 3.2.0 {
173c3da667bSdan  DELETE FROM p1;
174c3da667bSdan  INSERT INTO p1 VALUES('a', 'A'), ('b', 'B'), ('c', 'C');
175c3da667bSdan
176c3da667bSdan  CREATE TABLE c1(a, b, FOREIGN KEY(a) REFERENCES p1 ON DELETE SET NULL);
177c3da667bSdan  CREATE TABLE c2(a, b, FOREIGN KEY(a) REFERENCES p1 ON DELETE SET DEFAULT);
178c3da667bSdan  CREATE TABLE c3(a, b, FOREIGN KEY(a) REFERENCES p1 ON DELETE CASCADE);
179c3da667bSdan  INSERT INTO c1 VALUES('a', 'aaa');
180c3da667bSdan  INSERT INTO c2 VALUES('b', 'bbb');
181c3da667bSdan  INSERT INTO c3 VALUES('c', 'ccc');
182c3da667bSdan
183c3da667bSdan  INSERT INTO p1 VALUES('d', 'D'), ('e', 'E'), ('f', 'F');
184c3da667bSdan  CREATE TABLE c4(a, b, FOREIGN KEY(a) REFERENCES p1 ON UPDATE SET NULL);
185c3da667bSdan  CREATE TABLE c5(a, b, FOREIGN KEY(a) REFERENCES p1 ON UPDATE SET DEFAULT);
186c3da667bSdan  CREATE TABLE c6(a, b, FOREIGN KEY(a) REFERENCES p1 ON UPDATE CASCADE);
187c3da667bSdan  INSERT INTO c4 VALUES('d', 'aaa');
188c3da667bSdan  INSERT INTO c5 VALUES('e', 'bbb');
189c3da667bSdan  INSERT INTO c6 VALUES('f', 'ccc');
190c3da667bSdan
191c3da667bSdan  PRAGMA foreign_keys = ON;
192c3da667bSdan}
193c3da667bSdan
194c3da667bSdando_changes_test 3.2.1 { DELETE FROM p1 WHERE one = 'a' } 1
195c3da667bSdando_changes_test 3.2.2 { DELETE FROM p1 WHERE one = 'b' } 1
196c3da667bSdando_changes_test 3.2.3 { DELETE FROM p1 WHERE one = 'c' } 1
197c3da667bSdando_execsql_test 3.2.4 {
198c3da667bSdan  SELECT * FROM c1;
199c3da667bSdan  SELECT * FROM c2;
200c3da667bSdan  SELECT * FROM c3;
201c3da667bSdan} {{} aaa {} bbb}
202c3da667bSdan
203c3da667bSdando_changes_test 3.2.5 { UPDATE p1 SET one = 'g' WHERE one = 'd' } 1
204c3da667bSdando_changes_test 3.2.6 { UPDATE p1 SET one = 'h' WHERE one = 'e' } 1
205c3da667bSdando_changes_test 3.2.7 { UPDATE p1 SET one = 'i' WHERE one = 'f' } 1
206c3da667bSdando_execsql_test 3.2.8 {
207c3da667bSdan  SELECT * FROM c4;
208c3da667bSdan  SELECT * FROM c5;
209c3da667bSdan  SELECT * FROM c6;
210c3da667bSdan} {{} aaa {} bbb i ccc}
211c3da667bSdan
212c3da667bSdando_execsql_test 3.3.0 {
213c3da667bSdan  CREATE TABLE r1(a UNIQUE, b UNIQUE);
214c3da667bSdan  INSERT INTO r1 VALUES('i', 'i');
215c3da667bSdan  INSERT INTO r1 VALUES('ii', 'ii');
216c3da667bSdan  INSERT INTO r1 VALUES('iii', 'iii');
217c3da667bSdan  INSERT INTO r1 VALUES('iv', 'iv');
218c3da667bSdan  INSERT INTO r1 VALUES('v', 'v');
219c3da667bSdan  INSERT INTO r1 VALUES('vi', 'vi');
220c3da667bSdan  INSERT INTO r1 VALUES('vii', 'vii');
221c3da667bSdan}
222c3da667bSdan
223c3da667bSdando_changes_test 3.3.1 { INSERT OR REPLACE INTO r1 VALUES('i', 1)    }   1
224c3da667bSdando_changes_test 3.3.2 { INSERT OR REPLACE INTO r1 VALUES('iv', 'v') }   1
225c3da667bSdando_changes_test 3.3.3 { UPDATE OR REPLACE r1 SET b='v' WHERE a='iii' }  1
226c3da667bSdando_changes_test 3.3.4 { UPDATE OR REPLACE r1 SET b='vi',a='vii' WHERE a='ii' } 1
227c3da667bSdando_execsql_test 3.3.5 {
228c3da667bSdan  SELECT * FROM r1 ORDER BY a;
229c3da667bSdan} {i 1   iii v   vii vi}
230c3da667bSdan
231c3da667bSdan
232c3da667bSdan#--------------------------------------------------------------------------
233c3da667bSdan# EVIDENCE-OF: R-09813-48563 The value returned by sqlite3_changes()
234c3da667bSdan# immediately after an INSERT, UPDATE or DELETE statement run on a view
235c3da667bSdan# is always zero.
236c3da667bSdan#
237c3da667bSdanreset_db
238c3da667bSdando_execsql_test 4.1 {
239c3da667bSdan  CREATE TABLE log(log);
240c3da667bSdan  CREATE TABLE t1(x, y);
241c3da667bSdan  INSERT INTO t1 VALUES(1, 2);
242c3da667bSdan  INSERT INTO t1 VALUES(3, 4);
243c3da667bSdan  INSERT INTO t1 VALUES(5, 6);
244c3da667bSdan
245c3da667bSdan  CREATE VIEW v1 AS SELECT * FROM t1;
246c3da667bSdan  CREATE TRIGGER v1_i INSTEAD OF INSERT ON v1 BEGIN
247c3da667bSdan    INSERT INTO log VALUES('insert');
248c3da667bSdan  END;
249c3da667bSdan  CREATE TRIGGER v1_u INSTEAD OF UPDATE ON v1 BEGIN
250c3da667bSdan    INSERT INTO log VALUES('update'), ('update');
251c3da667bSdan  END;
252c3da667bSdan  CREATE TRIGGER v1_d INSTEAD OF DELETE ON v1 BEGIN
253c3da667bSdan    INSERT INTO log VALUES('delete'), ('delete'), ('delete');
254c3da667bSdan  END;
255c3da667bSdan}
256c3da667bSdan
257c3da667bSdando_changes_test 4.2.1 { INSERT INTO t1 SELECT * FROM t1 }  3
258c3da667bSdando_changes_test 4.2.2 { INSERT INTO v1 VALUES(1, 2) }      0
259c3da667bSdan
260c3da667bSdando_changes_test 4.3.1 { INSERT INTO t1 SELECT * FROM t1 }  6
261c3da667bSdando_changes_test 4.3.2 { UPDATE v1 SET y='xyz' WHERE x=1 }  0
262c3da667bSdan
263c3da667bSdando_changes_test 4.4.1 { INSERT INTO t1 SELECT * FROM t1 } 12
264c3da667bSdando_changes_test 4.4.2 { DELETE FROM v1 WHERE x=5 }         0
265c3da667bSdan
266c3da667bSdan
267c3da667bSdan#--------------------------------------------------------------------------
268c3da667bSdan# EVIDENCE-OF: R-32918-61474 Before entering a trigger program the value
269c3da667bSdan# returned by sqlite3_changes() function is saved. After the trigger
270c3da667bSdan# program has finished, the original value is restored.
271c3da667bSdan#
272c3da667bSdanreset_db
273c3da667bSdandb func my_changes my_changes
274c3da667bSdanset ::changes [list]
275c3da667bSdanproc my_changes {x} {
276c3da667bSdan  set res [db changes]
277c3da667bSdan  lappend ::changes $x $res
278c3da667bSdan  return $res
279c3da667bSdan}
280c3da667bSdan
281c3da667bSdando_execsql_test 5.1.0 {
282c3da667bSdan  CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
283c3da667bSdan  CREATE TABLE t2(x);
284c3da667bSdan  INSERT INTO t1 VALUES(1, NULL);
285c3da667bSdan  INSERT INTO t1 VALUES(2, NULL);
286c3da667bSdan  INSERT INTO t1 VALUES(3, NULL);
287c3da667bSdan  CREATE TRIGGER AFTER UPDATE ON t1 BEGIN
288c3da667bSdan    INSERT INTO t2 VALUES('a'), ('b'), ('c');
289c3da667bSdan    SELECT my_changes('trigger');
290c3da667bSdan  END;
291c3da667bSdan}
292c3da667bSdan
293c3da667bSdando_execsql_test 5.1.1 {
294c3da667bSdan  INSERT INTO t2 VALUES('a'), ('b');
295c3da667bSdan  UPDATE t1 SET b = my_changes('update');
296c3da667bSdan  SELECT * FROM t1;
297c3da667bSdan} {1 2 2 2 3 2}
298c3da667bSdan
299c3da667bSdan# Value is being restored to "2" when the trigger program exits.
300c3da667bSdando_test 5.1.2 {
301c3da667bSdan  set ::changes
302c3da667bSdan} {update 2 trigger 3 update 2 trigger 3 update 2 trigger 3}
303c3da667bSdan
304c3da667bSdan
305c3da667bSdanreset_db
306c3da667bSdando_execsql_test 5.2.0 {
307c3da667bSdan  CREATE TABLE t1(a, b);
308c3da667bSdan  CREATE TABLE log(x);
309c3da667bSdan  INSERT INTO t1 VALUES(1, 0);
310c3da667bSdan  INSERT INTO t1 VALUES(2, 0);
311c3da667bSdan  INSERT INTO t1 VALUES(3, 0);
312c3da667bSdan  CREATE TRIGGER t1_a_u AFTER UPDATE ON t1 BEGIN
313c3da667bSdan    INSERT INTO log VALUES(old.b || ' -> ' || new.b || ' c = ' || changes() );
314c3da667bSdan  END;
315c3da667bSdan  CREATE TABLE t2(a);
316c3da667bSdan  INSERT INTO t2 VALUES(1), (2), (3);
317c3da667bSdan  UPDATE t1 SET b = changes();
318c3da667bSdan}
319c3da667bSdando_execsql_test 5.2.1 {
320c3da667bSdan  SELECT * FROM t1;
321c3da667bSdan} {1 3 2 3 3 3}
322c3da667bSdando_execsql_test 5.2.2 {
323c3da667bSdan  SELECT * FROM log;
324c3da667bSdan} {{0 -> 3 c = 3} {0 -> 3 c = 3} {0 -> 3 c = 3}}
325c3da667bSdan
326c3da667bSdan
327c3da667bSdan#--------------------------------------------------------------------------
328c3da667bSdan# EVIDENCE-OF: R-17146-37073 Within a trigger program each INSERT,
329c3da667bSdan# UPDATE and DELETE statement sets the value returned by
330c3da667bSdan# sqlite3_changes() upon completion as normal. Of course, this value
331c3da667bSdan# will not include any changes performed by sub-triggers, as the
332c3da667bSdan# sqlite3_changes() value will be saved and restored after each
333c3da667bSdan# sub-trigger has run.
334c3da667bSdanreset_db
335c3da667bSdando_execsql_test 6.0 {
336c3da667bSdan
337c3da667bSdan  CREATE TABLE t1(a, b);
338c3da667bSdan  CREATE TABLE t2(a, b);
339c3da667bSdan  CREATE TABLE t3(a, b);
340c3da667bSdan  CREATE TABLE log(x);
341c3da667bSdan
342c3da667bSdan  CREATE TRIGGER t1_i BEFORE INSERT ON t1 BEGIN
343c3da667bSdan    INSERT INTO t2 VALUES(new.a, new.b), (new.a, new.b);
344c3da667bSdan    INSERT INTO log VALUES('t2->' || changes());
345c3da667bSdan  END;
346c3da667bSdan
347c3da667bSdan  CREATE TRIGGER t2_i AFTER INSERT ON t2 BEGIN
348c3da667bSdan    INSERT INTO t3 VALUES(new.a, new.b), (new.a, new.b), (new.a, new.b);
349c3da667bSdan    INSERT INTO log VALUES('t3->' || changes());
350c3da667bSdan  END;
351c3da667bSdan
352c3da667bSdan  CREATE TRIGGER t1_u AFTER UPDATE ON t1 BEGIN
353c3da667bSdan    UPDATE t2 SET b=new.b WHERE a=old.a;
354c3da667bSdan    INSERT INTO log VALUES('t2->' || changes());
355c3da667bSdan  END;
356c3da667bSdan
357c3da667bSdan  CREATE TRIGGER t2_u BEFORE UPDATE ON t2 BEGIN
358c3da667bSdan    UPDATE t3 SET b=new.b WHERE a=old.a;
359c3da667bSdan    INSERT INTO log VALUES('t3->' || changes());
360c3da667bSdan  END;
361c3da667bSdan
362c3da667bSdan  CREATE TRIGGER t1_d AFTER DELETE ON t1 BEGIN
363c3da667bSdan    DELETE FROM t2 WHERE a=old.a AND b=old.b;
364c3da667bSdan    INSERT INTO log VALUES('t2->' || changes());
365c3da667bSdan  END;
366c3da667bSdan
367c3da667bSdan  CREATE TRIGGER t2_d BEFORE DELETE ON t2 BEGIN
368c3da667bSdan    DELETE FROM t3 WHERE a=old.a AND b=old.b;
369c3da667bSdan    INSERT INTO log VALUES('t3->' || changes());
370c3da667bSdan  END;
371c3da667bSdan}
372c3da667bSdan
373c3da667bSdando_changes_test 6.1 {
374c3da667bSdan  INSERT INTO t1 VALUES('+', 'o');
375c3da667bSdan  SELECT * FROM log;
376c3da667bSdan} {t3->3 t3->3 t2->2 1}
377c3da667bSdan
378c3da667bSdando_changes_test 6.2 {
379c3da667bSdan  DELETE FROM log;
380c3da667bSdan  UPDATE t1 SET b='*';
381c3da667bSdan  SELECT * FROM log;
382c3da667bSdan} {t3->6 t3->6 t2->2 1}
383c3da667bSdan
384c3da667bSdando_changes_test 6.3 {
385c3da667bSdan  DELETE FROM log;
386c3da667bSdan  DELETE FROM t1;
387c3da667bSdan  SELECT * FROM log;
388c3da667bSdan} {t3->6 t3->0 t2->2 1}
389c3da667bSdan
390c3da667bSdan
391c3da667bSdan#--------------------------------------------------------------------------
392c3da667bSdan# EVIDENCE-OF: R-43399-09409 This means that if the changes() SQL
393c3da667bSdan# function (or similar) is used by the first INSERT, UPDATE or DELETE
394c3da667bSdan# statement within a trigger, it returns the value as set when the
395c3da667bSdan# calling statement began executing.
396c3da667bSdan#
397c3da667bSdan# EVIDENCE-OF: R-53215-27584 If it is used by the second or subsequent
398c3da667bSdan# such statement within a trigger program, the value returned reflects
399c3da667bSdan# the number of rows modified by the previous INSERT, UPDATE or DELETE
400c3da667bSdan# statement within the same trigger.
401c3da667bSdan#
402c3da667bSdanreset_db
403c3da667bSdando_execsql_test 7.1 {
404c3da667bSdan  CREATE TABLE q1(t);
405c3da667bSdan  CREATE TABLE q2(u, v);
406c3da667bSdan  CREATE TABLE q3(w);
407c3da667bSdan
408c3da667bSdan  CREATE TRIGGER q2_insert BEFORE INSERT ON q2 BEGIN
409c3da667bSdan
410c3da667bSdan    /* changes() returns value from previous I/U/D in callers context */
411c3da667bSdan    INSERT INTO q1 VALUES('1:' || changes());
412c3da667bSdan
413c3da667bSdan    /* changes() returns value of previous I/U/D in this context */
414c3da667bSdan    INSERT INTO q3 VALUES(changes()), (2), (3);
415c3da667bSdan    INSERT INTO q1 VALUES('2:' || changes());
416c3da667bSdan    INSERT INTO q3 VALUES(changes() + 3), (changes()+4);
417c3da667bSdan    SELECT 'this does not affect things!';
418c3da667bSdan    INSERT INTO q1 VALUES('3:' || changes());
419c3da667bSdan    UPDATE q3 SET w = w+10 WHERE w%2;
420c3da667bSdan    INSERT INTO q1 VALUES('4:' || changes());
421c3da667bSdan    DELETE FROM q3;
422c3da667bSdan    INSERT INTO q1 VALUES('5:' || changes());
423c3da667bSdan  END;
424c3da667bSdan}
425c3da667bSdan
426c3da667bSdando_execsql_test 7.2 {
427c3da667bSdan  INSERT INTO q2 VALUES('x', 'y');
428c3da667bSdan  SELECT * FROM q1;
429c3da667bSdan} {
430c3da667bSdan  1:0   2:3   3:2   4:3   5:5
431c3da667bSdan}
432c3da667bSdan
433c3da667bSdando_execsql_test 7.3 {
434c3da667bSdan  DELETE FROM q1;
435c3da667bSdan  INSERT INTO q2 VALUES('x', 'y');
436c3da667bSdan  SELECT * FROM q1;
437c3da667bSdan} {
438c3da667bSdan  1:5   2:3   3:2   4:3   5:5
439c3da667bSdan}
440c3da667bSdan
441c3da667bSdan
442c3da667bSdan
443c3da667bSdanfinish_test
444