blob: fe5483f6e67b958495cfa197d944a646f81955f4 [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#
danielk1977ed429312006-01-19 08:43:31 +000012# $Id: shared.test,v 1.19 2006/01/19 08:43:32 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().
danielk1977de0fe3e2006-01-06 06:33:12 +000066#
danielk1977aef0bf62005-12-30 16:28:01 +000067
danielk1977a96a7102006-01-16 12:46:41 +000068do_test shared-$av.1.1 {
danielk1977aef0bf62005-12-30 16:28:01 +000069 # Open a second database on the file test.db. It should use the same pager
70 # cache and schema as the original connection. Verify that only 1 file is
71 # opened.
72 sqlite3 db2 test.db
danielk1977aef0bf62005-12-30 16:28:01 +000073 set ::sqlite_open_file_count
74} {1}
danielk1977a96a7102006-01-16 12:46:41 +000075do_test shared-$av.1.2 {
danielk1977aef0bf62005-12-30 16:28:01 +000076 # Add a table and a single row of data via the first connection.
77 # Ensure that the second connection can see them.
78 execsql {
79 CREATE TABLE abc(a, b, c);
80 INSERT INTO abc VALUES(1, 2, 3);
81 } db
82 execsql {
83 SELECT * FROM abc;
84 } db2
85} {1 2 3}
danielk1977a96a7102006-01-16 12:46:41 +000086do_test shared-$av.1.3 {
danielk1977aef0bf62005-12-30 16:28:01 +000087 # Have the first connection begin a transaction and obtain a read-lock
88 # on table abc. This should not prevent the second connection from
89 # querying abc.
90 execsql {
91 BEGIN;
92 SELECT * FROM abc;
93 }
94 execsql {
95 SELECT * FROM abc;
96 } db2
97} {1 2 3}
danielk1977a96a7102006-01-16 12:46:41 +000098do_test shared-$av.1.4 {
danielk1977aef0bf62005-12-30 16:28:01 +000099 # Try to insert a row into abc via connection 2. This should fail because
100 # of the read-lock connection 1 is holding on table abc (obtained in the
101 # previous test case).
102 catchsql {
103 INSERT INTO abc VALUES(4, 5, 6);
104 } db2
danielk1977c00da102006-01-07 13:21:04 +0000105} {1 {database table is locked: abc}}
danielk1977a96a7102006-01-16 12:46:41 +0000106do_test shared-$av.1.5 {
danielk1977da184232006-01-05 11:34:32 +0000107 # Using connection 2 (the one without the open transaction), try to create
108 # a new table. This should fail because of the open read transaction
109 # held by connection 1.
110 catchsql {
111 CREATE TABLE def(d, e, f);
112 } db2
danielk1977c00da102006-01-07 13:21:04 +0000113} {1 {database table is locked: sqlite_master}}
danielk1977a96a7102006-01-16 12:46:41 +0000114do_test shared-$av.1.6 {
danielk1977da184232006-01-05 11:34:32 +0000115 # Upgrade connection 1's transaction to a write transaction. Create
116 # a new table - def - and insert a row into it. Because the connection 1
117 # transaction modifies the schema, it should not be possible for
118 # connection 2 to access the database at all until the connection 1
119 # has finished the transaction.
danielk1977aef0bf62005-12-30 16:28:01 +0000120 execsql {
121 CREATE TABLE def(d, e, f);
danielk1977aef0bf62005-12-30 16:28:01 +0000122 INSERT INTO def VALUES('IV', 'V', 'VI');
123 }
124} {}
danielk1977a96a7102006-01-16 12:46:41 +0000125do_test shared-$av.1.7 {
danielk1977aef0bf62005-12-30 16:28:01 +0000126 # Read from the sqlite_master table with connection 1 (inside the
danielk1977da184232006-01-05 11:34:32 +0000127 # transaction). Then test that we can not do this with connection 2. This
128 # is because of the schema-modified lock established by connection 1
129 # in the previous test case.
danielk1977aef0bf62005-12-30 16:28:01 +0000130 execsql {
131 SELECT * FROM sqlite_master;
132 }
133 catchsql {
danielk1977da184232006-01-05 11:34:32 +0000134 SELECT * FROM sqlite_master;
danielk1977aef0bf62005-12-30 16:28:01 +0000135 } db2
danielk1977c87d34d2006-01-06 13:00:28 +0000136} {1 {database schema is locked: main}}
danielk1977a96a7102006-01-16 12:46:41 +0000137do_test shared-$av.1.8 {
danielk1977aef0bf62005-12-30 16:28:01 +0000138 # Commit the connection 1 transaction.
139 execsql {
140 COMMIT;
141 }
142} {}
143
danielk1977a96a7102006-01-16 12:46:41 +0000144do_test shared-$av.2.1 {
danielk1977aef0bf62005-12-30 16:28:01 +0000145 # Open connection db3 to the database. Use a different path to the same
146 # file so that db3 does *not* share the same pager cache as db and db2
147 # (there should be two open file handles).
148 sqlite3 db3 ./test.db
149 set ::sqlite_open_file_count
150} {2}
danielk1977a96a7102006-01-16 12:46:41 +0000151do_test shared-$av.2.2 {
danielk1977aef0bf62005-12-30 16:28:01 +0000152 # Start read transactions on db and db2 (the shared pager cache). Ensure
153 # db3 cannot write to the database.
154 execsql {
155 BEGIN;
156 SELECT * FROM abc;
157 }
158 execsql {
159 BEGIN;
160 SELECT * FROM abc;
161 } db2
162 catchsql {
163 INSERT INTO abc VALUES(1, 2, 3);
164 } db2
danielk1977c00da102006-01-07 13:21:04 +0000165} {1 {database table is locked: abc}}
danielk1977a96a7102006-01-16 12:46:41 +0000166do_test shared-$av.2.3 {
danielk1977aef0bf62005-12-30 16:28:01 +0000167 # Turn db's transaction into a write-transaction. db3 should still be
168 # able to read from table def (but will not see the new row). Connection
169 # db2 should not be able to read def (because of the write-lock).
170
171# Todo: The failed "INSERT INTO abc ..." statement in the above test
172# has started a write-transaction on db2 (should this be so?). This
173# would prevent connection db from starting a write-transaction. So roll the
174# db2 transaction back and replace it with a new read transaction.
175 execsql {
176 ROLLBACK;
177 BEGIN;
178 SELECT * FROM abc;
179 } db2
180
181 execsql {
182 INSERT INTO def VALUES('VII', 'VIII', 'IX');
183 }
184 concat [
185 catchsql { SELECT * FROM def; } db3
186 ] [
187 catchsql { SELECT * FROM def; } db2
188 ]
danielk1977c00da102006-01-07 13:21:04 +0000189} {0 {IV V VI} 1 {database table is locked: def}}
danielk1977a96a7102006-01-16 12:46:41 +0000190do_test shared-$av.2.4 {
danielk1977aef0bf62005-12-30 16:28:01 +0000191 # Commit the open transaction on db. db2 still holds a read-transaction.
192 # This should prevent db3 from writing to the database, but not from
193 # reading.
194 execsql {
195 COMMIT;
196 }
197 concat [
198 catchsql { SELECT * FROM def; } db3
199 ] [
200 catchsql { INSERT INTO def VALUES('X', 'XI', 'XII'); } db3
201 ]
danielk1977da184232006-01-05 11:34:32 +0000202} {0 {IV V VI VII VIII IX} 1 {database is locked}}
danielk1977aef0bf62005-12-30 16:28:01 +0000203
danielk1977da184232006-01-05 11:34:32 +0000204catchsql COMMIT db2
205
danielk1977a96a7102006-01-16 12:46:41 +0000206do_test shared-$av.3.1.1 {
danielk1977da184232006-01-05 11:34:32 +0000207 # This test case starts a linear scan of table 'seq' using a
208 # read-uncommitted connection. In the middle of the scan, rows are added
209 # to the end of the seq table (ahead of the current cursor position).
210 # The uncommitted rows should be included in the results of the scan.
211 execsql "
danielk1977191c3e72006-01-19 07:18:14 +0000212 CREATE TABLE seq(i PRIMARY KEY, x);
danielk1977da184232006-01-05 11:34:32 +0000213 INSERT INTO seq VALUES(1, '[string repeat X 500]');
214 INSERT INTO seq VALUES(2, '[string repeat X 500]');
215 "
216 execsql {SELECT * FROM sqlite_master} db2
217 execsql {PRAGMA read_uncommitted = 1} db2
218
219 set ret [list]
danielk1977191c3e72006-01-19 07:18:14 +0000220 db2 eval {SELECT i FROM seq ORDER BY i} {
danielk1977da184232006-01-05 11:34:32 +0000221 if {$i < 4} {
danielk19771576cd92006-01-14 08:02:28 +0000222 set max [execsql {SELECT max(i) FROM seq}]
223 db eval {
danielk19773bdca9c2006-01-17 09:35:01 +0000224 INSERT INTO seq SELECT i + :max, x FROM seq;
danielk1977da184232006-01-05 11:34:32 +0000225 }
226 }
227 lappend ret $i
228 }
229 set ret
230} {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16}
danielk1977a96a7102006-01-16 12:46:41 +0000231do_test shared-$av.3.1.2 {
danielk1977da184232006-01-05 11:34:32 +0000232 # Another linear scan through table seq using a read-uncommitted connection.
233 # This time, delete each row as it is read. Should not affect the results of
234 # the scan, but the table should be empty after the scan is concluded
235 # (test 3.1.3 verifies this).
236 set ret [list]
237 db2 eval {SELECT i FROM seq} {
danielk19773bdca9c2006-01-17 09:35:01 +0000238 db eval {DELETE FROM seq WHERE i = :i}
danielk1977da184232006-01-05 11:34:32 +0000239 lappend ret $i
240 }
241 set ret
242} {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16}
danielk1977a96a7102006-01-16 12:46:41 +0000243do_test shared-$av.3.1.3 {
danielk1977da184232006-01-05 11:34:32 +0000244 execsql {
245 SELECT * FROM seq;
246 }
247} {}
danielk1977aef0bf62005-12-30 16:28:01 +0000248
249catch {db close}
250catch {db2 close}
251catch {db3 close}
252
danielk1977de0fe3e2006-01-06 06:33:12 +0000253#--------------------------------------------------------------------------
254# Tests shared-4.* test that the schema locking rules are applied
255# correctly. i.e.:
256#
257# 1. All transactions require a read-lock on the schemas of databases they
258# access.
259# 2. Transactions that modify a database schema require a write-lock on that
260# schema.
261# 3. It is not possible to compile a statement while another handle has a
262# write-lock on the schema.
263#
264
265# Open two database handles db and db2. Each has a single attach database
266# (as well as main):
267#
268# db.main -> ./test.db
269# db.test2 -> ./test2.db
270# db2.main -> ./test2.db
271# db2.test -> ./test.db
272#
273file delete -force test.db
274file delete -force test2.db
275file delete -force test2.db-journal
276sqlite3 db test.db
277sqlite3 db2 test2.db
danielk1977a96a7102006-01-16 12:46:41 +0000278do_test shared-$av.4.1.1 {
danielk1977de0fe3e2006-01-06 06:33:12 +0000279 set sqlite_open_file_count
280} {2}
danielk1977a96a7102006-01-16 12:46:41 +0000281do_test shared-$av.4.1.2 {
danielk1977de0fe3e2006-01-06 06:33:12 +0000282 execsql {ATTACH 'test2.db' AS test2}
283 set sqlite_open_file_count
284} {2}
danielk1977a96a7102006-01-16 12:46:41 +0000285do_test shared-$av.4.1.3 {
danielk1977de0fe3e2006-01-06 06:33:12 +0000286 execsql {ATTACH 'test.db' AS test} db2
287 set sqlite_open_file_count
288} {2}
289
danielk1977c87d34d2006-01-06 13:00:28 +0000290# Sanity check: Create a table in ./test.db via handle db, and test that handle
291# db2 can "see" the new table immediately. A handle using a seperate pager
292# cache would have to reload the database schema before this were possible.
293#
danielk1977a96a7102006-01-16 12:46:41 +0000294do_test shared-$av.4.2.1 {
danielk1977de0fe3e2006-01-06 06:33:12 +0000295 execsql {
296 CREATE TABLE abc(a, b, c);
danielk1977c87d34d2006-01-06 13:00:28 +0000297 CREATE TABLE def(d, e, f);
danielk1977de0fe3e2006-01-06 06:33:12 +0000298 INSERT INTO abc VALUES('i', 'ii', 'iii');
danielk1977c87d34d2006-01-06 13:00:28 +0000299 INSERT INTO def VALUES('I', 'II', 'III');
danielk1977de0fe3e2006-01-06 06:33:12 +0000300 }
301} {}
danielk1977a96a7102006-01-16 12:46:41 +0000302do_test shared-$av.4.2.2 {
danielk1977de0fe3e2006-01-06 06:33:12 +0000303 execsql {
304 SELECT * FROM test.abc;
305 } db2
306} {i ii iii}
307
danielk1977c87d34d2006-01-06 13:00:28 +0000308# Open a read-transaction and read from table abc via handle 2. Check that
309# handle 1 can read table abc. Check that handle 1 cannot modify table abc
310# or the database schema. Then check that handle 1 can modify table def.
311#
danielk1977a96a7102006-01-16 12:46:41 +0000312do_test shared-$av.4.3.1 {
danielk1977c87d34d2006-01-06 13:00:28 +0000313 execsql {
314 BEGIN;
315 SELECT * FROM test.abc;
316 } db2
317} {i ii iii}
danielk1977a96a7102006-01-16 12:46:41 +0000318do_test shared-$av.4.3.2 {
danielk1977c87d34d2006-01-06 13:00:28 +0000319 catchsql {
320 INSERT INTO abc VALUES('iv', 'v', 'vi');
321 }
danielk1977c00da102006-01-07 13:21:04 +0000322} {1 {database table is locked: abc}}
danielk1977a96a7102006-01-16 12:46:41 +0000323do_test shared-$av.4.3.3 {
danielk1977c87d34d2006-01-06 13:00:28 +0000324 catchsql {
325 CREATE TABLE ghi(g, h, i);
326 }
danielk1977c00da102006-01-07 13:21:04 +0000327} {1 {database table is locked: sqlite_master}}
danielk1977a96a7102006-01-16 12:46:41 +0000328do_test shared-$av.4.3.3 {
danielk1977c87d34d2006-01-06 13:00:28 +0000329 catchsql {
330 INSERT INTO def VALUES('IV', 'V', 'VI');
331 }
332} {0 {}}
danielk1977a96a7102006-01-16 12:46:41 +0000333do_test shared-$av.4.3.4 {
danielk1977c87d34d2006-01-06 13:00:28 +0000334 # Cleanup: commit the transaction opened by db2.
335 execsql {
336 COMMIT
337 } db2
338} {}
339
340# Open a write-transaction using handle 1 and modify the database schema.
341# Then try to execute a compiled statement to read from the same
342# database via handle 2 (fails to get the lock on sqlite_master). Also
343# try to compile a read of the same database using handle 2 (also fails).
344# Finally, compile a read of the other database using handle 2. This
345# should also fail.
346#
danielk1977ff890792006-01-16 16:24:25 +0000347ifcapable compound {
348 do_test shared-$av.4.4.1.2 {
349 # Sanity check 1: Check that the schema is what we think it is when viewed
350 # via handle 1.
351 execsql {
352 CREATE TABLE test2.ghi(g, h, i);
353 SELECT 'test.db:'||name FROM sqlite_master
354 UNION ALL
355 SELECT 'test2.db:'||name FROM test2.sqlite_master;
356 }
357 } {test.db:abc test.db:def test2.db:ghi}
358 do_test shared-$av.4.4.1.2 {
359 # Sanity check 2: Check that the schema is what we think it is when viewed
360 # via handle 2.
361 execsql {
362 SELECT 'test2.db:'||name FROM sqlite_master
363 UNION ALL
364 SELECT 'test.db:'||name FROM test.sqlite_master;
365 } db2
366 } {test2.db:ghi test.db:abc test.db:def}
367}
danielk1977c87d34d2006-01-06 13:00:28 +0000368
danielk1977a96a7102006-01-16 12:46:41 +0000369do_test shared-$av.4.4.2 {
danielk1977c87d34d2006-01-06 13:00:28 +0000370 set ::DB2 [sqlite3_connection_pointer db2]
371 set sql {SELECT * FROM abc}
372 set ::STMT1 [sqlite3_prepare $::DB2 $sql -1 DUMMY]
373 execsql {
374 BEGIN;
375 CREATE TABLE jkl(j, k, l);
376 }
377 sqlite3_step $::STMT1
378} {SQLITE_ERROR}
danielk1977a96a7102006-01-16 12:46:41 +0000379do_test shared-$av.4.4.3 {
danielk1977c87d34d2006-01-06 13:00:28 +0000380 sqlite3_finalize $::STMT1
381} {SQLITE_LOCKED}
danielk1977a96a7102006-01-16 12:46:41 +0000382do_test shared-$av.4.4.4 {
danielk1977c87d34d2006-01-06 13:00:28 +0000383 set rc [catch {
384 set ::STMT1 [sqlite3_prepare $::DB2 $sql -1 DUMMY]
385 } msg]
386 list $rc $msg
387} {1 {(6) database schema is locked: test}}
danielk1977a96a7102006-01-16 12:46:41 +0000388do_test shared-$av.4.4.5 {
danielk1977c87d34d2006-01-06 13:00:28 +0000389 set rc [catch {
390 set ::STMT1 [sqlite3_prepare $::DB2 "SELECT * FROM ghi" -1 DUMMY]
391 } msg]
392 list $rc $msg
393} {1 {(6) database schema is locked: test}}
394
danielk1977aaf22682006-01-06 15:03:48 +0000395
danielk1977de0fe3e2006-01-06 06:33:12 +0000396catch {db2 close}
397catch {db close}
398
danielk1977aaf22682006-01-06 15:03:48 +0000399#--------------------------------------------------------------------------
400# Tests shared-5.*
401#
402foreach db [list test.db test1.db test2.db test3.db] {
403 file delete -force $db ${db}-journal
404}
danielk1977a96a7102006-01-16 12:46:41 +0000405do_test shared-$av.5.1.1 {
danielk1977aaf22682006-01-06 15:03:48 +0000406 sqlite3 db1 test.db
407 sqlite3 db2 test.db
408 execsql {
409 ATTACH 'test1.db' AS test1;
410 ATTACH 'test2.db' AS test2;
411 ATTACH 'test3.db' AS test3;
412 } db1
413 execsql {
414 ATTACH 'test3.db' AS test3;
415 ATTACH 'test2.db' AS test2;
416 ATTACH 'test1.db' AS test1;
417 } db2
418} {}
danielk1977a96a7102006-01-16 12:46:41 +0000419do_test shared-$av.5.1.2 {
danielk1977aaf22682006-01-06 15:03:48 +0000420 execsql {
421 CREATE TABLE test1.t1(a, b);
422 CREATE INDEX test1.i1 ON t1(a, b);
danielk1977aaf22682006-01-06 15:03:48 +0000423 } db1
danielk19773bdca9c2006-01-17 09:35:01 +0000424} {}
425ifcapable view {
426 do_test shared-$av.5.1.3 {
427 execsql {
428 CREATE VIEW test1.v1 AS SELECT * FROM t1;
429 } db1
430 } {}
431}
432ifcapable trigger {
433 do_test shared-$av.5.1.4 {
434 execsql {
435 CREATE TRIGGER test1.trig1 AFTER INSERT ON t1 BEGIN
436 INSERT INTO t1 VALUES(new.a, new.b);
437 END;
438 } db1
439 } {}
440}
441do_test shared-$av.5.1.5 {
danielk1977aaf22682006-01-06 15:03:48 +0000442 execsql {
443 DROP INDEX i1;
danielk19773bdca9c2006-01-17 09:35:01 +0000444 } db2
445} {}
446ifcapable view {
447 do_test shared-$av.5.1.6 {
448 execsql {
449 DROP VIEW v1;
450 } db2
451 } {}
452}
453ifcapable trigger {
454 do_test shared-$av.5.1.7 {
455 execsql {
456 DROP TRIGGER trig1;
457 } db2
458 } {}
459}
460do_test shared-$av.5.1.8 {
461 execsql {
danielk1977aaf22682006-01-06 15:03:48 +0000462 DROP TABLE t1;
463 } db2
464} {}
danielk1977ff890792006-01-16 16:24:25 +0000465ifcapable compound {
danielk19773bdca9c2006-01-17 09:35:01 +0000466 do_test shared-$av.5.1.9 {
danielk1977ff890792006-01-16 16:24:25 +0000467 execsql {
468 SELECT * FROM sqlite_master UNION ALL SELECT * FROM test1.sqlite_master
469 } db1
470 } {}
471}
danielk1977aaf22682006-01-06 15:03:48 +0000472
danielk1977c00da102006-01-07 13:21:04 +0000473#--------------------------------------------------------------------------
474# Tests shared-6.* test that a query obtains all the read-locks it needs
475# before starting execution of the query. This means that there is no chance
476# some rows of data will be returned before a lock fails and SQLITE_LOCK
477# is returned.
478#
danielk1977a96a7102006-01-16 12:46:41 +0000479do_test shared-$av.6.1.1 {
danielk1977c00da102006-01-07 13:21:04 +0000480 execsql {
481 CREATE TABLE t1(a, b);
482 CREATE TABLE t2(a, b);
483 INSERT INTO t1 VALUES(1, 2);
484 INSERT INTO t2 VALUES(3, 4);
485 } db1
danielk1977ff890792006-01-16 16:24:25 +0000486} {}
487ifcapable compound {
488 do_test shared-$av.6.1.2 {
489 execsql {
490 SELECT * FROM t1 UNION ALL SELECT * FROM t2;
491 } db2
492 } {1 2 3 4}
493}
494do_test shared-$av.6.1.3 {
danielk1977c00da102006-01-07 13:21:04 +0000495 # Establish a write lock on table t2 via connection db2. Then make a
496 # UNION all query using connection db1 that first accesses t1, followed
497 # by t2. If the locks are grabbed at the start of the statement (as
498 # they should be), no rows are returned. If (as was previously the case)
499 # they are grabbed as the tables are accessed, the t1 rows will be
500 # returned before the query fails.
501 #
502 execsql {
503 BEGIN;
504 INSERT INTO t2 VALUES(5, 6);
505 } db2
506 set ret [list]
507 catch {
508 db1 eval {SELECT * FROM t1 UNION ALL SELECT * FROM t2} {
509 lappend ret $a $b
510 }
511 }
512 set ret
513} {}
danielk1977ff890792006-01-16 16:24:25 +0000514do_test shared-$av.6.1.4 {
danielk1977c00da102006-01-07 13:21:04 +0000515 execsql {
516 COMMIT;
517 BEGIN;
518 INSERT INTO t1 VALUES(7, 8);
519 } db2
520 set ret [list]
521 catch {
522 db1 eval {
523 SELECT (CASE WHEN a>4 THEN (SELECT a FROM t1) ELSE 0 END) AS d FROM t2;
524 } {
525 lappend ret $d
526 }
527 }
528 set ret
529} {}
530
danielk1977aaf22682006-01-06 15:03:48 +0000531catch {db1 close}
532catch {db2 close}
danielk1977e501b892006-01-09 06:29:47 +0000533foreach f [list test.db test2.db] {
534 file delete -force $f ${f}-journal
535}
536
537#--------------------------------------------------------------------------
538# Tests shared-7.* test auto-vacuum does not invalidate cursors from
539# other shared-cache users when it reorganizes the database on
540# COMMIT.
541#
danielk1977a96a7102006-01-16 12:46:41 +0000542do_test shared-$av.7.1 {
danielk197714db2662006-01-09 16:12:04 +0000543 # This test case sets up a test database in auto-vacuum mode consisting
544 # of two tables, t1 and t2. Both have a single index. Table t1 is
545 # populated first (so consists of pages toward the start of the db file),
546 # t2 second (pages toward the end of the file).
danielk1977e501b892006-01-09 06:29:47 +0000547 sqlite3 db test.db
548 sqlite3 db2 test.db
549 execsql {
danielk1977e501b892006-01-09 06:29:47 +0000550 BEGIN;
551 CREATE TABLE t1(a PRIMARY KEY, b);
552 CREATE TABLE t2(a PRIMARY KEY, b);
553 }
drh7a91dd82006-01-11 01:08:34 +0000554 set ::contents {}
danielk1977e501b892006-01-09 06:29:47 +0000555 for {set i 0} {$i < 100} {incr i} {
556 set a [string repeat "$i " 20]
557 set b [string repeat "$i " 20]
558 db eval {
danielk19773bdca9c2006-01-17 09:35:01 +0000559 INSERT INTO t1 VALUES(:a, :b);
danielk1977e501b892006-01-09 06:29:47 +0000560 }
561 lappend ::contents [list [expr $i+1] $a $b]
562 }
563 execsql {
564 INSERT INTO t2 SELECT * FROM t1;
565 COMMIT;
566 }
danielk1977bab45c62006-01-16 15:14:27 +0000567} {}
danielk1977a96a7102006-01-16 12:46:41 +0000568do_test shared-$av.7.2 {
danielk197714db2662006-01-09 16:12:04 +0000569 # This test case deletes the contents of table t1 (the one at the start of
570 # the file) while many cursors are open on table t2 and it's index. All of
571 # the non-root pages will be moved from the end to the start of the file
572 # when the DELETE is committed - this test verifies that moving the pages
573 # does not disturb the open cursors.
574 #
575
danielk1977e501b892006-01-09 06:29:47 +0000576 proc lockrow {db tbl oids body} {
577 set ret [list]
578 db eval "SELECT oid AS i, a, b FROM $tbl ORDER BY a" {
579 if {$i==[lindex $oids 0]} {
580 set noids [lrange $oids 1 end]
581 if {[llength $noids]==0} {
582 set subret [eval $body]
583 } else {
584 set subret [lockrow $db $tbl $noids $body]
585 }
586 }
587 lappend ret [list $i $a $b]
588 }
589 return [linsert $subret 0 $ret]
590 }
591 proc locktblrows {db tbl body} {
592 set oids [db eval "SELECT oid FROM $tbl"]
593 lockrow $db $tbl $oids $body
594 }
595
596 set scans [locktblrows db t2 {
597 execsql {
598 DELETE FROM t1;
599 } db2
600 }]
601 set error 0
danielk197714db2662006-01-09 16:12:04 +0000602
603 # Test that each SELECT query returned the expected contents of t2.
danielk1977e501b892006-01-09 06:29:47 +0000604 foreach s $scans {
605 if {[lsort -integer -index 0 $s]!=$::contents} {
606 set error 1
607 }
608 }
609 set error
610} {0}
611
612catch {db close}
613catch {db2 close}
drh7a91dd82006-01-11 01:08:34 +0000614unset -nocomplain contents
danielk1977aaf22682006-01-06 15:03:48 +0000615
danielk197714db2662006-01-09 16:12:04 +0000616#--------------------------------------------------------------------------
617# The following tests try to trick the shared-cache code into assuming
618# the wrong encoding for a database.
619#
620file delete -force test.db test.db-journal
danielk19773bdca9c2006-01-17 09:35:01 +0000621ifcapable utf16 {
622 do_test shared-$av.8.1.1 {
623 sqlite3 db test.db
624 execsql {
625 PRAGMA encoding = 'UTF-16';
626 SELECT * FROM sqlite_master;
627 }
628 } {}
629 do_test shared-$av.8.1.2 {
630 string range [execsql {PRAGMA encoding;}] 0 end-2
631 } {UTF-16}
632 do_test shared-$av.8.1.3 {
633 sqlite3 db2 test.db
634 execsql {
635 PRAGMA encoding = 'UTF-8';
636 CREATE TABLE abc(a, b, c);
637 } db2
638 } {}
639 do_test shared-$av.8.1.4 {
640 execsql {
641 SELECT * FROM sqlite_master;
642 }
643 } "table abc abc [expr $AUTOVACUUM?3:2] {CREATE TABLE abc(a, b, c)}"
644 do_test shared-$av.8.1.5 {
645 db2 close
646 execsql {
647 PRAGMA encoding;
648 }
649 } {UTF-8}
650 file delete -force test2.db test2.db-journal
651 do_test shared-$av.8.2.1 {
652 execsql {
653 ATTACH 'test2.db' AS aux;
654 SELECT * FROM aux.sqlite_master;
655 }
656 } {}
657 do_test shared-$av.8.2.2 {
658 sqlite3 db2 test2.db
659 execsql {
660 PRAGMA encoding = 'UTF-16';
661 CREATE TABLE def(d, e, f);
662 } db2
663 string range [execsql {PRAGMA encoding;} db2] 0 end-2
664 } {UTF-16}
665 do_test shared-$av.8.2.3 {
666 catchsql {
667 SELECT * FROM aux.sqlite_master;
668 }
669 } {1 {attached databases must use the same text encoding as main database}}
670}
danielk197714db2662006-01-09 16:12:04 +0000671
672catch {db close}
673catch {db2 close}
danielk1977eecfb3e2006-01-10 12:31:39 +0000674file delete -force test.db test2.db
675
danielk1977eecfb3e2006-01-10 12:31:39 +0000676#---------------------------------------------------------------------------
677# The following tests - shared-9.* - test interactions between TEMP triggers
678# and shared-schemas.
679#
680ifcapable trigger&&tempdb {
681
danielk1977a96a7102006-01-16 12:46:41 +0000682do_test shared-$av.9.1 {
danielk1977eecfb3e2006-01-10 12:31:39 +0000683 sqlite3 db test.db
684 sqlite3 db2 test.db
685 execsql {
686 CREATE TABLE abc(a, b, c);
687 CREATE TABLE abc_mirror(a, b, c);
688 CREATE TEMP TRIGGER BEFORE INSERT ON abc BEGIN
689 INSERT INTO abc_mirror(a, b, c) VALUES(new.a, new.b, new.c);
690 END;
691 INSERT INTO abc VALUES(1, 2, 3);
692 SELECT * FROM abc_mirror;
693 }
694} {1 2 3}
danielk1977a96a7102006-01-16 12:46:41 +0000695do_test shared-$av.9.2 {
danielk1977eecfb3e2006-01-10 12:31:39 +0000696 execsql {
697 INSERT INTO abc VALUES(4, 5, 6);
698 SELECT * FROM abc_mirror;
699 } db2
700} {1 2 3}
danielk1977a96a7102006-01-16 12:46:41 +0000701do_test shared-$av.9.3 {
danielk1977eecfb3e2006-01-10 12:31:39 +0000702 db close
703 db2 close
704} {}
705
706} ; # End shared-9.*
danielk197714db2662006-01-09 16:12:04 +0000707
danielk1977b597f742006-01-15 11:39:18 +0000708#---------------------------------------------------------------------------
709# The following tests - shared-10.* - test that the library behaves
710# correctly when a connection to a shared-cache is closed.
711#
danielk1977a96a7102006-01-16 12:46:41 +0000712do_test shared-$av.10.1 {
danielk1977b597f742006-01-15 11:39:18 +0000713 # Create a small sample database with two connections to it (db and db2).
714 file delete -force test.db
715 sqlite3 db test.db
716 sqlite3 db2 test.db
717 execsql {
718 CREATE TABLE ab(a PRIMARY KEY, b);
719 CREATE TABLE de(d PRIMARY KEY, e);
720 INSERT INTO ab VALUES('Chiang Mai', 100000);
721 INSERT INTO ab VALUES('Bangkok', 8000000);
722 INSERT INTO de VALUES('Ubon', 120000);
723 INSERT INTO de VALUES('Khon Kaen', 200000);
724 }
725} {}
danielk1977a96a7102006-01-16 12:46:41 +0000726do_test shared-$av.10.2 {
danielk1977b597f742006-01-15 11:39:18 +0000727 # Open a read-transaction with the first connection, a write-transaction
728 # with the second.
729 execsql {
730 BEGIN;
731 SELECT * FROM ab;
732 }
733 execsql {
734 BEGIN;
735 INSERT INTO de VALUES('Pataya', 30000);
736 } db2
737} {}
danielk1977a96a7102006-01-16 12:46:41 +0000738do_test shared-$av.10.3 {
danielk1977b597f742006-01-15 11:39:18 +0000739 # An external connection should be able to read the database, but not
740 # prepare a write operation.
741 sqlite3 db3 ./test.db
742 execsql {
743 SELECT * FROM ab;
744 } db3
745 catchsql {
746 BEGIN;
747 INSERT INTO de VALUES('Pataya', 30000);
748 } db3
749} {1 {database is locked}}
danielk1977a96a7102006-01-16 12:46:41 +0000750do_test shared-$av.10.4 {
danielk1977b597f742006-01-15 11:39:18 +0000751 # Close the connection with the write-transaction open
752 db2 close
753} {}
danielk1977a96a7102006-01-16 12:46:41 +0000754do_test shared-$av.10.5 {
danielk1977b597f742006-01-15 11:39:18 +0000755 # Test that the db2 transaction has been automatically rolled back.
756 # If it has not the ('Pataya', 30000) entry will still be in the table.
757 execsql {
758 SELECT * FROM de;
759 }
760} {Ubon 120000 {Khon Kaen} 200000}
danielk1977a96a7102006-01-16 12:46:41 +0000761do_test shared-$av.10.5 {
danielk1977b597f742006-01-15 11:39:18 +0000762 # Closing db2 should have dropped the shared-cache back to a read-lock.
763 # So db3 should be able to prepare a write...
764 catchsql {INSERT INTO de VALUES('Pataya', 30000);} db3
765} {0 {}}
danielk1977a96a7102006-01-16 12:46:41 +0000766do_test shared-$av.10.6 {
danielk1977b597f742006-01-15 11:39:18 +0000767 # ... but not commit it.
768 catchsql {COMMIT} db3
769} {1 {database is locked}}
danielk1977a96a7102006-01-16 12:46:41 +0000770do_test shared-$av.10.7 {
danielk1977b597f742006-01-15 11:39:18 +0000771 # Commit the (read-only) db transaction. Check via db3 to make sure the
772 # contents of table "de" are still as they should be.
773 execsql {
774 COMMIT;
775 }
776 execsql {
777 SELECT * FROM de;
778 } db3
779} {Ubon 120000 {Khon Kaen} 200000 Pataya 30000}
danielk1977a96a7102006-01-16 12:46:41 +0000780do_test shared-$av.10.9 {
danielk1977b597f742006-01-15 11:39:18 +0000781 # Commit the external transaction.
782 catchsql {COMMIT} db3
783} {0 {}}
danielk1977a96a7102006-01-16 12:46:41 +0000784integrity_check shared-$av.10.10
785do_test shared-$av.10.11 {
danielk1977b597f742006-01-15 11:39:18 +0000786 db close
787 db3 close
788} {}
789
danielk1977a96a7102006-01-16 12:46:41 +0000790}
791
danielk1977aef0bf62005-12-30 16:28:01 +0000792sqlite3_enable_shared_cache $::enable_shared_cache
danielk1977a96a7102006-01-16 12:46:41 +0000793finish_test