1# The author disclaims copyright to this source code. In place of 2# a legal notice, here is a blessing: 3# 4# May you do good and not evil. 5# May you find forgiveness for yourself and forgive others. 6# May you share freely, never taking more than you give. 7# 8#*********************************************************************** 9# 10# Tests to make sure that values returned by changes() and total_changes() 11# are updated properly, especially inside triggers 12# 13# Note 1: changes() remains constant within a statement and only updates 14# once the statement is finished (triggers count as part of 15# statement). 16# Note 2: changes() is changed within the context of a trigger much like 17# last_insert_rowid() (see lastinsert.test), but is restored once 18# the trigger exits. 19# Note 3: changes() is not changed by a change to a view (since everything 20# is done within instead of trigger context). 21# 22 23set testdir [file dirname $argv0] 24source $testdir/tester.tcl 25 26# ---------------------------------------------------------------------------- 27# 1.x - basic tests (no triggers) 28 29# changes() set properly after insert 30do_test laststmtchanges-1.1 { 31 catchsql { 32 create table t0 (x); 33 insert into t0 values (1); 34 insert into t0 values (1); 35 insert into t0 values (2); 36 insert into t0 values (2); 37 insert into t0 values (1); 38 insert into t0 values (1); 39 insert into t0 values (1); 40 insert into t0 values (2); 41 select changes(), total_changes(); 42 } 43} {0 {1 8}} 44 45# changes() set properly after update 46do_test laststmtchanges-1.2 { 47 catchsql { 48 update t0 set x=3 where x=1; 49 select changes(), total_changes(); 50 } 51} {0 {5 13}} 52 53# changes() unchanged within an update statement 54do_test laststmtchanges-1.3 { 55 catchsql { 56 update t0 set x=x+changes() where x=3; 57 select count() from t0 where x=8; 58 } 59} {0 5} 60 61# changes() set properly after update on table where no rows changed 62do_test laststmtchanges-1.4 { 63 catchsql { 64 update t0 set x=77 where x=88; 65 select changes(); 66 } 67} {0 0} 68 69# changes() set properly after delete from table 70do_test laststmtchanges-1.5 { 71 catchsql { 72 delete from t0 where x=2; 73 select changes(); 74 } 75} {0 3} 76 77# All remaining tests involve triggers. Skip them if triggers are not 78# supported in this build. 79# 80ifcapable {!trigger} { 81 finish_test 82 return 83} 84 85 86# ---------------------------------------------------------------------------- 87# 2.x - tests with after insert trigger 88 89# changes() changed properly after insert into table containing after trigger 90do_test laststmtchanges-2.1 { 91 set ::tc [db total_changes] 92 catchsql { 93 create table t1 (k integer primary key); 94 create table t2 (k integer primary key, v1, v2); 95 create trigger r1 after insert on t1 for each row begin 96 insert into t2 values (NULL, changes(), NULL); 97 update t0 set x=x; 98 update t2 set v2=changes(); 99 end; 100 insert into t1 values (77); 101 select changes(); 102 } 103} {0 1} 104 105# changes() unchanged upon entry into after insert trigger 106do_test laststmtchanges-2.2 { 107 catchsql { 108 select v1 from t2; 109 } 110} {0 3} 111 112# changes() changed properly by update within context of after insert trigger 113do_test laststmtchanges-2.3 { 114 catchsql { 115 select v2 from t2; 116 } 117} {0 5} 118 119# Total changes caused by firing the trigger above: 120# 121# 1 from "insert into t1 values(77)" + 122# 1 from "insert into t2 values (NULL, changes(), NULL);" + 123# 5 from "update t0 set x=x;" + 124# 1 from "update t2 set v2=changes();" 125# 126do_test laststmtchanges-2.4 { 127 expr [db total_changes] - $::tc 128} {8} 129 130# ---------------------------------------------------------------------------- 131# 3.x - tests with after update trigger 132 133# changes() changed properly after update into table containing after trigger 134do_test laststmtchanges-3.1 { 135 catchsql { 136 drop trigger r1; 137 delete from t2; delete from t2; 138 create trigger r1 after update on t1 for each row begin 139 insert into t2 values (NULL, changes(), NULL); 140 delete from t0 where oid=1 or oid=2; 141 update t2 set v2=changes(); 142 end; 143 update t1 set k=k; 144 select changes(); 145 } 146} {0 1} 147 148# changes() unchanged upon entry into after update trigger 149do_test laststmtchanges-3.2 { 150 catchsql { 151 select v1 from t2; 152 } 153} {0 0} 154 155# changes() changed properly by delete within context of after update trigger 156do_test laststmtchanges-3.3 { 157 catchsql { 158 select v2 from t2; 159 } 160} {0 2} 161 162# ---------------------------------------------------------------------------- 163# 4.x - tests with before delete trigger 164 165# changes() changed properly on delete from table containing before trigger 166do_test laststmtchanges-4.1 { 167 catchsql { 168 drop trigger r1; 169 delete from t2; delete from t2; 170 create trigger r1 before delete on t1 for each row begin 171 insert into t2 values (NULL, changes(), NULL); 172 insert into t0 values (5); 173 update t2 set v2=changes(); 174 end; 175 delete from t1; 176 select changes(); 177 } 178} {0 1} 179 180# changes() unchanged upon entry into before delete trigger 181do_test laststmtchanges-4.2 { 182 catchsql { 183 select v1 from t2; 184 } 185} {0 0} 186 187# changes() changed properly by insert within context of before delete trigger 188do_test laststmtchanges-4.3 { 189 catchsql { 190 select v2 from t2; 191 } 192} {0 1} 193 194# ---------------------------------------------------------------------------- 195# 5.x - complex tests with temporary tables and nested instead of triggers 196# These tests cannot run if the library does not have view support enabled. 197 198ifcapable view&&tempdb { 199 200do_test laststmtchanges-5.1 { 201 catchsql { 202 drop table t0; drop table t1; drop table t2; 203 create temp table t0(x); 204 create temp table t1 (k integer primary key); 205 create temp table t2 (k integer primary key); 206 create temp view v1 as select * from t1; 207 create temp view v2 as select * from t2; 208 create temp table n1 (k integer primary key, n); 209 create temp table n2 (k integer primary key, n); 210 insert into t0 values (1); 211 insert into t0 values (2); 212 insert into t0 values (1); 213 insert into t0 values (1); 214 insert into t0 values (1); 215 insert into t0 values (2); 216 insert into t0 values (2); 217 insert into t0 values (1); 218 create temp trigger r1 instead of insert on v1 for each row begin 219 insert into n1 values (NULL, changes()); 220 update t0 set x=x*10 where x=1; 221 insert into n1 values (NULL, changes()); 222 insert into t1 values (NEW.k); 223 insert into n1 values (NULL, changes()); 224 update t0 set x=x*10 where x=0; 225 insert into v2 values (100+NEW.k); 226 insert into n1 values (NULL, changes()); 227 end; 228 create temp trigger r2 instead of insert on v2 for each row begin 229 insert into n2 values (NULL, changes()); 230 insert into t2 values (1000+NEW.k); 231 insert into n2 values (NULL, changes()); 232 update t0 set x=x*100 where x=0; 233 insert into n2 values (NULL, changes()); 234 delete from t0 where x=2; 235 insert into n2 values (NULL, changes()); 236 end; 237 insert into t1 values (77); 238 select changes(); 239 } 240} {0 1} 241 242do_test laststmtchanges-5.2 { 243 catchsql { 244 delete from t1 where k=88; 245 select changes(); 246 } 247} {0 0} 248 249do_test laststmtchanges-5.3 { 250 catchsql { 251 insert into v1 values (5); 252 select changes(); 253 } 254} {0 0} 255 256do_test laststmtchanges-5.4 { 257 catchsql { 258 select n from n1; 259 } 260} {0 {0 5 1 0}} 261 262do_test laststmtchanges-5.5 { 263 catchsql { 264 select n from n2; 265 } 266} {0 {0 1 0 3}} 267 268} ;# ifcapable view 269 270finish_test 271