000001 # 2010 November 29 000002 # 000003 # The author disclaims copyright to this source code. In place of 000004 # a legal notice, here is a blessing: 000005 # 000006 # May you do good and not evil. 000007 # May you find forgiveness for yourself and forgive others. 000008 # May you share freely, never taking more than you give. 000009 # 000010 #*********************************************************************** 000011 # 000012 # This file implements tests to verify that the "testable statements" in 000013 # the lang_droptrigger.html document are correct. 000014 # 000015 000016 set testdir [file dirname $argv0] 000017 source $testdir/tester.tcl 000018 set ::testprefix e_droptrigger 000019 000020 ifcapable !trigger { finish_test ; return } 000021 000022 proc do_droptrigger_tests {nm args} { 000023 uplevel do_select_tests [list e_createtable-$nm] $args 000024 } 000025 000026 proc list_all_triggers {{db db}} { 000027 set res [list] 000028 $db eval { PRAGMA database_list } { 000029 if {$name == "temp"} { 000030 set tbl sqlite_temp_master 000031 } else { 000032 set tbl "$name.sqlite_master" 000033 } 000034 lappend res {*}[ 000035 db eval "SELECT '$name.' || name FROM $tbl WHERE type = 'trigger'" 000036 ] 000037 } 000038 set res 000039 } 000040 000041 000042 proc droptrigger_reopen_db {{event INSERT}} { 000043 db close 000044 forcedelete test.db test.db2 000045 sqlite3 db test.db 000046 000047 set ::triggers_fired [list] 000048 proc r {x} { lappend ::triggers_fired $x } 000049 db func r r 000050 000051 db eval " 000052 ATTACH 'test.db2' AS aux; 000053 000054 CREATE TEMP TABLE t1(a, b); 000055 INSERT INTO t1 VALUES('a', 'b'); 000056 CREATE TRIGGER tr1 AFTER $event ON t1 BEGIN SELECT r('temp.tr1') ; END; 000057 000058 CREATE TABLE t2(a, b); 000059 INSERT INTO t2 VALUES('a', 'b'); 000060 CREATE TRIGGER tr1 BEFORE $event ON t2 BEGIN SELECT r('main.tr1') ; END; 000061 CREATE TRIGGER tr2 AFTER $event ON t2 BEGIN SELECT r('main.tr2') ; END; 000062 000063 CREATE TABLE aux.t3(a, b); 000064 INSERT INTO t3 VALUES('a', 'b'); 000065 CREATE TRIGGER aux.tr1 BEFORE $event ON t3 BEGIN SELECT r('aux.tr1') ; END; 000066 CREATE TRIGGER aux.tr2 AFTER $event ON t3 BEGIN SELECT r('aux.tr2') ; END; 000067 CREATE TRIGGER aux.tr3 AFTER $event ON t3 BEGIN SELECT r('aux.tr3') ; END; 000068 " 000069 } 000070 000071 000072 # -- syntax diagram drop-trigger-stmt 000073 # 000074 do_droptrigger_tests 1.1 -repair { 000075 droptrigger_reopen_db 000076 } -tclquery { 000077 list_all_triggers 000078 } { 000079 1 "DROP TRIGGER main.tr1" 000080 {main.tr2 temp.tr1 aux.tr1 aux.tr2 aux.tr3} 000081 2 "DROP TRIGGER IF EXISTS main.tr1" 000082 {main.tr2 temp.tr1 aux.tr1 aux.tr2 aux.tr3} 000083 3 "DROP TRIGGER tr1" 000084 {main.tr1 main.tr2 aux.tr1 aux.tr2 aux.tr3} 000085 4 "DROP TRIGGER IF EXISTS tr1" 000086 {main.tr1 main.tr2 aux.tr1 aux.tr2 aux.tr3} 000087 000088 5 "DROP TRIGGER aux.tr1" 000089 {main.tr1 main.tr2 temp.tr1 aux.tr2 aux.tr3} 000090 6 "DROP TRIGGER IF EXISTS aux.tr1" 000091 {main.tr1 main.tr2 temp.tr1 aux.tr2 aux.tr3} 000092 000093 7 "DROP TRIGGER IF EXISTS aux.xxx" 000094 {main.tr1 main.tr2 temp.tr1 aux.tr1 aux.tr2 aux.tr3} 000095 8 "DROP TRIGGER IF EXISTS aux.xxx" 000096 {main.tr1 main.tr2 temp.tr1 aux.tr1 aux.tr2 aux.tr3} 000097 } 000098 000099 # EVIDENCE-OF: R-61172-15671 The DROP TRIGGER statement removes a 000100 # trigger created by the CREATE TRIGGER statement. 000101 # 000102 foreach {tn tbl droptrigger before after} { 000103 1 t1 "DROP TRIGGER tr1" {temp.tr1} {} 000104 2 t2 "DROP TRIGGER tr1" {main.tr1 main.tr2} {main.tr1 main.tr2} 000105 3 t3 "DROP TRIGGER tr1" {aux.tr1 aux.tr3 aux.tr2} {aux.tr1 aux.tr3 aux.tr2} 000106 000107 4 t1 "DROP TRIGGER tr2" {temp.tr1} {temp.tr1} 000108 5 t2 "DROP TRIGGER tr2" {main.tr1 main.tr2} {main.tr1} 000109 6 t3 "DROP TRIGGER tr2" {aux.tr1 aux.tr3 aux.tr2} {aux.tr1 aux.tr3 aux.tr2} 000110 000111 7 t1 "DROP TRIGGER tr3" {temp.tr1} {temp.tr1} 000112 8 t2 "DROP TRIGGER tr3" {main.tr1 main.tr2} {main.tr1 main.tr2} 000113 9 t3 "DROP TRIGGER tr3" {aux.tr1 aux.tr3 aux.tr2} {aux.tr1 aux.tr2} 000114 } { 000115 000116 do_test 2.$tn.1 { 000117 droptrigger_reopen_db 000118 execsql " INSERT INTO $tbl VALUES('1', '2') " 000119 set ::triggers_fired 000120 } $before 000121 000122 do_test 2.$tn.2 { 000123 droptrigger_reopen_db 000124 execsql $droptrigger 000125 execsql " INSERT INTO $tbl VALUES('1', '2') " 000126 set ::triggers_fired 000127 } $after 000128 } 000129 000130 # EVIDENCE-OF: R-50239-29811 Once removed, the trigger definition is no 000131 # longer present in the sqlite_master (or sqlite_temp_master) table and 000132 # is not fired by any subsequent INSERT, UPDATE or DELETE statements. 000133 # 000134 # Test cases e_droptrigger-1.* test the first part of this statement 000135 # (that dropped triggers do not appear in the schema table), and tests 000136 # droptrigger-2.* test that dropped triggers are not fired by INSERT 000137 # statements. The following tests verify that they are not fired by 000138 # UPDATE or DELETE statements. 000139 # 000140 foreach {tn tbl droptrigger before after} { 000141 1 t1 "DROP TRIGGER tr1" {temp.tr1} {} 000142 2 t2 "DROP TRIGGER tr1" {main.tr1 main.tr2} {main.tr1 main.tr2} 000143 3 t3 "DROP TRIGGER tr1" {aux.tr1 aux.tr3 aux.tr2} {aux.tr1 aux.tr3 aux.tr2} 000144 000145 4 t1 "DROP TRIGGER tr2" {temp.tr1} {temp.tr1} 000146 5 t2 "DROP TRIGGER tr2" {main.tr1 main.tr2} {main.tr1} 000147 6 t3 "DROP TRIGGER tr2" {aux.tr1 aux.tr3 aux.tr2} {aux.tr1 aux.tr3 aux.tr2} 000148 000149 7 t1 "DROP TRIGGER tr3" {temp.tr1} {temp.tr1} 000150 8 t2 "DROP TRIGGER tr3" {main.tr1 main.tr2} {main.tr1 main.tr2} 000151 9 t3 "DROP TRIGGER tr3" {aux.tr1 aux.tr3 aux.tr2} {aux.tr1 aux.tr2} 000152 } { 000153 000154 do_test 3.1.$tn.1 { 000155 droptrigger_reopen_db UPDATE 000156 execsql "UPDATE $tbl SET a = 'abc'" 000157 set ::triggers_fired 000158 } $before 000159 000160 do_test 3.1.$tn.2 { 000161 droptrigger_reopen_db UPDATE 000162 execsql $droptrigger 000163 execsql "UPDATE $tbl SET a = 'abc'" 000164 set ::triggers_fired 000165 } $after 000166 } 000167 foreach {tn tbl droptrigger before after} { 000168 1 t1 "DROP TRIGGER tr1" {temp.tr1} {} 000169 2 t2 "DROP TRIGGER tr1" {main.tr1 main.tr2} {main.tr1 main.tr2} 000170 3 t3 "DROP TRIGGER tr1" {aux.tr1 aux.tr3 aux.tr2} {aux.tr1 aux.tr3 aux.tr2} 000171 000172 4 t1 "DROP TRIGGER tr2" {temp.tr1} {temp.tr1} 000173 5 t2 "DROP TRIGGER tr2" {main.tr1 main.tr2} {main.tr1} 000174 6 t3 "DROP TRIGGER tr2" {aux.tr1 aux.tr3 aux.tr2} {aux.tr1 aux.tr3 aux.tr2} 000175 000176 7 t1 "DROP TRIGGER tr3" {temp.tr1} {temp.tr1} 000177 8 t2 "DROP TRIGGER tr3" {main.tr1 main.tr2} {main.tr1 main.tr2} 000178 9 t3 "DROP TRIGGER tr3" {aux.tr1 aux.tr3 aux.tr2} {aux.tr1 aux.tr2} 000179 } { 000180 000181 do_test 3.2.$tn.1 { 000182 droptrigger_reopen_db DELETE 000183 execsql "DELETE FROM $tbl" 000184 set ::triggers_fired 000185 } $before 000186 000187 do_test 3.2.$tn.2 { 000188 droptrigger_reopen_db DELETE 000189 execsql $droptrigger 000190 execsql "DELETE FROM $tbl" 000191 set ::triggers_fired 000192 } $after 000193 } 000194 000195 # EVIDENCE-OF: R-37808-62273 Note that triggers are automatically 000196 # dropped when the associated table is dropped. 000197 # 000198 do_test 4.1 { 000199 droptrigger_reopen_db 000200 list_all_triggers 000201 } {main.tr1 main.tr2 temp.tr1 aux.tr1 aux.tr2 aux.tr3} 000202 do_test 4.2 { 000203 droptrigger_reopen_db 000204 execsql "DROP TABLE t1" 000205 list_all_triggers 000206 } {main.tr1 main.tr2 aux.tr1 aux.tr2 aux.tr3} 000207 do_test 4.3 { 000208 droptrigger_reopen_db 000209 execsql "DROP TABLE t1" 000210 list_all_triggers 000211 } {main.tr1 main.tr2 aux.tr1 aux.tr2 aux.tr3} 000212 do_test 4.4 { 000213 droptrigger_reopen_db 000214 execsql "DROP TABLE t1" 000215 list_all_triggers 000216 } {main.tr1 main.tr2 aux.tr1 aux.tr2 aux.tr3} 000217 000218 finish_test