blob: f8705685419e6ede6afa710d211619c8106846c8 [file] [log] [blame]
drh3c8bf552003-07-01 18:13:14 +00001# 2003 July 1
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 script is testing the ATTACH and DETACH commands
13# and related functionality.
14#
drh85b623f2007-12-13 21:54:09 +000015# $Id: attach2.test,v 1.38 2007/12/13 21:54:11 drh Exp $
drh3c8bf552003-07-01 18:13:14 +000016#
drh3c8bf552003-07-01 18:13:14 +000017
18set testdir [file dirname $argv0]
19source $testdir/tester.tcl
20
danielk19775a8f9372007-10-09 08:29:32 +000021ifcapable !attach {
22 finish_test
23 return
24}
25
drh3c8bf552003-07-01 18:13:14 +000026# Ticket #354
27#
drh2ac3ee92004-06-07 16:27:46 +000028# Databases test.db and test2.db contain identical schemas. Make
29# sure we can attach test2.db from test.db.
30#
drh3c8bf552003-07-01 18:13:14 +000031do_test attach2-1.1 {
32 db eval {
33 CREATE TABLE t1(a,b);
34 CREATE INDEX x1 ON t1(a);
35 }
mistachkinfda06be2011-08-02 00:57:34 +000036 forcedelete test2.db
37 forcedelete test2.db-journal
drhef4ac8f2004-06-19 00:16:31 +000038 sqlite3 db2 test2.db
drh3c8bf552003-07-01 18:13:14 +000039 db2 eval {
40 CREATE TABLE t1(a,b);
41 CREATE INDEX x1 ON t1(a);
42 }
43 catchsql {
44 ATTACH 'test2.db' AS t2;
45 }
46} {0 {}}
47
drh447623d2003-12-06 22:22:35 +000048# Ticket #514
49#
50proc db_list {db} {
51 set list {}
52 foreach {idx name file} [execsql {PRAGMA database_list} $db] {
53 lappend list $idx $name
54 }
55 return $list
56}
57db eval {DETACH t2}
58do_test attach2-2.1 {
drh2ac3ee92004-06-07 16:27:46 +000059 # lock test2.db then try to attach it. This is no longer an error because
60 # db2 just RESERVES the database. It does not obtain a write-lock until
61 # we COMMIT.
drh447623d2003-12-06 22:22:35 +000062 db2 eval {BEGIN}
danielk19771d850a72004-05-31 08:26:49 +000063 db2 eval {UPDATE t1 SET a = 0 WHERE 0}
drh447623d2003-12-06 22:22:35 +000064 catchsql {
65 ATTACH 'test2.db' AS t2;
66 }
drh447623d2003-12-06 22:22:35 +000067} {0 {}}
danielk197727188fb2004-11-23 10:13:03 +000068ifcapable schema_pragmas {
drh2ac3ee92004-06-07 16:27:46 +000069do_test attach2-2.2 {
70 # make sure test2.db did get attached.
drh447623d2003-12-06 22:22:35 +000071 db_list db
drh2b74d702004-08-18 16:05:18 +000072} {0 main 2 t2}
danielk197727188fb2004-11-23 10:13:03 +000073} ;# ifcapable schema_pragmas
drh2ac3ee92004-06-07 16:27:46 +000074db2 eval {COMMIT}
75
drh447623d2003-12-06 22:22:35 +000076do_test attach2-2.5 {
drh2ac3ee92004-06-07 16:27:46 +000077 # Make sure we can read test2.db from db
drh447623d2003-12-06 22:22:35 +000078 catchsql {
79 SELECT name FROM t2.sqlite_master;
80 }
81} {0 {t1 x1}}
82do_test attach2-2.6 {
drh2ac3ee92004-06-07 16:27:46 +000083 # lock test2.db and try to read from it. This should still work because
84 # the lock is only a RESERVED lock which does not prevent reading.
85 #
drh447623d2003-12-06 22:22:35 +000086 db2 eval BEGIN
danielk19771d850a72004-05-31 08:26:49 +000087 db2 eval {UPDATE t1 SET a = 0 WHERE 0}
drh447623d2003-12-06 22:22:35 +000088 catchsql {
89 SELECT name FROM t2.sqlite_master;
90 }
drh2ac3ee92004-06-07 16:27:46 +000091} {0 {t1 x1}}
drh447623d2003-12-06 22:22:35 +000092do_test attach2-2.7 {
93 # but we can still read from test1.db even though test2.db is locked.
94 catchsql {
95 SELECT name FROM main.sqlite_master;
96 }
97} {0 {t1 x1}}
98do_test attach2-2.8 {
99 # start a transaction on test.db even though test2.db is locked.
100 catchsql {
101 BEGIN;
102 INSERT INTO t1 VALUES(8,9);
103 }
104} {0 {}}
105do_test attach2-2.9 {
106 execsql {
107 SELECT * FROM t1
108 }
109} {8 9}
110do_test attach2-2.10 {
111 # now try to write to test2.db. the write should fail
112 catchsql {
113 INSERT INTO t2.t1 VALUES(1,2);
114 }
115} {1 {database is locked}}
116do_test attach2-2.11 {
117 # when the write failed in the previous test, the transaction should
118 # have rolled back.
danielk19771d850a72004-05-31 08:26:49 +0000119 #
120 # Update for version 3: A transaction is no longer rolled back if a
121 # database is found to be busy.
122 execsql {rollback}
drh8ef83ff2004-02-12 15:31:21 +0000123 db2 eval ROLLBACK
drh447623d2003-12-06 22:22:35 +0000124 execsql {
125 SELECT * FROM t1
126 }
127} {}
128do_test attach2-2.12 {
129 catchsql {
130 COMMIT
131 }
132} {1 {cannot commit - no transaction is active}}
133
drh2ac3ee92004-06-07 16:27:46 +0000134# Ticket #574: Make sure it works using the non-callback API
drh0bca3532004-01-20 11:54:03 +0000135#
136do_test attach2-3.1 {
drhdddca282006-01-03 00:33:50 +0000137 set DB [sqlite3_connection_pointer db]
danielk19774ad17132004-05-21 01:47:26 +0000138 set rc [catch {sqlite3_prepare $DB "ATTACH 'test2.db' AS t2" -1 TAIL} VM]
drh0bca3532004-01-20 11:54:03 +0000139 if {$rc} {lappend rc $VM}
danielk1977f744bb52005-12-06 17:19:11 +0000140 sqlite3_step $VM
danielk1977106bb232004-05-21 10:08:53 +0000141 sqlite3_finalize $VM
drh0bca3532004-01-20 11:54:03 +0000142 set rc
143} {0}
144do_test attach2-3.2 {
danielk19774ad17132004-05-21 01:47:26 +0000145 set rc [catch {sqlite3_prepare $DB "DETACH t2" -1 TAIL} VM]
drh0bca3532004-01-20 11:54:03 +0000146 if {$rc} {lappend rc $VM}
danielk1977f744bb52005-12-06 17:19:11 +0000147 sqlite3_step $VM
danielk1977106bb232004-05-21 10:08:53 +0000148 sqlite3_finalize $VM
drh0bca3532004-01-20 11:54:03 +0000149 set rc
150} {0}
151
drh9cb733c2003-07-18 01:25:34 +0000152db close
drh3c8bf552003-07-01 18:13:14 +0000153for {set i 2} {$i<=15} {incr i} {
154 catch {db$i close}
155}
drha6abd042004-06-09 17:37:22 +0000156
157# A procedure to verify the status of locks on a database.
158#
159proc lock_status {testnum db expected_result} {
danielk197753c0f742005-03-29 03:10:59 +0000160 # If the database was compiled with OMIT_TEMPDB set, then
161 # the lock_status list will not contain an entry for the temp
drh85b623f2007-12-13 21:54:09 +0000162 # db. But the test code doesn't know this, so its easiest
danielk1977aef0bf62005-12-30 16:28:01 +0000163 # to filter it out of the $expected_result list here.
danielk197753c0f742005-03-29 03:10:59 +0000164 ifcapable !tempdb {
165 set expected_result [concat \
166 [lrange $expected_result 0 1] \
167 [lrange $expected_result 4 end] \
168 ]
169 }
drha6abd042004-06-09 17:37:22 +0000170 do_test attach2-$testnum [subst {
drhd5a71b52005-01-24 01:38:32 +0000171 $db cache flush ;# The lock_status pragma should not be cached
drha6abd042004-06-09 17:37:22 +0000172 execsql {PRAGMA lock_status} $db
173 }] $expected_result
174}
drh2ac3ee92004-06-07 16:27:46 +0000175set sqlite_os_trace 0
danielk19773a81de12004-05-31 12:34:53 +0000176
177# Tests attach2-4.* test that read-locks work correctly with attached
178# databases.
179do_test attach2-4.1 {
drhef4ac8f2004-06-19 00:16:31 +0000180 sqlite3 db test.db
181 sqlite3 db2 test.db
danielk19773a81de12004-05-31 12:34:53 +0000182 execsql {ATTACH 'test2.db' as file2}
183 execsql {ATTACH 'test2.db' as file2} db2
184} {}
185
drhdc3ff9c2004-08-18 02:10:15 +0000186lock_status 4.1.1 db {main unlocked temp closed file2 unlocked}
187lock_status 4.1.2 db2 {main unlocked temp closed file2 unlocked}
drha6abd042004-06-09 17:37:22 +0000188
danielk19773a81de12004-05-31 12:34:53 +0000189do_test attach2-4.2 {
drh2ac3ee92004-06-07 16:27:46 +0000190 # Handle 'db' read-locks test.db
danielk19773a81de12004-05-31 12:34:53 +0000191 execsql {BEGIN}
192 execsql {SELECT * FROM t1}
drhfaa57ac2004-06-09 14:01:51 +0000193 # Lock status:
194 # db - shared(main)
195 # db2 -
danielk19773a81de12004-05-31 12:34:53 +0000196} {}
drha6abd042004-06-09 17:37:22 +0000197
drhdc3ff9c2004-08-18 02:10:15 +0000198lock_status 4.2.1 db {main shared temp closed file2 unlocked}
199lock_status 4.2.2 db2 {main unlocked temp closed file2 unlocked}
drha6abd042004-06-09 17:37:22 +0000200
danielk19773a81de12004-05-31 12:34:53 +0000201do_test attach2-4.3 {
drh2ac3ee92004-06-07 16:27:46 +0000202 # The read lock held by db does not prevent db2 from reading test.db
danielk19773a81de12004-05-31 12:34:53 +0000203 execsql {SELECT * FROM t1} db2
204} {}
drha6abd042004-06-09 17:37:22 +0000205
drhdc3ff9c2004-08-18 02:10:15 +0000206lock_status 4.3.1 db {main shared temp closed file2 unlocked}
207lock_status 4.3.2 db2 {main unlocked temp closed file2 unlocked}
drha6abd042004-06-09 17:37:22 +0000208
danielk19773a81de12004-05-31 12:34:53 +0000209do_test attach2-4.4 {
drhfaa57ac2004-06-09 14:01:51 +0000210 # db is holding a read lock on test.db, so we should not be able
drh2ac3ee92004-06-07 16:27:46 +0000211 # to commit a write to test.db from db2
drhfaa57ac2004-06-09 14:01:51 +0000212 catchsql {
213 INSERT INTO t1 VALUES(1, 2)
214 } db2
danielk19773a81de12004-05-31 12:34:53 +0000215} {1 {database is locked}}
drha6abd042004-06-09 17:37:22 +0000216
drhdc3ff9c2004-08-18 02:10:15 +0000217lock_status 4.4.1 db {main shared temp closed file2 unlocked}
drh34f47322004-08-18 15:58:22 +0000218lock_status 4.4.2 db2 {main unlocked temp closed file2 unlocked}
drha6abd042004-06-09 17:37:22 +0000219
drhb7712282007-08-10 19:46:13 +0000220# We have to make sure that the cache_size and the soft_heap_limit
221# are large enough to hold the entire change in memory. If either
222# is set too small, then changes will spill to the database, forcing
223# a reserved lock to promote to exclusive. That will mess up our
224# test results.
225
226set soft_limit [sqlite3_soft_heap_limit 0]
227
228
danielk19773a81de12004-05-31 12:34:53 +0000229do_test attach2-4.5 {
drh2ac3ee92004-06-07 16:27:46 +0000230 # Handle 'db2' reserves file2.
danielk19773a81de12004-05-31 12:34:53 +0000231 execsql {BEGIN} db2
232 execsql {INSERT INTO file2.t1 VALUES(1, 2)} db2
drhfaa57ac2004-06-09 14:01:51 +0000233 # Lock status:
234 # db - shared(main)
235 # db2 - reserved(file2)
danielk19773a81de12004-05-31 12:34:53 +0000236} {}
drha6abd042004-06-09 17:37:22 +0000237
drhdc3ff9c2004-08-18 02:10:15 +0000238lock_status 4.5.1 db {main shared temp closed file2 unlocked}
drh34f47322004-08-18 15:58:22 +0000239lock_status 4.5.2 db2 {main unlocked temp closed file2 reserved}
drha6abd042004-06-09 17:37:22 +0000240
drh2ac3ee92004-06-07 16:27:46 +0000241do_test attach2-4.6.1 {
242 # Reads are allowed against a reserved database.
243 catchsql {
244 SELECT * FROM file2.t1;
245 }
drhfaa57ac2004-06-09 14:01:51 +0000246 # Lock status:
247 # db - shared(main), shared(file2)
248 # db2 - reserved(file2)
drh2ac3ee92004-06-07 16:27:46 +0000249} {0 {}}
drha6abd042004-06-09 17:37:22 +0000250
drhdc3ff9c2004-08-18 02:10:15 +0000251lock_status 4.6.1.1 db {main shared temp closed file2 shared}
drh34f47322004-08-18 15:58:22 +0000252lock_status 4.6.1.2 db2 {main unlocked temp closed file2 reserved}
drha6abd042004-06-09 17:37:22 +0000253
drh2ac3ee92004-06-07 16:27:46 +0000254do_test attach2-4.6.2 {
255 # Writes against a reserved database are not allowed.
256 catchsql {
257 UPDATE file2.t1 SET a=0;
258 }
danielk19773a81de12004-05-31 12:34:53 +0000259} {1 {database is locked}}
drha6abd042004-06-09 17:37:22 +0000260
drh34f47322004-08-18 15:58:22 +0000261lock_status 4.6.2.1 db {main shared temp closed file2 shared}
262lock_status 4.6.2.2 db2 {main unlocked temp closed file2 reserved}
drha6abd042004-06-09 17:37:22 +0000263
danielk19773a81de12004-05-31 12:34:53 +0000264do_test attach2-4.7 {
265 # Ensure handle 'db' retains the lock on the main file after
drh2ac3ee92004-06-07 16:27:46 +0000266 # failing to obtain a write-lock on file2.
267 catchsql {
268 INSERT INTO t1 VALUES(1, 2)
269 } db2
drha6abd042004-06-09 17:37:22 +0000270} {0 {}}
271
drh34f47322004-08-18 15:58:22 +0000272lock_status 4.7.1 db {main shared temp closed file2 shared}
273lock_status 4.7.2 db2 {main reserved temp closed file2 reserved}
drha6abd042004-06-09 17:37:22 +0000274
danielk19773a81de12004-05-31 12:34:53 +0000275do_test attach2-4.8 {
drha6abd042004-06-09 17:37:22 +0000276 # We should still be able to read test.db from db2
danielk19773a81de12004-05-31 12:34:53 +0000277 execsql {SELECT * FROM t1} db2
drha6abd042004-06-09 17:37:22 +0000278} {1 2}
279
drh34f47322004-08-18 15:58:22 +0000280lock_status 4.8.1 db {main shared temp closed file2 shared}
281lock_status 4.8.2 db2 {main reserved temp closed file2 reserved}
drha6abd042004-06-09 17:37:22 +0000282
danielk19773a81de12004-05-31 12:34:53 +0000283do_test attach2-4.9 {
284 # Try to upgrade the handle 'db' lock.
drh2ac3ee92004-06-07 16:27:46 +0000285 catchsql {
286 INSERT INTO t1 VALUES(1, 2)
287 }
danielk19773a81de12004-05-31 12:34:53 +0000288} {1 {database is locked}}
drha6abd042004-06-09 17:37:22 +0000289
drh34f47322004-08-18 15:58:22 +0000290lock_status 4.9.1 db {main shared temp closed file2 shared}
291lock_status 4.9.2 db2 {main reserved temp closed file2 reserved}
drha6abd042004-06-09 17:37:22 +0000292
danielk19773a81de12004-05-31 12:34:53 +0000293do_test attach2-4.10 {
drhff13c7d2004-06-09 21:01:11 +0000294 # We cannot commit db2 while db is holding a read-lock
295 catchsql {COMMIT} db2
296} {1 {database is locked}}
drha6abd042004-06-09 17:37:22 +0000297
drh34f47322004-08-18 15:58:22 +0000298lock_status 4.10.1 db {main shared temp closed file2 shared}
299lock_status 4.10.2 db2 {main pending temp closed file2 reserved}
drha6abd042004-06-09 17:37:22 +0000300
drh3cde3bb2004-06-12 02:17:14 +0000301set sqlite_os_trace 0
danielk19773a81de12004-05-31 12:34:53 +0000302do_test attach2-4.11 {
drhff13c7d2004-06-09 21:01:11 +0000303 # db is able to commit.
304 catchsql {COMMIT}
305} {0 {}}
306
drh34f47322004-08-18 15:58:22 +0000307lock_status 4.11.1 db {main unlocked temp closed file2 unlocked}
308lock_status 4.11.2 db2 {main pending temp closed file2 reserved}
drhff13c7d2004-06-09 21:01:11 +0000309
310do_test attach2-4.12 {
311 # Now we can commit db2
312 catchsql {COMMIT} db2
313} {0 {}}
314
drh34f47322004-08-18 15:58:22 +0000315lock_status 4.12.1 db {main unlocked temp closed file2 unlocked}
316lock_status 4.12.2 db2 {main unlocked temp closed file2 unlocked}
drhff13c7d2004-06-09 21:01:11 +0000317
318do_test attach2-4.13 {
danielk19773a81de12004-05-31 12:34:53 +0000319 execsql {SELECT * FROM file2.t1}
320} {1 2}
drhff13c7d2004-06-09 21:01:11 +0000321do_test attach2-4.14 {
danielk19773a81de12004-05-31 12:34:53 +0000322 execsql {INSERT INTO t1 VALUES(1, 2)}
323} {}
drhff13c7d2004-06-09 21:01:11 +0000324do_test attach2-4.15 {
danielk19773a81de12004-05-31 12:34:53 +0000325 execsql {SELECT * FROM t1} db2
drhff13c7d2004-06-09 21:01:11 +0000326} {1 2 1 2}
danielk19773a81de12004-05-31 12:34:53 +0000327
328db close
329db2 close
mistachkinfda06be2011-08-02 00:57:34 +0000330forcedelete test2.db
drhb7712282007-08-10 19:46:13 +0000331sqlite3_soft_heap_limit $soft_limit
drh3c8bf552003-07-01 18:13:14 +0000332
danielk1977962398d2004-06-14 09:35:16 +0000333# These tests - attach2-5.* - check that the master journal file is deleted
334# correctly when a multi-file transaction is committed or rolled back.
335#
336# Update: It's not actually created if a rollback occurs, so that test
337# doesn't really prove too much.
mistachkinfda06be2011-08-02 00:57:34 +0000338foreach f [glob test.db*] {forcedelete $f}
danielk1977962398d2004-06-14 09:35:16 +0000339do_test attach2-5.1 {
drhef4ac8f2004-06-19 00:16:31 +0000340 sqlite3 db test.db
danielk1977962398d2004-06-14 09:35:16 +0000341 execsql {
342 ATTACH 'test.db2' AS aux;
343 }
344} {}
345do_test attach2-5.2 {
346 execsql {
347 BEGIN;
348 CREATE TABLE tbl(a, b, c);
349 CREATE TABLE aux.tbl(a, b, c);
350 COMMIT;
351 }
352} {}
353do_test attach2-5.3 {
drh57790b82004-10-07 22:22:39 +0000354 lsort [glob test.db*]
danielk1977962398d2004-06-14 09:35:16 +0000355} {test.db test.db2}
356do_test attach2-5.4 {
357 execsql {
358 BEGIN;
359 DROP TABLE aux.tbl;
360 DROP TABLE tbl;
361 ROLLBACK;
362 }
363} {}
364do_test attach2-5.5 {
drh57790b82004-10-07 22:22:39 +0000365 lsort [glob test.db*]
danielk1977962398d2004-06-14 09:35:16 +0000366} {test.db test.db2}
367
danielk197792f9a1b2004-06-19 09:08:16 +0000368# Check that a database cannot be ATTACHed or DETACHed during a transaction.
369do_test attach2-6.1 {
370 execsql {
371 BEGIN;
372 }
373} {}
374do_test attach2-6.2 {
375 catchsql {
376 ATTACH 'test3.db' as aux2;
377 }
378} {1 {cannot ATTACH database within transaction}}
379
drhcf9fca42013-10-11 23:37:57 +0000380# EVIDENCE-OF: R-59740-55581 This statement will fail if SQLite is in
381# the middle of a transaction.
382#
danielk197792f9a1b2004-06-19 09:08:16 +0000383do_test attach2-6.3 {
384 catchsql {
385 DETACH aux;
386 }
387} {1 {cannot DETACH database within transaction}}
388do_test attach2-6.4 {
389 execsql {
390 COMMIT;
391 DETACH aux;
392 }
393} {}
394
danielk1977962398d2004-06-14 09:35:16 +0000395db close
396
drh3c8bf552003-07-01 18:13:14 +0000397finish_test