blob: 5bb46c26861012a4669bc9f7d807c5a5d6c059bf [file] [log] [blame]
dan41fb5cd2012-10-04 19:33:00 +00001# 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
17set testdir [file dirname $argv0]
18source $testdir/tester.tcl
dan6b9bb592012-10-05 19:43:02 +000019source $testdir/lock_common.tcl
dan41fb5cd2012-10-04 19:33:00 +000020set testprefix shared9
dana2ebe4b2012-10-05 17:18:16 +000021
drh9c5e1e42022-08-15 12:26:26 +000022ifcapable !view||!trigger||!shared_cache {
dana2ebe4b2012-10-05 17:18:16 +000023 finish_test
24 return
25}
26
dan41fb5cd2012-10-04 19:33:00 +000027db close
28set enable_shared_cache [sqlite3_enable_shared_cache 1]
29
dan41fb5cd2012-10-04 19:33:00 +000030sqlite3 db1 test.db
31sqlite3 db2 test.db
32forcedelete test.db2
33
34do_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
51do_test 1.2 { db2 eval "ATTACH 'test.db2' AS 'jones'" } {}
dana2ebe4b2012-10-05 17:18:16 +000052do_test 1.3 { db2 eval "SELECT * FROM v1" } {}
53do_test 1.4 { db2 eval "INSERT INTO t2 VALUES(3, 4)" } {}
dan41fb5cd2012-10-04 19:33:00 +000054
dana2ebe4b2012-10-05 17:18:16 +000055ifcapable 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 } {}
dan41fb5cd2012-10-04 19:33:00 +000062
dana2ebe4b2012-10-05 17:18:16 +000063 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}}
dan41fb5cd2012-10-04 19:33:00 +000069
dana2ebe4b2012-10-05 17:18:16 +000070 do_test 1.7 {
71 db1 eval {
72 SELECT * FROM t4 WHERE t4 MATCH 'c*';
73 }
74 } {{shared cache}}
75}
dan41fb5cd2012-10-04 19:33:00 +000076
77db1 close
78db2 close
dana2ebe4b2012-10-05 17:18:16 +000079
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#
86forcedelete test.db test.db2
87sqlite3 db1 test.db
88sqlite3 db2 test.db
89foreach x {collate1 collate2 collate3} {
90 proc $x {a b} { string compare $a $b }
91 db1 collate $x $x
92 db2 collate $x $x
93}
94do_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} {}
100do_test 2.2 {
101 db1 close
102 db2 eval "INSERT INTO t1 VALUES('abc', 'def', 'ghi')"
103} {}
104db2 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#
111forcedelete test.db test.db2
112sqlite3 db1 test.db
113sqlite3 db2 test.db
114
115proc mycollate_db1 {a b} {set ::invoked_mycollate_db1 1 ; string compare $a $b}
116proc mycollate_db2 {a b} {string compare $a $b}
117
118db1 collate mycollate mycollate_db1
119db2 collate mycollate mycollate_db2
120
121do_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}
130do_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
drh74358f02012-12-06 15:15:15 +0000139forcedelete test.db test.db2
140sqlite3 db1 test.db
141sqlite3 db2 test.db
142db1 collate mycollate mycollate_db1
143db2 collate mycollate mycollate_db2
144
145do_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}
154do_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
dan6b9bb592012-10-05 19:43:02 +0000163#-------------------------------------------------------------------------
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#
168forcedelete test.db test.db2
169sqlite3 db1 test.db
170sqlite3 db2 test.db
171
172proc busyhandler {handle args} {
173 set ::busyhandler_invoked_for $handle
174 return 1
175}
176db1 busy [list busyhandler db1]
177db2 busy [list busyhandler db2]
178
179do_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
mistachkin3038cfe2012-10-07 05:34:39 +0000197do_test 3.2 {
dan6b9bb592012-10-05 19:43:02 +0000198 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
mistachkin3038cfe2012-10-07 05:34:39 +0000208do_test 3.3 {
dan6b9bb592012-10-05 19:43:02 +0000209 db2 eval { SELECT * FROM t2 }
210} {1 2}
211
mistachkin3038cfe2012-10-07 05:34:39 +0000212do_test 3.4 {
dan6b9bb592012-10-05 19:43:02 +0000213 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.
mistachkin3038cfe2012-10-07 05:34:39 +0000218do_test 3.5 {
dan6b9bb592012-10-05 19:43:02 +0000219 set ::busyhandler_invoked_for
220} {db1}
mistachkin3038cfe2012-10-07 05:34:39 +0000221do_test 3.6 {
dan6b9bb592012-10-05 19:43:02 +0000222 close $::tf
223 db1 eval COMMIT
224} {}
225
226db1 close
227db2 close
228
dan41fb5cd2012-10-04 19:33:00 +0000229sqlite3_enable_shared_cache $::enable_shared_cache
230finish_test