1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
|
# 2020 May 06
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
# TESTRUNNER: slow
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
set testprefix walsetlk3
ifcapable !wal {finish_test ; return }
ifcapable !setlk_timeout {finish_test ; return }
do_execsql_test 1.0 {
CREATE TABLE t1(x, y);
PRAGMA journal_mode = wal;
INSERT INTO t1 VALUES(1, 2);
INSERT INTO t1 VALUES(3, 4);
} {wal}
db close
proc sql_block_on_close {sql} {
testfixture_nb done [string map [list %SQL% $sql] {
testvfs tvfs
tvfs script xWrite
tvfs filter xWrite
set ::delay_done 0
proc xWrite {method fname args} {
if {[file tail $fname]=="test.db" && $::delay_done==0} {
after 3000
set ::delay_done 1
}
return 0
}
sqlite3 db test.db -vfs tvfs
db eval {%SQL%}
db close
}]
}
# Start a second process that writes to the db, then blocks within the
# [db close] holding an EXCLUSIVE on the db in order to checkpoint and
# delete the wal file. Then try to read the db.
#
# Without the SQLITE_SETLK_BLOCK_ON_CONNECT flag, this should fail with
# SQLITE_BUSY.
#
sql_block_on_close {
INSERT INTO t1 VALUES(5, 6);
INSERT INTO t1 VALUES(7, 8);
}
after 500 {set ok 1}
vwait ok
sqlite3 db test.db
sqlite3_setlk_timeout db 2000
do_catchsql_test 1.1 {
SELECT * FROM t1
} {1 {database is locked}}
vwait ::done
# But with SQLITE_SETLK_BLOCK_ON_CONNECT flag, it should succeed.
#
sql_block_on_close {
INSERT INTO t1 VALUES(9, 10);
INSERT INTO t1 VALUES(11, 12);
}
after 500 {set ok 1}
vwait ok
sqlite3 db test.db
sqlite3_setlk_timeout -block db 2000
do_catchsql_test 1.2 {
SELECT * FROM t1
} {0 {1 2 3 4 5 6 7 8 9 10 11 12}}
vwait ::done
#-------------------------------------------------------------------------
# Check that the SQLITE_SETLK_BLOCK_ON_CONNECT does not cause connections
# to block when taking a SHARED lock on a rollback mode database.
#
reset_db
do_execsql_test 2.1 {
CREATE TABLE x1(a);
INSERT INTO x1 VALUES(1), (2), (3);
}
proc sql_block_on_write {sql} {
testfixture_nb done [string map [list %SQL% $sql] {
sqlite3 db test.db
db eval "BEGIN EXCLUSIVE"
db eval {%SQL%}
after 3000
db eval COMMIT
db close
}]
}
db close
sql_block_on_write {
INSERT INTO x1 VALUES(4);
}
after 500 {set ok 1}
vwait ok
sqlite3 db test.db
sqlite3_setlk_timeout -block db 2000
do_catchsql_test 2.2 {
SELECT * FROM x1
} {1 {database is locked}}
vwait ::done
after 500 {set ok 1}
vwait ok
do_catchsql_test 2.3 {
SELECT * FROM x1
} {0 {1 2 3 4}}
finish_test
|