xref: /sqlite-3.40.0/test/shared9.test (revision 9c5e1e40)
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
17set testdir [file dirname $argv0]
18source $testdir/tester.tcl
19source $testdir/lock_common.tcl
20set testprefix shared9
21
22ifcapable !view||!trigger||!shared_cache {
23  finish_test
24  return
25}
26
27db close
28set enable_shared_cache [sqlite3_enable_shared_cache 1]
29
30sqlite3 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'" } {}
52do_test 1.3 { db2 eval "SELECT * FROM v1"             } {}
53do_test 1.4 { db2 eval "INSERT INTO t2 VALUES(3, 4)"  } {}
54
55ifcapable 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
77db1 close
78db2 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#
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
139forcedelete 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
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#
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
197do_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
208do_test 3.3 {
209  db2 eval { SELECT * FROM t2 }
210} {1 2}
211
212do_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.
218do_test 3.5 {
219  set ::busyhandler_invoked_for
220} {db1}
221do_test 3.6 {
222  close $::tf
223  db1 eval COMMIT
224} {}
225
226db1 close
227db2 close
228
229sqlite3_enable_shared_cache $::enable_shared_cache
230finish_test
231