1# 2010 December 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 file is testing the operation of the library in 13# "PRAGMA journal_mode=WAL" mode. 14# 15 16set testdir [file dirname $argv0] 17set testprefix wal6 18source $testdir/tester.tcl 19source $testdir/lock_common.tcl 20source $testdir/wal_common.tcl 21source $testdir/malloc_common.tcl 22ifcapable !wal {finish_test ; return } 23 24#------------------------------------------------------------------------- 25# Changing to WAL mode in one connection forces the change in others. 26# 27db close 28forcedelete test.db 29 30set all_journal_modes {delete persist truncate memory off} 31foreach jmode $all_journal_modes { 32 33 do_test wal6-1.0.$jmode { 34 sqlite3 db test.db 35 execsql "PRAGMA journal_mode = $jmode;" 36 } $jmode 37 38 do_test wal6-1.1.$jmode { 39 execsql { 40 CREATE TABLE t1(a INTEGER PRIMARY KEY, b); 41 INSERT INTO t1 VALUES(1,2); 42 SELECT * FROM t1; 43 } 44 } {1 2} 45 46# Under Windows, you'll get an error trying to delete 47# a file this is already opened. Close the first connection 48# so the other tests work. 49if {$tcl_platform(platform)=="windows"} { 50 if {$jmode=="persist" || $jmode=="truncate"} { 51 db close 52 } 53} 54 55 do_test wal6-1.2.$jmode { 56 sqlite3 db2 test.db 57 execsql { 58 PRAGMA journal_mode=WAL; 59 INSERT INTO t1 VALUES(3,4); 60 SELECT * FROM t1 ORDER BY a; 61 } db2 62 } {wal 1 2 3 4} 63 64if {$tcl_platform(platform)=="windows"} { 65 if {$jmode=="persist" || $jmode=="truncate"} { 66 sqlite3 db test.db 67 } 68} 69 70 do_test wal6-1.3.$jmode { 71 execsql { 72 SELECT * FROM t1 ORDER BY a; 73 } 74 } {1 2 3 4} 75 76 db close 77 db2 close 78 forcedelete test.db 79 80} 81 82#------------------------------------------------------------------------- 83# Test that SQLITE_BUSY_SNAPSHOT is returned as expected. 84# 85reset_db 86sqlite3 db2 test.db 87 88do_execsql_test 2.1 { 89 PRAGMA journal_mode = WAL; 90 CREATE TABLE t1(a PRIMARY KEY, b TEXT); 91 INSERT INTO t1 VALUES(1, 'one'); 92 INSERT INTO t1 VALUES(2, 'two'); 93 BEGIN; 94 SELECT * FROM t1; 95} {wal 1 one 2 two} 96 97do_test 2.2 { 98 execsql { 99 SELECT * FROM t1; 100 INSERT INTO t1 VALUES(3, 'three'); 101 } db2 102} {1 one 2 two} 103 104do_catchsql_test 2.3 { 105 INSERT INTO t1 VALUES('x', 'x') 106} {1 {database is locked}} 107 108do_test 2.4 { 109 list [sqlite3_errcode db] [sqlite3_extended_errcode db] 110} {SQLITE_BUSY SQLITE_BUSY_SNAPSHOT} 111 112do_execsql_test 2.5 { 113 SELECT * FROM t1; 114 COMMIT; 115 INSERT INTO t1 VALUES('x', 'x') 116} {1 one 2 two} 117 118proc test3 {prefix} { 119 do_test $prefix.1 { 120 execsql { SELECT count(*) FROM t1 } 121 } {0} 122 do_test $prefix.2 { 123 execsql { INSERT INTO t1 VALUES('x', 'x') } db2 124 } {} 125 do_test $prefix.3 { 126 execsql { INSERT INTO t1 VALUES('y', 'y') } 127 } {} 128 do_test $prefix.4 { 129 execsql { SELECT count(*) FROM t1 } 130 } {2} 131} 132 133do_execsql_test 2.6.1 { DELETE FROM t1 } 134test3 2.6.2 135 136db func test3 test3 137do_execsql_test 2.6.3 { DELETE FROM t1 } 138db eval {SELECT test3('2.6.4')} 139 140do_test 2.x { 141 db2 close 142} {} 143 144#------------------------------------------------------------------------- 145# Check that if BEGIN IMMEDIATE fails, it does not leave the user with 146# an open read-transaction (unless one was already open before the BEGIN 147# IMMEDIATE). Even if there are other active VMs. 148# 149 150proc test4 {prefix} { 151 do_test $prefix.1 { 152 catchsql { BEGIN IMMEDIATE } 153 } {1 {database is locked}} 154 155 do_test $prefix.2 { 156 execsql { COMMIT } db2 157 } {} 158 159 do_test $prefix.3 { 160 execsql { BEGIN IMMEDIATE } 161 } {} 162 do_test $prefix.4 { 163 execsql { COMMIT } 164 } {} 165} 166 167reset_db 168sqlite3 db2 test.db 169do_execsql_test 3.1 { 170 PRAGMA journal_mode = WAL; 171 CREATE TABLE ab(a PRIMARY KEY, b); 172} {wal} 173 174do_test 3.2.1 { 175 execsql { 176 BEGIN; 177 INSERT INTO ab VALUES(1, 2); 178 } db2 179} {} 180test4 3.2.2 181 182db func test4 test4 183do_test 3.3.1 { 184 execsql { 185 BEGIN; 186 INSERT INTO ab VALUES(3, 4); 187 } db2 188} {} 189 190db eval {SELECT test4('3.3.2')} 191 192do_test 3.x { 193 db2 close 194} {} 195 196#------------------------------------------------------------------------- 197# Check that if a wal file has been partially checkpointed, no frames are 198# read from the checkpointed part. 199# 200reset_db 201do_execsql_test 4.1 { 202 PRAGMA page_size = 1024; 203 PRAGMA journal_mode = wal; 204 CREATE TABLE t1(a, b); 205 CREATE TABLE t2(a, b); 206 PRAGMA wal_checkpoint = truncate; 207} {wal 0 0 0} 208 209do_test 4.2 { 210 execsql { INSERT INTO t1 VALUES(1, 2) } 211 file size test.db-wal 212} [wal_file_size 1 1024] 213 214do_test 4.3 { 215 sqlite3 db2 test.db 216 execsql { 217 BEGIN; 218 INSERT INTO t2 VALUES(3, 4); 219 } 220 execsql { PRAGMA wal_checkpoint = passive } db2 221} {0 1 1} 222 223do_test 4.3 { 224 execsql { COMMIT } 225 db2 close 226 hexio_write test.db-wal 0 [string repeat 00 2000] 227 sqlite3 db2 test.db 228} {} 229 230do_test 4.4.1 { 231 catchsql { SELECT * FROM t1 } db2 232} {0 {1 2}} 233do_test 4.4.2 { 234 catchsql { SELECT * FROM t2 } db2 235} {1 {database disk image is malformed}} 236 237#------------------------------------------------------------------------- 238# Confirm that it is possible to get an SQLITE_BUSY_SNAPSHOT error from 239# "BEGIN EXCLUSIVE" if the connection already has an open read-transaction. 240# 241db close 242db2 close 243reset_db 244sqlite3 db2 test.db 245do_execsql_test 5.1 { 246 PRAGMA journal_mode = wal; 247 CREATE TABLE t1(x, y); 248 INSERT INTO t1 VALUES(1, 2); 249 INSERT INTO t1 VALUES(3, 4); 250} {wal} 251do_test 5.2 { 252 set res [list] 253 db eval { 254 SELECT * FROM t1 255 } { 256 if {$x==1} { 257 db2 eval { INSERT INTO t1 VALUES(5, 6) } 258 } 259 if {$x==3} { 260 set res [catchsql {BEGIN EXCLUSIVE}] 261 lappend res [sqlite3_extended_errcode db] 262 } 263 } 264 set res 265} {1 {database is locked} SQLITE_BUSY_SNAPSHOT} 266 267 268 269finish_test 270