Merge latest trunk changes with this branch.
[sqlite.git] / test / shared9.test
blob1982a593e34dbc8a85741aa3324229ab32d2f56f
1 # 2012 October 5
3 # The author disclaims copyright to this source code.  In place of
4 # a legal notice, here is a blessing:
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.
10 #***********************************************************************
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.
17 set testdir [file dirname $argv0]
18 source $testdir/tester.tcl
19 source $testdir/lock_common.tcl
20 set testprefix shared9
22 ifcapable !view||!trigger {
23   finish_test
24   return
27 db close
28 set enable_shared_cache [sqlite3_enable_shared_cache 1]
30 sqlite3 db1 test.db
31 sqlite3 db2 test.db
32 forcedelete test.db2
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;
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}
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)"  } {}
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   } {}
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}}
70   do_test 1.7 {
71     db1 eval {
72       SELECT * FROM t4 WHERE t4 MATCH 'c*';
73     }
74   } {{shared cache}}
77 db1 close
78 db2 close
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.
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
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
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.
111 forcedelete test.db test.db2
112 sqlite3 db1 test.db
113 sqlite3 db2 test.db
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}
118 db1 collate mycollate mycollate_db1
119 db2 collate mycollate mycollate_db2
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}
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
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}
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.
168 forcedelete test.db test.db2
169 sqlite3 db1 test.db
170 sqlite3 db2 test.db
172 proc busyhandler {handle args} {
173   set ::busyhandler_invoked_for $handle
174   return 1
176 db1 busy [list busyhandler db1]
177 db2 busy [list busyhandler db2]
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 } {}
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}
208 do_test 3.3 {
209   db2 eval { SELECT * FROM t2 }
210 } {1 2}
212 do_test 3.4 {
213   list [catch { db1 eval COMMIT } msg] $msg
214 } {1 {database is locked}}
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
229 sqlite3_enable_shared_cache $::enable_shared_cache
230 finish_test