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# ---------------------------------------------------------------------------- 78# 2.x - tests with after insert trigger 79 80# changes() changed properly after insert into table containing after trigger 81do_test laststmtchanges-2.1 { 82 set ::tc [db total_changes] 83 catchsql { 84 create table t1 (k integer primary key); 85 create table t2 (k integer primary key, v1, v2); 86 create trigger r1 after insert on t1 for each row begin 87 insert into t2 values (NULL, changes(), NULL); 88 update t0 set x=x; 89 update t2 set v2=changes(); 90 end; 91 insert into t1 values (77); 92 select changes(); 93 } 94} {0 1} 95 96# changes() unchanged upon entry into after insert trigger 97do_test laststmtchanges-2.2 { 98 catchsql { 99 select v1 from t2; 100 } 101} {0 3} 102 103# changes() changed properly by update within context of after insert trigger 104do_test laststmtchanges-2.3 { 105 catchsql { 106 select v2 from t2; 107 } 108} {0 5} 109 110# Total changes caused by firing the trigger above: 111# 112# 1 from "insert into t1 values(77)" + 113# 1 from "insert into t2 values (NULL, changes(), NULL);" + 114# 5 from "update t0 set x=x;" + 115# 1 from "update t2 set v2=changes();" 116# 117do_test laststmtchanges-2.4 { 118 expr [db total_changes] - $::tc 119} {8} 120 121# ---------------------------------------------------------------------------- 122# 3.x - tests with after update trigger 123 124# changes() changed properly after update into table containing after trigger 125do_test laststmtchanges-3.1 { 126 catchsql { 127 drop trigger r1; 128 delete from t2; delete from t2; 129 create trigger r1 after update on t1 for each row begin 130 insert into t2 values (NULL, changes(), NULL); 131 delete from t0 where oid=1 or oid=2; 132 update t2 set v2=changes(); 133 end; 134 update t1 set k=k; 135 select changes(); 136 } 137} {0 1} 138 139# changes() unchanged upon entry into after update trigger 140do_test laststmtchanges-3.2 { 141 catchsql { 142 select v1 from t2; 143 } 144} {0 0} 145 146# changes() changed properly by delete within context of after update trigger 147do_test laststmtchanges-3.3 { 148 catchsql { 149 select v2 from t2; 150 } 151} {0 2} 152 153# ---------------------------------------------------------------------------- 154# 4.x - tests with before delete trigger 155 156# changes() changed properly on delete from table containing before trigger 157do_test laststmtchanges-4.1 { 158 catchsql { 159 drop trigger r1; 160 delete from t2; delete from t2; 161 create trigger r1 before delete on t1 for each row begin 162 insert into t2 values (NULL, changes(), NULL); 163 insert into t0 values (5); 164 update t2 set v2=changes(); 165 end; 166 delete from t1; 167 select changes(); 168 } 169} {0 1} 170 171# changes() unchanged upon entry into before delete trigger 172do_test laststmtchanges-4.2 { 173 catchsql { 174 select v1 from t2; 175 } 176} {0 0} 177 178# changes() changed properly by insert within context of before delete trigger 179do_test laststmtchanges-4.3 { 180 catchsql { 181 select v2 from t2; 182 } 183} {0 1} 184 185# ---------------------------------------------------------------------------- 186# 5.x - complex tests with temporary tables and nested instead of triggers 187 188do_test laststmtchanges-5.1 { 189 catchsql { 190 drop table t0; drop table t1; drop table t2; 191 create temp table t0(x); 192 create temp table t1 (k integer primary key); 193 create temp table t2 (k integer primary key); 194 create temp view v1 as select * from t1; 195 create temp view v2 as select * from t2; 196 create temp table n1 (k integer primary key, n); 197 create temp table n2 (k integer primary key, n); 198 insert into t0 values (1); 199 insert into t0 values (2); 200 insert into t0 values (1); 201 insert into t0 values (1); 202 insert into t0 values (1); 203 insert into t0 values (2); 204 insert into t0 values (2); 205 insert into t0 values (1); 206 create temp trigger r1 instead of insert on v1 for each row begin 207 insert into n1 values (NULL, changes()); 208 update t0 set x=x*10 where x=1; 209 insert into n1 values (NULL, changes()); 210 insert into t1 values (NEW.k); 211 insert into n1 values (NULL, changes()); 212 update t0 set x=x*10 where x=0; 213 insert into v2 values (100+NEW.k); 214 insert into n1 values (NULL, changes()); 215 end; 216 create temp trigger r2 instead of insert on v2 for each row begin 217 insert into n2 values (NULL, changes()); 218 insert into t2 values (1000+NEW.k); 219 insert into n2 values (NULL, changes()); 220 update t0 set x=x*100 where x=0; 221 insert into n2 values (NULL, changes()); 222 delete from t0 where x=2; 223 insert into n2 values (NULL, changes()); 224 end; 225 insert into t1 values (77); 226 select changes(); 227 } 228} {0 1} 229 230do_test laststmtchanges-5.2 { 231 catchsql { 232 delete from t1 where k=88; 233 select changes(); 234 } 235} {0 0} 236 237do_test laststmtchanges-5.3 { 238 catchsql { 239 insert into v1 values (5); 240 select changes(); 241 } 242} {0 0} 243 244do_test laststmtchanges-5.4 { 245 catchsql { 246 select n from n1; 247 } 248} {0 {0 5 1 0}} 249 250do_test laststmtchanges-5.5 { 251 catchsql { 252 select n from n2; 253 } 254} {0 {0 1 0 3}} 255 256finish_test 257 258