172fe10fdSshaneh# 2010 December 1 272fe10fdSshaneh# 372fe10fdSshaneh# The author disclaims copyright to this source code. In place of 472fe10fdSshaneh# a legal notice, here is a blessing: 572fe10fdSshaneh# 672fe10fdSshaneh# May you do good and not evil. 772fe10fdSshaneh# May you find forgiveness for yourself and forgive others. 872fe10fdSshaneh# May you share freely, never taking more than you give. 972fe10fdSshaneh# 1072fe10fdSshaneh#*********************************************************************** 1172fe10fdSshaneh# This file implements regression tests for SQLite library. The 1272fe10fdSshaneh# focus of this file is testing the operation of the library in 1372fe10fdSshaneh# "PRAGMA journal_mode=WAL" mode. 1472fe10fdSshaneh# 1572fe10fdSshaneh 1672fe10fdSshanehset testdir [file dirname $argv0] 17f73819afSdanset testprefix wal6 1872fe10fdSshanehsource $testdir/tester.tcl 1972fe10fdSshanehsource $testdir/lock_common.tcl 2072fe10fdSshanehsource $testdir/wal_common.tcl 2172fe10fdSshanehsource $testdir/malloc_common.tcl 2272fe10fdSshanehifcapable !wal {finish_test ; return } 2372fe10fdSshaneh 2472fe10fdSshaneh#------------------------------------------------------------------------- 2572fe10fdSshaneh# Changing to WAL mode in one connection forces the change in others. 2672fe10fdSshaneh# 2772fe10fdSshanehdb close 2872fe10fdSshanehforcedelete test.db 2972fe10fdSshaneh 3072fe10fdSshanehset all_journal_modes {delete persist truncate memory off} 3172fe10fdSshanehforeach jmode $all_journal_modes { 3272fe10fdSshaneh 3372fe10fdSshaneh do_test wal6-1.0.$jmode { 3472fe10fdSshaneh sqlite3 db test.db 3572fe10fdSshaneh execsql "PRAGMA journal_mode = $jmode;" 3672fe10fdSshaneh } $jmode 3772fe10fdSshaneh 3872fe10fdSshaneh do_test wal6-1.1.$jmode { 3972fe10fdSshaneh execsql { 4072fe10fdSshaneh CREATE TABLE t1(a INTEGER PRIMARY KEY, b); 4172fe10fdSshaneh INSERT INTO t1 VALUES(1,2); 4272fe10fdSshaneh SELECT * FROM t1; 4372fe10fdSshaneh } 4472fe10fdSshaneh } {1 2} 4572fe10fdSshaneh 4672fe10fdSshaneh# Under Windows, you'll get an error trying to delete 4752564d70Sdrh# a file this is already opened. Close the first connection 4872fe10fdSshaneh# so the other tests work. 4972fe10fdSshanehif {$tcl_platform(platform)=="windows"} { 5072fe10fdSshaneh if {$jmode=="persist" || $jmode=="truncate"} { 5172fe10fdSshaneh db close 5272fe10fdSshaneh } 5372fe10fdSshaneh} 5472fe10fdSshaneh 5572fe10fdSshaneh do_test wal6-1.2.$jmode { 5672fe10fdSshaneh sqlite3 db2 test.db 5772fe10fdSshaneh execsql { 5872fe10fdSshaneh PRAGMA journal_mode=WAL; 5972fe10fdSshaneh INSERT INTO t1 VALUES(3,4); 6072fe10fdSshaneh SELECT * FROM t1 ORDER BY a; 6172fe10fdSshaneh } db2 6272fe10fdSshaneh } {wal 1 2 3 4} 6372fe10fdSshaneh 6472fe10fdSshanehif {$tcl_platform(platform)=="windows"} { 6572fe10fdSshaneh if {$jmode=="persist" || $jmode=="truncate"} { 6672fe10fdSshaneh sqlite3 db test.db 6772fe10fdSshaneh } 6872fe10fdSshaneh} 6972fe10fdSshaneh 7072fe10fdSshaneh do_test wal6-1.3.$jmode { 7172fe10fdSshaneh execsql { 7272fe10fdSshaneh SELECT * FROM t1 ORDER BY a; 7372fe10fdSshaneh } 7472fe10fdSshaneh } {1 2 3 4} 7572fe10fdSshaneh 7672fe10fdSshaneh db close 7772fe10fdSshaneh db2 close 7872fe10fdSshaneh forcedelete test.db 7972fe10fdSshaneh 8072fe10fdSshaneh} 8172fe10fdSshaneh 82f73819afSdan#------------------------------------------------------------------------- 83f73819afSdan# Test that SQLITE_BUSY_SNAPSHOT is returned as expected. 84f73819afSdan# 85f73819afSdanreset_db 86f73819afSdansqlite3 db2 test.db 87f73819afSdan 88f73819afSdando_execsql_test 2.1 { 89f73819afSdan PRAGMA journal_mode = WAL; 90f73819afSdan CREATE TABLE t1(a PRIMARY KEY, b TEXT); 91f73819afSdan INSERT INTO t1 VALUES(1, 'one'); 92f73819afSdan INSERT INTO t1 VALUES(2, 'two'); 93f73819afSdan BEGIN; 94f73819afSdan SELECT * FROM t1; 95f73819afSdan} {wal 1 one 2 two} 96f73819afSdan 97f73819afSdando_test 2.2 { 98f73819afSdan execsql { 99f73819afSdan SELECT * FROM t1; 100f73819afSdan INSERT INTO t1 VALUES(3, 'three'); 101f73819afSdan } db2 102f73819afSdan} {1 one 2 two} 103f73819afSdan 104f73819afSdando_catchsql_test 2.3 { 105f73819afSdan INSERT INTO t1 VALUES('x', 'x') 106f73819afSdan} {1 {database is locked}} 107f73819afSdan 108f73819afSdando_test 2.4 { 109f73819afSdan list [sqlite3_errcode db] [sqlite3_extended_errcode db] 110f73819afSdan} {SQLITE_BUSY SQLITE_BUSY_SNAPSHOT} 111f73819afSdan 112f73819afSdando_execsql_test 2.5 { 113f73819afSdan SELECT * FROM t1; 114f73819afSdan COMMIT; 115f73819afSdan INSERT INTO t1 VALUES('x', 'x') 116f73819afSdan} {1 one 2 two} 117f73819afSdan 118f73819afSdanproc test3 {prefix} { 119f73819afSdan do_test $prefix.1 { 120f73819afSdan execsql { SELECT count(*) FROM t1 } 121f73819afSdan } {0} 122f73819afSdan do_test $prefix.2 { 123f73819afSdan execsql { INSERT INTO t1 VALUES('x', 'x') } db2 124f73819afSdan } {} 125f73819afSdan do_test $prefix.3 { 126f73819afSdan execsql { INSERT INTO t1 VALUES('y', 'y') } 127f73819afSdan } {} 128f73819afSdan do_test $prefix.4 { 129f73819afSdan execsql { SELECT count(*) FROM t1 } 130f73819afSdan } {2} 131f73819afSdan} 132f73819afSdan 133f73819afSdando_execsql_test 2.6.1 { DELETE FROM t1 } 134f73819afSdantest3 2.6.2 135f73819afSdan 136f73819afSdandb func test3 test3 137f73819afSdando_execsql_test 2.6.3 { DELETE FROM t1 } 138f73819afSdandb eval {SELECT test3('2.6.4')} 139f73819afSdan 140f73819afSdando_test 2.x { 141f73819afSdan db2 close 142f73819afSdan} {} 143f73819afSdan 144e8e570abSdan#------------------------------------------------------------------------- 145e8e570abSdan# Check that if BEGIN IMMEDIATE fails, it does not leave the user with 146e8e570abSdan# an open read-transaction (unless one was already open before the BEGIN 147e8e570abSdan# IMMEDIATE). Even if there are other active VMs. 148e8e570abSdan# 149e8e570abSdan 150e8e570abSdanproc test4 {prefix} { 151e8e570abSdan do_test $prefix.1 { 152e8e570abSdan catchsql { BEGIN IMMEDIATE } 153e8e570abSdan } {1 {database is locked}} 154e8e570abSdan 155e8e570abSdan do_test $prefix.2 { 156e8e570abSdan execsql { COMMIT } db2 157e8e570abSdan } {} 158e8e570abSdan 159e8e570abSdan do_test $prefix.3 { 160e8e570abSdan execsql { BEGIN IMMEDIATE } 161e8e570abSdan } {} 162e8e570abSdan do_test $prefix.4 { 163e8e570abSdan execsql { COMMIT } 164e8e570abSdan } {} 165e8e570abSdan} 166e8e570abSdan 167e8e570abSdanreset_db 168e8e570abSdansqlite3 db2 test.db 169e8e570abSdando_execsql_test 3.1 { 170e8e570abSdan PRAGMA journal_mode = WAL; 171e8e570abSdan CREATE TABLE ab(a PRIMARY KEY, b); 172e8e570abSdan} {wal} 173e8e570abSdan 174e8e570abSdando_test 3.2.1 { 175e8e570abSdan execsql { 176e8e570abSdan BEGIN; 177e8e570abSdan INSERT INTO ab VALUES(1, 2); 178e8e570abSdan } db2 179e8e570abSdan} {} 180e8e570abSdantest4 3.2.2 181e8e570abSdan 182e8e570abSdandb func test4 test4 183e8e570abSdando_test 3.3.1 { 184e8e570abSdan execsql { 185e8e570abSdan BEGIN; 186e8e570abSdan INSERT INTO ab VALUES(3, 4); 187e8e570abSdan } db2 188e8e570abSdan} {} 189e8e570abSdan 190e8e570abSdandb eval {SELECT test4('3.3.2')} 191e8e570abSdan 192e8e570abSdando_test 3.x { 193e8e570abSdan db2 close 194e8e570abSdan} {} 195e8e570abSdan 1966df003c7Sdan#------------------------------------------------------------------------- 1976df003c7Sdan# Check that if a wal file has been partially checkpointed, no frames are 1986df003c7Sdan# read from the checkpointed part. 1996df003c7Sdan# 2006df003c7Sdanreset_db 2016df003c7Sdando_execsql_test 4.1 { 2026df003c7Sdan PRAGMA page_size = 1024; 2036df003c7Sdan PRAGMA journal_mode = wal; 2046df003c7Sdan CREATE TABLE t1(a, b); 2056df003c7Sdan CREATE TABLE t2(a, b); 2066df003c7Sdan PRAGMA wal_checkpoint = truncate; 2076df003c7Sdan} {wal 0 0 0} 2086df003c7Sdan 2096df003c7Sdando_test 4.2 { 2106df003c7Sdan execsql { INSERT INTO t1 VALUES(1, 2) } 2116df003c7Sdan file size test.db-wal 2126df003c7Sdan} [wal_file_size 1 1024] 2136df003c7Sdan 2146df003c7Sdando_test 4.3 { 2156df003c7Sdan sqlite3 db2 test.db 2166df003c7Sdan execsql { 2176df003c7Sdan BEGIN; 2186df003c7Sdan INSERT INTO t2 VALUES(3, 4); 2196df003c7Sdan } 2206df003c7Sdan execsql { PRAGMA wal_checkpoint = passive } db2 2216df003c7Sdan} {0 1 1} 2226df003c7Sdan 2236df003c7Sdando_test 4.3 { 2246df003c7Sdan execsql { COMMIT } 2256df003c7Sdan db2 close 2266df003c7Sdan hexio_write test.db-wal 0 [string repeat 00 2000] 2276df003c7Sdan sqlite3 db2 test.db 2286df003c7Sdan} {} 2296df003c7Sdan 2306df003c7Sdando_test 4.4.1 { 2316df003c7Sdan catchsql { SELECT * FROM t1 } db2 2326df003c7Sdan} {0 {1 2}} 2336df003c7Sdando_test 4.4.2 { 2346df003c7Sdan catchsql { SELECT * FROM t2 } db2 2356df003c7Sdan} {1 {database disk image is malformed}} 2366df003c7Sdan 23701e697b4Sdan#------------------------------------------------------------------------- 23801e697b4Sdan# Confirm that it is possible to get an SQLITE_BUSY_SNAPSHOT error from 23901e697b4Sdan# "BEGIN EXCLUSIVE" if the connection already has an open read-transaction. 24001e697b4Sdan# 241*506a1400Sdrhdb close 242*506a1400Sdrhdb2 close 24301e697b4Sdanreset_db 24401e697b4Sdansqlite3 db2 test.db 24501e697b4Sdando_execsql_test 5.1 { 24601e697b4Sdan PRAGMA journal_mode = wal; 24701e697b4Sdan CREATE TABLE t1(x, y); 24801e697b4Sdan INSERT INTO t1 VALUES(1, 2); 24901e697b4Sdan INSERT INTO t1 VALUES(3, 4); 25001e697b4Sdan} {wal} 25101e697b4Sdando_test 5.2 { 25201e697b4Sdan set res [list] 25301e697b4Sdan db eval { 25401e697b4Sdan SELECT * FROM t1 25501e697b4Sdan } { 25601e697b4Sdan if {$x==1} { 25701e697b4Sdan db2 eval { INSERT INTO t1 VALUES(5, 6) } 25801e697b4Sdan } 25901e697b4Sdan if {$x==3} { 26001e697b4Sdan set res [catchsql {BEGIN EXCLUSIVE}] 26101e697b4Sdan lappend res [sqlite3_extended_errcode db] 26201e697b4Sdan } 26301e697b4Sdan } 26401e697b4Sdan set res 26501e697b4Sdan} {1 {database is locked} SQLITE_BUSY_SNAPSHOT} 26601e697b4Sdan 26701e697b4Sdan 2686df003c7Sdan 26972fe10fdSshanehfinish_test 270