blob: 8eea636d9fb3bf67052939044359b4fe12f224af [file] [log] [blame]
danielk1977aef0bf62005-12-30 16:28:01 +00001# 2005 December 30
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#***********************************************************************
danielk1977aef0bf62005-12-30 16:28:01 +000011#
danielk19774b202ae2006-01-23 05:50:58 +000012# $Id: shared.test,v 1.20 2006/01/23 05:50:58 danielk1977 Exp $
danielk1977aef0bf62005-12-30 16:28:01 +000013
14set testdir [file dirname $argv0]
15source $testdir/tester.tcl
16db close
17
18ifcapable !shared_cache {
19 finish_test
20 return
21}
danielk1977a96a7102006-01-16 12:46:41 +000022
danielk1977da184232006-01-05 11:34:32 +000023set ::enable_shared_cache [sqlite3_enable_shared_cache 1]
danielk1977aef0bf62005-12-30 16:28:01 +000024
danielk1977a96a7102006-01-16 12:46:41 +000025foreach av [list 0 1] {
26
danielk1977bab45c62006-01-16 15:14:27 +000027# Open the database connection and execute the auto-vacuum pragma
28file delete -force test.db
29sqlite3 db test.db
30
31ifcapable autovacuum {
32 do_test shared-[expr $av+1].1.0 {
33 execsql "pragma auto_vacuum=$::av"
34 execsql {pragma auto_vacuum}
35 } "$av"
36} else {
37 if {$av} {
38 db close
39 break
40 }
danielk1977a96a7102006-01-16 12:46:41 +000041}
42
danielk1977191c3e72006-01-19 07:18:14 +000043# $av is currently 0 if this loop iteration is to test with auto-vacuum turned
44# off, and 1 if it is turned on. Increment it so that (1 -> no auto-vacuum)
45# and (2 -> auto-vacuum). The sole reason for this is so that it looks nicer
46# when we use this variable as part of test-case names.
47#
danielk1977a96a7102006-01-16 12:46:41 +000048incr av
49
danielk1977aef0bf62005-12-30 16:28:01 +000050# Test organization:
51#
52# shared-1.*: Simple test to verify basic sanity of table level locking when
53# two connections share a pager cache.
54# shared-2.*: Test that a read transaction can co-exist with a
55# write-transaction, including a simple test to ensure the
56# external locking protocol is still working.
danielk1977da184232006-01-05 11:34:32 +000057# shared-3.*: Simple test of read-uncommitted mode.
danielk1977de0fe3e2006-01-06 06:33:12 +000058# shared-4.*: Check that the schema is locked and unlocked correctly.
danielk1977aaf22682006-01-06 15:03:48 +000059# shared-5.*: Test that creating/dropping schema items works when databases
60# are attached in different orders to different handles.
danielk1977c00da102006-01-07 13:21:04 +000061# shared-6.*: Locking, UNION ALL queries and sub-queries.
danielk197714db2662006-01-09 16:12:04 +000062# shared-7.*: Autovacuum and shared-cache.
danielk1977ed429312006-01-19 08:43:31 +000063# shared-8.*: Tests related to the text encoding of shared-cache databases.
64# shared-9.*: TEMP triggers and shared-cache databases.
65# shared-10.*: Tests of sqlite3_close().
danielk19774b202ae2006-01-23 05:50:58 +000066# shared-11.*: Test transaction locking.
danielk1977de0fe3e2006-01-06 06:33:12 +000067#
danielk1977aef0bf62005-12-30 16:28:01 +000068
danielk1977a96a7102006-01-16 12:46:41 +000069do_test shared-$av.1.1 {
danielk1977aef0bf62005-12-30 16:28:01 +000070 # Open a second database on the file test.db. It should use the same pager
71 # cache and schema as the original connection. Verify that only 1 file is
72 # opened.
73 sqlite3 db2 test.db
danielk1977aef0bf62005-12-30 16:28:01 +000074 set ::sqlite_open_file_count
75} {1}
danielk1977a96a7102006-01-16 12:46:41 +000076do_test shared-$av.1.2 {
danielk1977aef0bf62005-12-30 16:28:01 +000077 # Add a table and a single row of data via the first connection.
78 # Ensure that the second connection can see them.
79 execsql {
80 CREATE TABLE abc(a, b, c);
81 INSERT INTO abc VALUES(1, 2, 3);
82 } db
83 execsql {
84 SELECT * FROM abc;
85 } db2
86} {1 2 3}
danielk1977a96a7102006-01-16 12:46:41 +000087do_test shared-$av.1.3 {
danielk1977aef0bf62005-12-30 16:28:01 +000088 # Have the first connection begin a transaction and obtain a read-lock
89 # on table abc. This should not prevent the second connection from
90 # querying abc.
91 execsql {
92 BEGIN;
93 SELECT * FROM abc;
94 }
95 execsql {
96 SELECT * FROM abc;
97 } db2
98} {1 2 3}
danielk1977a96a7102006-01-16 12:46:41 +000099do_test shared-$av.1.4 {
danielk1977aef0bf62005-12-30 16:28:01 +0000100 # Try to insert a row into abc via connection 2. This should fail because
101 # of the read-lock connection 1 is holding on table abc (obtained in the
102 # previous test case).
103 catchsql {
104 INSERT INTO abc VALUES(4, 5, 6);
105 } db2
danielk1977c00da102006-01-07 13:21:04 +0000106} {1 {database table is locked: abc}}
danielk1977a96a7102006-01-16 12:46:41 +0000107do_test shared-$av.1.5 {
danielk1977da184232006-01-05 11:34:32 +0000108 # Using connection 2 (the one without the open transaction), try to create
109 # a new table. This should fail because of the open read transaction
110 # held by connection 1.
111 catchsql {
112 CREATE TABLE def(d, e, f);
113 } db2
danielk1977c00da102006-01-07 13:21:04 +0000114} {1 {database table is locked: sqlite_master}}
danielk1977a96a7102006-01-16 12:46:41 +0000115do_test shared-$av.1.6 {
danielk1977da184232006-01-05 11:34:32 +0000116 # Upgrade connection 1's transaction to a write transaction. Create
117 # a new table - def - and insert a row into it. Because the connection 1
118 # transaction modifies the schema, it should not be possible for
119 # connection 2 to access the database at all until the connection 1
120 # has finished the transaction.
danielk1977aef0bf62005-12-30 16:28:01 +0000121 execsql {
122 CREATE TABLE def(d, e, f);
danielk1977aef0bf62005-12-30 16:28:01 +0000123 INSERT INTO def VALUES('IV', 'V', 'VI');
124 }
125} {}
danielk1977a96a7102006-01-16 12:46:41 +0000126do_test shared-$av.1.7 {
danielk1977aef0bf62005-12-30 16:28:01 +0000127 # Read from the sqlite_master table with connection 1 (inside the
danielk1977da184232006-01-05 11:34:32 +0000128 # transaction). Then test that we can not do this with connection 2. This
129 # is because of the schema-modified lock established by connection 1
130 # in the previous test case.
danielk1977aef0bf62005-12-30 16:28:01 +0000131 execsql {
132 SELECT * FROM sqlite_master;
133 }
134 catchsql {
danielk1977da184232006-01-05 11:34:32 +0000135 SELECT * FROM sqlite_master;
danielk1977aef0bf62005-12-30 16:28:01 +0000136 } db2
danielk1977c87d34d2006-01-06 13:00:28 +0000137} {1 {database schema is locked: main}}
danielk1977a96a7102006-01-16 12:46:41 +0000138do_test shared-$av.1.8 {
danielk1977aef0bf62005-12-30 16:28:01 +0000139 # Commit the connection 1 transaction.
140 execsql {
141 COMMIT;
142 }
143} {}
144
danielk1977a96a7102006-01-16 12:46:41 +0000145do_test shared-$av.2.1 {
danielk1977aef0bf62005-12-30 16:28:01 +0000146 # Open connection db3 to the database. Use a different path to the same
147 # file so that db3 does *not* share the same pager cache as db and db2
148 # (there should be two open file handles).
149 sqlite3 db3 ./test.db
150 set ::sqlite_open_file_count
151} {2}
danielk1977a96a7102006-01-16 12:46:41 +0000152do_test shared-$av.2.2 {
danielk1977aef0bf62005-12-30 16:28:01 +0000153 # Start read transactions on db and db2 (the shared pager cache). Ensure
154 # db3 cannot write to the database.
155 execsql {
156 BEGIN;
157 SELECT * FROM abc;
158 }
159 execsql {
160 BEGIN;
161 SELECT * FROM abc;
162 } db2
163 catchsql {
164 INSERT INTO abc VALUES(1, 2, 3);
165 } db2
danielk1977c00da102006-01-07 13:21:04 +0000166} {1 {database table is locked: abc}}
danielk1977a96a7102006-01-16 12:46:41 +0000167do_test shared-$av.2.3 {
danielk1977aef0bf62005-12-30 16:28:01 +0000168 # Turn db's transaction into a write-transaction. db3 should still be
169 # able to read from table def (but will not see the new row). Connection
170 # db2 should not be able to read def (because of the write-lock).
171
172# Todo: The failed "INSERT INTO abc ..." statement in the above test
173# has started a write-transaction on db2 (should this be so?). This
174# would prevent connection db from starting a write-transaction. So roll the
175# db2 transaction back and replace it with a new read transaction.
176 execsql {
177 ROLLBACK;
178 BEGIN;
179 SELECT * FROM abc;
180 } db2
181
182 execsql {
183 INSERT INTO def VALUES('VII', 'VIII', 'IX');
184 }
185 concat [
186 catchsql { SELECT * FROM def; } db3
187 ] [
188 catchsql { SELECT * FROM def; } db2
189 ]
danielk1977c00da102006-01-07 13:21:04 +0000190} {0 {IV V VI} 1 {database table is locked: def}}
danielk1977a96a7102006-01-16 12:46:41 +0000191do_test shared-$av.2.4 {
danielk1977aef0bf62005-12-30 16:28:01 +0000192 # Commit the open transaction on db. db2 still holds a read-transaction.
193 # This should prevent db3 from writing to the database, but not from
194 # reading.
195 execsql {
196 COMMIT;
197 }
198 concat [
199 catchsql { SELECT * FROM def; } db3
200 ] [
201 catchsql { INSERT INTO def VALUES('X', 'XI', 'XII'); } db3
202 ]
danielk1977da184232006-01-05 11:34:32 +0000203} {0 {IV V VI VII VIII IX} 1 {database is locked}}
danielk1977aef0bf62005-12-30 16:28:01 +0000204
danielk1977da184232006-01-05 11:34:32 +0000205catchsql COMMIT db2
206
danielk1977a96a7102006-01-16 12:46:41 +0000207do_test shared-$av.3.1.1 {
danielk1977da184232006-01-05 11:34:32 +0000208 # This test case starts a linear scan of table 'seq' using a
209 # read-uncommitted connection. In the middle of the scan, rows are added
210 # to the end of the seq table (ahead of the current cursor position).
211 # The uncommitted rows should be included in the results of the scan.
212 execsql "
danielk1977191c3e72006-01-19 07:18:14 +0000213 CREATE TABLE seq(i PRIMARY KEY, x);
danielk1977da184232006-01-05 11:34:32 +0000214 INSERT INTO seq VALUES(1, '[string repeat X 500]');
215 INSERT INTO seq VALUES(2, '[string repeat X 500]');
216 "
217 execsql {SELECT * FROM sqlite_master} db2
218 execsql {PRAGMA read_uncommitted = 1} db2
219
220 set ret [list]
danielk1977191c3e72006-01-19 07:18:14 +0000221 db2 eval {SELECT i FROM seq ORDER BY i} {
danielk1977da184232006-01-05 11:34:32 +0000222 if {$i < 4} {
danielk19771576cd92006-01-14 08:02:28 +0000223 set max [execsql {SELECT max(i) FROM seq}]
224 db eval {
danielk19773bdca9c2006-01-17 09:35:01 +0000225 INSERT INTO seq SELECT i + :max, x FROM seq;
danielk1977da184232006-01-05 11:34:32 +0000226 }
227 }
228 lappend ret $i
229 }
230 set ret
231} {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16}
danielk1977a96a7102006-01-16 12:46:41 +0000232do_test shared-$av.3.1.2 {
danielk1977da184232006-01-05 11:34:32 +0000233 # Another linear scan through table seq using a read-uncommitted connection.
234 # This time, delete each row as it is read. Should not affect the results of
235 # the scan, but the table should be empty after the scan is concluded
236 # (test 3.1.3 verifies this).
237 set ret [list]
238 db2 eval {SELECT i FROM seq} {
danielk19773bdca9c2006-01-17 09:35:01 +0000239 db eval {DELETE FROM seq WHERE i = :i}
danielk1977da184232006-01-05 11:34:32 +0000240 lappend ret $i
241 }
242 set ret
243} {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16}
danielk1977a96a7102006-01-16 12:46:41 +0000244do_test shared-$av.3.1.3 {
danielk1977da184232006-01-05 11:34:32 +0000245 execsql {
246 SELECT * FROM seq;
247 }
248} {}
danielk1977aef0bf62005-12-30 16:28:01 +0000249
250catch {db close}
251catch {db2 close}
252catch {db3 close}
253
danielk1977de0fe3e2006-01-06 06:33:12 +0000254#--------------------------------------------------------------------------
255# Tests shared-4.* test that the schema locking rules are applied
256# correctly. i.e.:
257#
258# 1. All transactions require a read-lock on the schemas of databases they
259# access.
260# 2. Transactions that modify a database schema require a write-lock on that
261# schema.
262# 3. It is not possible to compile a statement while another handle has a
263# write-lock on the schema.
264#
265
266# Open two database handles db and db2. Each has a single attach database
267# (as well as main):
268#
269# db.main -> ./test.db
270# db.test2 -> ./test2.db
271# db2.main -> ./test2.db
272# db2.test -> ./test.db
273#
274file delete -force test.db
275file delete -force test2.db
276file delete -force test2.db-journal
277sqlite3 db test.db
278sqlite3 db2 test2.db
danielk1977a96a7102006-01-16 12:46:41 +0000279do_test shared-$av.4.1.1 {
danielk1977de0fe3e2006-01-06 06:33:12 +0000280 set sqlite_open_file_count
281} {2}
danielk1977a96a7102006-01-16 12:46:41 +0000282do_test shared-$av.4.1.2 {
danielk1977de0fe3e2006-01-06 06:33:12 +0000283 execsql {ATTACH 'test2.db' AS test2}
284 set sqlite_open_file_count
285} {2}
danielk1977a96a7102006-01-16 12:46:41 +0000286do_test shared-$av.4.1.3 {
danielk1977de0fe3e2006-01-06 06:33:12 +0000287 execsql {ATTACH 'test.db' AS test} db2
288 set sqlite_open_file_count
289} {2}
290
danielk1977c87d34d2006-01-06 13:00:28 +0000291# Sanity check: Create a table in ./test.db via handle db, and test that handle
292# db2 can "see" the new table immediately. A handle using a seperate pager
293# cache would have to reload the database schema before this were possible.
294#
danielk1977a96a7102006-01-16 12:46:41 +0000295do_test shared-$av.4.2.1 {
danielk1977de0fe3e2006-01-06 06:33:12 +0000296 execsql {
297 CREATE TABLE abc(a, b, c);
danielk1977c87d34d2006-01-06 13:00:28 +0000298 CREATE TABLE def(d, e, f);
danielk1977de0fe3e2006-01-06 06:33:12 +0000299 INSERT INTO abc VALUES('i', 'ii', 'iii');
danielk1977c87d34d2006-01-06 13:00:28 +0000300 INSERT INTO def VALUES('I', 'II', 'III');
danielk1977de0fe3e2006-01-06 06:33:12 +0000301 }
302} {}
danielk1977a96a7102006-01-16 12:46:41 +0000303do_test shared-$av.4.2.2 {
danielk1977de0fe3e2006-01-06 06:33:12 +0000304 execsql {
305 SELECT * FROM test.abc;
306 } db2
307} {i ii iii}
308
danielk1977c87d34d2006-01-06 13:00:28 +0000309# Open a read-transaction and read from table abc via handle 2. Check that
310# handle 1 can read table abc. Check that handle 1 cannot modify table abc
311# or the database schema. Then check that handle 1 can modify table def.
312#
danielk1977a96a7102006-01-16 12:46:41 +0000313do_test shared-$av.4.3.1 {
danielk1977c87d34d2006-01-06 13:00:28 +0000314 execsql {
315 BEGIN;
316 SELECT * FROM test.abc;
317 } db2
318} {i ii iii}
danielk1977a96a7102006-01-16 12:46:41 +0000319do_test shared-$av.4.3.2 {
danielk1977c87d34d2006-01-06 13:00:28 +0000320 catchsql {
321 INSERT INTO abc VALUES('iv', 'v', 'vi');
322 }
danielk1977c00da102006-01-07 13:21:04 +0000323} {1 {database table is locked: abc}}
danielk1977a96a7102006-01-16 12:46:41 +0000324do_test shared-$av.4.3.3 {
danielk1977c87d34d2006-01-06 13:00:28 +0000325 catchsql {
326 CREATE TABLE ghi(g, h, i);
327 }
danielk1977c00da102006-01-07 13:21:04 +0000328} {1 {database table is locked: sqlite_master}}
danielk1977a96a7102006-01-16 12:46:41 +0000329do_test shared-$av.4.3.3 {
danielk1977c87d34d2006-01-06 13:00:28 +0000330 catchsql {
331 INSERT INTO def VALUES('IV', 'V', 'VI');
332 }
333} {0 {}}
danielk1977a96a7102006-01-16 12:46:41 +0000334do_test shared-$av.4.3.4 {
danielk1977c87d34d2006-01-06 13:00:28 +0000335 # Cleanup: commit the transaction opened by db2.
336 execsql {
337 COMMIT
338 } db2
339} {}
340
341# Open a write-transaction using handle 1 and modify the database schema.
342# Then try to execute a compiled statement to read from the same
343# database via handle 2 (fails to get the lock on sqlite_master). Also
344# try to compile a read of the same database using handle 2 (also fails).
345# Finally, compile a read of the other database using handle 2. This
346# should also fail.
347#
danielk1977ff890792006-01-16 16:24:25 +0000348ifcapable compound {
349 do_test shared-$av.4.4.1.2 {
350 # Sanity check 1: Check that the schema is what we think it is when viewed
351 # via handle 1.
352 execsql {
353 CREATE TABLE test2.ghi(g, h, i);
354 SELECT 'test.db:'||name FROM sqlite_master
355 UNION ALL
356 SELECT 'test2.db:'||name FROM test2.sqlite_master;
357 }
358 } {test.db:abc test.db:def test2.db:ghi}
359 do_test shared-$av.4.4.1.2 {
360 # Sanity check 2: Check that the schema is what we think it is when viewed
361 # via handle 2.
362 execsql {
363 SELECT 'test2.db:'||name FROM sqlite_master
364 UNION ALL
365 SELECT 'test.db:'||name FROM test.sqlite_master;
366 } db2
367 } {test2.db:ghi test.db:abc test.db:def}
368}
danielk1977c87d34d2006-01-06 13:00:28 +0000369
danielk1977a96a7102006-01-16 12:46:41 +0000370do_test shared-$av.4.4.2 {
danielk1977c87d34d2006-01-06 13:00:28 +0000371 set ::DB2 [sqlite3_connection_pointer db2]
372 set sql {SELECT * FROM abc}
373 set ::STMT1 [sqlite3_prepare $::DB2 $sql -1 DUMMY]
374 execsql {
375 BEGIN;
376 CREATE TABLE jkl(j, k, l);
377 }
378 sqlite3_step $::STMT1
379} {SQLITE_ERROR}
danielk1977a96a7102006-01-16 12:46:41 +0000380do_test shared-$av.4.4.3 {
danielk1977c87d34d2006-01-06 13:00:28 +0000381 sqlite3_finalize $::STMT1
382} {SQLITE_LOCKED}
danielk1977a96a7102006-01-16 12:46:41 +0000383do_test shared-$av.4.4.4 {
danielk1977c87d34d2006-01-06 13:00:28 +0000384 set rc [catch {
385 set ::STMT1 [sqlite3_prepare $::DB2 $sql -1 DUMMY]
386 } msg]
387 list $rc $msg
388} {1 {(6) database schema is locked: test}}
danielk1977a96a7102006-01-16 12:46:41 +0000389do_test shared-$av.4.4.5 {
danielk1977c87d34d2006-01-06 13:00:28 +0000390 set rc [catch {
391 set ::STMT1 [sqlite3_prepare $::DB2 "SELECT * FROM ghi" -1 DUMMY]
392 } msg]
393 list $rc $msg
394} {1 {(6) database schema is locked: test}}
395
danielk1977aaf22682006-01-06 15:03:48 +0000396
danielk1977de0fe3e2006-01-06 06:33:12 +0000397catch {db2 close}
398catch {db close}
399
danielk1977aaf22682006-01-06 15:03:48 +0000400#--------------------------------------------------------------------------
401# Tests shared-5.*
402#
403foreach db [list test.db test1.db test2.db test3.db] {
404 file delete -force $db ${db}-journal
405}
danielk1977a96a7102006-01-16 12:46:41 +0000406do_test shared-$av.5.1.1 {
danielk1977aaf22682006-01-06 15:03:48 +0000407 sqlite3 db1 test.db
408 sqlite3 db2 test.db
409 execsql {
410 ATTACH 'test1.db' AS test1;
411 ATTACH 'test2.db' AS test2;
412 ATTACH 'test3.db' AS test3;
413 } db1
414 execsql {
415 ATTACH 'test3.db' AS test3;
416 ATTACH 'test2.db' AS test2;
417 ATTACH 'test1.db' AS test1;
418 } db2
419} {}
danielk1977a96a7102006-01-16 12:46:41 +0000420do_test shared-$av.5.1.2 {
danielk1977aaf22682006-01-06 15:03:48 +0000421 execsql {
422 CREATE TABLE test1.t1(a, b);
423 CREATE INDEX test1.i1 ON t1(a, b);
danielk1977aaf22682006-01-06 15:03:48 +0000424 } db1
danielk19773bdca9c2006-01-17 09:35:01 +0000425} {}
426ifcapable view {
427 do_test shared-$av.5.1.3 {
428 execsql {
429 CREATE VIEW test1.v1 AS SELECT * FROM t1;
430 } db1
431 } {}
432}
433ifcapable trigger {
434 do_test shared-$av.5.1.4 {
435 execsql {
436 CREATE TRIGGER test1.trig1 AFTER INSERT ON t1 BEGIN
437 INSERT INTO t1 VALUES(new.a, new.b);
438 END;
439 } db1
440 } {}
441}
442do_test shared-$av.5.1.5 {
danielk1977aaf22682006-01-06 15:03:48 +0000443 execsql {
444 DROP INDEX i1;
danielk19773bdca9c2006-01-17 09:35:01 +0000445 } db2
446} {}
447ifcapable view {
448 do_test shared-$av.5.1.6 {
449 execsql {
450 DROP VIEW v1;
451 } db2
452 } {}
453}
454ifcapable trigger {
455 do_test shared-$av.5.1.7 {
456 execsql {
457 DROP TRIGGER trig1;
458 } db2
459 } {}
460}
461do_test shared-$av.5.1.8 {
462 execsql {
danielk1977aaf22682006-01-06 15:03:48 +0000463 DROP TABLE t1;
464 } db2
465} {}
danielk1977ff890792006-01-16 16:24:25 +0000466ifcapable compound {
danielk19773bdca9c2006-01-17 09:35:01 +0000467 do_test shared-$av.5.1.9 {
danielk1977ff890792006-01-16 16:24:25 +0000468 execsql {
469 SELECT * FROM sqlite_master UNION ALL SELECT * FROM test1.sqlite_master
470 } db1
471 } {}
472}
danielk1977aaf22682006-01-06 15:03:48 +0000473
danielk1977c00da102006-01-07 13:21:04 +0000474#--------------------------------------------------------------------------
475# Tests shared-6.* test that a query obtains all the read-locks it needs
476# before starting execution of the query. This means that there is no chance
477# some rows of data will be returned before a lock fails and SQLITE_LOCK
478# is returned.
479#
danielk1977a96a7102006-01-16 12:46:41 +0000480do_test shared-$av.6.1.1 {
danielk1977c00da102006-01-07 13:21:04 +0000481 execsql {
482 CREATE TABLE t1(a, b);
483 CREATE TABLE t2(a, b);
484 INSERT INTO t1 VALUES(1, 2);
485 INSERT INTO t2 VALUES(3, 4);
486 } db1
danielk1977ff890792006-01-16 16:24:25 +0000487} {}
488ifcapable compound {
489 do_test shared-$av.6.1.2 {
490 execsql {
491 SELECT * FROM t1 UNION ALL SELECT * FROM t2;
492 } db2
493 } {1 2 3 4}
494}
495do_test shared-$av.6.1.3 {
danielk1977c00da102006-01-07 13:21:04 +0000496 # Establish a write lock on table t2 via connection db2. Then make a
497 # UNION all query using connection db1 that first accesses t1, followed
498 # by t2. If the locks are grabbed at the start of the statement (as
499 # they should be), no rows are returned. If (as was previously the case)
500 # they are grabbed as the tables are accessed, the t1 rows will be
501 # returned before the query fails.
502 #
503 execsql {
504 BEGIN;
505 INSERT INTO t2 VALUES(5, 6);
506 } db2
507 set ret [list]
508 catch {
509 db1 eval {SELECT * FROM t1 UNION ALL SELECT * FROM t2} {
510 lappend ret $a $b
511 }
512 }
513 set ret
514} {}
danielk1977ff890792006-01-16 16:24:25 +0000515do_test shared-$av.6.1.4 {
danielk1977c00da102006-01-07 13:21:04 +0000516 execsql {
517 COMMIT;
518 BEGIN;
519 INSERT INTO t1 VALUES(7, 8);
520 } db2
521 set ret [list]
522 catch {
523 db1 eval {
524 SELECT (CASE WHEN a>4 THEN (SELECT a FROM t1) ELSE 0 END) AS d FROM t2;
525 } {
526 lappend ret $d
527 }
528 }
529 set ret
530} {}
531
danielk1977aaf22682006-01-06 15:03:48 +0000532catch {db1 close}
533catch {db2 close}
danielk1977e501b892006-01-09 06:29:47 +0000534foreach f [list test.db test2.db] {
535 file delete -force $f ${f}-journal
536}
537
538#--------------------------------------------------------------------------
539# Tests shared-7.* test auto-vacuum does not invalidate cursors from
540# other shared-cache users when it reorganizes the database on
541# COMMIT.
542#
danielk1977a96a7102006-01-16 12:46:41 +0000543do_test shared-$av.7.1 {
danielk197714db2662006-01-09 16:12:04 +0000544 # This test case sets up a test database in auto-vacuum mode consisting
545 # of two tables, t1 and t2. Both have a single index. Table t1 is
546 # populated first (so consists of pages toward the start of the db file),
547 # t2 second (pages toward the end of the file).
danielk1977e501b892006-01-09 06:29:47 +0000548 sqlite3 db test.db
549 sqlite3 db2 test.db
550 execsql {
danielk1977e501b892006-01-09 06:29:47 +0000551 BEGIN;
552 CREATE TABLE t1(a PRIMARY KEY, b);
553 CREATE TABLE t2(a PRIMARY KEY, b);
554 }
drh7a91dd82006-01-11 01:08:34 +0000555 set ::contents {}
danielk1977e501b892006-01-09 06:29:47 +0000556 for {set i 0} {$i < 100} {incr i} {
557 set a [string repeat "$i " 20]
558 set b [string repeat "$i " 20]
559 db eval {
danielk19773bdca9c2006-01-17 09:35:01 +0000560 INSERT INTO t1 VALUES(:a, :b);
danielk1977e501b892006-01-09 06:29:47 +0000561 }
562 lappend ::contents [list [expr $i+1] $a $b]
563 }
564 execsql {
565 INSERT INTO t2 SELECT * FROM t1;
566 COMMIT;
567 }
danielk1977bab45c62006-01-16 15:14:27 +0000568} {}
danielk1977a96a7102006-01-16 12:46:41 +0000569do_test shared-$av.7.2 {
danielk197714db2662006-01-09 16:12:04 +0000570 # This test case deletes the contents of table t1 (the one at the start of
571 # the file) while many cursors are open on table t2 and it's index. All of
572 # the non-root pages will be moved from the end to the start of the file
573 # when the DELETE is committed - this test verifies that moving the pages
574 # does not disturb the open cursors.
575 #
576
danielk1977e501b892006-01-09 06:29:47 +0000577 proc lockrow {db tbl oids body} {
578 set ret [list]
579 db eval "SELECT oid AS i, a, b FROM $tbl ORDER BY a" {
580 if {$i==[lindex $oids 0]} {
581 set noids [lrange $oids 1 end]
582 if {[llength $noids]==0} {
583 set subret [eval $body]
584 } else {
585 set subret [lockrow $db $tbl $noids $body]
586 }
587 }
588 lappend ret [list $i $a $b]
589 }
590 return [linsert $subret 0 $ret]
591 }
592 proc locktblrows {db tbl body} {
593 set oids [db eval "SELECT oid FROM $tbl"]
594 lockrow $db $tbl $oids $body
595 }
596
597 set scans [locktblrows db t2 {
598 execsql {
599 DELETE FROM t1;
600 } db2
601 }]
602 set error 0
danielk197714db2662006-01-09 16:12:04 +0000603
604 # Test that each SELECT query returned the expected contents of t2.
danielk1977e501b892006-01-09 06:29:47 +0000605 foreach s $scans {
606 if {[lsort -integer -index 0 $s]!=$::contents} {
607 set error 1
608 }
609 }
610 set error
611} {0}
612
613catch {db close}
614catch {db2 close}
drh7a91dd82006-01-11 01:08:34 +0000615unset -nocomplain contents
danielk1977aaf22682006-01-06 15:03:48 +0000616
danielk197714db2662006-01-09 16:12:04 +0000617#--------------------------------------------------------------------------
618# The following tests try to trick the shared-cache code into assuming
619# the wrong encoding for a database.
620#
621file delete -force test.db test.db-journal
danielk19773bdca9c2006-01-17 09:35:01 +0000622ifcapable utf16 {
623 do_test shared-$av.8.1.1 {
624 sqlite3 db test.db
625 execsql {
626 PRAGMA encoding = 'UTF-16';
627 SELECT * FROM sqlite_master;
628 }
629 } {}
630 do_test shared-$av.8.1.2 {
631 string range [execsql {PRAGMA encoding;}] 0 end-2
632 } {UTF-16}
633 do_test shared-$av.8.1.3 {
634 sqlite3 db2 test.db
635 execsql {
636 PRAGMA encoding = 'UTF-8';
637 CREATE TABLE abc(a, b, c);
638 } db2
639 } {}
640 do_test shared-$av.8.1.4 {
641 execsql {
642 SELECT * FROM sqlite_master;
643 }
644 } "table abc abc [expr $AUTOVACUUM?3:2] {CREATE TABLE abc(a, b, c)}"
645 do_test shared-$av.8.1.5 {
646 db2 close
647 execsql {
648 PRAGMA encoding;
649 }
650 } {UTF-8}
651 file delete -force test2.db test2.db-journal
652 do_test shared-$av.8.2.1 {
653 execsql {
654 ATTACH 'test2.db' AS aux;
655 SELECT * FROM aux.sqlite_master;
656 }
657 } {}
658 do_test shared-$av.8.2.2 {
659 sqlite3 db2 test2.db
660 execsql {
661 PRAGMA encoding = 'UTF-16';
662 CREATE TABLE def(d, e, f);
663 } db2
664 string range [execsql {PRAGMA encoding;} db2] 0 end-2
665 } {UTF-16}
666 do_test shared-$av.8.2.3 {
667 catchsql {
668 SELECT * FROM aux.sqlite_master;
669 }
670 } {1 {attached databases must use the same text encoding as main database}}
671}
danielk197714db2662006-01-09 16:12:04 +0000672
673catch {db close}
674catch {db2 close}
danielk1977eecfb3e2006-01-10 12:31:39 +0000675file delete -force test.db test2.db
676
danielk1977eecfb3e2006-01-10 12:31:39 +0000677#---------------------------------------------------------------------------
678# The following tests - shared-9.* - test interactions between TEMP triggers
679# and shared-schemas.
680#
681ifcapable trigger&&tempdb {
682
danielk1977a96a7102006-01-16 12:46:41 +0000683do_test shared-$av.9.1 {
danielk1977eecfb3e2006-01-10 12:31:39 +0000684 sqlite3 db test.db
685 sqlite3 db2 test.db
686 execsql {
687 CREATE TABLE abc(a, b, c);
688 CREATE TABLE abc_mirror(a, b, c);
689 CREATE TEMP TRIGGER BEFORE INSERT ON abc BEGIN
690 INSERT INTO abc_mirror(a, b, c) VALUES(new.a, new.b, new.c);
691 END;
692 INSERT INTO abc VALUES(1, 2, 3);
693 SELECT * FROM abc_mirror;
694 }
695} {1 2 3}
danielk1977a96a7102006-01-16 12:46:41 +0000696do_test shared-$av.9.2 {
danielk1977eecfb3e2006-01-10 12:31:39 +0000697 execsql {
698 INSERT INTO abc VALUES(4, 5, 6);
699 SELECT * FROM abc_mirror;
700 } db2
701} {1 2 3}
danielk1977a96a7102006-01-16 12:46:41 +0000702do_test shared-$av.9.3 {
danielk1977eecfb3e2006-01-10 12:31:39 +0000703 db close
704 db2 close
705} {}
706
707} ; # End shared-9.*
danielk197714db2662006-01-09 16:12:04 +0000708
danielk1977b597f742006-01-15 11:39:18 +0000709#---------------------------------------------------------------------------
710# The following tests - shared-10.* - test that the library behaves
711# correctly when a connection to a shared-cache is closed.
712#
danielk1977a96a7102006-01-16 12:46:41 +0000713do_test shared-$av.10.1 {
danielk1977b597f742006-01-15 11:39:18 +0000714 # Create a small sample database with two connections to it (db and db2).
715 file delete -force test.db
716 sqlite3 db test.db
717 sqlite3 db2 test.db
718 execsql {
719 CREATE TABLE ab(a PRIMARY KEY, b);
720 CREATE TABLE de(d PRIMARY KEY, e);
721 INSERT INTO ab VALUES('Chiang Mai', 100000);
722 INSERT INTO ab VALUES('Bangkok', 8000000);
723 INSERT INTO de VALUES('Ubon', 120000);
724 INSERT INTO de VALUES('Khon Kaen', 200000);
725 }
726} {}
danielk1977a96a7102006-01-16 12:46:41 +0000727do_test shared-$av.10.2 {
danielk1977b597f742006-01-15 11:39:18 +0000728 # Open a read-transaction with the first connection, a write-transaction
729 # with the second.
730 execsql {
731 BEGIN;
732 SELECT * FROM ab;
733 }
734 execsql {
735 BEGIN;
736 INSERT INTO de VALUES('Pataya', 30000);
737 } db2
738} {}
danielk1977a96a7102006-01-16 12:46:41 +0000739do_test shared-$av.10.3 {
danielk1977b597f742006-01-15 11:39:18 +0000740 # An external connection should be able to read the database, but not
741 # prepare a write operation.
742 sqlite3 db3 ./test.db
743 execsql {
744 SELECT * FROM ab;
745 } db3
746 catchsql {
747 BEGIN;
748 INSERT INTO de VALUES('Pataya', 30000);
749 } db3
750} {1 {database is locked}}
danielk1977a96a7102006-01-16 12:46:41 +0000751do_test shared-$av.10.4 {
danielk1977b597f742006-01-15 11:39:18 +0000752 # Close the connection with the write-transaction open
753 db2 close
754} {}
danielk1977a96a7102006-01-16 12:46:41 +0000755do_test shared-$av.10.5 {
danielk1977b597f742006-01-15 11:39:18 +0000756 # Test that the db2 transaction has been automatically rolled back.
757 # If it has not the ('Pataya', 30000) entry will still be in the table.
758 execsql {
759 SELECT * FROM de;
760 }
761} {Ubon 120000 {Khon Kaen} 200000}
danielk1977a96a7102006-01-16 12:46:41 +0000762do_test shared-$av.10.5 {
danielk1977b597f742006-01-15 11:39:18 +0000763 # Closing db2 should have dropped the shared-cache back to a read-lock.
764 # So db3 should be able to prepare a write...
765 catchsql {INSERT INTO de VALUES('Pataya', 30000);} db3
766} {0 {}}
danielk1977a96a7102006-01-16 12:46:41 +0000767do_test shared-$av.10.6 {
danielk1977b597f742006-01-15 11:39:18 +0000768 # ... but not commit it.
769 catchsql {COMMIT} db3
770} {1 {database is locked}}
danielk1977a96a7102006-01-16 12:46:41 +0000771do_test shared-$av.10.7 {
danielk1977b597f742006-01-15 11:39:18 +0000772 # Commit the (read-only) db transaction. Check via db3 to make sure the
773 # contents of table "de" are still as they should be.
774 execsql {
775 COMMIT;
776 }
777 execsql {
778 SELECT * FROM de;
779 } db3
780} {Ubon 120000 {Khon Kaen} 200000 Pataya 30000}
danielk1977a96a7102006-01-16 12:46:41 +0000781do_test shared-$av.10.9 {
danielk1977b597f742006-01-15 11:39:18 +0000782 # Commit the external transaction.
783 catchsql {COMMIT} db3
784} {0 {}}
danielk1977a96a7102006-01-16 12:46:41 +0000785integrity_check shared-$av.10.10
786do_test shared-$av.10.11 {
danielk1977b597f742006-01-15 11:39:18 +0000787 db close
788 db3 close
789} {}
790
danielk19774b202ae2006-01-23 05:50:58 +0000791do_test shared-$av.11.1 {
792 file delete -force test.db
793 sqlite3 db test.db
794 sqlite3 db2 test.db
795 execsql {
796 CREATE TABLE abc(a, b, c);
797 CREATE TABLE abc2(a, b, c);
798 BEGIN;
799 INSERT INTO abc VALUES(1, 2, 3);
800 }
801} {}
802do_test shared-$av.11.2 {
803 catchsql {BEGIN;} db2
804 catchsql {SELECT * FROM abc;} db2
805} {1 {database table is locked: abc}}
806do_test shared-$av.11.3 {
807 catchsql {BEGIN} db2
808} {1 {cannot start a transaction within a transaction}}
809do_test shared-$av.11.4 {
810 catchsql {SELECT * FROM abc2;} db2
811} {0 {}}
812do_test shared-$av.11.5 {
813 catchsql {INSERT INTO abc2 VALUES(1, 2, 3);} db2
814} {1 {database is locked}}
815do_test shared-$av.11.6 {
816 catchsql {SELECT * FROM abc2}
817} {0 {}}
818do_test shared-$av.11.6 {
819 execsql {
820 ROLLBACK;
821 PRAGMA read_uncommitted = 1;
822 } db2
823} {}
824do_test shared-$av.11.7 {
825 execsql {
826 INSERT INTO abc2 VALUES(4, 5, 6);
827 INSERT INTO abc2 VALUES(7, 8, 9);
828 }
829} {}
830do_test shared-$av.11.8 {
831 set res [list]
832 breakpoint
833 db2 eval {
834 SELECT abc.a as I, abc2.a as II FROM abc, abc2;
835 } {
836 execsql {
837 DELETE FROM abc WHERE 1;
838 }
839 lappend res $I $II
840 }
841 set res
842} {1 4 {} 7}
843
844do_test shared-$av.11.11 {
845 db close
846 db2 close
847} {}
848
danielk1977a96a7102006-01-16 12:46:41 +0000849}
850
danielk1977aef0bf62005-12-30 16:28:01 +0000851sqlite3_enable_shared_cache $::enable_shared_cache
danielk1977a96a7102006-01-16 12:46:41 +0000852finish_test