github.com/jdgcs/sqlite3@v1.12.1-0.20210908114423-bc5f96e4dd51/testdata/tcl/shared9.test (about) 1 # 2012 October 5 2 # 3 # The author disclaims copyright to this source code. In place of 4 # a legal notice, here is a blessing: 5 # 6 # May you do good and not evil. 7 # May you find forgiveness for yourself and forgive others. 8 # May you share freely, never taking more than you give. 9 # 10 #*********************************************************************** 11 # 12 # The tests in this file are intended to show if two connections attach 13 # to the same shared cache using different database names, views and 14 # virtual tables may still be accessed. 15 # 16 17 set testdir [file dirname $argv0] 18 source $testdir/tester.tcl 19 source $testdir/lock_common.tcl 20 set testprefix shared9 21 22 ifcapable !view||!trigger { 23 finish_test 24 return 25 } 26 27 db close 28 set enable_shared_cache [sqlite3_enable_shared_cache 1] 29 30 sqlite3 db1 test.db 31 sqlite3 db2 test.db 32 forcedelete test.db2 33 34 do_test 1.1 { 35 db1 eval { 36 ATTACH 'test.db2' AS 'fred'; 37 CREATE TABLE fred.t1(a, b, c); 38 CREATE VIEW fred.v1 AS SELECT * FROM t1; 39 40 CREATE TABLE fred.t2(a, b); 41 CREATE TABLE fred.t3(a, b); 42 CREATE TRIGGER fred.trig AFTER INSERT ON t2 BEGIN 43 DELETE FROM t3; 44 INSERT INTO t3 SELECT * FROM t2; 45 END; 46 INSERT INTO t2 VALUES(1, 2); 47 SELECT * FROM t3; 48 } 49 } {1 2} 50 51 do_test 1.2 { db2 eval "ATTACH 'test.db2' AS 'jones'" } {} 52 do_test 1.3 { db2 eval "SELECT * FROM v1" } {} 53 do_test 1.4 { db2 eval "INSERT INTO t2 VALUES(3, 4)" } {} 54 55 ifcapable fts3 { 56 do_test 1.5 { 57 db1 eval { 58 CREATE VIRTUAL TABLE fred.t4 USING fts4; 59 INSERT INTO t4 VALUES('hello world'); 60 } 61 } {} 62 63 do_test 1.6 { 64 db2 eval { 65 INSERT INTO t4 VALUES('shared cache'); 66 SELECT * FROM t4 WHERE t4 MATCH 'hello'; 67 } 68 } {{hello world}} 69 70 do_test 1.7 { 71 db1 eval { 72 SELECT * FROM t4 WHERE t4 MATCH 'c*'; 73 } 74 } {{shared cache}} 75 } 76 77 db1 close 78 db2 close 79 80 #------------------------------------------------------------------------- 81 # The following tests attempt to find a similar problem with collation 82 # sequence names - pointers to database handle specific allocations leaking 83 # into schema objects and being used after the original handle has been 84 # closed. 85 # 86 forcedelete test.db test.db2 87 sqlite3 db1 test.db 88 sqlite3 db2 test.db 89 foreach x {collate1 collate2 collate3} { 90 proc $x {a b} { string compare $a $b } 91 db1 collate $x $x 92 db2 collate $x $x 93 } 94 do_test 2.1 { 95 db1 eval { 96 CREATE TABLE t1(a, b, c COLLATE collate1); 97 CREATE INDEX i1 ON t1(a COLLATE collate2, c, b); 98 } 99 } {} 100 do_test 2.2 { 101 db1 close 102 db2 eval "INSERT INTO t1 VALUES('abc', 'def', 'ghi')" 103 } {} 104 db2 close 105 106 #------------------------------------------------------------------------- 107 # At one point, the following would cause a collation sequence belonging 108 # to connection [db1] to be invoked by a call to [db2 eval]. Which is a 109 # problem if [db1] has already been closed. 110 # 111 forcedelete test.db test.db2 112 sqlite3 db1 test.db 113 sqlite3 db2 test.db 114 115 proc mycollate_db1 {a b} {set ::invoked_mycollate_db1 1 ; string compare $a $b} 116 proc mycollate_db2 {a b} {string compare $a $b} 117 118 db1 collate mycollate mycollate_db1 119 db2 collate mycollate mycollate_db2 120 121 do_test 2.3 { 122 set ::invoked_mycollate_db1 0 123 db1 eval { 124 CREATE TABLE t1(a COLLATE mycollate, CHECK (a IN ('one', 'two', 'three'))); 125 INSERT INTO t1 VALUES('one'); 126 } 127 db1 close 128 set ::invoked_mycollate_db1 129 } {1} 130 do_test 2.4 { 131 set ::invoked_mycollate_db1 0 132 db2 eval { 133 INSERT INTO t1 VALUES('two'); 134 } 135 db2 close 136 set ::invoked_mycollate_db1 137 } {0} 138 139 forcedelete test.db test.db2 140 sqlite3 db1 test.db 141 sqlite3 db2 test.db 142 db1 collate mycollate mycollate_db1 143 db2 collate mycollate mycollate_db2 144 145 do_test 2.13 { 146 set ::invoked_mycollate_db1 0 147 db1 eval { 148 CREATE TABLE t1(a, CHECK (a COLLATE mycollate IN ('one', 'two', 'three'))); 149 INSERT INTO t1 VALUES('one'); 150 } 151 db1 close 152 set ::invoked_mycollate_db1 153 } {1} 154 do_test 2.14 { 155 set ::invoked_mycollate_db1 0 156 db2 eval { 157 INSERT INTO t1 VALUES('two'); 158 } 159 db2 close 160 set ::invoked_mycollate_db1 161 } {0} 162 163 #------------------------------------------------------------------------- 164 # This test verifies that a bug causing a busy-handler belonging to one 165 # shared-cache connection to be executed as a result of an sqlite3_step() 166 # on another has been fixed. 167 # 168 forcedelete test.db test.db2 169 sqlite3 db1 test.db 170 sqlite3 db2 test.db 171 172 proc busyhandler {handle args} { 173 set ::busyhandler_invoked_for $handle 174 return 1 175 } 176 db1 busy [list busyhandler db1] 177 db2 busy [list busyhandler db2] 178 179 do_test 3.1 { 180 db1 eval { 181 BEGIN; 182 CREATE TABLE t1(a, b); 183 CREATE TABLE t2(a, b); 184 INSERT INTO t1 VALUES(1, 2); 185 INSERT INTO t2 VALUES(1, 2); 186 } 187 # Keep this next COMMIT as a separate statement. This ensures that COMMIT 188 # has already been compiled and loaded into the tcl interface statement 189 # cache when it is attempted below. 190 db1 eval COMMIT 191 db1 eval { 192 BEGIN; 193 INSERT INTO t1 VALUES(3, 4); 194 } 195 } {} 196 197 do_test 3.2 { 198 set ::tf [launch_testfixture] 199 testfixture $::tf { 200 sqlite3 db test.db 201 db eval { 202 BEGIN; 203 SELECT * FROM t1; 204 } 205 } 206 } {1 2} 207 208 do_test 3.3 { 209 db2 eval { SELECT * FROM t2 } 210 } {1 2} 211 212 do_test 3.4 { 213 list [catch { db1 eval COMMIT } msg] $msg 214 } {1 {database is locked}} 215 216 # At one point the following would fail, showing that the busy-handler 217 # belonging to [db2] was invoked instead. 218 do_test 3.5 { 219 set ::busyhandler_invoked_for 220 } {db1} 221 do_test 3.6 { 222 close $::tf 223 db1 eval COMMIT 224 } {} 225 226 db1 close 227 db2 close 228 229 sqlite3_enable_shared_cache $::enable_shared_cache 230 finish_test