1436355a0Sdan# 2009 August 24 2436355a0Sdan# 3436355a0Sdan# The author disclaims copyright to this source code. In place of 4436355a0Sdan# a legal notice', here is a blessing: 5436355a0Sdan# 6436355a0Sdan# May you do good and not evil. 7436355a0Sdan# May you find forgiveness for yourself and forgive others. 8436355a0Sdan# May you share freely, never taking more than you give. 9436355a0Sdan# 10436355a0Sdan#*********************************************************************** 11436355a0Sdan# 12436355a0Sdan 13436355a0Sdanset testdir [file dirname $argv0] 14436355a0Sdansource $testdir/tester.tcl 1546408354Sdanset testprefix triggerC 16436355a0Sdanifcapable {!trigger} { 17436355a0Sdan finish_test 18436355a0Sdan return 19436355a0Sdan} 20436355a0Sdan 212283d46cSdan#------------------------------------------------------------------------- 222283d46cSdan# Test organization: 232283d46cSdan# 242283d46cSdan# triggerC-1.*: Haphazardly designed trigger related tests that were useful 252283d46cSdan# during an upgrade of the triggers sub-system. 262283d46cSdan# 272283d46cSdan# triggerC-2.*: 282283d46cSdan# 292283d46cSdan# triggerC-3.*: 302283d46cSdan# 312283d46cSdan# triggerC-4.*: 322283d46cSdan# 332283d46cSdan# triggerC-5.*: Test that when recursive triggers are enabled DELETE 342283d46cSdan# triggers are fired when rows are deleted as part of OR 352283d46cSdan# REPLACE conflict resolution. And that they are not fired 362283d46cSdan# if recursive triggers are not enabled. 372283d46cSdan# 38e0af83acSdan# triggerC-6.*: Test that the recursive_triggers pragma returns correct 39e0af83acSdan# results when invoked without an argument. 40e0af83acSdan# 412283d46cSdan 42436355a0Sdan# Enable recursive triggers for this file. 43436355a0Sdan# 445bde73c4Sdanexecsql { PRAGMA recursive_triggers = on } 45436355a0Sdan 46436355a0Sdan#sqlite3_db_config_lookaside db 0 0 0 47436355a0Sdan 48436355a0Sdan#------------------------------------------------------------------------- 49436355a0Sdan# This block of tests, triggerC-1.*, are not aimed at any specific 50436355a0Sdan# property of the triggers sub-system. They were created to debug 51436355a0Sdan# specific problems while modifying SQLite to support recursive 52436355a0Sdan# triggers. They are left here in case they can help debug the 53436355a0Sdan# same problems again. 54436355a0Sdan# 55436355a0Sdando_test triggerC-1.1 { 56436355a0Sdan execsql { 57436355a0Sdan CREATE TABLE t1(a, b, c); 58436355a0Sdan CREATE TABLE log(t, a1, b1, c1, a2, b2, c2); 59436355a0Sdan CREATE TRIGGER trig1 BEFORE INSERT ON t1 BEGIN 60436355a0Sdan INSERT INTO log VALUES('before', NULL, NULL, NULL, new.a, new.b, new.c); 61436355a0Sdan END; 62436355a0Sdan CREATE TRIGGER trig2 AFTER INSERT ON t1 BEGIN 63436355a0Sdan INSERT INTO log VALUES('after', NULL, NULL, NULL, new.a, new.b, new.c); 64436355a0Sdan END; 65436355a0Sdan CREATE TRIGGER trig3 BEFORE UPDATE ON t1 BEGIN 66436355a0Sdan INSERT INTO log VALUES('before', old.a,old.b,old.c, new.a,new.b,new.c); 67436355a0Sdan END; 68436355a0Sdan CREATE TRIGGER trig4 AFTER UPDATE ON t1 BEGIN 69436355a0Sdan INSERT INTO log VALUES('after', old.a,old.b,old.c, new.a,new.b,new.c); 70436355a0Sdan END; 71436355a0Sdan 72436355a0Sdan CREATE TRIGGER trig5 BEFORE DELETE ON t1 BEGIN 73436355a0Sdan INSERT INTO log VALUES('before', old.a,old.b,old.c, NULL,NULL,NULL); 74436355a0Sdan END; 75436355a0Sdan CREATE TRIGGER trig6 AFTER DELETE ON t1 BEGIN 76436355a0Sdan INSERT INTO log VALUES('after', old.a,old.b,old.c, NULL,NULL,NULL); 77436355a0Sdan END; 78436355a0Sdan } 79436355a0Sdan} {} 80436355a0Sdando_test triggerC-1.2 { 81436355a0Sdan execsql { 82436355a0Sdan INSERT INTO t1 VALUES('A', 'B', 'C'); 83436355a0Sdan SELECT * FROM log; 84436355a0Sdan } 85436355a0Sdan} {before {} {} {} A B C after {} {} {} A B C} 86436355a0Sdando_test triggerC-1.3 { 87436355a0Sdan execsql { SELECT * FROM t1 } 88436355a0Sdan} {A B C} 89436355a0Sdando_test triggerC-1.4 { 90436355a0Sdan execsql { 91436355a0Sdan DELETE FROM log; 92436355a0Sdan UPDATE t1 SET a = 'a'; 93436355a0Sdan SELECT * FROM log; 94436355a0Sdan } 95436355a0Sdan} {before A B C a B C after A B C a B C} 96436355a0Sdando_test triggerC-1.5 { 97436355a0Sdan execsql { SELECT * FROM t1 } 98436355a0Sdan} {a B C} 99436355a0Sdando_test triggerC-1.6 { 100436355a0Sdan execsql { 101436355a0Sdan DELETE FROM log; 102436355a0Sdan DELETE FROM t1; 103436355a0Sdan SELECT * FROM log; 104436355a0Sdan } 105436355a0Sdan} {before a B C {} {} {} after a B C {} {} {}} 106436355a0Sdando_test triggerC-1.7 { 107436355a0Sdan execsql { SELECT * FROM t1 } 108436355a0Sdan} {} 109436355a0Sdando_test triggerC-1.8 { 110436355a0Sdan execsql { 111436355a0Sdan CREATE TABLE t4(a, b); 112436355a0Sdan CREATE TRIGGER t4t AFTER DELETE ON t4 BEGIN 113436355a0Sdan SELECT RAISE(ABORT, 'delete is not supported'); 114436355a0Sdan END; 115436355a0Sdan } 116436355a0Sdan} {} 117436355a0Sdando_test triggerC-1.9 { 118436355a0Sdan execsql { INSERT INTO t4 VALUES(1, 2) } 119436355a0Sdan catchsql { DELETE FROM t4 } 120436355a0Sdan} {1 {delete is not supported}} 121436355a0Sdando_test triggerC-1.10 { 122436355a0Sdan execsql { SELECT * FROM t4 } 123436355a0Sdan} {1 2} 124436355a0Sdando_test triggerC-1.11 { 125436355a0Sdan execsql { 126436355a0Sdan CREATE TABLE t5 (a primary key, b, c); 127436355a0Sdan INSERT INTO t5 values (1, 2, 3); 128436355a0Sdan CREATE TRIGGER au_tbl AFTER UPDATE ON t5 BEGIN 129436355a0Sdan UPDATE OR IGNORE t5 SET a = new.a, c = 10; 130436355a0Sdan END; 131436355a0Sdan } 132436355a0Sdan} {} 133436355a0Sdando_test triggerC-1.12 { 134436355a0Sdan catchsql { UPDATE OR REPLACE t5 SET a = 4 WHERE a = 1 } 135436355a0Sdan} {1 {too many levels of trigger recursion}} 136436355a0Sdando_test triggerC-1.13 { 137436355a0Sdan execsql { 138436355a0Sdan CREATE TABLE t6(a INTEGER PRIMARY KEY, b); 139436355a0Sdan INSERT INTO t6 VALUES(1, 2); 140436355a0Sdan create trigger r1 after update on t6 for each row begin 141436355a0Sdan SELECT 1; 142436355a0Sdan end; 143436355a0Sdan UPDATE t6 SET a=a; 144436355a0Sdan } 145436355a0Sdan} {} 146436355a0Sdando_test triggerC-1.14 { 147436355a0Sdan execsql { 148436355a0Sdan DROP TABLE t1; 149436355a0Sdan CREATE TABLE cnt(n); 150436355a0Sdan INSERT INTO cnt VALUES(0); 151436355a0Sdan CREATE TABLE t1(a INTEGER PRIMARY KEY, b UNIQUE, c, d, e); 152436355a0Sdan CREATE INDEX t1cd ON t1(c,d); 153436355a0Sdan CREATE TRIGGER t1r1 AFTER UPDATE ON t1 BEGIN UPDATE cnt SET n=n+1; END; 154436355a0Sdan INSERT INTO t1 VALUES(1,2,3,4,5); 155436355a0Sdan INSERT INTO t1 VALUES(6,7,8,9,10); 156436355a0Sdan INSERT INTO t1 VALUES(11,12,13,14,15); 157436355a0Sdan } 158436355a0Sdan} {} 159436355a0Sdando_test triggerC-1.15 { 160436355a0Sdan catchsql { UPDATE OR ROLLBACK t1 SET a=100 } 161f9c8ce3cSdrh} {1 {UNIQUE constraint failed: t1.a}} 162436355a0Sdan 163436355a0Sdan 164436355a0Sdan#------------------------------------------------------------------------- 165436355a0Sdan# This block of tests, triggerC-2.*, tests that recursive trigger 166436355a0Sdan# programs (triggers that fire themselves) work. More specifically, 167436355a0Sdan# this block focuses on recursive INSERT triggers. 168436355a0Sdan# 169436355a0Sdando_test triggerC-2.1.0 { 170436355a0Sdan execsql { 171436355a0Sdan CREATE TABLE t2(a PRIMARY KEY); 172436355a0Sdan } 173436355a0Sdan} {} 174436355a0Sdan 175436355a0Sdanforeach {n tdefn rc} { 176436355a0Sdan 1 { 177436355a0Sdan CREATE TRIGGER t2_trig AFTER INSERT ON t2 WHEN (new.a>0) BEGIN 178436355a0Sdan INSERT INTO t2 VALUES(new.a - 1); 179436355a0Sdan END; 180436355a0Sdan } {0 {10 9 8 7 6 5 4 3 2 1 0}} 181436355a0Sdan 182436355a0Sdan 2 { 183436355a0Sdan CREATE TRIGGER t2_trig AFTER INSERT ON t2 BEGIN 184436355a0Sdan SELECT CASE WHEN new.a==2 THEN RAISE(IGNORE) ELSE NULL END; 185436355a0Sdan INSERT INTO t2 VALUES(new.a - 1); 186436355a0Sdan END; 187436355a0Sdan } {0 {10 9 8 7 6 5 4 3 2}} 188436355a0Sdan 189436355a0Sdan 3 { 190436355a0Sdan CREATE TRIGGER t2_trig BEFORE INSERT ON t2 WHEN (new.a>0) BEGIN 191436355a0Sdan INSERT INTO t2 VALUES(new.a - 1); 192436355a0Sdan END; 193436355a0Sdan } {0 {0 1 2 3 4 5 6 7 8 9 10}} 194436355a0Sdan 195436355a0Sdan 4 { 196436355a0Sdan CREATE TRIGGER t2_trig BEFORE INSERT ON t2 BEGIN 197436355a0Sdan SELECT CASE WHEN new.a==2 THEN RAISE(IGNORE) ELSE NULL END; 198436355a0Sdan INSERT INTO t2 VALUES(new.a - 1); 199436355a0Sdan END; 200436355a0Sdan } {0 {3 4 5 6 7 8 9 10}} 201436355a0Sdan 202436355a0Sdan 5 { 203436355a0Sdan CREATE TRIGGER t2_trig BEFORE INSERT ON t2 BEGIN 204436355a0Sdan INSERT INTO t2 VALUES(new.a - 1); 205436355a0Sdan END; 206436355a0Sdan } {1 {too many levels of trigger recursion}} 207436355a0Sdan 208436355a0Sdan 6 { 209436355a0Sdan CREATE TRIGGER t2_trig AFTER INSERT ON t2 WHEN (new.a>0) BEGIN 210436355a0Sdan INSERT OR IGNORE INTO t2 VALUES(new.a); 211436355a0Sdan END; 212436355a0Sdan } {0 10} 213436355a0Sdan 214436355a0Sdan 7 { 215436355a0Sdan CREATE TRIGGER t2_trig BEFORE INSERT ON t2 WHEN (new.a>0) BEGIN 216436355a0Sdan INSERT OR IGNORE INTO t2 VALUES(new.a); 217436355a0Sdan END; 218436355a0Sdan } {1 {too many levels of trigger recursion}} 219436355a0Sdan} { 220436355a0Sdan do_test triggerC-2.1.$n { 221436355a0Sdan catchsql { DROP TRIGGER t2_trig } 222436355a0Sdan execsql { DELETE FROM t2 } 223436355a0Sdan execsql $tdefn 224436355a0Sdan catchsql { 225436355a0Sdan INSERT INTO t2 VALUES(10); 2263f4d1d1bSdrh SELECT * FROM t2 ORDER BY rowid; 227436355a0Sdan } 228436355a0Sdan } $rc 229436355a0Sdan} 230436355a0Sdan 231436355a0Sdando_test triggerC-2.2 { 232f9032cbcSshaneh execsql " 233436355a0Sdan CREATE TABLE t22(x); 234436355a0Sdan 235436355a0Sdan CREATE TRIGGER t22a AFTER INSERT ON t22 BEGIN 236436355a0Sdan INSERT INTO t22 SELECT x + (SELECT max(x) FROM t22) FROM t22; 237436355a0Sdan END; 238436355a0Sdan CREATE TRIGGER t22b BEFORE INSERT ON t22 BEGIN 239f9032cbcSshaneh SELECT CASE WHEN (SELECT count(*) FROM t22) >= [expr $SQLITE_MAX_TRIGGER_DEPTH / 2] 240436355a0Sdan THEN RAISE(IGNORE) 241436355a0Sdan ELSE NULL END; 242436355a0Sdan END; 243436355a0Sdan 244436355a0Sdan INSERT INTO t22 VALUES(1); 245436355a0Sdan SELECT count(*) FROM t22; 246f9032cbcSshaneh " 247f9032cbcSshaneh} [list [expr $SQLITE_MAX_TRIGGER_DEPTH / 2]] 248436355a0Sdan 249436355a0Sdando_test triggerC-2.3 { 25035913a49Sshaneh execsql " 251436355a0Sdan CREATE TABLE t23(x PRIMARY KEY); 252436355a0Sdan 253436355a0Sdan CREATE TRIGGER t23a AFTER INSERT ON t23 BEGIN 254436355a0Sdan INSERT INTO t23 VALUES(new.x + 1); 255436355a0Sdan END; 256436355a0Sdan 257436355a0Sdan CREATE TRIGGER t23b BEFORE INSERT ON t23 BEGIN 25835913a49Sshaneh SELECT CASE WHEN new.x>[expr $SQLITE_MAX_TRIGGER_DEPTH / 2] 259436355a0Sdan THEN RAISE(IGNORE) 260436355a0Sdan ELSE NULL END; 261436355a0Sdan END; 262436355a0Sdan 263436355a0Sdan INSERT INTO t23 VALUES(1); 264436355a0Sdan SELECT count(*) FROM t23; 26535913a49Sshaneh " 26635913a49Sshaneh} [list [expr $SQLITE_MAX_TRIGGER_DEPTH / 2]] 267436355a0Sdan 268436355a0Sdan 269436355a0Sdan#----------------------------------------------------------------------- 270436355a0Sdan# This block of tests, triggerC-3.*, test that SQLite throws an exception 271436355a0Sdan# when it detects excessive recursion. 272436355a0Sdan# 273436355a0Sdando_test triggerC-3.1.1 { 274436355a0Sdan execsql { 275436355a0Sdan CREATE TABLE t3(a, b); 276436355a0Sdan CREATE TRIGGER t3i AFTER INSERT ON t3 BEGIN 277436355a0Sdan DELETE FROM t3 WHERE rowid = new.rowid; 278436355a0Sdan END; 279436355a0Sdan CREATE TRIGGER t3d AFTER DELETE ON t3 BEGIN 280436355a0Sdan INSERT INTO t3 VALUES(old.a, old.b); 281436355a0Sdan END; 282436355a0Sdan } 283436355a0Sdan} {} 284436355a0Sdando_test triggerC-3.1.2 { 285436355a0Sdan catchsql { INSERT INTO t3 VALUES(0,0) } 286436355a0Sdan} {1 {too many levels of trigger recursion}} 287436355a0Sdando_test triggerC-3.1.3 { 288436355a0Sdan execsql { SELECT * FROM t3 } 289436355a0Sdan} {} 290436355a0Sdan 291417168adSdrhdo_test triggerC-3.2.1 { 29235913a49Sshaneh execsql " 293417168adSdrh CREATE TABLE t3b(x); 29435913a49Sshaneh CREATE TRIGGER t3bi AFTER INSERT ON t3b WHEN new.x<[expr $SQLITE_MAX_TRIGGER_DEPTH * 2] BEGIN 295417168adSdrh INSERT INTO t3b VALUES(new.x+1); 296417168adSdrh END; 29735913a49Sshaneh " 298417168adSdrh catchsql { 299417168adSdrh INSERT INTO t3b VALUES(1); 300417168adSdrh } 301417168adSdrh} {1 {too many levels of trigger recursion}} 302417168adSdrhdo_test triggerC-3.2.2 { 303417168adSdrh db eval {SELECT * FROM t3b} 304417168adSdrh} {} 305417168adSdrh 306417168adSdrhdo_test triggerC-3.3.1 { 30735913a49Sshaneh catchsql " 30835913a49Sshaneh INSERT INTO t3b VALUES([expr $SQLITE_MAX_TRIGGER_DEPTH + 1]); 30935913a49Sshaneh " 310417168adSdrh} {0 {}} 311417168adSdrhdo_test triggerC-3.3.2 { 312417168adSdrh db eval {SELECT count(*), max(x), min(x) FROM t3b} 31335913a49Sshaneh} [list $SQLITE_MAX_TRIGGER_DEPTH [expr $SQLITE_MAX_TRIGGER_DEPTH * 2] [expr $SQLITE_MAX_TRIGGER_DEPTH + 1]] 314417168adSdrh 315417168adSdrhdo_test triggerC-3.4.1 { 31635913a49Sshaneh catchsql " 317417168adSdrh DELETE FROM t3b; 31835913a49Sshaneh INSERT INTO t3b VALUES([expr $SQLITE_MAX_TRIGGER_DEPTH - 1]); 31935913a49Sshaneh " 320417168adSdrh} {1 {too many levels of trigger recursion}} 321417168adSdrhdo_test triggerC-3.4.2 { 322417168adSdrh db eval {SELECT count(*), max(x), min(x) FROM t3b} 323417168adSdrh} {0 {} {}} 324417168adSdrh 325417168adSdrhdo_test triggerC-3.5.1 { 32635913a49Sshaneh sqlite3_limit db SQLITE_LIMIT_TRIGGER_DEPTH [expr $SQLITE_MAX_TRIGGER_DEPTH / 10] 32735913a49Sshaneh catchsql " 32835913a49Sshaneh INSERT INTO t3b VALUES([expr ($SQLITE_MAX_TRIGGER_DEPTH * 2) - ($SQLITE_MAX_TRIGGER_DEPTH / 10) + 1]); 32935913a49Sshaneh " 330417168adSdrh} {0 {}} 331417168adSdrhdo_test triggerC-3.5.2 { 332417168adSdrh db eval {SELECT count(*), max(x), min(x) FROM t3b} 33335913a49Sshaneh} [list [expr $SQLITE_MAX_TRIGGER_DEPTH / 10] [expr $SQLITE_MAX_TRIGGER_DEPTH * 2] [expr ($SQLITE_MAX_TRIGGER_DEPTH * 2) - ($SQLITE_MAX_TRIGGER_DEPTH / 10) + 1]] 334417168adSdrh 335417168adSdrhdo_test triggerC-3.5.3 { 33635913a49Sshaneh catchsql " 337417168adSdrh DELETE FROM t3b; 33835913a49Sshaneh INSERT INTO t3b VALUES([expr ($SQLITE_MAX_TRIGGER_DEPTH * 2) - ($SQLITE_MAX_TRIGGER_DEPTH / 10)]); 33935913a49Sshaneh " 340417168adSdrh} {1 {too many levels of trigger recursion}} 341417168adSdrhdo_test triggerC-3.5.4 { 342417168adSdrh db eval {SELECT count(*), max(x), min(x) FROM t3b} 343417168adSdrh} {0 {} {}} 344417168adSdrh 345417168adSdrhdo_test triggerC-3.6.1 { 346417168adSdrh sqlite3_limit db SQLITE_LIMIT_TRIGGER_DEPTH 1 34735913a49Sshaneh catchsql " 34835913a49Sshaneh INSERT INTO t3b VALUES([expr $SQLITE_MAX_TRIGGER_DEPTH * 2]); 34935913a49Sshaneh " 350417168adSdrh} {0 {}} 351417168adSdrhdo_test triggerC-3.6.2 { 352417168adSdrh db eval {SELECT count(*), max(x), min(x) FROM t3b} 35335913a49Sshaneh} [list 1 [expr $SQLITE_MAX_TRIGGER_DEPTH * 2] [expr $SQLITE_MAX_TRIGGER_DEPTH * 2]] 354417168adSdrh 355417168adSdrhdo_test triggerC-3.6.3 { 35635913a49Sshaneh catchsql " 357417168adSdrh DELETE FROM t3b; 35835913a49Sshaneh INSERT INTO t3b VALUES([expr ($SQLITE_MAX_TRIGGER_DEPTH * 2) - 1]); 35935913a49Sshaneh " 360417168adSdrh} {1 {too many levels of trigger recursion}} 361417168adSdrhdo_test triggerC-3.6.4 { 362417168adSdrh db eval {SELECT count(*), max(x), min(x) FROM t3b} 363417168adSdrh} {0 {} {}} 36435913a49Sshanehsqlite3_limit db SQLITE_LIMIT_TRIGGER_DEPTH $SQLITE_MAX_TRIGGER_DEPTH 365417168adSdrh 366417168adSdrh 367436355a0Sdan#----------------------------------------------------------------------- 368436355a0Sdan# This next block of tests, triggerC-4.*, checks that affinity 369436355a0Sdan# transformations and constraint processing is performed at the correct 370436355a0Sdan# times relative to BEFORE and AFTER triggers. 371436355a0Sdan# 372436355a0Sdan# For an INSERT statement, for each row to be inserted: 373436355a0Sdan# 374436355a0Sdan# 1. Apply affinities to non-rowid values to be inserted. 375436355a0Sdan# 2. Fire BEFORE triggers. 376436355a0Sdan# 3. Process constraints. 377436355a0Sdan# 4. Insert new record. 378436355a0Sdan# 5. Fire AFTER triggers. 379436355a0Sdan# 380436355a0Sdan# If the value of the rowid field is to be automatically assigned, it is 381436355a0Sdan# set to -1 in the new.* record. Even if it is explicitly set to NULL 382436355a0Sdan# by the INSERT statement. 383436355a0Sdan# 384436355a0Sdan# For an UPDATE statement, for each row to be deleted: 385436355a0Sdan# 386436355a0Sdan# 1. Apply affinities to non-rowid values to be inserted. 387436355a0Sdan# 2. Fire BEFORE triggers. 388436355a0Sdan# 3. Process constraints. 389436355a0Sdan# 4. Insert new record. 390436355a0Sdan# 5. Fire AFTER triggers. 391436355a0Sdan# 392436355a0Sdan# For a DELETE statement, for each row to be deleted: 393436355a0Sdan# 394436355a0Sdan# 1. Fire BEFORE triggers. 395436355a0Sdan# 2. Remove database record. 396436355a0Sdan# 3. Fire AFTER triggers. 397436355a0Sdan# 398436355a0Sdan# When a numeric value that as an exact integer representation is stored 399436355a0Sdan# in a column with REAL affinity, it is actually stored as an integer. 400436355a0Sdan# These tests check that the typeof() such values is always 'real', 401436355a0Sdan# not 'integer'. 402436355a0Sdan# 403436355a0Sdan# triggerC-4.1.*: Check that affinity transformations are made before 404436355a0Sdan# triggers are invoked. 405436355a0Sdan# 406436355a0Sdando_test triggerC-4.1.1 { 407436355a0Sdan catchsql { DROP TABLE log } 408436355a0Sdan catchsql { DROP TABLE t4 } 409436355a0Sdan execsql { 410436355a0Sdan CREATE TABLE log(t); 411436355a0Sdan CREATE TABLE t4(a TEXT,b INTEGER,c REAL); 412436355a0Sdan CREATE TRIGGER t4bi BEFORE INSERT ON t4 BEGIN 413436355a0Sdan INSERT INTO log VALUES(new.rowid || ' ' || typeof(new.rowid) || ' ' || 414436355a0Sdan new.a || ' ' || typeof(new.a) || ' ' || 415436355a0Sdan new.b || ' ' || typeof(new.b) || ' ' || 416436355a0Sdan new.c || ' ' || typeof(new.c) 417436355a0Sdan ); 418436355a0Sdan END; 419436355a0Sdan CREATE TRIGGER t4ai AFTER INSERT ON t4 BEGIN 420436355a0Sdan INSERT INTO log VALUES(new.rowid || ' ' || typeof(new.rowid) || ' ' || 421436355a0Sdan new.a || ' ' || typeof(new.a) || ' ' || 422436355a0Sdan new.b || ' ' || typeof(new.b) || ' ' || 423436355a0Sdan new.c || ' ' || typeof(new.c) 424436355a0Sdan ); 425436355a0Sdan END; 426436355a0Sdan CREATE TRIGGER t4bd BEFORE DELETE ON t4 BEGIN 427436355a0Sdan INSERT INTO log VALUES(old.rowid || ' ' || typeof(old.rowid) || ' ' || 428436355a0Sdan old.a || ' ' || typeof(old.a) || ' ' || 429436355a0Sdan old.b || ' ' || typeof(old.b) || ' ' || 430436355a0Sdan old.c || ' ' || typeof(old.c) 431436355a0Sdan ); 432436355a0Sdan END; 433436355a0Sdan CREATE TRIGGER t4ad AFTER DELETE ON t4 BEGIN 434436355a0Sdan INSERT INTO log VALUES(old.rowid || ' ' || typeof(old.rowid) || ' ' || 435436355a0Sdan old.a || ' ' || typeof(old.a) || ' ' || 436436355a0Sdan old.b || ' ' || typeof(old.b) || ' ' || 437436355a0Sdan old.c || ' ' || typeof(old.c) 438436355a0Sdan ); 439436355a0Sdan END; 440436355a0Sdan CREATE TRIGGER t4bu BEFORE UPDATE ON t4 BEGIN 441436355a0Sdan INSERT INTO log VALUES(old.rowid || ' ' || typeof(old.rowid) || ' ' || 442436355a0Sdan old.a || ' ' || typeof(old.a) || ' ' || 443436355a0Sdan old.b || ' ' || typeof(old.b) || ' ' || 444436355a0Sdan old.c || ' ' || typeof(old.c) 445436355a0Sdan ); 446436355a0Sdan INSERT INTO log VALUES(new.rowid || ' ' || typeof(new.rowid) || ' ' || 447436355a0Sdan new.a || ' ' || typeof(new.a) || ' ' || 448436355a0Sdan new.b || ' ' || typeof(new.b) || ' ' || 449436355a0Sdan new.c || ' ' || typeof(new.c) 450436355a0Sdan ); 451436355a0Sdan END; 452436355a0Sdan CREATE TRIGGER t4au AFTER UPDATE ON t4 BEGIN 453436355a0Sdan INSERT INTO log VALUES(old.rowid || ' ' || typeof(old.rowid) || ' ' || 454436355a0Sdan old.a || ' ' || typeof(old.a) || ' ' || 455436355a0Sdan old.b || ' ' || typeof(old.b) || ' ' || 456436355a0Sdan old.c || ' ' || typeof(old.c) 457436355a0Sdan ); 458436355a0Sdan INSERT INTO log VALUES(new.rowid || ' ' || typeof(new.rowid) || ' ' || 459436355a0Sdan new.a || ' ' || typeof(new.a) || ' ' || 460436355a0Sdan new.b || ' ' || typeof(new.b) || ' ' || 461436355a0Sdan new.c || ' ' || typeof(new.c) 462436355a0Sdan ); 463436355a0Sdan END; 464436355a0Sdan } 465436355a0Sdan} {} 466436355a0Sdanforeach {n insert log} { 467436355a0Sdan 468436355a0Sdan 2 { 469436355a0Sdan INSERT INTO t4 VALUES('1', '1', '1'); 470436355a0Sdan DELETE FROM t4; 471436355a0Sdan } { 472436355a0Sdan -1 integer 1 text 1 integer 1.0 real 473436355a0Sdan 1 integer 1 text 1 integer 1.0 real 474436355a0Sdan 1 integer 1 text 1 integer 1.0 real 475436355a0Sdan 1 integer 1 text 1 integer 1.0 real 476436355a0Sdan } 477436355a0Sdan 478436355a0Sdan 3 { 479436355a0Sdan INSERT INTO t4(rowid,a,b,c) VALUES(45, 45, 45, 45); 480436355a0Sdan DELETE FROM t4; 481436355a0Sdan } { 482436355a0Sdan 45 integer 45 text 45 integer 45.0 real 483436355a0Sdan 45 integer 45 text 45 integer 45.0 real 484436355a0Sdan 45 integer 45 text 45 integer 45.0 real 485436355a0Sdan 45 integer 45 text 45 integer 45.0 real 486436355a0Sdan } 487436355a0Sdan 488436355a0Sdan 4 { 489436355a0Sdan INSERT INTO t4(rowid,a,b,c) VALUES(-42.0, -42.0, -42.0, -42.0); 490436355a0Sdan DELETE FROM t4; 491436355a0Sdan } { 492436355a0Sdan -42 integer -42.0 text -42 integer -42.0 real 493436355a0Sdan -42 integer -42.0 text -42 integer -42.0 real 494436355a0Sdan -42 integer -42.0 text -42 integer -42.0 real 495436355a0Sdan -42 integer -42.0 text -42 integer -42.0 real 496436355a0Sdan } 497436355a0Sdan 498436355a0Sdan 5 { 499436355a0Sdan INSERT INTO t4(rowid,a,b,c) VALUES(NULL, -42.4, -42.4, -42.4); 500436355a0Sdan DELETE FROM t4; 501436355a0Sdan } { 502436355a0Sdan -1 integer -42.4 text -42.4 real -42.4 real 503436355a0Sdan 1 integer -42.4 text -42.4 real -42.4 real 504436355a0Sdan 1 integer -42.4 text -42.4 real -42.4 real 505436355a0Sdan 1 integer -42.4 text -42.4 real -42.4 real 506436355a0Sdan } 507436355a0Sdan 508436355a0Sdan 6 { 509436355a0Sdan INSERT INTO t4 VALUES(7, 7, 7); 510436355a0Sdan UPDATE t4 SET a=8, b=8, c=8; 511436355a0Sdan } { 512436355a0Sdan -1 integer 7 text 7 integer 7.0 real 513436355a0Sdan 1 integer 7 text 7 integer 7.0 real 514436355a0Sdan 1 integer 7 text 7 integer 7.0 real 515436355a0Sdan 1 integer 8 text 8 integer 8.0 real 516436355a0Sdan 1 integer 7 text 7 integer 7.0 real 517436355a0Sdan 1 integer 8 text 8 integer 8.0 real 518436355a0Sdan } 519436355a0Sdan 520436355a0Sdan 7 { 521436355a0Sdan UPDATE t4 SET rowid=2; 522436355a0Sdan } { 523436355a0Sdan 1 integer 8 text 8 integer 8.0 real 524436355a0Sdan 2 integer 8 text 8 integer 8.0 real 525436355a0Sdan 1 integer 8 text 8 integer 8.0 real 526436355a0Sdan 2 integer 8 text 8 integer 8.0 real 527436355a0Sdan } 528436355a0Sdan 529436355a0Sdan 8 { 530436355a0Sdan UPDATE t4 SET a='9', b='9', c='9'; 531436355a0Sdan } { 532436355a0Sdan 2 integer 8 text 8 integer 8.0 real 533436355a0Sdan 2 integer 9 text 9 integer 9.0 real 534436355a0Sdan 2 integer 8 text 8 integer 8.0 real 535436355a0Sdan 2 integer 9 text 9 integer 9.0 real 536436355a0Sdan } 537436355a0Sdan 538436355a0Sdan 9 { 539436355a0Sdan UPDATE t4 SET a='9.1', b='9.1', c='9.1'; 540436355a0Sdan } { 541436355a0Sdan 2 integer 9 text 9 integer 9.0 real 542436355a0Sdan 2 integer 9.1 text 9.1 real 9.1 real 543436355a0Sdan 2 integer 9 text 9 integer 9.0 real 544436355a0Sdan 2 integer 9.1 text 9.1 real 9.1 real 545436355a0Sdan } 546436355a0Sdan} { 547436355a0Sdan do_test triggerC-4.1.$n { 548436355a0Sdan eval concat [execsql " 549436355a0Sdan DELETE FROM log; 550436355a0Sdan $insert ; 5513f4d1d1bSdrh SELECT * FROM log ORDER BY rowid; 552436355a0Sdan "] 553436355a0Sdan } [join $log " "] 554436355a0Sdan} 555436355a0Sdan 5562283d46cSdan#------------------------------------------------------------------------- 5572283d46cSdan# This block of tests, triggerC-5.*, test that DELETE triggers are fired 5582283d46cSdan# if a row is deleted as a result of OR REPLACE conflict resolution. 5592283d46cSdan# 5602283d46cSdando_test triggerC-5.1.0 { 5612283d46cSdan execsql { 5622283d46cSdan DROP TABLE IF EXISTS t5; 5632283d46cSdan CREATE TABLE t5(a INTEGER PRIMARY KEY, b); 5642283d46cSdan CREATE UNIQUE INDEX t5i ON t5(b); 5652283d46cSdan INSERT INTO t5 VALUES(1, 'a'); 5662283d46cSdan INSERT INTO t5 VALUES(2, 'b'); 5672283d46cSdan INSERT INTO t5 VALUES(3, 'c'); 5682283d46cSdan 5692283d46cSdan CREATE TABLE t5g(a, b, c); 5702283d46cSdan CREATE TRIGGER t5t BEFORE DELETE ON t5 BEGIN 5712283d46cSdan INSERT INTO t5g VALUES(old.a, old.b, (SELECT count(*) FROM t5)); 5722283d46cSdan END; 5732283d46cSdan } 5742283d46cSdan} {} 5752283d46cSdanforeach {n dml t5g t5} { 5762283d46cSdan 1 "DELETE FROM t5 WHERE a=2" {2 b 3} {1 a 3 c} 5772283d46cSdan 2 "INSERT OR REPLACE INTO t5 VALUES(2, 'd')" {2 b 3} {1 a 2 d 3 c} 5782283d46cSdan 3 "UPDATE OR REPLACE t5 SET a = 2 WHERE a = 3" {2 b 3} {1 a 2 c} 5792283d46cSdan 4 "INSERT OR REPLACE INTO t5 VALUES(4, 'b')" {2 b 3} {1 a 3 c 4 b} 5802283d46cSdan 5 "UPDATE OR REPLACE t5 SET b = 'b' WHERE b = 'c'" {2 b 3} {1 a 3 b} 5812283d46cSdan 6 "INSERT OR REPLACE INTO t5 VALUES(2, 'c')" {2 b 3 3 c 2} {1 a 2 c} 5822283d46cSdan 7 "UPDATE OR REPLACE t5 SET a=1, b='b' WHERE a = 3" {1 a 3 2 b 2} {1 b} 5832283d46cSdan} { 5842283d46cSdan do_test triggerC-5.1.$n { 5852283d46cSdan execsql " 5862283d46cSdan BEGIN; 5872283d46cSdan $dml ; 5883f4d1d1bSdrh SELECT * FROM t5g ORDER BY rowid; 5893f4d1d1bSdrh SELECT * FROM t5 ORDER BY rowid; 5902283d46cSdan ROLLBACK; 5912283d46cSdan " 5922283d46cSdan } [concat $t5g $t5] 5932283d46cSdan} 5942283d46cSdando_test triggerC-5.2.0 { 5952283d46cSdan execsql { 5962283d46cSdan DROP TRIGGER t5t; 5972283d46cSdan CREATE TRIGGER t5t AFTER DELETE ON t5 BEGIN 5982283d46cSdan INSERT INTO t5g VALUES(old.a, old.b, (SELECT count(*) FROM t5)); 5992283d46cSdan END; 6002283d46cSdan } 6012283d46cSdan} {} 6022283d46cSdanforeach {n dml t5g t5} { 6032283d46cSdan 1 "DELETE FROM t5 WHERE a=2" {2 b 2} {1 a 3 c} 6042283d46cSdan 2 "INSERT OR REPLACE INTO t5 VALUES(2, 'd')" {2 b 2} {1 a 2 d 3 c} 6052283d46cSdan 3 "UPDATE OR REPLACE t5 SET a = 2 WHERE a = 3" {2 b 2} {1 a 2 c} 6062283d46cSdan 4 "INSERT OR REPLACE INTO t5 VALUES(4, 'b')" {2 b 2} {1 a 3 c 4 b} 6072283d46cSdan 5 "UPDATE OR REPLACE t5 SET b = 'b' WHERE b = 'c'" {2 b 2} {1 a 3 b} 6082283d46cSdan 6 "INSERT OR REPLACE INTO t5 VALUES(2, 'c')" {2 b 2 3 c 1} {1 a 2 c} 6092283d46cSdan 7 "UPDATE OR REPLACE t5 SET a=1, b='b' WHERE a = 3" {1 a 2 2 b 1} {1 b} 6102283d46cSdan} { 6112283d46cSdan do_test triggerC-5.2.$n { 6122283d46cSdan execsql " 6132283d46cSdan BEGIN; 6142283d46cSdan $dml ; 6153f4d1d1bSdrh SELECT * FROM t5g ORDER BY rowid; 6163f4d1d1bSdrh SELECT * FROM t5 ORDER BY rowid; 6172283d46cSdan ROLLBACK; 6182283d46cSdan " 6192283d46cSdan } [concat $t5g $t5] 6202283d46cSdan} 6212283d46cSdando_test triggerC-5.3.0 { 6222283d46cSdan execsql { PRAGMA recursive_triggers = off } 6232283d46cSdan} {} 6242283d46cSdanforeach {n dml t5g t5} { 6252283d46cSdan 1 "DELETE FROM t5 WHERE a=2" {2 b 2} {1 a 3 c} 6262283d46cSdan 2 "INSERT OR REPLACE INTO t5 VALUES(2, 'd')" {} {1 a 2 d 3 c} 6272283d46cSdan 3 "UPDATE OR REPLACE t5 SET a = 2 WHERE a = 3" {} {1 a 2 c} 6282283d46cSdan 4 "INSERT OR REPLACE INTO t5 VALUES(4, 'b')" {} {1 a 3 c 4 b} 6292283d46cSdan 5 "UPDATE OR REPLACE t5 SET b = 'b' WHERE b = 'c'" {} {1 a 3 b} 6302283d46cSdan 6 "INSERT OR REPLACE INTO t5 VALUES(2, 'c')" {} {1 a 2 c} 6312283d46cSdan 7 "UPDATE OR REPLACE t5 SET a=1, b='b' WHERE a = 3" {} {1 b} 6322283d46cSdan} { 6332283d46cSdan do_test triggerC-5.3.$n { 6342283d46cSdan execsql " 6352283d46cSdan BEGIN; 6362283d46cSdan $dml ; 6373f4d1d1bSdrh SELECT * FROM t5g ORDER BY rowid; 6383f4d1d1bSdrh SELECT * FROM t5 ORDER BY rowid; 6392283d46cSdan ROLLBACK; 6402283d46cSdan " 6412283d46cSdan } [concat $t5g $t5] 6422283d46cSdan} 6432283d46cSdando_test triggerC-5.3.8 { 6442283d46cSdan execsql { PRAGMA recursive_triggers = on } 6452283d46cSdan} {} 6462283d46cSdan 6472283d46cSdan#------------------------------------------------------------------------- 6482283d46cSdan# This block of tests, triggerC-6.*, tests that "PRAGMA recursive_triggers" 6492283d46cSdan# statements return the current value of the recursive triggers flag. 6502283d46cSdan# 6512283d46cSdando_test triggerC-6.1 { 6522283d46cSdan execsql { PRAGMA recursive_triggers } 6532283d46cSdan} {1} 6542283d46cSdando_test triggerC-6.2 { 6552283d46cSdan execsql { 6562283d46cSdan PRAGMA recursive_triggers = off; 6572283d46cSdan PRAGMA recursive_triggers; 6582283d46cSdan } 6592283d46cSdan} {0} 6602283d46cSdando_test triggerC-6.3 { 6612283d46cSdan execsql { 6622283d46cSdan PRAGMA recursive_triggers = on; 6632283d46cSdan PRAGMA recursive_triggers; 6642283d46cSdan } 6652283d46cSdan} {1} 6662283d46cSdan 667e0af83acSdan#------------------------------------------------------------------------- 668e0af83acSdan# Test some of the "undefined behaviour" associated with triggers. The 669e0af83acSdan# undefined behaviour occurs when a row being updated or deleted is 670e0af83acSdan# manipulated by a BEFORE trigger. 671e0af83acSdan# 672ae0931edSdando_test triggerC-7.1 { 673ae0931edSdan execsql { 674ae0931edSdan CREATE TABLE t8(x); 675ae0931edSdan CREATE TABLE t7(a, b); 676ae0931edSdan INSERT INTO t7 VALUES(1, 2); 677ae0931edSdan INSERT INTO t7 VALUES(3, 4); 678ae0931edSdan INSERT INTO t7 VALUES(5, 6); 679ae0931edSdan CREATE TRIGGER t7t BEFORE UPDATE ON t7 BEGIN 680ae0931edSdan DELETE FROM t7 WHERE a = 1; 681ae0931edSdan END; 682ae0931edSdan CREATE TRIGGER t7ta AFTER UPDATE ON t7 BEGIN 683ae0931edSdan INSERT INTO t8 VALUES('after fired ' || old.rowid || '->' || new.rowid); 684ae0931edSdan END; 685ae0931edSdan } 686ae0931edSdan} {} 687ae0931edSdando_test triggerC-7.2 { 688ae0931edSdan execsql { 689ae0931edSdan BEGIN; 690ae0931edSdan UPDATE t7 SET b=7 WHERE a = 5; 691ae0931edSdan SELECT * FROM t7; 692ae0931edSdan SELECT * FROM t8; 693ae0931edSdan ROLLBACK; 694ae0931edSdan } 695ae0931edSdan} {3 4 5 7 {after fired 3->3}} 696ae0931edSdando_test triggerC-7.3 { 697ae0931edSdan execsql { 698ae0931edSdan BEGIN; 699ae0931edSdan UPDATE t7 SET b=7 WHERE a = 1; 700ae0931edSdan SELECT * FROM t7; 701ae0931edSdan SELECT * FROM t8; 702ae0931edSdan ROLLBACK; 703ae0931edSdan } 704ae0931edSdan} {3 4 5 6} 705ae0931edSdan 706ae0931edSdando_test triggerC-7.4 { 707ae0931edSdan execsql { 708ae0931edSdan DROP TRIGGER t7t; 709ae0931edSdan CREATE TRIGGER t7t BEFORE UPDATE ON t7 WHEN (old.rowid!=1 OR new.rowid!=8) 710ae0931edSdan BEGIN 711ae0931edSdan UPDATE t7 set rowid = 8 WHERE rowid=1; 712ae0931edSdan END; 713ae0931edSdan } 714ae0931edSdan} {} 715ae0931edSdando_test triggerC-7.5 { 716ae0931edSdan execsql { 717ae0931edSdan BEGIN; 718ae0931edSdan UPDATE t7 SET b=7 WHERE a = 5; 719ae0931edSdan SELECT rowid, * FROM t7; 720ae0931edSdan SELECT * FROM t8; 721ae0931edSdan ROLLBACK; 722ae0931edSdan } 723ae0931edSdan} {2 3 4 3 5 7 8 1 2 {after fired 1->8} {after fired 3->3}} 724ae0931edSdando_test triggerC-7.6 { 725ae0931edSdan execsql { 726ae0931edSdan BEGIN; 727ae0931edSdan UPDATE t7 SET b=7 WHERE a = 1; 728ae0931edSdan SELECT rowid, * FROM t7; 729ae0931edSdan SELECT * FROM t8; 730ae0931edSdan ROLLBACK; 731ae0931edSdan } 732ae0931edSdan} {2 3 4 3 5 6 8 1 2 {after fired 1->8}} 733ae0931edSdan 734ae0931edSdando_test triggerC-7.7 { 735ae0931edSdan execsql { 736ae0931edSdan DROP TRIGGER t7t; 737ae0931edSdan DROP TRIGGER t7ta; 738ae0931edSdan CREATE TRIGGER t7t BEFORE DELETE ON t7 BEGIN 739ae0931edSdan UPDATE t7 set rowid = 8 WHERE rowid=1; 740ae0931edSdan END; 741ae0931edSdan CREATE TRIGGER t7ta AFTER DELETE ON t7 BEGIN 742ae0931edSdan INSERT INTO t8 VALUES('after fired ' || old.rowid); 743ae0931edSdan END; 744ae0931edSdan } 745ae0931edSdan} {} 746ae0931edSdando_test triggerC-7.8 { 747ae0931edSdan execsql { 748ae0931edSdan BEGIN; 749ae0931edSdan DELETE FROM t7 WHERE a = 3; 750ae0931edSdan SELECT rowid, * FROM t7; 751ae0931edSdan SELECT * FROM t8; 752ae0931edSdan ROLLBACK; 753ae0931edSdan } 754ae0931edSdan} {3 5 6 8 1 2 {after fired 2}} 755ae0931edSdando_test triggerC-7.9 { 756ae0931edSdan execsql { 757ae0931edSdan BEGIN; 758ae0931edSdan DELETE FROM t7 WHERE a = 1; 759ae0931edSdan SELECT rowid, * FROM t7; 760ae0931edSdan SELECT * FROM t8; 761ae0931edSdan ROLLBACK; 762ae0931edSdan } 763ae0931edSdan} {2 3 4 3 5 6 8 1 2} 764e0af83acSdan 7653991bb0dSdrh# Ticket [e25d9ea771febc9c311928c1c01c3163dcb26643] 7663991bb0dSdrh# 7673991bb0dSdrhdo_test triggerC-9.1 { 7683991bb0dSdrh execsql { 7693991bb0dSdrh CREATE TABLE t9(a,b); 7703991bb0dSdrh CREATE INDEX t9b ON t9(b); 7713991bb0dSdrh INSERT INTO t9 VALUES(1,0); 7723991bb0dSdrh INSERT INTO t9 VALUES(2,1); 7733991bb0dSdrh INSERT INTO t9 VALUES(3,2); 7743991bb0dSdrh INSERT INTO t9 SELECT a+3, a+2 FROM t9; 7753991bb0dSdrh INSERT INTO t9 SELECT a+6, a+5 FROM t9; 7763991bb0dSdrh SELECT a FROM t9 ORDER BY a; 7773991bb0dSdrh } 7783991bb0dSdrh} {1 2 3 4 5 6 7 8 9 10 11 12} 7793991bb0dSdrhdo_test triggerC-9.2 { 7803991bb0dSdrh execsql { 7813991bb0dSdrh CREATE TRIGGER t9r1 AFTER DELETE ON t9 BEGIN 7823991bb0dSdrh DELETE FROM t9 WHERE b=old.a; 7833991bb0dSdrh END; 7843991bb0dSdrh DELETE FROM t9 WHERE b=4; 7853991bb0dSdrh SELECT a FROM t9 ORDER BY a; 7863991bb0dSdrh } 7873991bb0dSdrh} {1 2 3 4} 7883991bb0dSdrh 789bb5f168fSdan# At one point (between versions 3.6.18 and 3.6.20 inclusive), an UPDATE 790bb5f168fSdan# that fired a BEFORE trigger that itself updated the same row as the 791bb5f168fSdan# statement causing it to fire was causing a strange side-effect: The 792bb5f168fSdan# values updated by the statement within the trigger were being overwritten 793bb5f168fSdan# by the values in the new.* array, even if those values were not 794bb5f168fSdan# themselves written by the parent UPDATE statement. 795bb5f168fSdan# 796bb5f168fSdan# Technically speaking this was not a bug. The SQLite documentation says 797bb5f168fSdan# that if a BEFORE UPDATE or BEFORE DELETE trigger modifies or deletes the 798bb5f168fSdan# row that the parent statement is operating on the results are undefined. 799bb5f168fSdan# But as of 3.6.21 behaviour is restored to the way it was in versions 800bb5f168fSdan# 3.6.17 and earlier to avoid causing unnecessary difficulties. 801bb5f168fSdan# 802bb5f168fSdando_test triggerC-10.1 { 803bb5f168fSdan execsql { 804bb5f168fSdan CREATE TABLE t10(a, updatecnt DEFAULT 0); 805bb5f168fSdan CREATE TRIGGER t10_bu BEFORE UPDATE OF a ON t10 BEGIN 806bb5f168fSdan UPDATE t10 SET updatecnt = updatecnt+1 WHERE rowid = old.rowid; 807bb5f168fSdan END; 808bb5f168fSdan INSERT INTO t10(a) VALUES('hello'); 809bb5f168fSdan } 8103991bb0dSdrh 811bb5f168fSdan # Before the problem was fixed, table t10 would contain the tuple 812bb5f168fSdan # (world, 0) after running the following script (because the value 813bb5f168fSdan # 1 written to column "updatecnt" was clobbered by the old value 0). 814bb5f168fSdan # 815bb5f168fSdan execsql { 816bb5f168fSdan UPDATE t10 SET a = 'world'; 817bb5f168fSdan SELECT * FROM t10; 818bb5f168fSdan } 819bb5f168fSdan} {world 1} 820bb5f168fSdan 821bb5f168fSdando_test triggerC-10.2 { 822bb5f168fSdan execsql { 823bb5f168fSdan UPDATE t10 SET a = 'tcl', updatecnt = 5; 824bb5f168fSdan SELECT * FROM t10; 825bb5f168fSdan } 826bb5f168fSdan} {tcl 5} 827bb5f168fSdan 828bb5f168fSdando_test triggerC-10.3 { 829bb5f168fSdan execsql { 830bb5f168fSdan CREATE TABLE t11( 831bb5f168fSdan c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, 832bb5f168fSdan c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, 833bb5f168fSdan c21, c22, c23, c24, c25, c26, c27, c28, c29, c30, 834bb5f168fSdan c31, c32, c33, c34, c35, c36, c37, c38, c39, c40 835bb5f168fSdan ); 836bb5f168fSdan 837bb5f168fSdan CREATE TRIGGER t11_bu BEFORE UPDATE OF c1 ON t11 BEGIN 838bb5f168fSdan UPDATE t11 SET c31 = c31+1, c32=c32+1 WHERE rowid = old.rowid; 839bb5f168fSdan END; 840bb5f168fSdan 841bb5f168fSdan INSERT INTO t11 VALUES( 842bb5f168fSdan 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 843bb5f168fSdan 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 844bb5f168fSdan 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 845bb5f168fSdan 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 846bb5f168fSdan ); 847bb5f168fSdan } 848bb5f168fSdan 849bb5f168fSdan # Before the problem was fixed, table t10 would contain the tuple 850bb5f168fSdan # (world, 0) after running the following script (because the value 851bb5f168fSdan # 1 written to column "updatecnt" was clobbered by the old value 0). 852bb5f168fSdan # 853bb5f168fSdan execsql { 854bb5f168fSdan UPDATE t11 SET c4=35, c33=22, c1=5; 855bb5f168fSdan SELECT * FROM t11; 856bb5f168fSdan } 857bb5f168fSdan} {5 2 3 35 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 32 33 22 34 35 36 37 38 39 40} 8583991bb0dSdrh 8597ba45971Sdan#------------------------------------------------------------------------- 8607ba45971Sdan# Test that bug [371bab5d65] has been fixed. BEFORE INSERT and INSTEAD OF 8617ba45971Sdan# INSERT triggers with the DEFAULT VALUES INSERT syntax. 8627ba45971Sdan# 8637ba45971Sdando_test triggerC-11.0 { 8647ba45971Sdan catchsql { DROP TABLE log } 8657ba45971Sdan execsql { CREATE TABLE log(a, b) } 8667ba45971Sdan} {} 8677ba45971Sdan 8687ba45971Sdanforeach {testno tbl defaults} { 8697ba45971Sdan 1 "CREATE TABLE t1(a, b)" {{} {}} 8707ba45971Sdan 2 "CREATE TABLE t1(a DEFAULT 1, b DEFAULT 'abc')" {1 abc} 8717ba45971Sdan 3 "CREATE TABLE t1(a, b DEFAULT 4.5)" {{} 4.5} 8727ba45971Sdan} { 8737ba45971Sdan do_test triggerC-11.$testno.1 { 8747ba45971Sdan catchsql { DROP TABLE t1 } 8757ba45971Sdan execsql { DELETE FROM log } 8767ba45971Sdan execsql $tbl 8777ba45971Sdan execsql { 8787ba45971Sdan CREATE TRIGGER tt1 BEFORE INSERT ON t1 BEGIN 8797ba45971Sdan INSERT INTO log VALUES(new.a, new.b); 8807ba45971Sdan END; 8817ba45971Sdan INSERT INTO t1 DEFAULT VALUES; 8827ba45971Sdan SELECT * FROM log; 8837ba45971Sdan } 8847ba45971Sdan } $defaults 8857ba45971Sdan 8867ba45971Sdan do_test triggerC-11.$testno.2 { 8877ba45971Sdan execsql { DELETE FROM log } 8887ba45971Sdan execsql { 8897ba45971Sdan CREATE TRIGGER tt2 AFTER INSERT ON t1 BEGIN 8907ba45971Sdan INSERT INTO log VALUES(new.a, new.b); 8917ba45971Sdan END; 8927ba45971Sdan INSERT INTO t1 DEFAULT VALUES; 8937ba45971Sdan SELECT * FROM log; 8947ba45971Sdan } 8957ba45971Sdan } [concat $defaults $defaults] 8967ba45971Sdan 8977ba45971Sdan do_test triggerC-11.$testno.3 { 8987ba45971Sdan execsql { DROP TRIGGER tt1 } 8997ba45971Sdan execsql { DELETE FROM log } 9007ba45971Sdan execsql { 9017ba45971Sdan INSERT INTO t1 DEFAULT VALUES; 9027ba45971Sdan SELECT * FROM log; 9037ba45971Sdan } 9047ba45971Sdan } $defaults 9057ba45971Sdan} 9067ba45971Sdando_test triggerC-11.4 { 9077ba45971Sdan catchsql { DROP TABLE t2 } 9087ba45971Sdan execsql { 9097ba45971Sdan DELETE FROM log; 9107ba45971Sdan CREATE TABLE t2(a, b); 9117ba45971Sdan CREATE VIEW v2 AS SELECT * FROM t2; 9127ba45971Sdan CREATE TRIGGER tv2 INSTEAD OF INSERT ON v2 BEGIN 9137ba45971Sdan INSERT INTO log VALUES(new.a, new.b); 9147ba45971Sdan END; 9157ba45971Sdan INSERT INTO v2 DEFAULT VALUES; 9167ba45971Sdan SELECT a, b, a IS NULL, b IS NULL FROM log; 9177ba45971Sdan } 9187ba45971Sdan} {{} {} 1 1} 9197ba45971Sdan 92098530cacSdando_test triggerC-12.1 { 92198530cacSdan db close 922fda06befSmistachkin forcedelete test.db 92398530cacSdan sqlite3 db test.db 92498530cacSdan 92598530cacSdan execsql { 92698530cacSdan CREATE TABLE t1(a, b); 92798530cacSdan INSERT INTO t1 VALUES(1, 2); 92898530cacSdan INSERT INTO t1 VALUES(3, 4); 92998530cacSdan INSERT INTO t1 VALUES(5, 6); 93098530cacSdan CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN SELECT 1 ; END ; 93198530cacSdan SELECT count(*) FROM sqlite_master; 93298530cacSdan } 93398530cacSdan} {2} 93498530cacSdando_test triggerC-12.2 { 93598530cacSdan db eval { SELECT * FROM t1 } { 93698530cacSdan if {$a == 3} { execsql { DROP TRIGGER tr1 } } 93798530cacSdan } 93898530cacSdan execsql { SELECT count(*) FROM sqlite_master } 93998530cacSdan} {1} 94098530cacSdan 94127106570Sdando_execsql_test triggerC-13.1 { 94227106570Sdan PRAGMA recursive_triggers = ON; 94327106570Sdan CREATE TABLE t12(a, b); 94427106570Sdan INSERT INTO t12 VALUES(1, 2); 94527106570Sdan CREATE TRIGGER tr12 AFTER UPDATE ON t12 BEGIN 94627106570Sdan UPDATE t12 SET a=new.a+1, b=new.b+1; 94727106570Sdan END; 94827106570Sdan} {} 94927106570Sdando_catchsql_test triggerC-13.2 { 95027106570Sdan UPDATE t12 SET a=a+1, b=b+1; 95127106570Sdan} {1 {too many levels of trigger recursion}} 95227106570Sdan 953f78baafeSdan#------------------------------------------------------------------------- 954f78baafeSdan# The following tests seek to verify that constant values (i.e. literals) 955f78baafeSdan# are not factored out of loops within trigger programs. SQLite does 956f78baafeSdan# not factor constants out of loops within trigger programs as it may only 957f78baafeSdan# do so in code generated before the first table or index is opened. And 958f78baafeSdan# by the time a trigger program is coded, at least one table or index has 959f78baafeSdan# always been opened. 960f78baafeSdan# 961f78baafeSdan# At one point, due to a bug allowing constant factoring within triggers, 962f78baafeSdan# the following SQL would produce the wrong result. 963f78baafeSdan# 964f78baafeSdanset SQL { 965f78baafeSdan CREATE TABLE t1(a, b, c); 966f78baafeSdan CREATE INDEX i1 ON t1(a, c); 967f78baafeSdan CREATE INDEX i2 ON t1(b, c); 968f78baafeSdan INSERT INTO t1 VALUES(1, 2, 3); 9697ba45971Sdan 970f78baafeSdan CREATE TABLE t2(e, f); 971f78baafeSdan CREATE INDEX i3 ON t2(e); 972f78baafeSdan INSERT INTO t2 VALUES(1234567, 3); 973f78baafeSdan 974f78baafeSdan CREATE TABLE empty(x); 975f78baafeSdan CREATE TABLE not_empty(x); 976f78baafeSdan INSERT INTO not_empty VALUES(2); 977f78baafeSdan 978f78baafeSdan CREATE TABLE t4(x); 979f78baafeSdan CREATE TABLE t5(g, h, i); 980f78baafeSdan 981f78baafeSdan CREATE TRIGGER trig BEFORE INSERT ON t4 BEGIN 982f78baafeSdan INSERT INTO t5 SELECT * FROM t1 WHERE 983f78baafeSdan (a IN (SELECT x FROM empty) OR b IN (SELECT x FROM not_empty)) 984f78baafeSdan AND c IN (SELECT f FROM t2 WHERE e=1234567); 985f78baafeSdan END; 986f78baafeSdan 987f78baafeSdan INSERT INTO t4 VALUES(0); 988f78baafeSdan SELECT * FROM t5; 989f78baafeSdan} 990f78baafeSdan 991f78baafeSdanreset_db 992f78baafeSdando_execsql_test triggerC-14.1 $SQL {1 2 3} 993f78baafeSdanreset_db 994f78baafeSdanoptimization_control db factor-constants 0 995f78baafeSdando_execsql_test triggerC-14.2 $SQL {1 2 3} 9962283d46cSdan 99746408354Sdan#------------------------------------------------------------------------- 99846408354Sdan# Check that table names used by trigger programs are dequoted exactly 99946408354Sdan# once. 100046408354Sdan# 100146408354Sdando_execsql_test 15.1.1 { 100246408354Sdan PRAGMA recursive_triggers = 1; 100346408354Sdan CREATE TABLE node( 100446408354Sdan id int not null primary key, 100546408354Sdan pid int not null default 0 references node, 100646408354Sdan key varchar not null, 100746408354Sdan path varchar default '', 100846408354Sdan unique(pid, key) 100946408354Sdan ); 101046408354Sdan CREATE TRIGGER node_delete_referencing AFTER DELETE ON "node" 101146408354Sdan BEGIN 101246408354Sdan DELETE FROM "node" WHERE pid = old."id"; 101346408354Sdan END; 101446408354Sdan} 101546408354Sdando_execsql_test 15.1.2 { 101646408354Sdan INSERT INTO node(id, pid, key) VALUES(9, 0, 'test'); 101746408354Sdan INSERT INTO node(id, pid, key) VALUES(90, 9, 'test1'); 101846408354Sdan INSERT INTO node(id, pid, key) VALUES(900, 90, 'test2'); 101946408354Sdan DELETE FROM node WHERE id=9; 102046408354Sdan SELECT * FROM node; 102146408354Sdan} 102246408354Sdan 102346408354Sdando_execsql_test 15.2.1 { 102446408354Sdan CREATE TABLE x1 (x); 102546408354Sdan 102646408354Sdan CREATE TABLE x2 (a, b); 102746408354Sdan CREATE TABLE '"x2"'(a, b); 102846408354Sdan 102946408354Sdan INSERT INTO x2 VALUES(1, 2); 103046408354Sdan INSERT INTO x2 VALUES(3, 4); 103146408354Sdan INSERT INTO '"x2"' SELECT * FROM x2; 103246408354Sdan 103346408354Sdan CREATE TRIGGER x1ai AFTER INSERT ON x1 BEGIN 103446408354Sdan INSERT INTO """x2""" VALUES('x', 'y'); 103546408354Sdan DELETE FROM """x2""" WHERE a=1; 103646408354Sdan UPDATE """x2""" SET b = 11 WHERE a = 3; 103746408354Sdan END; 103846408354Sdan 103946408354Sdan INSERT INTO x1 VALUES('go!'); 104046408354Sdan} 104146408354Sdan 104246408354Sdando_execsql_test 15.2.2 { SELECT * FROM x2; } {1 2 3 4} 104346408354Sdando_execsql_test 15.2.3 { SELECT * FROM """x2"""; } {3 11 x y} 104446408354Sdan 104516dd3985Sdan#------------------------------------------------------------------------- 104616dd3985Sdan# At one point queries such as the following were causing segfaults. 104716dd3985Sdan# 104816dd3985Sdando_catchsql_test 16.1 { 104916dd3985Sdan SELECT raise(ABORT, 'msg') FROM sqlite_master 105016dd3985Sdan UNION SELECT 1 105116dd3985Sdan ORDER BY raise(IGNORE); 105216dd3985Sdan} {1 {1st ORDER BY term does not match any column in the result set}} 105316dd3985Sdan 105416dd3985Sdando_catchsql_test 16.2 { 105516dd3985Sdan SELECT count(*) FROM sqlite_master 105616dd3985Sdan GROUP BY raise(IGNORE) 105716dd3985Sdan HAVING raise(ABORT, 'msg'); 105816dd3985Sdan} {1 {RAISE() may only be used within a trigger-program}} 105916dd3985Sdan 1060*b84b38fdSdan#------------------------------------------------------------------------- 1061*b84b38fdSdan# Datatype mismatch on IPK when there are BEFORE triggers. 1062*b84b38fdSdan# 1063*b84b38fdSdando_execsql_test 17.0 { 1064*b84b38fdSdan CREATE TABLE xyz(x INTEGER PRIMARY KEY, y, z); 1065*b84b38fdSdan CREATE TRIGGER xyz_tr BEFORE INSERT ON xyz BEGIN 1066*b84b38fdSdan SELECT new.x; 1067*b84b38fdSdan END; 1068*b84b38fdSdan} 1069*b84b38fdSdando_catchsql_test 17.1 { 1070*b84b38fdSdan INSERT INTO xyz VALUES('hello', 2, 3); 1071*b84b38fdSdan} {1 {datatype mismatch}} 1072*b84b38fdSdan 1073*b84b38fdSdan 1074436355a0Sdanfinish_test 1075