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 value returned by last_insert_rowid() (LIRID) 11# is updated properly, especially inside triggers 12# 13# Note 1: insert into table is now the only statement which changes LIRID 14# Note 2: upon entry into before or instead of triggers, 15# LIRID is unchanged (rather than -1) 16# Note 3: LIRID is changed within the context of a trigger, 17# but is restored once the trigger exits 18# Note 4: LIRID is not changed by an insert into a view (since everything 19# is done within instead of trigger context) 20# 21 22set testdir [file dirname $argv0] 23source $testdir/tester.tcl 24 25# ---------------------------------------------------------------------------- 26# 1.x - basic tests (no triggers) 27 28# LIRID changed properly after an insert into a table 29do_test lastinsert-1.1 { 30 catchsql { 31 create table t1 (k integer primary key); 32 insert into t1 values (1); 33 insert into t1 values (NULL); 34 insert into t1 values (NULL); 35 select last_insert_rowid(); 36 } 37} {0 3} 38 39# LIRID unchanged after an update on a table 40do_test lastinsert-1.2 { 41 catchsql { 42 update t1 set k=4 where k=2; 43 select last_insert_rowid(); 44 } 45} {0 3} 46 47# LIRID unchanged after a delete from a table 48do_test lastinsert-1.3 { 49 catchsql { 50 delete from t1 where k=4; 51 select last_insert_rowid(); 52 } 53} {0 3} 54 55# LIRID unchanged after create table/view statements 56do_test lastinsert-1.4.1 { 57 catchsql { 58 create table t2 (k integer primary key, val1, val2, val3); 59 select last_insert_rowid(); 60 } 61} {0 3} 62ifcapable view { 63do_test lastinsert-1.4.2 { 64 catchsql { 65 create view v as select * from t1; 66 select last_insert_rowid(); 67 } 68} {0 3} 69} ;# ifcapable view 70 71# All remaining tests involve triggers. Skip them if triggers are not 72# supported in this build. 73# 74ifcapable {!trigger} { 75 finish_test 76 return 77} 78 79# ---------------------------------------------------------------------------- 80# 2.x - tests with after insert trigger 81 82# LIRID changed properly after an insert into table containing an after trigger 83do_test lastinsert-2.1 { 84 catchsql { 85 delete from t2; 86 create trigger r1 after insert on t1 for each row begin 87 insert into t2 values (NEW.k*2, last_insert_rowid(), NULL, NULL); 88 update t2 set k=k+10, val2=100+last_insert_rowid(); 89 update t2 set val3=1000+last_insert_rowid(); 90 end; 91 insert into t1 values (13); 92 select last_insert_rowid(); 93 } 94} {0 13} 95 96# LIRID equals NEW.k upon entry into after insert trigger 97do_test lastinsert-2.2 { 98 catchsql { 99 select val1 from t2; 100 } 101} {0 13} 102 103# LIRID changed properly by insert within context of after insert trigger 104do_test lastinsert-2.3 { 105 catchsql { 106 select val2 from t2; 107 } 108} {0 126} 109 110# LIRID unchanged by update within context of after insert trigger 111do_test lastinsert-2.4 { 112 catchsql { 113 select val3 from t2; 114 } 115} {0 1026} 116 117# ---------------------------------------------------------------------------- 118# 3.x - tests with after update trigger 119 120# LIRID not changed after an update onto a table containing an after trigger 121do_test lastinsert-3.1 { 122 catchsql { 123 delete from t2; 124 drop trigger r1; 125 create trigger r1 after update on t1 for each row begin 126 insert into t2 values (NEW.k*2, last_insert_rowid(), NULL, NULL); 127 update t2 set k=k+10, val2=100+last_insert_rowid(); 128 update t2 set val3=1000+last_insert_rowid(); 129 end; 130 update t1 set k=14 where k=3; 131 select last_insert_rowid(); 132 } 133} {0 13} 134 135# LIRID unchanged upon entry into after update trigger 136do_test lastinsert-3.2 { 137 catchsql { 138 select val1 from t2; 139 } 140} {0 13} 141 142# LIRID changed properly by insert within context of after update trigger 143do_test lastinsert-3.3 { 144 catchsql { 145 select val2 from t2; 146 } 147} {0 128} 148 149# LIRID unchanged by update within context of after update trigger 150do_test lastinsert-3.4 { 151 catchsql { 152 select val3 from t2; 153 } 154} {0 1028} 155 156# ---------------------------------------------------------------------------- 157# 4.x - tests with instead of insert trigger 158# These may not be run if either views or triggers were disabled at 159# compile-time 160 161ifcapable {view && trigger} { 162# LIRID not changed after an insert into view containing an instead of trigger 163do_test lastinsert-4.1 { 164 catchsql { 165 delete from t2; 166 drop trigger r1; 167 create trigger r1 instead of insert on v for each row begin 168 insert into t2 values (NEW.k*2, last_insert_rowid(), NULL, NULL); 169 update t2 set k=k+10, val2=100+last_insert_rowid(); 170 update t2 set val3=1000+last_insert_rowid(); 171 end; 172 insert into v values (15); 173 select last_insert_rowid(); 174 } 175} {0 13} 176 177# LIRID unchanged upon entry into instead of trigger 178do_test lastinsert-4.2 { 179 catchsql { 180 select val1 from t2; 181 } 182} {0 13} 183 184# LIRID changed properly by insert within context of instead of trigger 185do_test lastinsert-4.3 { 186 catchsql { 187 select val2 from t2; 188 } 189} {0 130} 190 191# LIRID unchanged by update within context of instead of trigger 192do_test lastinsert-4.4 { 193 catchsql { 194 select val3 from t2; 195 } 196} {0 1030} 197} ;# ifcapable (view && trigger) 198 199# ---------------------------------------------------------------------------- 200# 5.x - tests with before delete trigger 201 202# LIRID not changed after a delete on a table containing a before trigger 203do_test lastinsert-5.1 { 204 catchsql { 205 drop trigger r1; -- This was not created if views are disabled. 206 } 207 catchsql { 208 delete from t2; 209 create trigger r1 before delete on t1 for each row begin 210 insert into t2 values (77, last_insert_rowid(), NULL, NULL); 211 update t2 set k=k+10, val2=100+last_insert_rowid(); 212 update t2 set val3=1000+last_insert_rowid(); 213 end; 214 delete from t1 where k=1; 215 select last_insert_rowid(); 216 } 217} {0 13} 218 219# LIRID unchanged upon entry into delete trigger 220do_test lastinsert-5.2 { 221 catchsql { 222 select val1 from t2; 223 } 224} {0 13} 225 226# LIRID changed properly by insert within context of delete trigger 227do_test lastinsert-5.3 { 228 catchsql { 229 select val2 from t2; 230 } 231} {0 177} 232 233# LIRID unchanged by update within context of delete trigger 234do_test lastinsert-5.4 { 235 catchsql { 236 select val3 from t2; 237 } 238} {0 1077} 239 240# ---------------------------------------------------------------------------- 241# 6.x - tests with instead of update trigger 242# These tests may not run if either views or triggers are disabled. 243 244ifcapable {view && trigger} { 245# LIRID not changed after an update on a view containing an instead of trigger 246do_test lastinsert-6.1 { 247 catchsql { 248 delete from t2; 249 drop trigger r1; 250 create trigger r1 instead of update on v for each row begin 251 insert into t2 values (NEW.k*2, last_insert_rowid(), NULL, NULL); 252 update t2 set k=k+10, val2=100+last_insert_rowid(); 253 update t2 set val3=1000+last_insert_rowid(); 254 end; 255 update v set k=16 where k=14; 256 select last_insert_rowid(); 257 } 258} {0 13} 259 260# LIRID unchanged upon entry into instead of trigger 261do_test lastinsert-6.2 { 262 catchsql { 263 select val1 from t2; 264 } 265} {0 13} 266 267# LIRID changed properly by insert within context of instead of trigger 268do_test lastinsert-6.3 { 269 catchsql { 270 select val2 from t2; 271 } 272} {0 132} 273 274# LIRID unchanged by update within context of instead of trigger 275do_test lastinsert-6.4 { 276 catchsql { 277 select val3 from t2; 278 } 279} {0 1032} 280} ;# ifcapable (view && trigger) 281 282# ---------------------------------------------------------------------------- 283# 7.x - complex tests with temporary tables and nested instead of triggers 284# These do not run if views or triggers are disabled. 285 286ifcapable {trigger && view && tempdb} { 287do_test lastinsert-7.1 { 288 catchsql { 289 drop table t1; drop table t2; drop trigger r1; 290 create temp table t1 (k integer primary key); 291 create temp table t2 (k integer primary key); 292 create temp view v1 as select * from t1; 293 create temp view v2 as select * from t2; 294 create temp table rid (k integer primary key, rin, rout); 295 insert into rid values (1, NULL, NULL); 296 insert into rid values (2, NULL, NULL); 297 create temp trigger r1 instead of insert on v1 for each row begin 298 update rid set rin=last_insert_rowid() where k=1; 299 insert into t1 values (100+NEW.k); 300 insert into v2 values (100+last_insert_rowid()); 301 update rid set rout=last_insert_rowid() where k=1; 302 end; 303 create temp trigger r2 instead of insert on v2 for each row begin 304 update rid set rin=last_insert_rowid() where k=2; 305 insert into t2 values (1000+NEW.k); 306 update rid set rout=last_insert_rowid() where k=2; 307 end; 308 insert into t1 values (77); 309 select last_insert_rowid(); 310 } 311} {0 77} 312 313do_test lastinsert-7.2 { 314 catchsql { 315 insert into v1 values (5); 316 select last_insert_rowid(); 317 } 318} {0 77} 319 320do_test lastinsert-7.3 { 321 catchsql { 322 select rin from rid where k=1; 323 } 324} {0 77} 325 326do_test lastinsert-7.4 { 327 catchsql { 328 select rout from rid where k=1; 329 } 330} {0 105} 331 332do_test lastinsert-7.5 { 333 catchsql { 334 select rin from rid where k=2; 335 } 336} {0 105} 337 338do_test lastinsert-7.6 { 339 catchsql { 340 select rout from rid where k=2; 341 } 342} {0 1205} 343 344do_test lastinsert-8.1 { 345 db close 346 sqlite3 db test.db 347 execsql { 348 CREATE TABLE t2(x INTEGER PRIMARY KEY, y); 349 CREATE TABLE t3(a, b); 350 CREATE TRIGGER after_t2 AFTER INSERT ON t2 BEGIN 351 INSERT INTO t3 VALUES(new.x, new.y); 352 END; 353 INSERT INTO t2 VALUES(5000000000, 1); 354 SELECT last_insert_rowid(); 355 } 356} 5000000000 357 358do_test lastinsert-9.1 { 359 db eval {INSERT INTO t2 VALUES(123456789012345,0)} 360 db last_insert_rowid 361} {123456789012345} 362 363 364} ;# ifcapable (view && trigger) 365 366finish_test 367