1*c7af484bSdanielk1977# 2a503d731Srdc# The author disclaims copyright to this source code. In place of 3a503d731Srdc# a legal notice, here is a blessing: 4a503d731Srdc# 5a503d731Srdc# May you do good and not evil. 6a503d731Srdc# May you find forgiveness for yourself and forgive others. 7a503d731Srdc# May you share freely, never taking more than you give. 8a503d731Srdc# 9a503d731Srdc#*********************************************************************** 10a503d731Srdc# 11b28af71aSdanielk1977# Tests to make sure that values returned by changes() and total_changes() 12b28af71aSdanielk1977# are updated properly, especially inside triggers 13a503d731Srdc# 14b28af71aSdanielk1977# Note 1: changes() remains constant within a statement and only updates 15b28af71aSdanielk1977# once the statement is finished (triggers count as part of 16b28af71aSdanielk1977# statement). 17b28af71aSdanielk1977# Note 2: changes() is changed within the context of a trigger much like 18b28af71aSdanielk1977# last_insert_rowid() (see lastinsert.test), but is restored once 19b28af71aSdanielk1977# the trigger exits. 20b28af71aSdanielk1977# Note 3: changes() is not changed by a change to a view (since everything 21b28af71aSdanielk1977# is done within instead of trigger context). 22a503d731Srdc# 23*c7af484bSdanielk1977# $Id: laststmtchanges.test,v 1.7 2008/10/27 13:59:34 danielk1977 Exp $ 24a503d731Srdc 25a503d731Srdcset testdir [file dirname $argv0] 26a503d731Srdcsource $testdir/tester.tcl 27a503d731Srdc 28a503d731Srdc# ---------------------------------------------------------------------------- 29a503d731Srdc# 1.x - basic tests (no triggers) 30a503d731Srdc 31b28af71aSdanielk1977# changes() set properly after insert 32a503d731Srdcdo_test laststmtchanges-1.1 { 33a503d731Srdc catchsql { 34a503d731Srdc create table t0 (x); 35a503d731Srdc insert into t0 values (1); 36a503d731Srdc insert into t0 values (1); 37a503d731Srdc insert into t0 values (2); 38a503d731Srdc insert into t0 values (2); 39a503d731Srdc insert into t0 values (1); 40a503d731Srdc insert into t0 values (1); 41a503d731Srdc insert into t0 values (1); 42a503d731Srdc insert into t0 values (2); 43b28af71aSdanielk1977 select changes(), total_changes(); 44a503d731Srdc } 45b28af71aSdanielk1977} {0 {1 8}} 46a503d731Srdc 47b28af71aSdanielk1977# changes() set properly after update 48a503d731Srdcdo_test laststmtchanges-1.2 { 49a503d731Srdc catchsql { 50a503d731Srdc update t0 set x=3 where x=1; 51b28af71aSdanielk1977 select changes(), total_changes(); 52a503d731Srdc } 53b28af71aSdanielk1977} {0 {5 13}} 54a503d731Srdc 55e0e11e2dSdrh# There was some goofy change-counting logic in sqlite3_exec() that 56e0e11e2dSdrh# appears to have been left over from SQLite version 2. This test 57e0e11e2dSdrh# makes sure it has been removed. 58e0e11e2dSdrh# 59e0e11e2dSdrhdo_test laststmtchanges-1.2.1 { 60e0e11e2dSdrh db cache flush 61e0e11e2dSdrh sqlite3_exec_printf db {update t0 set x=4 where x=3; select 1;} {} 62e0e11e2dSdrh execsql {select changes()} 63e0e11e2dSdrh} {5} 64e0e11e2dSdrh 65b28af71aSdanielk1977# changes() unchanged within an update statement 66a503d731Srdcdo_test laststmtchanges-1.3 { 67e0e11e2dSdrh execsql {update t0 set x=3 where x=4} 68a503d731Srdc catchsql { 69b28af71aSdanielk1977 update t0 set x=x+changes() where x=3; 70a503d731Srdc select count() from t0 where x=8; 71a503d731Srdc } 72a503d731Srdc} {0 5} 73a503d731Srdc 74b28af71aSdanielk1977# changes() set properly after update on table where no rows changed 75a503d731Srdcdo_test laststmtchanges-1.4 { 76a503d731Srdc catchsql { 77a503d731Srdc update t0 set x=77 where x=88; 78b28af71aSdanielk1977 select changes(); 79a503d731Srdc } 80a503d731Srdc} {0 0} 81a503d731Srdc 82b28af71aSdanielk1977# changes() set properly after delete from table 83a503d731Srdcdo_test laststmtchanges-1.5 { 84a503d731Srdc catchsql { 85a503d731Srdc delete from t0 where x=2; 86b28af71aSdanielk1977 select changes(); 87a503d731Srdc } 88a503d731Srdc} {0 3} 89a503d731Srdc 90798da52cSdrh# All remaining tests involve triggers. Skip them if triggers are not 91798da52cSdrh# supported in this build. 92798da52cSdrh# 93798da52cSdrhifcapable {!trigger} { 94798da52cSdrh finish_test 95798da52cSdrh return 96798da52cSdrh} 97798da52cSdrh 98798da52cSdrh 99a503d731Srdc# ---------------------------------------------------------------------------- 100a503d731Srdc# 2.x - tests with after insert trigger 101a503d731Srdc 102b28af71aSdanielk1977# changes() changed properly after insert into table containing after trigger 103a503d731Srdcdo_test laststmtchanges-2.1 { 104b28af71aSdanielk1977 set ::tc [db total_changes] 105a503d731Srdc catchsql { 106a503d731Srdc create table t1 (k integer primary key); 107a503d731Srdc create table t2 (k integer primary key, v1, v2); 108a503d731Srdc create trigger r1 after insert on t1 for each row begin 109b28af71aSdanielk1977 insert into t2 values (NULL, changes(), NULL); 110a503d731Srdc update t0 set x=x; 111b28af71aSdanielk1977 update t2 set v2=changes(); 112a503d731Srdc end; 113a503d731Srdc insert into t1 values (77); 114b28af71aSdanielk1977 select changes(); 115a503d731Srdc } 116a503d731Srdc} {0 1} 117a503d731Srdc 118b28af71aSdanielk1977# changes() unchanged upon entry into after insert trigger 119a503d731Srdcdo_test laststmtchanges-2.2 { 120a503d731Srdc catchsql { 121a503d731Srdc select v1 from t2; 122a503d731Srdc } 123a503d731Srdc} {0 3} 124a503d731Srdc 125b28af71aSdanielk1977# changes() changed properly by update within context of after insert trigger 126a503d731Srdcdo_test laststmtchanges-2.3 { 127a503d731Srdc catchsql { 128a503d731Srdc select v2 from t2; 129a503d731Srdc } 130a503d731Srdc} {0 5} 131a503d731Srdc 132b28af71aSdanielk1977# Total changes caused by firing the trigger above: 133b28af71aSdanielk1977# 134b28af71aSdanielk1977# 1 from "insert into t1 values(77)" + 135b28af71aSdanielk1977# 1 from "insert into t2 values (NULL, changes(), NULL);" + 136b28af71aSdanielk1977# 5 from "update t0 set x=x;" + 137b28af71aSdanielk1977# 1 from "update t2 set v2=changes();" 138b28af71aSdanielk1977# 139b28af71aSdanielk1977do_test laststmtchanges-2.4 { 140b28af71aSdanielk1977 expr [db total_changes] - $::tc 141b28af71aSdanielk1977} {8} 142b28af71aSdanielk1977 143a503d731Srdc# ---------------------------------------------------------------------------- 144a503d731Srdc# 3.x - tests with after update trigger 145a503d731Srdc 146b28af71aSdanielk1977# changes() changed properly after update into table containing after trigger 147a503d731Srdcdo_test laststmtchanges-3.1 { 148a503d731Srdc catchsql { 149a503d731Srdc drop trigger r1; 150a503d731Srdc delete from t2; delete from t2; 151a503d731Srdc create trigger r1 after update on t1 for each row begin 152b28af71aSdanielk1977 insert into t2 values (NULL, changes(), NULL); 153a503d731Srdc delete from t0 where oid=1 or oid=2; 154b28af71aSdanielk1977 update t2 set v2=changes(); 155a503d731Srdc end; 156a503d731Srdc update t1 set k=k; 157b28af71aSdanielk1977 select changes(); 158a503d731Srdc } 159a503d731Srdc} {0 1} 160a503d731Srdc 161b28af71aSdanielk1977# changes() unchanged upon entry into after update trigger 162a503d731Srdcdo_test laststmtchanges-3.2 { 163a503d731Srdc catchsql { 164a503d731Srdc select v1 from t2; 165a503d731Srdc } 166a503d731Srdc} {0 0} 167a503d731Srdc 168b28af71aSdanielk1977# changes() changed properly by delete within context of after update trigger 169a503d731Srdcdo_test laststmtchanges-3.3 { 170a503d731Srdc catchsql { 171a503d731Srdc select v2 from t2; 172a503d731Srdc } 173a503d731Srdc} {0 2} 174a503d731Srdc 175a503d731Srdc# ---------------------------------------------------------------------------- 176a503d731Srdc# 4.x - tests with before delete trigger 177a503d731Srdc 178b28af71aSdanielk1977# changes() changed properly on delete from table containing before trigger 179a503d731Srdcdo_test laststmtchanges-4.1 { 180a503d731Srdc catchsql { 181a503d731Srdc drop trigger r1; 182a503d731Srdc delete from t2; delete from t2; 183a503d731Srdc create trigger r1 before delete on t1 for each row begin 184b28af71aSdanielk1977 insert into t2 values (NULL, changes(), NULL); 185a503d731Srdc insert into t0 values (5); 186b28af71aSdanielk1977 update t2 set v2=changes(); 187a503d731Srdc end; 188a503d731Srdc delete from t1; 189b28af71aSdanielk1977 select changes(); 190a503d731Srdc } 191a503d731Srdc} {0 1} 192a503d731Srdc 193b28af71aSdanielk1977# changes() unchanged upon entry into before delete trigger 194a503d731Srdcdo_test laststmtchanges-4.2 { 195a503d731Srdc catchsql { 196a503d731Srdc select v1 from t2; 197a503d731Srdc } 198a503d731Srdc} {0 0} 199a503d731Srdc 200b28af71aSdanielk1977# changes() changed properly by insert within context of before delete trigger 201a503d731Srdcdo_test laststmtchanges-4.3 { 202a503d731Srdc catchsql { 203a503d731Srdc select v2 from t2; 204a503d731Srdc } 205a503d731Srdc} {0 1} 206a503d731Srdc 207a503d731Srdc# ---------------------------------------------------------------------------- 208a503d731Srdc# 5.x - complex tests with temporary tables and nested instead of triggers 2090fa8ddbdSdanielk1977# These tests cannot run if the library does not have view support enabled. 2100fa8ddbdSdanielk1977 21153c0f748Sdanielk1977ifcapable view&&tempdb { 212a503d731Srdc 213a503d731Srdcdo_test laststmtchanges-5.1 { 214a503d731Srdc catchsql { 215a503d731Srdc drop table t0; drop table t1; drop table t2; 216a503d731Srdc create temp table t0(x); 217a503d731Srdc create temp table t1 (k integer primary key); 218a503d731Srdc create temp table t2 (k integer primary key); 219a503d731Srdc create temp view v1 as select * from t1; 220a503d731Srdc create temp view v2 as select * from t2; 221a503d731Srdc create temp table n1 (k integer primary key, n); 222a503d731Srdc create temp table n2 (k integer primary key, n); 223a503d731Srdc insert into t0 values (1); 224a503d731Srdc insert into t0 values (2); 225a503d731Srdc insert into t0 values (1); 226a503d731Srdc insert into t0 values (1); 227a503d731Srdc insert into t0 values (1); 228a503d731Srdc insert into t0 values (2); 229a503d731Srdc insert into t0 values (2); 230a503d731Srdc insert into t0 values (1); 231a503d731Srdc create temp trigger r1 instead of insert on v1 for each row begin 232b28af71aSdanielk1977 insert into n1 values (NULL, changes()); 233a503d731Srdc update t0 set x=x*10 where x=1; 234b28af71aSdanielk1977 insert into n1 values (NULL, changes()); 235a503d731Srdc insert into t1 values (NEW.k); 236b28af71aSdanielk1977 insert into n1 values (NULL, changes()); 237a503d731Srdc update t0 set x=x*10 where x=0; 238a503d731Srdc insert into v2 values (100+NEW.k); 239b28af71aSdanielk1977 insert into n1 values (NULL, changes()); 240a503d731Srdc end; 241a503d731Srdc create temp trigger r2 instead of insert on v2 for each row begin 242b28af71aSdanielk1977 insert into n2 values (NULL, changes()); 243a503d731Srdc insert into t2 values (1000+NEW.k); 244b28af71aSdanielk1977 insert into n2 values (NULL, changes()); 245a503d731Srdc update t0 set x=x*100 where x=0; 246b28af71aSdanielk1977 insert into n2 values (NULL, changes()); 247a503d731Srdc delete from t0 where x=2; 248b28af71aSdanielk1977 insert into n2 values (NULL, changes()); 249a503d731Srdc end; 250a503d731Srdc insert into t1 values (77); 251b28af71aSdanielk1977 select changes(); 252a503d731Srdc } 253a503d731Srdc} {0 1} 254a503d731Srdc 255a503d731Srdcdo_test laststmtchanges-5.2 { 256a503d731Srdc catchsql { 257a503d731Srdc delete from t1 where k=88; 258b28af71aSdanielk1977 select changes(); 259a503d731Srdc } 260a503d731Srdc} {0 0} 261a503d731Srdc 262a503d731Srdcdo_test laststmtchanges-5.3 { 263a503d731Srdc catchsql { 264a503d731Srdc insert into v1 values (5); 265b28af71aSdanielk1977 select changes(); 266a503d731Srdc } 267a503d731Srdc} {0 0} 268a503d731Srdc 269a503d731Srdcdo_test laststmtchanges-5.4 { 270a503d731Srdc catchsql { 271a503d731Srdc select n from n1; 272a503d731Srdc } 273a503d731Srdc} {0 {0 5 1 0}} 274a503d731Srdc 275a503d731Srdcdo_test laststmtchanges-5.5 { 276a503d731Srdc catchsql { 277a503d731Srdc select n from n2; 278a503d731Srdc } 279a503d731Srdc} {0 {0 1 0 3}} 280a503d731Srdc 2810fa8ddbdSdanielk1977} ;# ifcapable view 2820fa8ddbdSdanielk1977 283*c7af484bSdanielk1977 284*c7af484bSdanielk1977# ---------------------------------------------------------------------------- 285*c7af484bSdanielk1977# 6.x - Test "DELETE FROM <table>" in the absence of triggers 286*c7af484bSdanielk1977# 287*c7af484bSdanielk1977do_test laststmtchanges-6.1 { 288*c7af484bSdanielk1977 execsql { 289*c7af484bSdanielk1977 CREATE TABLE t3(a, b, c); 290*c7af484bSdanielk1977 INSERT INTO t3 VALUES(1, 2, 3); 291*c7af484bSdanielk1977 INSERT INTO t3 VALUES(4, 5, 6); 292*c7af484bSdanielk1977 } 293*c7af484bSdanielk1977} {} 294*c7af484bSdanielk1977do_test laststmtchanges-6.2 { 295*c7af484bSdanielk1977 execsql { 296*c7af484bSdanielk1977 BEGIN; 297*c7af484bSdanielk1977 DELETE FROM t3; 298*c7af484bSdanielk1977 SELECT changes(); 299*c7af484bSdanielk1977 } 300*c7af484bSdanielk1977} {2} 301*c7af484bSdanielk1977do_test laststmtchanges-6.3 { 302*c7af484bSdanielk1977 execsql { 303*c7af484bSdanielk1977 ROLLBACK; 304*c7af484bSdanielk1977 BEGIN; 305*c7af484bSdanielk1977 DELETE FROM t3 WHERE a IS NOT NULL; 306*c7af484bSdanielk1977 SELECT changes(); 307*c7af484bSdanielk1977 } 308*c7af484bSdanielk1977} {2} 309*c7af484bSdanielk1977do_test laststmtchanges-6.4 { 310*c7af484bSdanielk1977 execsql { 311*c7af484bSdanielk1977 ROLLBACK; 312*c7af484bSdanielk1977 CREATE INDEX t3_i1 ON t3(a); 313*c7af484bSdanielk1977 BEGIN; 314*c7af484bSdanielk1977 DELETE FROM t3; 315*c7af484bSdanielk1977 SELECT changes(); 316*c7af484bSdanielk1977 } 317*c7af484bSdanielk1977} {2} 318*c7af484bSdanielk1977do_test laststmtchanges-6.5 { 319*c7af484bSdanielk1977 execsql { ROLLBACK } 320*c7af484bSdanielk1977 set nTotalChange [execsql {SELECT total_changes()}] 321*c7af484bSdanielk1977 expr 0 322*c7af484bSdanielk1977} {0} 323*c7af484bSdanielk1977do_test laststmtchanges-6.6 { 324*c7af484bSdanielk1977 execsql { 325*c7af484bSdanielk1977 SELECT total_changes(); 326*c7af484bSdanielk1977 DELETE FROM t3; 327*c7af484bSdanielk1977 SELECT total_changes(); 328*c7af484bSdanielk1977 } 329*c7af484bSdanielk1977} [list $nTotalChange [expr $nTotalChange+2]] 330*c7af484bSdanielk1977 331a503d731Srdcfinish_test 332