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# This file tests creating and dropping triggers, and interaction thereof 11# with the database COMMIT/ROLLBACK logic. 12# 13# 1. CREATE and DROP TRIGGER tests 14# trig-1.1: Error if table does not exist 15# trig-1.2: Error if trigger already exists 16# trig-1.3: Created triggers are deleted if the transaction is rolled back 17# trig-1.4: DROP TRIGGER removes trigger 18# trig-1.5: Dropped triggers are restored if the transaction is rolled back 19# trig-1.6: Error if dropped trigger doesn't exist 20# trig-1.7: Dropping the table automatically drops all triggers 21# trig-1.8: A trigger created on a TEMP table is not inserted into sqlite_master 22# trig-1.9: Ensure that we cannot create a trigger on sqlite_master 23# trig-1.10: 24# trig-1.11: 25# trig-1.12: Ensure that INSTEAD OF triggers cannot be created on tables 26# trig-1.13: Ensure that AFTER triggers cannot be created on views 27# trig-1.14: Ensure that BEFORE triggers cannot be created on views 28# 29 30set testdir [file dirname $argv0] 31source $testdir/tester.tcl 32 33do_test trigger1-1.1.2 { 34 catchsql { 35 CREATE TRIGGER trig UPDATE ON no_such_table BEGIN 36 SELECT * from sqlite_master; 37 END; 38 } 39} {1 {no such table: no_such_table}} 40do_test trigger1-1.1.2 { 41 catchsql { 42 CREATE TEMP TRIGGER trig UPDATE ON no_such_table BEGIN 43 SELECT * from sqlite_master; 44 END; 45 } 46} {1 {no such table: no_such_table}} 47 48execsql { 49 CREATE TABLE t1(a); 50} 51execsql { 52 CREATE TRIGGER tr1 INSERT ON t1 BEGIN 53 INSERT INTO t1 values(1); 54 END; 55} 56do_test trigger1-1.2 { 57 catchsql { 58 CREATE TRIGGER tr1 DELETE ON t1 BEGIN 59 SELECT * FROM sqlite_master; 60 END 61 } 62} {1 {trigger tr1 already exists}} 63 64do_test trigger1-1.3 { 65 catchsql { 66 BEGIN; 67 CREATE TRIGGER tr2 INSERT ON t1 BEGIN 68 SELECT * from sqlite_master; END; 69 ROLLBACK; 70 CREATE TRIGGER tr2 INSERT ON t1 BEGIN 71 SELECT * from sqlite_master; END; 72 } 73} {0 {}} 74 75do_test trigger1-1.4 { 76 catchsql { 77 DROP TRIGGER tr1; 78 CREATE TRIGGER tr1 DELETE ON t1 BEGIN 79 SELECT * FROM sqlite_master; 80 END 81 } 82} {0 {}} 83 84do_test trigger1-1.5 { 85 execsql { 86 BEGIN; 87 DROP TRIGGER tr2; 88 ROLLBACK; 89 DROP TRIGGER tr2; 90 } 91} {} 92 93do_test trigger1-1.6 { 94 catchsql { 95 DROP TRIGGER biggles; 96 } 97} {1 {no such trigger: biggles}} 98 99do_test trigger1-1.7 { 100 catchsql { 101 DROP TABLE t1; 102 DROP TRIGGER tr1; 103 } 104} {1 {no such trigger: tr1}} 105 106execsql { 107 CREATE TEMP TABLE temp_table(a); 108} 109do_test trigger1-1.8 { 110 execsql { 111 CREATE TRIGGER temp_trig UPDATE ON temp_table BEGIN 112 SELECT * from sqlite_master; 113 END; 114 SELECT count(*) FROM sqlite_master WHERE name = 'temp_trig'; 115 } 116} {0} 117 118do_test trigger1-1.9 { 119 catchsql { 120 CREATE TRIGGER tr1 AFTER UPDATE ON sqlite_master BEGIN 121 SELECT * FROM sqlite_master; 122 END; 123 } 124} {1 {cannot create trigger on system table}} 125 126# Check to make sure that a DELETE statement within the body of 127# a trigger does not mess up the DELETE that caused the trigger to 128# run in the first place. 129# 130do_test trigger1-1.10 { 131 execsql { 132 create table t1(a,b); 133 insert into t1 values(1,'a'); 134 insert into t1 values(2,'b'); 135 insert into t1 values(3,'c'); 136 insert into t1 values(4,'d'); 137 create trigger r1 after delete on t1 for each row begin 138 delete from t1 WHERE a=old.a+2; 139 end; 140 delete from t1 where a in (1,3); 141 select * from t1; 142 drop table t1; 143 } 144} {2 b 4 d} 145do_test trigger1-1.11 { 146 execsql { 147 create table t1(a,b); 148 insert into t1 values(1,'a'); 149 insert into t1 values(2,'b'); 150 insert into t1 values(3,'c'); 151 insert into t1 values(4,'d'); 152 create trigger r1 after update on t1 for each row begin 153 delete from t1 WHERE a=old.a+2; 154 end; 155 update t1 set b='x-' || b where a in (1,3); 156 select * from t1; 157 drop table t1; 158 } 159} {1 x-a 2 b 4 d} 160 161# Ensure that we cannot create INSTEAD OF triggers on tables 162do_test trigger1-1.12 { 163 catchsql { 164 create table t1(a,b); 165 create trigger t1t instead of update on t1 for each row begin 166 delete from t1 WHERE a=old.a+2; 167 end; 168 } 169} {1 {cannot create INSTEAD OF trigger on table: t1}} 170# Ensure that we cannot create BEFORE triggers on views 171do_test trigger1-1.13 { 172 catchsql { 173 create view v1 as select * from t1; 174 create trigger v1t before update on v1 for each row begin 175 delete from t1 WHERE a=old.a+2; 176 end; 177 } 178} {1 {cannot create BEFORE trigger on view: v1}} 179# Ensure that we cannot create AFTER triggers on views 180do_test trigger1-1.14 { 181 catchsql { 182 create table t1(a,b); 183 create view v1 as select * from t1; 184 create trigger v1t AFTER update on v1 for each row begin 185 delete from t1 WHERE a=old.a+2; 186 end; 187 } 188} {1 {cannot create AFTER trigger on view: v1}} 189 190# Check for memory leaks in the trigger parser 191# 192do_test trigger1-2.1 { 193 catchsql { 194 CREATE TRIGGER r1 AFTER INSERT ON t1 BEGIN 195 SELECT * FROM; -- Syntax error 196 END; 197 } 198} {1 {near ";": syntax error}} 199do_test trigger1-2.2 { 200 catchsql { 201 CREATE TRIGGER r1 AFTER INSERT ON t1 BEGIN 202 SELECT * FROM t1; 203 SELECT * FROM; -- Syntax error 204 END; 205 } 206} {1 {near ";": syntax error}} 207 208# Create a trigger that refers to a table that might not exist. 209# 210do_test trigger1-3.1 { 211 execsql { 212 CREATE TEMP TABLE t2(x,y); 213 } 214 catchsql { 215 CREATE TRIGGER r1 AFTER INSERT ON t1 BEGIN 216 INSERT INTO t2 VALUES(NEW.a,NEW.b); 217 END; 218 } 219} {0 {}} 220do_test trigger-3.2 { 221 catchsql { 222 INSERT INTO t1 VALUES(1,2); 223 SELECT * FROM t2; 224 } 225} {1 {no such table: main.t2}} 226do_test trigger-3.3 { 227 db close 228 set rc [catch {sqlite db test.db} err] 229 if {$rc} {lappend rc $err} 230 set rc 231} {0} 232do_test trigger-3.4 { 233 catchsql { 234 INSERT INTO t1 VALUES(1,2); 235 SELECT * FROM t2; 236 } 237} {1 {no such table: main.t2}} 238do_test trigger-3.5 { 239 catchsql { 240 CREATE TEMP TABLE t2(x,y); 241 INSERT INTO t1 VALUES(1,2); 242 SELECT * FROM t2; 243 } 244} {1 {no such table: main.t2}} 245do_test trigger-3.6 { 246 catchsql { 247 DROP TRIGGER r1; 248 CREATE TEMP TRIGGER r1 AFTER INSERT ON t1 BEGIN 249 INSERT INTO t2 VALUES(NEW.a,NEW.b); 250 END; 251 INSERT INTO t1 VALUES(1,2); 252 SELECT * FROM t2; 253 } 254} {0 {1 2}} 255do_test trigger-3.7 { 256 execsql { 257 DROP TABLE t2; 258 CREATE TABLE t2(x,y); 259 SELECT * FROM t2; 260 } 261} {} 262do_test trigger-3.8 { 263 execsql { 264 INSERT INTO t1 VALUES(3,4); 265 SELECT * FROM t1 UNION ALL SELECT * FROM t2; 266 } 267} {1 2 3 4 3 4} 268do_test trigger-3.9 { 269 db close 270 sqlite db test.db 271 execsql { 272 INSERT INTO t1 VALUES(5,6); 273 SELECT * FROM t1 UNION ALL SELECT * FROM t2; 274 } 275} {1 2 3 4 5 6 3 4} 276 277do_test trigger-4.1 { 278 execsql { 279 CREATE TEMP TRIGGER r1 BEFORE INSERT ON t1 BEGIN 280 INSERT INTO t2 VALUES(NEW.a,NEW.b); 281 END; 282 INSERT INTO t1 VALUES(7,8); 283 SELECT * FROM t2; 284 } 285} {3 4 7 8} 286do_test trigger-4.2 { 287 sqlite db2 test.db 288 execsql { 289 INSERT INTO t1 VALUES(9,10); 290 } db2; 291 db2 close 292 execsql { 293 SELECT * FROM t2; 294 } 295} {3 4 7 8} 296do_test trigger-4.3 { 297 execsql { 298 DROP TABLE t1; 299 SELECT * FROM t2; 300 }; 301} {3 4 7 8} 302do_test trigger-4.4 { 303 db close 304 sqlite db test.db 305 execsql { 306 SELECT * FROM t2; 307 }; 308} {3 4 7 8} 309 310integrity_check trigger-5.1 311 312# Create a trigger with the same name as a table. Make sure the 313# trigger works. Then drop the trigger. Make sure the table is 314# still there. 315# 316do_test trigger-6.1 { 317 execsql {SELECT type, name FROM sqlite_master} 318} {view v1 table t2} 319do_test trigger-6.2 { 320 execsql { 321 CREATE TRIGGER t2 BEFORE DELETE ON t2 BEGIN 322 SELECT RAISE(ABORT,'deletes are not allows'); 323 END; 324 SELECT type, name FROM sqlite_master; 325 } 326} {view v1 table t2 trigger t2} 327do_test trigger-6.3 { 328 catchsql {DELETE FROM t2} 329} {1 {deletes are not allows}} 330do_test trigger-6.4 { 331 execsql {SELECT * FROM t2} 332} {3 4 7 8} 333do_test trigger-6.5 { 334 db close 335 sqlite db test.db 336 execsql {SELECT type, name FROM sqlite_master} 337} {view v1 table t2 trigger t2} 338do_test trigger-6.6 { 339 execsql { 340 DROP TRIGGER t2; 341 SELECT type, name FROM sqlite_master; 342 } 343} {view v1 table t2} 344do_test trigger-6.7 { 345 execsql {SELECT * FROM t2} 346} {3 4 7 8} 347do_test trigger-6.8 { 348 db close 349 sqlite db test.db 350 execsql {SELECT * FROM t2} 351} {3 4 7 8} 352 353integrity_check trigger-7.1 354 355finish_test 356