blob: f785c4bb2384ecedaa37c2b184b48f660f908c53 [file] [log] [blame]
drhb19a2bc2001-09-16 00:13:26 +00001# 2001 September 15
drh2dfbbca2000-07-28 14:32:48 +00002#
drhb19a2bc2001-09-16 00:13:26 +00003# The author disclaims copyright to this source code. In place of
4# a legal notice, here is a blessing:
drh2dfbbca2000-07-28 14:32:48 +00005#
drhb19a2bc2001-09-16 00:13:26 +00006# 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.
drh2dfbbca2000-07-28 14:32:48 +00009#
10#***********************************************************************
11# This file implements regression tests for SQLite library. The
12# focus of this script is database locks.
13#
drh9da742f2009-06-16 17:49:36 +000014# $Id: lock.test,v 1.40 2009/06/16 17:49:36 drh Exp $
drh767c2002000-10-19 14:10:08 +000015
drh2dfbbca2000-07-28 14:32:48 +000016
17set testdir [file dirname $argv0]
18source $testdir/tester.tcl
19
drhecdc7532001-09-23 02:35:53 +000020# Create an alternative connection to the database
drh2dfbbca2000-07-28 14:32:48 +000021#
22do_test lock-1.0 {
drh94dfe472009-03-28 15:04:24 +000023 # Give a complex pathname to stress the path simplification logic in
24 # the vxworks driver and in test_async.
25 file mkdir tempdir/t1/t2
26 sqlite3 db2 ./tempdir/../tempdir/t1/.//t2/../../..//test.db
drhc22bd472002-05-10 13:14:07 +000027 set dummy {}
drh2dfbbca2000-07-28 14:32:48 +000028} {}
drh2dfbbca2000-07-28 14:32:48 +000029do_test lock-1.1 {
drhecdc7532001-09-23 02:35:53 +000030 execsql {SELECT name FROM sqlite_master WHERE type='table' ORDER BY name}
drh2dfbbca2000-07-28 14:32:48 +000031} {}
drhecdc7532001-09-23 02:35:53 +000032do_test lock-1.2 {
33 execsql {SELECT name FROM sqlite_master WHERE type='table' ORDER BY name} db2
34} {}
35do_test lock-1.3 {
36 execsql {CREATE TABLE t1(a int, b int)}
37 execsql {SELECT name FROM sqlite_master WHERE type='table' ORDER BY name}
38} {t1}
drhecdc7532001-09-23 02:35:53 +000039do_test lock-1.5 {
drhad75e982001-10-09 04:19:46 +000040 catchsql {
drhecdc7532001-09-23 02:35:53 +000041 SELECT name FROM sqlite_master WHERE type='table' ORDER BY name
drhad75e982001-10-09 04:19:46 +000042 } db2
drhecdc7532001-09-23 02:35:53 +000043} {0 t1}
drh2dfbbca2000-07-28 14:32:48 +000044
drhecdc7532001-09-23 02:35:53 +000045do_test lock-1.6 {
46 execsql {INSERT INTO t1 VALUES(1,2)}
47 execsql {SELECT * FROM t1}
48} {1 2}
danielk1977f9d19a62004-06-14 08:26:35 +000049# Update: The schema is now brought up to date by test lock-1.5.
50# do_test lock-1.7.1 {
51# catchsql {SELECT * FROM t1} db2
52# } {1 {no such table: t1}}
drhf8646692004-06-09 23:15:22 +000053do_test lock-1.7.2 {
drhf8646692004-06-09 23:15:22 +000054 catchsql {SELECT * FROM t1} db2
55} {0 {1 2}}
drhecdc7532001-09-23 02:35:53 +000056do_test lock-1.8 {
57 execsql {UPDATE t1 SET a=b, b=a} db2
58 execsql {SELECT * FROM t1} db2
59} {2 1}
60do_test lock-1.9 {
61 execsql {SELECT * FROM t1}
62} {2 1}
drhecdc7532001-09-23 02:35:53 +000063do_test lock-1.10 {
64 execsql {BEGIN TRANSACTION}
danielk19771d850a72004-05-31 08:26:49 +000065 execsql {UPDATE t1 SET a = 0 WHERE 0}
drhecdc7532001-09-23 02:35:53 +000066 execsql {SELECT * FROM t1}
67} {2 1}
68do_test lock-1.11 {
drhad75e982001-10-09 04:19:46 +000069 catchsql {SELECT * FROM t1} db2
drha6ecd332004-06-10 00:29:09 +000070} {0 {2 1}}
drhecdc7532001-09-23 02:35:53 +000071do_test lock-1.12 {
72 execsql {ROLLBACK}
drhad75e982001-10-09 04:19:46 +000073 catchsql {SELECT * FROM t1}
drhecdc7532001-09-23 02:35:53 +000074} {0 {2 1}}
drh2dfbbca2000-07-28 14:32:48 +000075
drhecdc7532001-09-23 02:35:53 +000076do_test lock-1.13 {
77 execsql {CREATE TABLE t2(x int, y int)}
78 execsql {INSERT INTO t2 VALUES(8,9)}
79 execsql {SELECT * FROM t2}
80} {8 9}
drha1f9b5e2004-02-14 16:31:02 +000081do_test lock-1.14.1 {
82 catchsql {SELECT * FROM t2} db2
drh9da742f2009-06-16 17:49:36 +000083} {0 {8 9}}
drha1f9b5e2004-02-14 16:31:02 +000084do_test lock-1.14.2 {
drhad75e982001-10-09 04:19:46 +000085 catchsql {SELECT * FROM t1} db2
drha1f9b5e2004-02-14 16:31:02 +000086} {0 {2 1}}
drhecdc7532001-09-23 02:35:53 +000087do_test lock-1.15 {
drhad75e982001-10-09 04:19:46 +000088 catchsql {SELECT * FROM t2} db2
drhecdc7532001-09-23 02:35:53 +000089} {0 {8 9}}
drh2dfbbca2000-07-28 14:32:48 +000090
drhecdc7532001-09-23 02:35:53 +000091do_test lock-1.16 {
92 db eval {SELECT * FROM t1} qv {
93 set x [db eval {SELECT * FROM t1}]
94 }
95 set x
96} {2 1}
97do_test lock-1.17 {
98 db eval {SELECT * FROM t1} qv {
99 set x [db eval {SELECT * FROM t2}]
100 }
101 set x
102} {8 9}
drh2dfbbca2000-07-28 14:32:48 +0000103
danielk197712b13002004-11-22 10:02:21 +0000104# You cannot UPDATE a table from within the callback of a SELECT
105# on that same table because the SELECT has the table locked.
drh980b1a72006-08-16 16:42:48 +0000106#
107# 2006-08-16: Reads no longer block writes within the same
108# database connection.
109#
110#do_test lock-1.18 {
111# db eval {SELECT * FROM t1} qv {
112# set r [catch {db eval {UPDATE t1 SET a=b, b=a}} msg]
113# lappend r $msg
114# }
115# set r
116#} {1 {database table is locked}}
drhecdc7532001-09-23 02:35:53 +0000117
118# But you can UPDATE a different table from the one that is used in
119# the SELECT.
120#
121do_test lock-1.19 {
122 db eval {SELECT * FROM t1} qv {
123 set r [catch {db eval {UPDATE t2 SET x=y, y=x}} msg]
124 lappend r $msg
125 }
126 set r
127} {0 {}}
128do_test lock-1.20 {
129 execsql {SELECT * FROM t2}
130} {9 8}
131
132# It is possible to do a SELECT of the same table within the
133# callback of another SELECT on that same table because two
134# or more read-only cursors can be open at once.
135#
136do_test lock-1.21 {
137 db eval {SELECT * FROM t1} qv {
138 set r [catch {db eval {SELECT a FROM t1}} msg]
139 lappend r $msg
140 }
141 set r
142} {0 2}
143
144# Under UNIX you can do two SELECTs at once with different database
145# connections, because UNIX supports reader/writer locks. Under windows,
146# this is not possible.
147#
148if {$::tcl_platform(platform)=="unix"} {
149 do_test lock-1.22 {
150 db eval {SELECT * FROM t1} qv {
151 set r [catch {db2 eval {SELECT a FROM t1}} msg]
152 lappend r $msg
153 }
154 set r
155 } {0 2}
156}
drh21504322002-06-25 13:16:02 +0000157integrity_check lock-1.23
drhecdc7532001-09-23 02:35:53 +0000158
drh90bfcda2001-09-23 19:46:51 +0000159# If one thread has a transaction another thread cannot start
drha6ecd332004-06-10 00:29:09 +0000160# a transaction. -> Not true in version 3.0. But if one thread
161# as a RESERVED lock another thread cannot acquire one.
drh90bfcda2001-09-23 19:46:51 +0000162#
163do_test lock-2.1 {
164 execsql {BEGIN TRANSACTION}
danielk19771d850a72004-05-31 08:26:49 +0000165 execsql {UPDATE t1 SET a = 0 WHERE 0}
166 execsql {BEGIN TRANSACTION} db2
167 set r [catch {execsql {UPDATE t1 SET a = 0 WHERE 0} db2} msg]
168 execsql {ROLLBACK} db2
drh90bfcda2001-09-23 19:46:51 +0000169 lappend r $msg
170} {1 {database is locked}}
171
drha6ecd332004-06-10 00:29:09 +0000172# A thread can read when another has a RESERVED lock.
drh90bfcda2001-09-23 19:46:51 +0000173#
174do_test lock-2.2 {
drha6ecd332004-06-10 00:29:09 +0000175 catchsql {SELECT * FROM t2} db2
176} {0 {9 8}}
drh90bfcda2001-09-23 19:46:51 +0000177
drha6ecd332004-06-10 00:29:09 +0000178# If the other thread (the one that does not hold the transaction with
drhb8ef32c2005-03-14 02:01:49 +0000179# a RESERVED lock) tries to get a RESERVED lock, we do get a busy callback
180# as long as we were not orginally holding a READ lock.
drh90bfcda2001-09-23 19:46:51 +0000181#
drhb8ef32c2005-03-14 02:01:49 +0000182do_test lock-2.3.1 {
danielk19772a764eb2004-06-12 01:43:26 +0000183 proc callback {count} {
184 set ::callback_value $count
drh90bfcda2001-09-23 19:46:51 +0000185 break
186 }
187 set ::callback_value {}
188 db2 busy callback
drhb8ef32c2005-03-14 02:01:49 +0000189 # db2 does not hold a lock so we should get a busy callback here
190 set r [catch {execsql {UPDATE t1 SET a=b, b=a} db2} msg]
191 lappend r $msg
192 lappend r $::callback_value
193} {1 {database is locked} 0}
194do_test lock-2.3.2 {
195 set ::callback_value {}
196 execsql {BEGIN; SELECT rowid FROM sqlite_master LIMIT 1} db2
197 # This time db2 does hold a read lock. No busy callback this time.
drha6ecd332004-06-10 00:29:09 +0000198 set r [catch {execsql {UPDATE t1 SET a=b, b=a} db2} msg]
drh90bfcda2001-09-23 19:46:51 +0000199 lappend r $msg
200 lappend r $::callback_value
drh1d64fc12004-08-07 23:54:48 +0000201} {1 {database is locked} {}}
drhb8ef32c2005-03-14 02:01:49 +0000202catch {execsql {ROLLBACK} db2}
203do_test lock-2.4.1 {
danielk19772a764eb2004-06-12 01:43:26 +0000204 proc callback {count} {
drh90bfcda2001-09-23 19:46:51 +0000205 lappend ::callback_value $count
206 if {$count>4} break
207 }
208 set ::callback_value {}
209 db2 busy callback
drhb8ef32c2005-03-14 02:01:49 +0000210 # We get a busy callback because db2 is not holding a lock
211 set r [catch {execsql {UPDATE t1 SET a=b, b=a} db2} msg]
212 lappend r $msg
213 lappend r $::callback_value
214} {1 {database is locked} {0 1 2 3 4 5}}
215do_test lock-2.4.2 {
216 proc callback {count} {
217 lappend ::callback_value $count
218 if {$count>4} break
219 }
220 set ::callback_value {}
221 db2 busy callback
222 execsql {BEGIN; SELECT rowid FROM sqlite_master LIMIT 1} db2
223 # No busy callback this time because we are holding a lock
drha6ecd332004-06-10 00:29:09 +0000224 set r [catch {execsql {UPDATE t1 SET a=b, b=a} db2} msg]
drh90bfcda2001-09-23 19:46:51 +0000225 lappend r $msg
226 lappend r $::callback_value
drh1d64fc12004-08-07 23:54:48 +0000227} {1 {database is locked} {}}
drhb8ef32c2005-03-14 02:01:49 +0000228catch {execsql {ROLLBACK} db2}
drh90bfcda2001-09-23 19:46:51 +0000229do_test lock-2.5 {
danielk19772a764eb2004-06-12 01:43:26 +0000230 proc callback {count} {
drh90bfcda2001-09-23 19:46:51 +0000231 lappend ::callback_value $count
232 if {$count>4} break
233 }
234 set ::callback_value {}
235 db2 busy callback
236 set r [catch {execsql {SELECT * FROM t1} db2} msg]
237 lappend r $msg
238 lappend r $::callback_value
drha6ecd332004-06-10 00:29:09 +0000239} {0 {2 1} {}}
drh1d64fc12004-08-07 23:54:48 +0000240execsql {ROLLBACK}
drhd1bec472004-01-15 13:29:31 +0000241
242# Test the built-in busy timeout handler
243#
drh9d356fb2015-02-27 20:28:08 +0000244# EVIDENCE-OF: R-23579-05241 PRAGMA busy_timeout; PRAGMA busy_timeout =
245# milliseconds; Query or change the setting of the busy timeout.
246#
drhd1bec472004-01-15 13:29:31 +0000247do_test lock-2.8 {
248 db2 timeout 400
249 execsql BEGIN
danielk19771d850a72004-05-31 08:26:49 +0000250 execsql {UPDATE t1 SET a = 0 WHERE 0}
danielk19774397de52005-01-12 12:44:03 +0000251 catchsql {BEGIN EXCLUSIVE;} db2
drhd1bec472004-01-15 13:29:31 +0000252} {1 {database is locked}}
drhf3603962012-09-07 16:46:59 +0000253do_test lock-2.8b {
254 db2 eval {PRAGMA busy_timeout}
255} {400}
drhd1bec472004-01-15 13:29:31 +0000256do_test lock-2.9 {
257 db2 timeout 0
258 execsql COMMIT
259} {}
drhf3603962012-09-07 16:46:59 +0000260do_test lock-2.9b {
261 db2 eval {PRAGMA busy_timeout}
262} {0}
drhd1bec472004-01-15 13:29:31 +0000263integrity_check lock-2.10
drhf3603962012-09-07 16:46:59 +0000264do_test lock-2.11 {
265 db2 eval {PRAGMA busy_timeout(400)}
266 execsql BEGIN
267 execsql {UPDATE t1 SET a = 0 WHERE 0}
268 catchsql {BEGIN EXCLUSIVE;} db2
269} {1 {database is locked}}
270do_test lock-2.11b {
271 db2 eval {PRAGMA busy_timeout}
272} {400}
273do_test lock-2.12 {
274 db2 eval {PRAGMA busy_timeout(0)}
275 execsql COMMIT
276} {}
mistachkin50610df2012-09-07 20:10:30 +0000277do_test lock-2.12b {
drhf3603962012-09-07 16:46:59 +0000278 db2 eval {PRAGMA busy_timeout}
279} {0}
mistachkin50610df2012-09-07 20:10:30 +0000280integrity_check lock-2.13
drh90bfcda2001-09-23 19:46:51 +0000281
282# Try to start two transactions in a row
283#
284do_test lock-3.1 {
285 execsql {BEGIN TRANSACTION}
286 set r [catch {execsql {BEGIN TRANSACTION}} msg]
287 execsql {ROLLBACK}
288 lappend r $msg
drh6b8b8742002-08-18 20:28:06 +0000289} {1 {cannot start a transaction within a transaction}}
drh21504322002-06-25 13:16:02 +0000290integrity_check lock-3.2
drhecdc7532001-09-23 02:35:53 +0000291
drh1e0ccab2002-08-29 23:59:47 +0000292# Make sure the busy handler and error messages work when
293# opening a new pointer to the database while another pointer
294# has the database locked.
295#
296do_test lock-4.1 {
297 db2 close
298 catch {db eval ROLLBACK}
299 db eval BEGIN
danielk19771d850a72004-05-31 08:26:49 +0000300 db eval {UPDATE t1 SET a=0 WHERE 0}
drhef4ac8f2004-06-19 00:16:31 +0000301 sqlite3 db2 ./test.db
drha6ecd332004-06-10 00:29:09 +0000302 catchsql {UPDATE t1 SET a=0} db2
drh1e0ccab2002-08-29 23:59:47 +0000303} {1 {database is locked}}
304do_test lock-4.2 {
305 set ::callback_value {}
drha6ecd332004-06-10 00:29:09 +0000306 set rc [catch {db2 eval {UPDATE t1 SET a=0}} msg]
drh1e0ccab2002-08-29 23:59:47 +0000307 lappend rc $msg $::callback_value
308} {1 {database is locked} {}}
309do_test lock-4.3 {
danielk19772a764eb2004-06-12 01:43:26 +0000310 proc callback {count} {
drh1e0ccab2002-08-29 23:59:47 +0000311 lappend ::callback_value $count
312 if {$count>4} break
313 }
314 db2 busy callback
drha6ecd332004-06-10 00:29:09 +0000315 set rc [catch {db2 eval {UPDATE t1 SET a=0}} msg]
drh1e0ccab2002-08-29 23:59:47 +0000316 lappend rc $msg $::callback_value
drhb8ef32c2005-03-14 02:01:49 +0000317} {1 {database is locked} {0 1 2 3 4 5}}
drhcabb0812002-09-14 13:47:32 +0000318execsql {ROLLBACK}
drh1e0ccab2002-08-29 23:59:47 +0000319
drhcabb0812002-09-14 13:47:32 +0000320# When one thread is writing, other threads cannot read. Except if the
321# writing thread is writing to its temporary tables, the other threads
drha6ecd332004-06-10 00:29:09 +0000322# can still read. -> Not so in 3.0. One thread can read while another
323# holds a RESERVED lock.
drhcabb0812002-09-14 13:47:32 +0000324#
325proc tx_exec {sql} {
326 db2 eval $sql
327}
328do_test lock-5.1 {
329 execsql {
330 SELECT * FROM t1
331 }
332} {2 1}
333do_test lock-5.2 {
334 db function tx_exec tx_exec
335 catchsql {
336 INSERT INTO t1(a,b) SELECT 3, tx_exec('SELECT y FROM t2 LIMIT 1');
337 }
drha6ecd332004-06-10 00:29:09 +0000338} {0 {}}
danielk197753c0f742005-03-29 03:10:59 +0000339
340ifcapable tempdb {
341 do_test lock-5.3 {
342 execsql {
343 CREATE TEMP TABLE t3(x);
344 SELECT * FROM t3;
345 }
346 } {}
347 do_test lock-5.4 {
348 catchsql {
349 INSERT INTO t3 SELECT tx_exec('SELECT y FROM t2 LIMIT 1');
350 }
351 } {0 {}}
352 do_test lock-5.5 {
353 execsql {
354 SELECT * FROM t3;
355 }
356 } {8}
357 do_test lock-5.6 {
358 catchsql {
359 UPDATE t1 SET a=tx_exec('SELECT x FROM t2');
360 }
361 } {0 {}}
362 do_test lock-5.7 {
363 execsql {
364 SELECT * FROM t1;
365 }
366 } {9 1 9 8}
367 do_test lock-5.8 {
368 catchsql {
369 UPDATE t3 SET x=tx_exec('SELECT x FROM t2');
370 }
371 } {0 {}}
372 do_test lock-5.9 {
373 execsql {
374 SELECT * FROM t3;
375 }
376 } {9}
377}
drh1e0ccab2002-08-29 23:59:47 +0000378
danielk1977104f1fe2009-01-14 17:45:57 +0000379do_test lock-6.1 {
380 execsql {
381 CREATE TABLE t4(a PRIMARY KEY, b);
382 INSERT INTO t4 VALUES(1, 'one');
383 INSERT INTO t4 VALUES(2, 'two');
384 INSERT INTO t4 VALUES(3, 'three');
385 }
386
387 set STMT [sqlite3_prepare $DB "SELECT * FROM sqlite_master" -1 TAIL]
388 sqlite3_step $STMT
389
390 execsql { DELETE FROM t4 }
391 execsql { SELECT * FROM sqlite_master } db2
392 execsql { SELECT * FROM t4 } db2
393} {}
394
395do_test lock-6.2 {
396 execsql {
397 BEGIN;
398 INSERT INTO t4 VALUES(1, 'one');
399 INSERT INTO t4 VALUES(2, 'two');
400 INSERT INTO t4 VALUES(3, 'three');
401 COMMIT;
402 }
403
404 execsql { SELECT * FROM t4 } db2
405} {1 one 2 two 3 three}
406
407do_test lock-6.3 {
408 execsql { SELECT a FROM t4 ORDER BY a } db2
409} {1 2 3}
410
411do_test lock-6.4 {
412 execsql { PRAGMA integrity_check } db2
413} {ok}
414
415do_test lock-6.5 {
416 sqlite3_finalize $STMT
417} {SQLITE_OK}
418
danielk19773cfe0702009-01-17 16:59:40 +0000419# At one point the following set of conditions would cause SQLite to
420# retain a RESERVED or EXCLUSIVE lock after the transaction was committed:
421#
422# * The journal-mode is set to something other than 'delete', and
423# * there exists one or more active read-only statements, and
424# * a transaction that modified zero database pages is committed.
425#
danielk19771435ccd2009-02-12 09:36:15 +0000426set temp_status unlocked
dand2db0902010-09-20 14:55:33 +0000427if {$TEMP_STORE>=2} {set temp_status unknown}
danielk19773cfe0702009-01-17 16:59:40 +0000428do_test lock-7.1 {
429 set STMT [sqlite3_prepare $DB "SELECT * FROM sqlite_master" -1 TAIL]
430 sqlite3_step $STMT
431} {SQLITE_ROW}
432do_test lock-7.2 {
433 execsql { PRAGMA lock_status }
danielk19771435ccd2009-02-12 09:36:15 +0000434} [list main shared temp $temp_status]
danielk19773cfe0702009-01-17 16:59:40 +0000435do_test lock-7.3 {
436 execsql {
437 PRAGMA journal_mode = truncate;
438 BEGIN;
439 UPDATE t4 SET a = 10 WHERE 0;
440 COMMIT;
441 }
442 execsql { PRAGMA lock_status }
danielk19771435ccd2009-02-12 09:36:15 +0000443} [list main shared temp $temp_status]
danielk19773cfe0702009-01-17 16:59:40 +0000444do_test lock-7.4 {
445 sqlite3_finalize $STMT
446} {SQLITE_OK}
447
drhecdc7532001-09-23 02:35:53 +0000448do_test lock-999.1 {
449 rename db2 {}
450} {}
drh2dfbbca2000-07-28 14:32:48 +0000451
452finish_test