blob: ea4c3892b75d257cf51a3f71864c537b93a4ba67 [file] [log] [blame]
danielk1977c7af4842008-10-27 13:59:33 +00001#
rdca503d732004-02-20 22:54:25 +00002# The author disclaims copyright to this source code. In place of
3# a legal notice, here is a blessing:
4#
5# May you do good and not evil.
6# May you find forgiveness for yourself and forgive others.
7# May you share freely, never taking more than you give.
8#
9#***********************************************************************
10#
danielk1977b28af712004-06-21 06:50:26 +000011# Tests to make sure that values returned by changes() and total_changes()
12# are updated properly, especially inside triggers
rdca503d732004-02-20 22:54:25 +000013#
danielk1977b28af712004-06-21 06:50:26 +000014# Note 1: changes() remains constant within a statement and only updates
15# once the statement is finished (triggers count as part of
16# statement).
17# Note 2: changes() is changed within the context of a trigger much like
18# last_insert_rowid() (see lastinsert.test), but is restored once
19# the trigger exits.
20# Note 3: changes() is not changed by a change to a view (since everything
21# is done within instead of trigger context).
rdca503d732004-02-20 22:54:25 +000022#
danielk1977c7af4842008-10-27 13:59:33 +000023# $Id: laststmtchanges.test,v 1.7 2008/10/27 13:59:34 danielk1977 Exp $
rdca503d732004-02-20 22:54:25 +000024
25set testdir [file dirname $argv0]
26source $testdir/tester.tcl
27
28# ----------------------------------------------------------------------------
29# 1.x - basic tests (no triggers)
30
danielk1977b28af712004-06-21 06:50:26 +000031# changes() set properly after insert
rdca503d732004-02-20 22:54:25 +000032do_test laststmtchanges-1.1 {
33 catchsql {
34 create table t0 (x);
35 insert into t0 values (1);
36 insert into t0 values (1);
37 insert into t0 values (2);
38 insert into t0 values (2);
39 insert into t0 values (1);
40 insert into t0 values (1);
41 insert into t0 values (1);
42 insert into t0 values (2);
danielk1977b28af712004-06-21 06:50:26 +000043 select changes(), total_changes();
rdca503d732004-02-20 22:54:25 +000044 }
danielk1977b28af712004-06-21 06:50:26 +000045} {0 {1 8}}
rdca503d732004-02-20 22:54:25 +000046
danielk1977b28af712004-06-21 06:50:26 +000047# changes() set properly after update
rdca503d732004-02-20 22:54:25 +000048do_test laststmtchanges-1.2 {
49 catchsql {
50 update t0 set x=3 where x=1;
danielk1977b28af712004-06-21 06:50:26 +000051 select changes(), total_changes();
rdca503d732004-02-20 22:54:25 +000052 }
danielk1977b28af712004-06-21 06:50:26 +000053} {0 {5 13}}
rdca503d732004-02-20 22:54:25 +000054
drhe0e11e22007-04-25 11:28:16 +000055# There was some goofy change-counting logic in sqlite3_exec() that
56# appears to have been left over from SQLite version 2. This test
57# makes sure it has been removed.
58#
59do_test laststmtchanges-1.2.1 {
60 db cache flush
61 sqlite3_exec_printf db {update t0 set x=4 where x=3; select 1;} {}
62 execsql {select changes()}
63} {5}
64
danielk1977b28af712004-06-21 06:50:26 +000065# changes() unchanged within an update statement
rdca503d732004-02-20 22:54:25 +000066do_test laststmtchanges-1.3 {
drhe0e11e22007-04-25 11:28:16 +000067 execsql {update t0 set x=3 where x=4}
rdca503d732004-02-20 22:54:25 +000068 catchsql {
danielk1977b28af712004-06-21 06:50:26 +000069 update t0 set x=x+changes() where x=3;
rdca503d732004-02-20 22:54:25 +000070 select count() from t0 where x=8;
71 }
72} {0 5}
73
danielk1977b28af712004-06-21 06:50:26 +000074# changes() set properly after update on table where no rows changed
rdca503d732004-02-20 22:54:25 +000075do_test laststmtchanges-1.4 {
76 catchsql {
77 update t0 set x=77 where x=88;
danielk1977b28af712004-06-21 06:50:26 +000078 select changes();
rdca503d732004-02-20 22:54:25 +000079 }
80} {0 0}
81
danielk1977b28af712004-06-21 06:50:26 +000082# changes() set properly after delete from table
rdca503d732004-02-20 22:54:25 +000083do_test laststmtchanges-1.5 {
84 catchsql {
85 delete from t0 where x=2;
danielk1977b28af712004-06-21 06:50:26 +000086 select changes();
rdca503d732004-02-20 22:54:25 +000087 }
88} {0 3}
89
drh798da522004-11-04 04:42:28 +000090# All remaining tests involve triggers. Skip them if triggers are not
91# supported in this build.
92#
93ifcapable {!trigger} {
94 finish_test
95 return
96}
97
98
rdca503d732004-02-20 22:54:25 +000099# ----------------------------------------------------------------------------
100# 2.x - tests with after insert trigger
101
danielk1977b28af712004-06-21 06:50:26 +0000102# changes() changed properly after insert into table containing after trigger
rdca503d732004-02-20 22:54:25 +0000103do_test laststmtchanges-2.1 {
danielk1977b28af712004-06-21 06:50:26 +0000104 set ::tc [db total_changes]
rdca503d732004-02-20 22:54:25 +0000105 catchsql {
106 create table t1 (k integer primary key);
107 create table t2 (k integer primary key, v1, v2);
108 create trigger r1 after insert on t1 for each row begin
danielk1977b28af712004-06-21 06:50:26 +0000109 insert into t2 values (NULL, changes(), NULL);
rdca503d732004-02-20 22:54:25 +0000110 update t0 set x=x;
danielk1977b28af712004-06-21 06:50:26 +0000111 update t2 set v2=changes();
rdca503d732004-02-20 22:54:25 +0000112 end;
113 insert into t1 values (77);
danielk1977b28af712004-06-21 06:50:26 +0000114 select changes();
rdca503d732004-02-20 22:54:25 +0000115 }
116} {0 1}
117
danielk1977b28af712004-06-21 06:50:26 +0000118# changes() unchanged upon entry into after insert trigger
rdca503d732004-02-20 22:54:25 +0000119do_test laststmtchanges-2.2 {
120 catchsql {
121 select v1 from t2;
122 }
123} {0 3}
124
danielk1977b28af712004-06-21 06:50:26 +0000125# changes() changed properly by update within context of after insert trigger
rdca503d732004-02-20 22:54:25 +0000126do_test laststmtchanges-2.3 {
127 catchsql {
128 select v2 from t2;
129 }
130} {0 5}
131
danielk1977b28af712004-06-21 06:50:26 +0000132# Total changes caused by firing the trigger above:
133#
134# 1 from "insert into t1 values(77)" +
135# 1 from "insert into t2 values (NULL, changes(), NULL);" +
136# 5 from "update t0 set x=x;" +
137# 1 from "update t2 set v2=changes();"
138#
139do_test laststmtchanges-2.4 {
140 expr [db total_changes] - $::tc
141} {8}
142
rdca503d732004-02-20 22:54:25 +0000143# ----------------------------------------------------------------------------
144# 3.x - tests with after update trigger
145
danielk1977b28af712004-06-21 06:50:26 +0000146# changes() changed properly after update into table containing after trigger
rdca503d732004-02-20 22:54:25 +0000147do_test laststmtchanges-3.1 {
148 catchsql {
149 drop trigger r1;
150 delete from t2; delete from t2;
151 create trigger r1 after update on t1 for each row begin
danielk1977b28af712004-06-21 06:50:26 +0000152 insert into t2 values (NULL, changes(), NULL);
rdca503d732004-02-20 22:54:25 +0000153 delete from t0 where oid=1 or oid=2;
danielk1977b28af712004-06-21 06:50:26 +0000154 update t2 set v2=changes();
rdca503d732004-02-20 22:54:25 +0000155 end;
156 update t1 set k=k;
danielk1977b28af712004-06-21 06:50:26 +0000157 select changes();
rdca503d732004-02-20 22:54:25 +0000158 }
159} {0 1}
160
danielk1977b28af712004-06-21 06:50:26 +0000161# changes() unchanged upon entry into after update trigger
rdca503d732004-02-20 22:54:25 +0000162do_test laststmtchanges-3.2 {
163 catchsql {
164 select v1 from t2;
165 }
166} {0 0}
167
danielk1977b28af712004-06-21 06:50:26 +0000168# changes() changed properly by delete within context of after update trigger
rdca503d732004-02-20 22:54:25 +0000169do_test laststmtchanges-3.3 {
170 catchsql {
171 select v2 from t2;
172 }
173} {0 2}
174
175# ----------------------------------------------------------------------------
176# 4.x - tests with before delete trigger
177
danielk1977b28af712004-06-21 06:50:26 +0000178# changes() changed properly on delete from table containing before trigger
rdca503d732004-02-20 22:54:25 +0000179do_test laststmtchanges-4.1 {
180 catchsql {
181 drop trigger r1;
182 delete from t2; delete from t2;
183 create trigger r1 before delete on t1 for each row begin
danielk1977b28af712004-06-21 06:50:26 +0000184 insert into t2 values (NULL, changes(), NULL);
rdca503d732004-02-20 22:54:25 +0000185 insert into t0 values (5);
danielk1977b28af712004-06-21 06:50:26 +0000186 update t2 set v2=changes();
rdca503d732004-02-20 22:54:25 +0000187 end;
188 delete from t1;
danielk1977b28af712004-06-21 06:50:26 +0000189 select changes();
rdca503d732004-02-20 22:54:25 +0000190 }
191} {0 1}
192
danielk1977b28af712004-06-21 06:50:26 +0000193# changes() unchanged upon entry into before delete trigger
rdca503d732004-02-20 22:54:25 +0000194do_test laststmtchanges-4.2 {
195 catchsql {
196 select v1 from t2;
197 }
198} {0 0}
199
danielk1977b28af712004-06-21 06:50:26 +0000200# changes() changed properly by insert within context of before delete trigger
rdca503d732004-02-20 22:54:25 +0000201do_test laststmtchanges-4.3 {
202 catchsql {
203 select v2 from t2;
204 }
205} {0 1}
206
207# ----------------------------------------------------------------------------
208# 5.x - complex tests with temporary tables and nested instead of triggers
danielk19770fa8ddb2004-11-22 08:43:32 +0000209# These tests cannot run if the library does not have view support enabled.
210
danielk197753c0f742005-03-29 03:10:59 +0000211ifcapable view&&tempdb {
rdca503d732004-02-20 22:54:25 +0000212
213do_test laststmtchanges-5.1 {
214 catchsql {
215 drop table t0; drop table t1; drop table t2;
216 create temp table t0(x);
217 create temp table t1 (k integer primary key);
218 create temp table t2 (k integer primary key);
219 create temp view v1 as select * from t1;
220 create temp view v2 as select * from t2;
221 create temp table n1 (k integer primary key, n);
222 create temp table n2 (k integer primary key, n);
223 insert into t0 values (1);
224 insert into t0 values (2);
225 insert into t0 values (1);
226 insert into t0 values (1);
227 insert into t0 values (1);
228 insert into t0 values (2);
229 insert into t0 values (2);
230 insert into t0 values (1);
231 create temp trigger r1 instead of insert on v1 for each row begin
danielk1977b28af712004-06-21 06:50:26 +0000232 insert into n1 values (NULL, changes());
rdca503d732004-02-20 22:54:25 +0000233 update t0 set x=x*10 where x=1;
danielk1977b28af712004-06-21 06:50:26 +0000234 insert into n1 values (NULL, changes());
rdca503d732004-02-20 22:54:25 +0000235 insert into t1 values (NEW.k);
danielk1977b28af712004-06-21 06:50:26 +0000236 insert into n1 values (NULL, changes());
rdca503d732004-02-20 22:54:25 +0000237 update t0 set x=x*10 where x=0;
238 insert into v2 values (100+NEW.k);
danielk1977b28af712004-06-21 06:50:26 +0000239 insert into n1 values (NULL, changes());
rdca503d732004-02-20 22:54:25 +0000240 end;
241 create temp trigger r2 instead of insert on v2 for each row begin
danielk1977b28af712004-06-21 06:50:26 +0000242 insert into n2 values (NULL, changes());
rdca503d732004-02-20 22:54:25 +0000243 insert into t2 values (1000+NEW.k);
danielk1977b28af712004-06-21 06:50:26 +0000244 insert into n2 values (NULL, changes());
rdca503d732004-02-20 22:54:25 +0000245 update t0 set x=x*100 where x=0;
danielk1977b28af712004-06-21 06:50:26 +0000246 insert into n2 values (NULL, changes());
rdca503d732004-02-20 22:54:25 +0000247 delete from t0 where x=2;
danielk1977b28af712004-06-21 06:50:26 +0000248 insert into n2 values (NULL, changes());
rdca503d732004-02-20 22:54:25 +0000249 end;
250 insert into t1 values (77);
danielk1977b28af712004-06-21 06:50:26 +0000251 select changes();
rdca503d732004-02-20 22:54:25 +0000252 }
253} {0 1}
254
255do_test laststmtchanges-5.2 {
256 catchsql {
257 delete from t1 where k=88;
danielk1977b28af712004-06-21 06:50:26 +0000258 select changes();
rdca503d732004-02-20 22:54:25 +0000259 }
260} {0 0}
261
262do_test laststmtchanges-5.3 {
263 catchsql {
264 insert into v1 values (5);
danielk1977b28af712004-06-21 06:50:26 +0000265 select changes();
rdca503d732004-02-20 22:54:25 +0000266 }
267} {0 0}
268
269do_test laststmtchanges-5.4 {
270 catchsql {
271 select n from n1;
272 }
273} {0 {0 5 1 0}}
274
275do_test laststmtchanges-5.5 {
276 catchsql {
277 select n from n2;
278 }
279} {0 {0 1 0 3}}
280
danielk19770fa8ddb2004-11-22 08:43:32 +0000281} ;# ifcapable view
282
danielk1977c7af4842008-10-27 13:59:33 +0000283
284# ----------------------------------------------------------------------------
285# 6.x - Test "DELETE FROM <table>" in the absence of triggers
286#
287do_test laststmtchanges-6.1 {
288 execsql {
289 CREATE TABLE t3(a, b, c);
290 INSERT INTO t3 VALUES(1, 2, 3);
291 INSERT INTO t3 VALUES(4, 5, 6);
292 }
293} {}
294do_test laststmtchanges-6.2 {
295 execsql {
296 BEGIN;
297 DELETE FROM t3;
298 SELECT changes();
299 }
300} {2}
301do_test laststmtchanges-6.3 {
302 execsql {
303 ROLLBACK;
304 BEGIN;
305 DELETE FROM t3 WHERE a IS NOT NULL;
306 SELECT changes();
307 }
308} {2}
309do_test laststmtchanges-6.4 {
310 execsql {
311 ROLLBACK;
312 CREATE INDEX t3_i1 ON t3(a);
313 BEGIN;
314 DELETE FROM t3;
315 SELECT changes();
316 }
317} {2}
318do_test laststmtchanges-6.5 {
319 execsql { ROLLBACK }
320 set nTotalChange [execsql {SELECT total_changes()}]
321 expr 0
322} {0}
323do_test laststmtchanges-6.6 {
324 execsql {
325 SELECT total_changes();
326 DELETE FROM t3;
327 SELECT total_changes();
328 }
329} [list $nTotalChange [expr $nTotalChange+2]]
330
rdca503d732004-02-20 22:54:25 +0000331finish_test