blob: 6929e50a0a8cf34f72202f543482669a485dda4c [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#***********************************************************************
11# This file implements regression tests for SQLite library. The
12# focus of this file is testing the SELECT statement.
13#
danielk1977c00da102006-01-07 13:21:04 +000014# $Id: shared.test,v 1.6 2006/01/07 13:21:04 danielk1977 Exp $
danielk1977aef0bf62005-12-30 16:28:01 +000015
16set testdir [file dirname $argv0]
17source $testdir/tester.tcl
18db close
19
20ifcapable !shared_cache {
21 finish_test
22 return
23}
danielk1977da184232006-01-05 11:34:32 +000024set ::enable_shared_cache [sqlite3_enable_shared_cache 1]
danielk1977aef0bf62005-12-30 16:28:01 +000025
26# Test organization:
27#
28# shared-1.*: Simple test to verify basic sanity of table level locking when
29# two connections share a pager cache.
30# shared-2.*: Test that a read transaction can co-exist with a
31# write-transaction, including a simple test to ensure the
32# external locking protocol is still working.
danielk1977da184232006-01-05 11:34:32 +000033# shared-3.*: Simple test of read-uncommitted mode.
danielk1977de0fe3e2006-01-06 06:33:12 +000034# shared-4.*: Check that the schema is locked and unlocked correctly.
danielk1977aaf22682006-01-06 15:03:48 +000035# shared-5.*: Test that creating/dropping schema items works when databases
36# are attached in different orders to different handles.
danielk1977c00da102006-01-07 13:21:04 +000037# shared-6.*: Locking, UNION ALL queries and sub-queries.
danielk1977de0fe3e2006-01-06 06:33:12 +000038#
danielk1977aef0bf62005-12-30 16:28:01 +000039
40do_test shared-1.1 {
41 # Open a second database on the file test.db. It should use the same pager
42 # cache and schema as the original connection. Verify that only 1 file is
43 # opened.
44 sqlite3 db2 test.db
45 sqlite3 db test.db
46 set ::sqlite_open_file_count
47} {1}
48do_test shared-1.2 {
49 # Add a table and a single row of data via the first connection.
50 # Ensure that the second connection can see them.
51 execsql {
52 CREATE TABLE abc(a, b, c);
53 INSERT INTO abc VALUES(1, 2, 3);
54 } db
55 execsql {
56 SELECT * FROM abc;
57 } db2
58} {1 2 3}
59do_test shared-1.3 {
60 # Have the first connection begin a transaction and obtain a read-lock
61 # on table abc. This should not prevent the second connection from
62 # querying abc.
63 execsql {
64 BEGIN;
65 SELECT * FROM abc;
66 }
67 execsql {
68 SELECT * FROM abc;
69 } db2
70} {1 2 3}
71do_test shared-1.4 {
72 # Try to insert a row into abc via connection 2. This should fail because
73 # of the read-lock connection 1 is holding on table abc (obtained in the
74 # previous test case).
75 catchsql {
76 INSERT INTO abc VALUES(4, 5, 6);
77 } db2
danielk1977c00da102006-01-07 13:21:04 +000078} {1 {database table is locked: abc}}
danielk1977aef0bf62005-12-30 16:28:01 +000079do_test shared-1.5 {
danielk1977da184232006-01-05 11:34:32 +000080 # Using connection 2 (the one without the open transaction), try to create
81 # a new table. This should fail because of the open read transaction
82 # held by connection 1.
83 catchsql {
84 CREATE TABLE def(d, e, f);
85 } db2
danielk1977c00da102006-01-07 13:21:04 +000086} {1 {database table is locked: sqlite_master}}
danielk1977da184232006-01-05 11:34:32 +000087do_test shared-1.6 {
88 # Upgrade connection 1's transaction to a write transaction. Create
89 # a new table - def - and insert a row into it. Because the connection 1
90 # transaction modifies the schema, it should not be possible for
91 # connection 2 to access the database at all until the connection 1
92 # has finished the transaction.
danielk1977aef0bf62005-12-30 16:28:01 +000093 execsql {
94 CREATE TABLE def(d, e, f);
danielk1977aef0bf62005-12-30 16:28:01 +000095 INSERT INTO def VALUES('IV', 'V', 'VI');
96 }
97} {}
98do_test shared-1.7 {
99 # Read from the sqlite_master table with connection 1 (inside the
danielk1977da184232006-01-05 11:34:32 +0000100 # transaction). Then test that we can not do this with connection 2. This
101 # is because of the schema-modified lock established by connection 1
102 # in the previous test case.
danielk1977aef0bf62005-12-30 16:28:01 +0000103 execsql {
104 SELECT * FROM sqlite_master;
105 }
106 catchsql {
danielk1977da184232006-01-05 11:34:32 +0000107 SELECT * FROM sqlite_master;
danielk1977aef0bf62005-12-30 16:28:01 +0000108 } db2
danielk1977c87d34d2006-01-06 13:00:28 +0000109} {1 {database schema is locked: main}}
danielk1977aef0bf62005-12-30 16:28:01 +0000110do_test shared-1.8 {
danielk1977aef0bf62005-12-30 16:28:01 +0000111 # Commit the connection 1 transaction.
112 execsql {
113 COMMIT;
114 }
115} {}
116
117do_test shared-2.1 {
118 # Open connection db3 to the database. Use a different path to the same
119 # file so that db3 does *not* share the same pager cache as db and db2
120 # (there should be two open file handles).
121 sqlite3 db3 ./test.db
122 set ::sqlite_open_file_count
123} {2}
124do_test shared-2.2 {
125 # Start read transactions on db and db2 (the shared pager cache). Ensure
126 # db3 cannot write to the database.
127 execsql {
128 BEGIN;
129 SELECT * FROM abc;
130 }
131 execsql {
132 BEGIN;
133 SELECT * FROM abc;
134 } db2
135 catchsql {
136 INSERT INTO abc VALUES(1, 2, 3);
137 } db2
danielk1977c00da102006-01-07 13:21:04 +0000138} {1 {database table is locked: abc}}
danielk1977aef0bf62005-12-30 16:28:01 +0000139do_test shared-2.3 {
140 # Turn db's transaction into a write-transaction. db3 should still be
141 # able to read from table def (but will not see the new row). Connection
142 # db2 should not be able to read def (because of the write-lock).
143
144# Todo: The failed "INSERT INTO abc ..." statement in the above test
145# has started a write-transaction on db2 (should this be so?). This
146# would prevent connection db from starting a write-transaction. So roll the
147# db2 transaction back and replace it with a new read transaction.
148 execsql {
149 ROLLBACK;
150 BEGIN;
151 SELECT * FROM abc;
152 } db2
153
154 execsql {
155 INSERT INTO def VALUES('VII', 'VIII', 'IX');
156 }
157 concat [
158 catchsql { SELECT * FROM def; } db3
159 ] [
160 catchsql { SELECT * FROM def; } db2
161 ]
danielk1977c00da102006-01-07 13:21:04 +0000162} {0 {IV V VI} 1 {database table is locked: def}}
danielk1977aef0bf62005-12-30 16:28:01 +0000163do_test shared-2.4 {
164 # Commit the open transaction on db. db2 still holds a read-transaction.
165 # This should prevent db3 from writing to the database, but not from
166 # reading.
167 execsql {
168 COMMIT;
169 }
170 concat [
171 catchsql { SELECT * FROM def; } db3
172 ] [
173 catchsql { INSERT INTO def VALUES('X', 'XI', 'XII'); } db3
174 ]
danielk1977da184232006-01-05 11:34:32 +0000175} {0 {IV V VI VII VIII IX} 1 {database is locked}}
danielk1977aef0bf62005-12-30 16:28:01 +0000176
danielk1977da184232006-01-05 11:34:32 +0000177catchsql COMMIT db2
178
179do_test shared-3.1.1 {
180 # This test case starts a linear scan of table 'seq' using a
181 # read-uncommitted connection. In the middle of the scan, rows are added
182 # to the end of the seq table (ahead of the current cursor position).
183 # The uncommitted rows should be included in the results of the scan.
184 execsql "
185 CREATE TABLE seq(i, x);
186 INSERT INTO seq VALUES(1, '[string repeat X 500]');
187 INSERT INTO seq VALUES(2, '[string repeat X 500]');
188 "
189 execsql {SELECT * FROM sqlite_master} db2
190 execsql {PRAGMA read_uncommitted = 1} db2
191
192 set ret [list]
193 db2 eval {SELECT i FROM seq} {
194 if {$i < 4} {
195 execsql {
196 INSERT INTO seq SELECT i + (SELECT max(i) FROM seq), x FROM seq;
197 }
198 }
199 lappend ret $i
200 }
201 set ret
202} {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16}
203do_test shared-3.1.2 {
204 # Another linear scan through table seq using a read-uncommitted connection.
205 # This time, delete each row as it is read. Should not affect the results of
206 # the scan, but the table should be empty after the scan is concluded
207 # (test 3.1.3 verifies this).
208 set ret [list]
209 db2 eval {SELECT i FROM seq} {
210 db eval {DELETE FROM seq WHERE i = $i}
211 lappend ret $i
212 }
213 set ret
214} {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16}
215do_test shared-3.1.3 {
216 execsql {
217 SELECT * FROM seq;
218 }
219} {}
danielk1977aef0bf62005-12-30 16:28:01 +0000220
221catch {db close}
222catch {db2 close}
223catch {db3 close}
224
danielk1977de0fe3e2006-01-06 06:33:12 +0000225#--------------------------------------------------------------------------
226# Tests shared-4.* test that the schema locking rules are applied
227# correctly. i.e.:
228#
229# 1. All transactions require a read-lock on the schemas of databases they
230# access.
231# 2. Transactions that modify a database schema require a write-lock on that
232# schema.
233# 3. It is not possible to compile a statement while another handle has a
234# write-lock on the schema.
235#
236
237# Open two database handles db and db2. Each has a single attach database
238# (as well as main):
239#
240# db.main -> ./test.db
241# db.test2 -> ./test2.db
242# db2.main -> ./test2.db
243# db2.test -> ./test.db
244#
245file delete -force test.db
246file delete -force test2.db
247file delete -force test2.db-journal
248sqlite3 db test.db
249sqlite3 db2 test2.db
250do_test shared-4.1.1 {
251 set sqlite_open_file_count
252} {2}
253do_test shared-4.1.2 {
254 execsql {ATTACH 'test2.db' AS test2}
255 set sqlite_open_file_count
256} {2}
257do_test shared-4.1.3 {
258 execsql {ATTACH 'test.db' AS test} db2
259 set sqlite_open_file_count
260} {2}
261
danielk1977c87d34d2006-01-06 13:00:28 +0000262# Sanity check: Create a table in ./test.db via handle db, and test that handle
263# db2 can "see" the new table immediately. A handle using a seperate pager
264# cache would have to reload the database schema before this were possible.
265#
danielk1977de0fe3e2006-01-06 06:33:12 +0000266do_test shared-4.2.1 {
267 execsql {
268 CREATE TABLE abc(a, b, c);
danielk1977c87d34d2006-01-06 13:00:28 +0000269 CREATE TABLE def(d, e, f);
danielk1977de0fe3e2006-01-06 06:33:12 +0000270 INSERT INTO abc VALUES('i', 'ii', 'iii');
danielk1977c87d34d2006-01-06 13:00:28 +0000271 INSERT INTO def VALUES('I', 'II', 'III');
danielk1977de0fe3e2006-01-06 06:33:12 +0000272 }
273} {}
274do_test shared-4.2.2 {
275 execsql {
276 SELECT * FROM test.abc;
277 } db2
278} {i ii iii}
279
danielk1977c87d34d2006-01-06 13:00:28 +0000280# Open a read-transaction and read from table abc via handle 2. Check that
281# handle 1 can read table abc. Check that handle 1 cannot modify table abc
282# or the database schema. Then check that handle 1 can modify table def.
283#
284do_test shared-4.3.1 {
285 execsql {
286 BEGIN;
287 SELECT * FROM test.abc;
288 } db2
289} {i ii iii}
290do_test shared-4.3.2 {
291 catchsql {
292 INSERT INTO abc VALUES('iv', 'v', 'vi');
293 }
danielk1977c00da102006-01-07 13:21:04 +0000294} {1 {database table is locked: abc}}
danielk1977c87d34d2006-01-06 13:00:28 +0000295do_test shared-4.3.3 {
296 catchsql {
297 CREATE TABLE ghi(g, h, i);
298 }
danielk1977c00da102006-01-07 13:21:04 +0000299} {1 {database table is locked: sqlite_master}}
danielk1977c87d34d2006-01-06 13:00:28 +0000300do_test shared-4.3.3 {
301 catchsql {
302 INSERT INTO def VALUES('IV', 'V', 'VI');
303 }
304} {0 {}}
305do_test shared-4.3.4 {
306 # Cleanup: commit the transaction opened by db2.
307 execsql {
308 COMMIT
309 } db2
310} {}
311
312# Open a write-transaction using handle 1 and modify the database schema.
313# Then try to execute a compiled statement to read from the same
314# database via handle 2 (fails to get the lock on sqlite_master). Also
315# try to compile a read of the same database using handle 2 (also fails).
316# Finally, compile a read of the other database using handle 2. This
317# should also fail.
318#
319do_test shared-4.4.1.2 {
320 # Sanity check 1: Check that the schema is what we think it is when viewed
321 # via handle 1.
322 execsql {
323 CREATE TABLE test2.ghi(g, h, i);
324 SELECT 'test.db:'||name FROM sqlite_master
325 UNION ALL
326 SELECT 'test2.db:'||name FROM test2.sqlite_master;
327 }
328} {test.db:abc test.db:def test2.db:ghi}
329do_test shared-4.4.1.2 {
330 # Sanity check 2: Check that the schema is what we think it is when viewed
331 # via handle 2.
332 execsql {
333 SELECT 'test2.db:'||name FROM sqlite_master
334 UNION ALL
335 SELECT 'test.db:'||name FROM test.sqlite_master;
336 } db2
337} {test2.db:ghi test.db:abc test.db:def}
338
339do_test shared-4.4.2 {
340 set ::DB2 [sqlite3_connection_pointer db2]
341 set sql {SELECT * FROM abc}
342 set ::STMT1 [sqlite3_prepare $::DB2 $sql -1 DUMMY]
343 execsql {
344 BEGIN;
345 CREATE TABLE jkl(j, k, l);
346 }
347 sqlite3_step $::STMT1
348} {SQLITE_ERROR}
349do_test shared-4.4.3 {
350 sqlite3_finalize $::STMT1
351} {SQLITE_LOCKED}
352do_test shared-4.4.4 {
353 set rc [catch {
354 set ::STMT1 [sqlite3_prepare $::DB2 $sql -1 DUMMY]
355 } msg]
356 list $rc $msg
357} {1 {(6) database schema is locked: test}}
358do_test shared-4.4.5 {
359 set rc [catch {
360 set ::STMT1 [sqlite3_prepare $::DB2 "SELECT * FROM ghi" -1 DUMMY]
361 } msg]
362 list $rc $msg
363} {1 {(6) database schema is locked: test}}
364
danielk1977aaf22682006-01-06 15:03:48 +0000365
danielk1977de0fe3e2006-01-06 06:33:12 +0000366catch {db2 close}
367catch {db close}
368
danielk1977aaf22682006-01-06 15:03:48 +0000369#--------------------------------------------------------------------------
370# Tests shared-5.*
371#
372foreach db [list test.db test1.db test2.db test3.db] {
373 file delete -force $db ${db}-journal
374}
375do_test shared-5.1.1 {
376 sqlite3 db1 test.db
377 sqlite3 db2 test.db
378 execsql {
379 ATTACH 'test1.db' AS test1;
380 ATTACH 'test2.db' AS test2;
381 ATTACH 'test3.db' AS test3;
382 } db1
383 execsql {
384 ATTACH 'test3.db' AS test3;
385 ATTACH 'test2.db' AS test2;
386 ATTACH 'test1.db' AS test1;
387 } db2
388} {}
389do_test shared-5.1.2 {
390 execsql {
391 CREATE TABLE test1.t1(a, b);
392 CREATE INDEX test1.i1 ON t1(a, b);
393 CREATE VIEW test1.v1 AS SELECT * FROM t1;
394 CREATE TRIGGER test1.trig1 AFTER INSERT ON t1 BEGIN
395 INSERT INTO t1 VALUES(new.a, new.b);
396 END;
397 } db1
398 execsql {
399 DROP INDEX i1;
400 DROP VIEW v1;
401 DROP TRIGGER trig1;
402 DROP TABLE t1;
403 } db2
404} {}
405do_test shared-5.1.2 {
406 execsql {
407 SELECT * FROM sqlite_master UNION ALL SELECT * FROM test1.sqlite_master
408 } db1
409} {}
410
danielk1977c00da102006-01-07 13:21:04 +0000411#--------------------------------------------------------------------------
412# Tests shared-6.* test that a query obtains all the read-locks it needs
413# before starting execution of the query. This means that there is no chance
414# some rows of data will be returned before a lock fails and SQLITE_LOCK
415# is returned.
416#
417do_test shared-6.1.1 {
418 execsql {
419 CREATE TABLE t1(a, b);
420 CREATE TABLE t2(a, b);
421 INSERT INTO t1 VALUES(1, 2);
422 INSERT INTO t2 VALUES(3, 4);
423 } db1
424 execsql {
425 SELECT * FROM t1 UNION ALL SELECT * FROM t2;
426 } db2
427} {1 2 3 4}
428do_test shared-6.1.2 {
429 # Establish a write lock on table t2 via connection db2. Then make a
430 # UNION all query using connection db1 that first accesses t1, followed
431 # by t2. If the locks are grabbed at the start of the statement (as
432 # they should be), no rows are returned. If (as was previously the case)
433 # they are grabbed as the tables are accessed, the t1 rows will be
434 # returned before the query fails.
435 #
436 execsql {
437 BEGIN;
438 INSERT INTO t2 VALUES(5, 6);
439 } db2
440 set ret [list]
441 catch {
442 db1 eval {SELECT * FROM t1 UNION ALL SELECT * FROM t2} {
443 lappend ret $a $b
444 }
445 }
446 set ret
447} {}
448do_test shared-6.1.3 {
449 execsql {
450 COMMIT;
451 BEGIN;
452 INSERT INTO t1 VALUES(7, 8);
453 } db2
454 set ret [list]
455 catch {
456 db1 eval {
457 SELECT (CASE WHEN a>4 THEN (SELECT a FROM t1) ELSE 0 END) AS d FROM t2;
458 } {
459 lappend ret $d
460 }
461 }
462 set ret
463} {}
464
danielk1977aaf22682006-01-06 15:03:48 +0000465catch {db1 close}
466catch {db2 close}
467
danielk1977aef0bf62005-12-30 16:28:01 +0000468finish_test
469sqlite3_enable_shared_cache $::enable_shared_cache
470