19a6b4e9aSdan# 2010 May 5 29a6b4e9aSdan# 39a6b4e9aSdan# The author disclaims copyright to this source code. In place of 49a6b4e9aSdan# a legal notice, here is a blessing: 59a6b4e9aSdan# 69a6b4e9aSdan# May you do good and not evil. 79a6b4e9aSdan# May you find forgiveness for yourself and forgive others. 89a6b4e9aSdan# May you share freely, never taking more than you give. 99a6b4e9aSdan# 109a6b4e9aSdan#*********************************************************************** 119a6b4e9aSdan# This file implements regression tests for SQLite library. The 129a6b4e9aSdan# focus of this file is testing the operation of the library in 139a6b4e9aSdan# "PRAGMA journal_mode=WAL" mode. 149a6b4e9aSdan# 159a6b4e9aSdan 169a6b4e9aSdanset testdir [file dirname $argv0] 179a6b4e9aSdansource $testdir/tester.tcl 189a6b4e9aSdansource $testdir/lock_common.tcl 1910f5a50eSdansource $testdir/malloc_common.tcl 2010f5a50eSdansource $testdir/wal_common.tcl 2110f5a50eSdan 2218826195Sdanset testprefix wal2 2318826195Sdan 249a6b4e9aSdanifcapable !wal {finish_test ; return } 259a6b4e9aSdan 269dd6e080Sshanehset sqlite_sync_count 0 279dd6e080Sshanehproc cond_incr_sync_count {adj} { 289dd6e080Sshaneh global sqlite_sync_count 299dd6e080Sshaneh if {$::tcl_platform(platform) == "windows"} { 309dd6e080Sshaneh incr sqlite_sync_count $adj 319dd6e080Sshaneh } { 329dd6e080Sshaneh ifcapable !dirsync { 339dd6e080Sshaneh incr sqlite_sync_count $adj 349dd6e080Sshaneh } 359dd6e080Sshaneh } 369dd6e080Sshaneh} 379dd6e080Sshaneh 389a6b4e9aSdanproc set_tvfs_hdr {file args} { 3971d89919Sdan 4071d89919Sdan # Set $nHdr to the number of bytes in the wal-index header: 4110f5a50eSdan set nHdr 48 4271d89919Sdan set nInt [expr {$nHdr/4}] 4371d89919Sdan 4423f71920Sdan if {[llength $args]>2} { 4523f71920Sdan error {wrong # args: should be "set_tvfs_hdr fileName ?val1? ?val2?"} 469a6b4e9aSdan } 479a6b4e9aSdan 489a6b4e9aSdan set blob [tvfs shm $file] 49957ed0b3Sdrh if {$::tcl_platform(byteOrder)=="bigEndian"} {set fmt I} {set fmt i} 50d0aa3427Sdan 519a6b4e9aSdan if {[llength $args]} { 5294b7f76bSdan set ia [lindex $args 0] 5323f71920Sdan set ib $ia 5423f71920Sdan if {[llength $args]==2} { 5523f71920Sdan set ib [lindex $args 1] 5623f71920Sdan } 57d0aa3427Sdan binary scan $blob a[expr $nHdr*2]a* dummy tail 58957ed0b3Sdrh set blob [binary format ${fmt}${nInt}${fmt}${nInt}a* $ia $ib $tail] 599a6b4e9aSdan tvfs shm $file $blob 609a6b4e9aSdan } 619a6b4e9aSdan 62957ed0b3Sdrh binary scan $blob ${fmt}${nInt} ints 639a6b4e9aSdan return $ints 649a6b4e9aSdan} 659a6b4e9aSdan 669a6b4e9aSdanproc incr_tvfs_hdr {file idx incrval} { 679a6b4e9aSdan set ints [set_tvfs_hdr $file] 689a6b4e9aSdan set v [lindex $ints $idx] 699a6b4e9aSdan incr v $incrval 709a6b4e9aSdan lset ints $idx $v 719a6b4e9aSdan set_tvfs_hdr $file $ints 729a6b4e9aSdan} 739a6b4e9aSdan 749a6b4e9aSdan 759a6b4e9aSdan#------------------------------------------------------------------------- 769a6b4e9aSdan# Test case wal2-1.*: 779a6b4e9aSdan# 789a6b4e9aSdan# Set up a small database containing a single table. The database is not 799a6b4e9aSdan# checkpointed during the test - all content resides in the log file. 809a6b4e9aSdan# 819a6b4e9aSdan# Two connections are established to the database file - a writer ([db]) 829a6b4e9aSdan# and a reader ([db2]). For each of the 8 integer fields in the wal-index 839a6b4e9aSdan# header (6 fields and 2 checksum values), do the following: 849a6b4e9aSdan# 859a6b4e9aSdan# 1. Modify the database using the writer. 869a6b4e9aSdan# 879a6b4e9aSdan# 2. Attempt to read the database using the reader. Before the reader 889a6b4e9aSdan# has a chance to snapshot the wal-index header, increment one 89d5578433Smistachkin# of the integer fields (so that the reader ends up with a corrupted 909a6b4e9aSdan# header). 919a6b4e9aSdan# 929a6b4e9aSdan# 3. Check that the reader recovers the wal-index and reads the correct 939a6b4e9aSdan# database content. 949a6b4e9aSdan# 959a6b4e9aSdando_test wal2-1.0 { 9613a3cb82Sdan proc tvfs_cb {method filename args} { 9713a3cb82Sdan set ::filename $filename 9813a3cb82Sdan return SQLITE_OK 9913a3cb82Sdan } 10013a3cb82Sdan 1011f55e28dSdan testvfs tvfs 1021f55e28dSdan tvfs script tvfs_cb 10313a3cb82Sdan tvfs filter xShmOpen 1049a6b4e9aSdan 1059a6b4e9aSdan sqlite3 db test.db -vfs tvfs 1069a6b4e9aSdan sqlite3 db2 test.db -vfs tvfs 1079a6b4e9aSdan 1089a6b4e9aSdan execsql { 1099a6b4e9aSdan PRAGMA journal_mode = WAL; 1109a6b4e9aSdan CREATE TABLE t1(a); 1119a6b4e9aSdan } db2 1129a6b4e9aSdan execsql { 1139a6b4e9aSdan INSERT INTO t1 VALUES(1); 1149a6b4e9aSdan INSERT INTO t1 VALUES(2); 1159a6b4e9aSdan INSERT INTO t1 VALUES(3); 1169a6b4e9aSdan INSERT INTO t1 VALUES(4); 1179a6b4e9aSdan SELECT count(a), sum(a) FROM t1; 1189a6b4e9aSdan } 1199a6b4e9aSdan} {4 10} 1209a6b4e9aSdando_test wal2-1.1 { 1219a6b4e9aSdan execsql { SELECT count(a), sum(a) FROM t1 } db2 1229a6b4e9aSdan} {4 10} 1239a6b4e9aSdan 124d0aa3427Sdanset RECOVER [list \ 125*cddfc392Sdan {0 1 lock exclusive} {1 2 lock exclusive} \ 126*cddfc392Sdan {4 1 lock exclusive} {4 1 unlock exclusive} \ 127*cddfc392Sdan {5 1 lock exclusive} {5 1 unlock exclusive} \ 128*cddfc392Sdan {6 1 lock exclusive} {6 1 unlock exclusive} \ 129*cddfc392Sdan {7 1 lock exclusive} {7 1 unlock exclusive} \ 130*cddfc392Sdan {1 2 unlock exclusive} {0 1 unlock exclusive} \ 131d0aa3427Sdan] 132d0aa3427Sdanset READ [list \ 133d0aa3427Sdan {4 1 lock shared} {4 1 unlock shared} \ 134d0aa3427Sdan] 1355373b76bSdanset INITSLOT [list \ 1365373b76bSdan {4 1 lock exclusive} {4 1 unlock exclusive} \ 1375373b76bSdan] 138d0aa3427Sdan 139d0aa3427Sdanforeach {tn iInsert res wal_index_hdr_mod wal_locks} " 140d0aa3427Sdan 2 5 {5 15} 0 {$RECOVER $READ} 141d0aa3427Sdan 3 6 {6 21} 1 {$RECOVER $READ} 142d0aa3427Sdan 4 7 {7 28} 2 {$RECOVER $READ} 143d0aa3427Sdan 5 8 {8 36} 3 {$RECOVER $READ} 144d0aa3427Sdan 6 9 {9 45} 4 {$RECOVER $READ} 145d0aa3427Sdan 7 10 {10 55} 5 {$RECOVER $READ} 146d0aa3427Sdan 8 11 {11 66} 6 {$RECOVER $READ} 147d0aa3427Sdan 9 12 {12 78} 7 {$RECOVER $READ} 148d0aa3427Sdan 10 13 {13 91} 8 {$RECOVER $READ} 149d0aa3427Sdan 11 14 {14 105} 9 {$RECOVER $READ} 1505373b76bSdan 12 15 {15 120} -1 {$INITSLOT $READ} 151d0aa3427Sdan" { 1529a6b4e9aSdan 1539a6b4e9aSdan do_test wal2-1.$tn.1 { 1549a6b4e9aSdan execsql { INSERT INTO t1 VALUES($iInsert) } 1559a6b4e9aSdan set ::locks [list] 1569a6b4e9aSdan proc tvfs_cb {method args} { 15713a3cb82Sdan lappend ::locks [lindex $args 2] 1589a6b4e9aSdan return SQLITE_OK 1599a6b4e9aSdan } 16013a3cb82Sdan tvfs filter xShmLock 16113a3cb82Sdan if {$::wal_index_hdr_mod >= 0} { 16213a3cb82Sdan incr_tvfs_hdr $::filename $::wal_index_hdr_mod 1 16313a3cb82Sdan } 1649a6b4e9aSdan execsql { SELECT count(a), sum(a) FROM t1 } db2 1659a6b4e9aSdan } $res 1669a6b4e9aSdan 1679a6b4e9aSdan do_test wal2-1.$tn.2 { 1689a6b4e9aSdan set ::locks 1699a6b4e9aSdan } $wal_locks 1709a6b4e9aSdan} 1719a6b4e9aSdandb close 1729a6b4e9aSdandb2 close 1739a6b4e9aSdantvfs delete 174fda06befSmistachkinforcedelete test.db test.db-wal test.db-journal 1759a6b4e9aSdan 1769a6b4e9aSdan#------------------------------------------------------------------------- 1779a6b4e9aSdan# This test case is very similar to the previous one, except, after 1789a6b4e9aSdan# the reader reads the corrupt wal-index header, but before it has 1799a6b4e9aSdan# a chance to re-read it under the cover of the RECOVER lock, the 1809a6b4e9aSdan# wal-index header is replaced with a valid, but out-of-date, header. 1819a6b4e9aSdan# 1829a6b4e9aSdan# Because the header checksum looks Ok, the reader does not run recovery, 1839a6b4e9aSdan# it simply drops back to a READ lock and proceeds. But because the 1849a6b4e9aSdan# header is out-of-date, the reader reads the out-of-date snapshot. 1859a6b4e9aSdan# 1869a6b4e9aSdan# After this, the header is corrupted again and the reader is allowed 1879a6b4e9aSdan# to run recovery. This time, it sees an up-to-date snapshot of the 1889a6b4e9aSdan# database file. 1899a6b4e9aSdan# 190d0aa3427Sdanset WRITER [list 0 1 lock exclusive] 191d0aa3427Sdanset LOCKS [list \ 192d0aa3427Sdan {0 1 lock exclusive} {0 1 unlock exclusive} \ 193db7f647eSdrh {4 1 lock exclusive} {4 1 unlock exclusive} \ 194d0aa3427Sdan {4 1 lock shared} {4 1 unlock shared} \ 195d0aa3427Sdan] 1969a6b4e9aSdando_test wal2-2.0 { 1979a6b4e9aSdan 1981f55e28dSdan testvfs tvfs 1991f55e28dSdan tvfs script tvfs_cb 20013a3cb82Sdan tvfs filter xShmOpen 2019a6b4e9aSdan proc tvfs_cb {method args} { 20213a3cb82Sdan set ::filename [lindex $args 0] 2039a6b4e9aSdan return SQLITE_OK 2049a6b4e9aSdan } 2059a6b4e9aSdan 2069a6b4e9aSdan sqlite3 db test.db -vfs tvfs 2079a6b4e9aSdan sqlite3 db2 test.db -vfs tvfs 2089a6b4e9aSdan 2099a6b4e9aSdan execsql { 2109a6b4e9aSdan PRAGMA journal_mode = WAL; 2119a6b4e9aSdan CREATE TABLE t1(a); 2129a6b4e9aSdan } db2 2139a6b4e9aSdan execsql { 2149a6b4e9aSdan INSERT INTO t1 VALUES(1); 2159a6b4e9aSdan INSERT INTO t1 VALUES(2); 2169a6b4e9aSdan INSERT INTO t1 VALUES(3); 2179a6b4e9aSdan INSERT INTO t1 VALUES(4); 2189a6b4e9aSdan SELECT count(a), sum(a) FROM t1; 2199a6b4e9aSdan } 2209a6b4e9aSdan} {4 10} 2219a6b4e9aSdando_test wal2-2.1 { 2229a6b4e9aSdan execsql { SELECT count(a), sum(a) FROM t1 } db2 2239a6b4e9aSdan} {4 10} 2249a6b4e9aSdan 2259a6b4e9aSdanforeach {tn iInsert res0 res1 wal_index_hdr_mod} { 2269a6b4e9aSdan 2 5 {4 10} {5 15} 0 2279a6b4e9aSdan 3 6 {5 15} {6 21} 1 2289a6b4e9aSdan 4 7 {6 21} {7 28} 2 2299a6b4e9aSdan 5 8 {7 28} {8 36} 3 2309a6b4e9aSdan 6 9 {8 36} {9 45} 4 2319a6b4e9aSdan 7 10 {9 45} {10 55} 5 2329a6b4e9aSdan 8 11 {10 55} {11 66} 6 2339a6b4e9aSdan 9 12 {11 66} {12 78} 7 2349a6b4e9aSdan} { 23513a3cb82Sdan tvfs filter xShmLock 23613a3cb82Sdan 2377e263728Sdrh do_test wal2-2.$tn.1 { 23813a3cb82Sdan set oldhdr [set_tvfs_hdr $::filename] 2399a6b4e9aSdan execsql { INSERT INTO t1 VALUES($iInsert) } 2409a6b4e9aSdan execsql { SELECT count(a), sum(a) FROM t1 } 2419a6b4e9aSdan } $res1 2429a6b4e9aSdan 2439a6b4e9aSdan do_test wal2-2.$tn.2 { 2449a6b4e9aSdan set ::locks [list] 2459a6b4e9aSdan proc tvfs_cb {method args} { 2469a6b4e9aSdan set lock [lindex $args 2] 2479a6b4e9aSdan lappend ::locks $lock 248d0aa3427Sdan if {$lock == $::WRITER} { 24913a3cb82Sdan set_tvfs_hdr $::filename $::oldhdr 2509a6b4e9aSdan } 2519a6b4e9aSdan return SQLITE_OK 2529a6b4e9aSdan } 2539a6b4e9aSdan 25413a3cb82Sdan if {$::wal_index_hdr_mod >= 0} { 25513a3cb82Sdan incr_tvfs_hdr $::filename $::wal_index_hdr_mod 1 25613a3cb82Sdan } 2579a6b4e9aSdan execsql { SELECT count(a), sum(a) FROM t1 } db2 2589a6b4e9aSdan } $res0 2599a6b4e9aSdan 2609a6b4e9aSdan do_test wal2-2.$tn.3 { 2619a6b4e9aSdan set ::locks 262d0aa3427Sdan } $LOCKS 2639a6b4e9aSdan 2649a6b4e9aSdan do_test wal2-2.$tn.4 { 2659a6b4e9aSdan set ::locks [list] 2669a6b4e9aSdan proc tvfs_cb {method args} { 2679a6b4e9aSdan set lock [lindex $args 2] 2689a6b4e9aSdan lappend ::locks $lock 2699a6b4e9aSdan return SQLITE_OK 2709a6b4e9aSdan } 2719a6b4e9aSdan 27213a3cb82Sdan if {$::wal_index_hdr_mod >= 0} { 27313a3cb82Sdan incr_tvfs_hdr $::filename $::wal_index_hdr_mod 1 27413a3cb82Sdan } 2759a6b4e9aSdan execsql { SELECT count(a), sum(a) FROM t1 } db2 2769a6b4e9aSdan } $res1 2779a6b4e9aSdan} 2789a6b4e9aSdandb close 2799a6b4e9aSdandb2 close 2809a6b4e9aSdantvfs delete 281fda06befSmistachkinforcedelete test.db test.db-wal test.db-journal 2829a6b4e9aSdan 283d0aa3427Sdan 284d0aa3427Sdanif 0 { 285ff6dfc73Sdan#------------------------------------------------------------------------- 286ff6dfc73Sdan# This test case - wal2-3.* - tests the response of the library to an 287ff6dfc73Sdan# SQLITE_BUSY when attempting to obtain a READ or RECOVER lock. 288ff6dfc73Sdan# 289ff6dfc73Sdan# wal2-3.0 - 2: SQLITE_BUSY when obtaining a READ lock 290ff6dfc73Sdan# wal2-3.3 - 6: SQLITE_BUSY when obtaining a RECOVER lock 291ff6dfc73Sdan# 292ff6dfc73Sdando_test wal2-3.0 { 293ff6dfc73Sdan proc tvfs_cb {method args} { 294ff6dfc73Sdan if {$method == "xShmLock"} { 295ff6dfc73Sdan if {[info exists ::locked]} { return SQLITE_BUSY } 296ff6dfc73Sdan } 297ff6dfc73Sdan return SQLITE_OK 298ff6dfc73Sdan } 299ff6dfc73Sdan 300ff6dfc73Sdan proc busyhandler x { 301ff6dfc73Sdan if {$x>3} { unset -nocomplain ::locked } 302ff6dfc73Sdan return 0 303ff6dfc73Sdan } 304ff6dfc73Sdan 3051f55e28dSdan testvfs tvfs 3061f55e28dSdan tvfs script tvfs_cb 307ff6dfc73Sdan sqlite3 db test.db -vfs tvfs 308ff6dfc73Sdan db busy busyhandler 309ff6dfc73Sdan 310ff6dfc73Sdan execsql { 311ff6dfc73Sdan PRAGMA journal_mode = WAL; 312ff6dfc73Sdan CREATE TABLE t1(a); 313ff6dfc73Sdan INSERT INTO t1 VALUES(1); 314ff6dfc73Sdan INSERT INTO t1 VALUES(2); 315ff6dfc73Sdan INSERT INTO t1 VALUES(3); 316ff6dfc73Sdan INSERT INTO t1 VALUES(4); 317ff6dfc73Sdan } 318ff6dfc73Sdan 319ff6dfc73Sdan set ::locked 1 320ff6dfc73Sdan info exists ::locked 321ff6dfc73Sdan} {1} 322ff6dfc73Sdando_test wal2-3.1 { 323ff6dfc73Sdan execsql { SELECT count(a), sum(a) FROM t1 } 324ff6dfc73Sdan} {4 10} 325ff6dfc73Sdando_test wal2-3.2 { 326ff6dfc73Sdan info exists ::locked 327ff6dfc73Sdan} {0} 328ff6dfc73Sdan 329ff6dfc73Sdando_test wal2-3.3 { 330ff6dfc73Sdan proc tvfs_cb {method args} { 331ff6dfc73Sdan if {$method == "xShmLock"} { 332ff6dfc73Sdan if {[info exists ::sabotage]} { 333ff6dfc73Sdan unset -nocomplain ::sabotage 334ff6dfc73Sdan incr_tvfs_hdr [lindex $args 0] 1 1 335ff6dfc73Sdan } 336ff6dfc73Sdan if {[info exists ::locked] && [lindex $args 2] == "RECOVER"} { 337ff6dfc73Sdan return SQLITE_BUSY 338ff6dfc73Sdan } 339ff6dfc73Sdan } 340ff6dfc73Sdan return SQLITE_OK 341ff6dfc73Sdan } 342ff6dfc73Sdan set ::sabotage 1 343ff6dfc73Sdan set ::locked 1 344ff6dfc73Sdan list [info exists ::sabotage] [info exists ::locked] 345ff6dfc73Sdan} {1 1} 346ff6dfc73Sdando_test wal2-3.4 { 347ff6dfc73Sdan execsql { SELECT count(a), sum(a) FROM t1 } 348ff6dfc73Sdan} {4 10} 349ff6dfc73Sdando_test wal2-3.5 { 350ff6dfc73Sdan list [info exists ::sabotage] [info exists ::locked] 351ff6dfc73Sdan} {0 0} 352ff6dfc73Sdandb close 353ff6dfc73Sdantvfs delete 354fda06befSmistachkinforcedelete test.db test.db-wal test.db-journal 355ff6dfc73Sdan 356d0aa3427Sdan} 357d0aa3427Sdan 358576bc329Sdan#------------------------------------------------------------------------- 359576bc329Sdan# Test that a database connection using a VFS that does not support the 360576bc329Sdan# xShmXXX interfaces cannot open a WAL database. 361576bc329Sdan# 362576bc329Sdando_test wal2-4.1 { 363576bc329Sdan sqlite3 db test.db 364576bc329Sdan execsql { 3657fa65fbfSdan PRAGMA auto_vacuum = 0; 366576bc329Sdan PRAGMA journal_mode = WAL; 367576bc329Sdan CREATE TABLE data(x); 368576bc329Sdan INSERT INTO data VALUES('need xShmOpen to see this'); 369576bc329Sdan PRAGMA wal_checkpoint; 370576bc329Sdan } 3710774bb59Sdan # Three pages in the WAL file at this point: One copy of page 1 and two 3720774bb59Sdan # of the root page for table "data". 3730774bb59Sdan} {wal 0 3 3} 374576bc329Sdando_test wal2-4.2 { 375576bc329Sdan db close 3761f55e28dSdan testvfs tvfs -noshm 1 377576bc329Sdan sqlite3 db test.db -vfs tvfs 378576bc329Sdan catchsql { SELECT * FROM data } 379576bc329Sdan} {1 {unable to open database file}} 380576bc329Sdando_test wal2-4.3 { 381576bc329Sdan db close 3821f55e28dSdan testvfs tvfs 383576bc329Sdan sqlite3 db test.db -vfs tvfs 384576bc329Sdan catchsql { SELECT * FROM data } 385576bc329Sdan} {0 {{need xShmOpen to see this}}} 386576bc329Sdandb close 387576bc329Sdantvfs delete 388576bc329Sdan 3895273f58fSdan#------------------------------------------------------------------------- 3905273f58fSdan# Test that if a database connection is forced to run recovery before it 39165be0d8cSdan# can perform a checkpoint, it does not transition into RECOVER state. 3925273f58fSdan# 393d0aa3427Sdan# UPDATE: This has now changed. When running a checkpoint, if recovery is 394d0aa3427Sdan# required the client grabs all exclusive locks (just as it would for a 395d0aa3427Sdan# recovery performed as a pre-cursor to a normal database transaction). 396d0aa3427Sdan# 3975f3f3b29Sdanset expected_locks [list] 3985f3f3b29Sdanlappend expected_locks {1 1 lock exclusive} ;# Lock checkpoint 3995f3f3b29Sdanlappend expected_locks {0 1 lock exclusive} ;# Lock writer 40044c8a97eSdanlappend expected_locks {2 1 lock exclusive} ;# Lock recovery 401*cddfc392Sdan# lappend expected_locks {4 4 lock exclusive} ;# Lock all aReadMark[] 402*cddfc392Sdanlappend expected_locks {4 1 lock exclusive} ;# Lock aReadMark[1] 403*cddfc392Sdanlappend expected_locks {4 1 unlock exclusive} ;# Unlock aReadMark[1] 404*cddfc392Sdanlappend expected_locks {5 1 lock exclusive} 405*cddfc392Sdanlappend expected_locks {5 1 unlock exclusive} 406*cddfc392Sdanlappend expected_locks {6 1 lock exclusive} 407*cddfc392Sdanlappend expected_locks {6 1 unlock exclusive} 408*cddfc392Sdanlappend expected_locks {7 1 lock exclusive} 409*cddfc392Sdanlappend expected_locks {7 1 unlock exclusive} 41044c8a97eSdanlappend expected_locks {2 1 unlock exclusive} ;# Unlock recovery 411*cddfc392Sdan# lappend expected_locks {4 4 unlock exclusive} ;# Unlock all aReadMark[] 4125f3f3b29Sdanlappend expected_locks {0 1 unlock exclusive} ;# Unlock writer 4135f3f3b29Sdanlappend expected_locks {3 1 lock exclusive} ;# Lock aReadMark[0] 4145f3f3b29Sdanlappend expected_locks {3 1 unlock exclusive} ;# Unlock aReadMark[0] 4155f3f3b29Sdanlappend expected_locks {1 1 unlock exclusive} ;# Unlock checkpoint 4165273f58fSdando_test wal2-5.1 { 4175273f58fSdan proc tvfs_cb {method args} { 4185273f58fSdan set ::shm_file [lindex $args 0] 4195273f58fSdan if {$method == "xShmLock"} { lappend ::locks [lindex $args 2] } 4205273f58fSdan return $::tvfs_cb_return 4215273f58fSdan } 4225273f58fSdan set tvfs_cb_return SQLITE_OK 4235273f58fSdan 4241f55e28dSdan testvfs tvfs 4251f55e28dSdan tvfs script tvfs_cb 4265273f58fSdan 4275273f58fSdan sqlite3 db test.db -vfs tvfs 4285273f58fSdan execsql { 4295273f58fSdan PRAGMA journal_mode = WAL; 4305273f58fSdan CREATE TABLE x(y); 4315273f58fSdan INSERT INTO x VALUES(1); 4325273f58fSdan } 4335273f58fSdan 4345273f58fSdan incr_tvfs_hdr $::shm_file 1 1 4355273f58fSdan set ::locks [list] 4365273f58fSdan execsql { PRAGMA wal_checkpoint } 4375273f58fSdan set ::locks 4385f3f3b29Sdan} $expected_locks 43965be0d8cSdandb close 44065be0d8cSdantvfs delete 4415273f58fSdan 4425543759bSdan#------------------------------------------------------------------------- 4435543759bSdan# This block, test cases wal2-6.*, tests the operation of WAL with 4445543759bSdan# "PRAGMA locking_mode=EXCLUSIVE" set. 4455543759bSdan# 4465543759bSdan# wal2-6.1.*: Changing to WAL mode before setting locking_mode=exclusive. 4475543759bSdan# 4485543759bSdan# wal2-6.2.*: Changing to WAL mode after setting locking_mode=exclusive. 4495543759bSdan# 4505543759bSdan# wal2-6.3.*: Changing back to rollback mode from WAL mode after setting 4515543759bSdan# locking_mode=exclusive. 4525543759bSdan# 4535543759bSdan# wal2-6.4.*: Check that xShmLock calls are omitted in exclusive locking 4545543759bSdan# mode. 4555543759bSdan# 4563cac5dc9Sdan# wal2-6.5.*: 4573cac5dc9Sdan# 4583cac5dc9Sdan# wal2-6.6.*: Check that if the xShmLock() to reaquire a WAL read-lock when 4593cac5dc9Sdan# exiting exclusive mode fails (i.e. SQLITE_IOERR), then the 4603cac5dc9Sdan# connection silently remains in exclusive mode. 4613cac5dc9Sdan# 4625543759bSdando_test wal2-6.1.1 { 463fda06befSmistachkin forcedelete test.db test.db-wal test.db-journal 4645543759bSdan sqlite3 db test.db 4655543759bSdan execsql { 4665543759bSdan Pragma Journal_Mode = Wal; 4675543759bSdan } 4688c408004Sdan} {wal} 4695543759bSdando_test wal2-6.1.2 { 4705543759bSdan execsql { PRAGMA lock_status } 4715543759bSdan} {main unlocked temp closed} 4725543759bSdando_test wal2-6.1.3 { 4735543759bSdan execsql { 4748c408004Sdan SELECT * FROM sqlite_master; 4758c408004Sdan Pragma Locking_Mode = Exclusive; 4768c408004Sdan } 4778c408004Sdan execsql { 4785543759bSdan BEGIN; 4795543759bSdan CREATE TABLE t1(a, b); 4805543759bSdan INSERT INTO t1 VALUES(1, 2); 4815543759bSdan COMMIT; 4825543759bSdan PRAGMA lock_status; 4835543759bSdan } 4845543759bSdan} {main exclusive temp closed} 4855543759bSdando_test wal2-6.1.4 { 4865543759bSdan execsql { 4875543759bSdan PRAGMA locking_mode = normal; 4885543759bSdan PRAGMA lock_status; 4895543759bSdan } 4905543759bSdan} {normal main exclusive temp closed} 4915543759bSdando_test wal2-6.1.5 { 4925543759bSdan execsql { 4935543759bSdan SELECT * FROM t1; 4945543759bSdan PRAGMA lock_status; 4955543759bSdan } 496d0864087Sdan} {1 2 main shared temp closed} 4975543759bSdando_test wal2-6.1.6 { 4985543759bSdan execsql { 4995543759bSdan INSERT INTO t1 VALUES(3, 4); 5005543759bSdan PRAGMA lock_status; 5015543759bSdan } 5025543759bSdan} {main shared temp closed} 5035543759bSdandb close 5045543759bSdan 5055543759bSdando_test wal2-6.2.1 { 506fda06befSmistachkin forcedelete test.db test.db-wal test.db-journal 5075543759bSdan sqlite3 db test.db 5085543759bSdan execsql { 5095543759bSdan Pragma Locking_Mode = Exclusive; 5105543759bSdan Pragma Journal_Mode = Wal; 5115543759bSdan Pragma Lock_Status; 5125543759bSdan } 5135543759bSdan} {exclusive wal main exclusive temp closed} 5145543759bSdando_test wal2-6.2.2 { 5155543759bSdan execsql { 5165543759bSdan BEGIN; 5175543759bSdan CREATE TABLE t1(a, b); 5185543759bSdan INSERT INTO t1 VALUES(1, 2); 5195543759bSdan COMMIT; 5205543759bSdan Pragma loCK_STATus; 5215543759bSdan } 5225543759bSdan} {main exclusive temp closed} 5235543759bSdando_test wal2-6.2.3 { 5245543759bSdan db close 5255543759bSdan sqlite3 db test.db 5268c408004Sdan execsql { SELECT * FROM sqlite_master } 5275543759bSdan execsql { PRAGMA LOCKING_MODE = EXCLUSIVE } 5285543759bSdan} {exclusive} 5295543759bSdando_test wal2-6.2.4 { 5305543759bSdan execsql { 5315543759bSdan SELECT * FROM t1; 5325543759bSdan pragma lock_status; 5335543759bSdan } 5345543759bSdan} {1 2 main shared temp closed} 5355543759bSdando_test wal2-6.2.5 { 5365543759bSdan execsql { 5375543759bSdan INSERT INTO t1 VALUES(3, 4); 5385543759bSdan pragma lock_status; 5395543759bSdan } 5405543759bSdan} {main exclusive temp closed} 5415543759bSdando_test wal2-6.2.6 { 5425543759bSdan execsql { 5435543759bSdan PRAGMA locking_mode = NORMAL; 5445543759bSdan pragma lock_status; 5455543759bSdan } 5465543759bSdan} {normal main exclusive temp closed} 5475543759bSdando_test wal2-6.2.7 { 5485543759bSdan execsql { 5495543759bSdan BEGIN IMMEDIATE; COMMIT; 5505543759bSdan pragma lock_status; 5515543759bSdan } 5525543759bSdan} {main shared temp closed} 5535543759bSdando_test wal2-6.2.8 { 5545543759bSdan execsql { 5555543759bSdan PRAGMA locking_mode = EXCLUSIVE; 5565543759bSdan BEGIN IMMEDIATE; COMMIT; 5575543759bSdan PRAGMA locking_mode = NORMAL; 5585543759bSdan } 5595543759bSdan execsql { 5605543759bSdan SELECT * FROM t1; 5615543759bSdan pragma lock_status; 5625543759bSdan } 563d0864087Sdan} {1 2 3 4 main shared temp closed} 5645543759bSdando_test wal2-6.2.9 { 5655543759bSdan execsql { 5665543759bSdan INSERT INTO t1 VALUES(5, 6); 5675543759bSdan SELECT * FROM t1; 5685543759bSdan pragma lock_status; 5695543759bSdan } 5705543759bSdan} {1 2 3 4 5 6 main shared temp closed} 5715543759bSdandb close 5725543759bSdan 5735543759bSdando_test wal2-6.3.1 { 574fda06befSmistachkin forcedelete test.db test.db-wal test.db-journal 5755543759bSdan sqlite3 db test.db 5765543759bSdan execsql { 5775543759bSdan PRAGMA journal_mode = WAL; 5785543759bSdan PRAGMA locking_mode = exclusive; 5795543759bSdan BEGIN; 5805543759bSdan CREATE TABLE t1(x); 5815543759bSdan INSERT INTO t1 VALUES('Chico'); 5825543759bSdan INSERT INTO t1 VALUES('Harpo'); 5835543759bSdan COMMIT; 5845543759bSdan } 5855543759bSdan list [file exists test.db-wal] [file exists test.db-journal] 5865543759bSdan} {1 0} 5875543759bSdando_test wal2-6.3.2 { 5885543759bSdan execsql { PRAGMA journal_mode = DELETE } 5895543759bSdan file exists test.db-wal 5905543759bSdan} {0} 5915543759bSdando_test wal2-6.3.3 { 5925543759bSdan execsql { PRAGMA lock_status } 5935543759bSdan} {main exclusive temp closed} 5945543759bSdando_test wal2-6.3.4 { 5955543759bSdan execsql { 5965543759bSdan BEGIN; 5975543759bSdan INSERT INTO t1 VALUES('Groucho'); 5985543759bSdan } 59969aedc8dSdan} {} 60069aedc8dSdanif {[atomic_batch_write test.db]==0} { 60169aedc8dSdan do_test wal2-6.3.4.1 { 6025543759bSdan list [file exists test.db-wal] [file exists test.db-journal] 6035543759bSdan } {0 1} 60469aedc8dSdan} 6055543759bSdando_test wal2-6.3.5 { 6065543759bSdan execsql { PRAGMA lock_status } 6075543759bSdan} {main exclusive temp closed} 6085543759bSdando_test wal2-6.3.6 { 6095543759bSdan execsql { COMMIT } 61069aedc8dSdan} {} 61169aedc8dSdanif {[atomic_batch_write test.db]==0} { 61269aedc8dSdan do_test wal2-6.3.6.1 { 6135543759bSdan list [file exists test.db-wal] [file exists test.db-journal] 6145543759bSdan } {0 1} 61569aedc8dSdan} 6165543759bSdando_test wal2-6.3.7 { 6175543759bSdan execsql { PRAGMA lock_status } 6185543759bSdan} {main exclusive temp closed} 6195543759bSdandb close 6205543759bSdan 6215f3f3b29Sdan 6225f3f3b29Sdan# This test - wal2-6.4.* - uses a single database connection and the 6235f3f3b29Sdan# [testvfs] instrumentation to test that xShmLock() is being called 6245f3f3b29Sdan# as expected when a WAL database is used with locking_mode=exclusive. 6255f3f3b29Sdan# 6265543759bSdando_test wal2-6.4.1 { 627fda06befSmistachkin forcedelete test.db test.db-wal test.db-journal 6285543759bSdan proc tvfs_cb {method args} { 6295543759bSdan set ::shm_file [lindex $args 0] 6305543759bSdan if {$method == "xShmLock"} { lappend ::locks [lindex $args 2] } 6315543759bSdan return "SQLITE_OK" 6325543759bSdan } 6331f55e28dSdan testvfs tvfs 6341f55e28dSdan tvfs script tvfs_cb 6355543759bSdan sqlite3 db test.db -vfs tvfs 636262765a7Sdan set {} {} 6375f3f3b29Sdan} {} 6385543759bSdan 6395f3f3b29Sdanset RECOVERY { 640*cddfc392Sdan {0 1 lock exclusive} {1 2 lock exclusive} 641*cddfc392Sdan {4 1 lock exclusive} {4 1 unlock exclusive} 642*cddfc392Sdan {5 1 lock exclusive} {5 1 unlock exclusive} 643*cddfc392Sdan {6 1 lock exclusive} {6 1 unlock exclusive} 644*cddfc392Sdan {7 1 lock exclusive} {7 1 unlock exclusive} 645*cddfc392Sdan {1 2 unlock exclusive} {0 1 unlock exclusive} 6465f3f3b29Sdan} 6475f3f3b29Sdanset READMARK0_READ { 6485f3f3b29Sdan {3 1 lock shared} {3 1 unlock shared} 6495f3f3b29Sdan} 6505f3f3b29Sdanset READMARK0_WRITE { 6515f3f3b29Sdan {3 1 lock shared} 6525f3f3b29Sdan {0 1 lock exclusive} {3 1 unlock shared} 6535f3f3b29Sdan {4 1 lock exclusive} {4 1 unlock exclusive} {4 1 lock shared} 6545f3f3b29Sdan {0 1 unlock exclusive} {4 1 unlock shared} 6555f3f3b29Sdan} 6565f3f3b29Sdanset READMARK1_SET { 6575f3f3b29Sdan {4 1 lock exclusive} {4 1 unlock exclusive} 6585f3f3b29Sdan} 6595f3f3b29Sdanset READMARK1_READ { 6605f3f3b29Sdan {4 1 lock shared} {4 1 unlock shared} 6615f3f3b29Sdan} 662d0864087Sdanset READMARK1_WRITE { 663d0864087Sdan {4 1 lock shared} 664d0864087Sdan {0 1 lock exclusive} {0 1 unlock exclusive} 665d0864087Sdan {4 1 unlock shared} 666d0864087Sdan} 6675f3f3b29Sdan 6685f3f3b29Sdanforeach {tn sql res expected_locks} { 6695f3f3b29Sdan 2 { 6707fa65fbfSdan PRAGMA auto_vacuum = 0; 6715543759bSdan PRAGMA journal_mode = WAL; 6725f3f3b29Sdan BEGIN; 6735543759bSdan CREATE TABLE t1(x); 6745543759bSdan INSERT INTO t1 VALUES('Leonard'); 6755543759bSdan INSERT INTO t1 VALUES('Arthur'); 6765f3f3b29Sdan COMMIT; 6775f3f3b29Sdan } {wal} { 6785f3f3b29Sdan $RECOVERY 6795f3f3b29Sdan $READMARK0_WRITE 6805f3f3b29Sdan } 6815f3f3b29Sdan 6825f3f3b29Sdan 3 { 6835f3f3b29Sdan # This test should do the READMARK1_SET locking to populate the 6845f3f3b29Sdan # aReadMark[1] slot with the current mxFrame value. Followed by 6855f3f3b29Sdan # READMARK1_READ to read the database. 6865f3f3b29Sdan # 6875f3f3b29Sdan SELECT * FROM t1 6885f3f3b29Sdan } {Leonard Arthur} { 6895f3f3b29Sdan $READMARK1_SET 6905f3f3b29Sdan $READMARK1_READ 6915f3f3b29Sdan } 6925f3f3b29Sdan 6935f3f3b29Sdan 4 { 6945f3f3b29Sdan # aReadMark[1] is already set to mxFrame. So just READMARK1_READ 6955f3f3b29Sdan # this time, not READMARK1_SET. 6965f3f3b29Sdan # 6975f3f3b29Sdan SELECT * FROM t1 ORDER BY x 6985f3f3b29Sdan } {Arthur Leonard} { 6995f3f3b29Sdan $READMARK1_READ 7005f3f3b29Sdan } 7015f3f3b29Sdan 7025f3f3b29Sdan 5 { 7035f3f3b29Sdan PRAGMA locking_mode = exclusive 7045f3f3b29Sdan } {exclusive} { } 7055f3f3b29Sdan 7065f3f3b29Sdan 6 { 7075f3f3b29Sdan INSERT INTO t1 VALUES('Julius Henry'); 7085f3f3b29Sdan SELECT * FROM t1; 7095f3f3b29Sdan } {Leonard Arthur {Julius Henry}} { 7105f3f3b29Sdan $READMARK1_READ 7115f3f3b29Sdan } 7125f3f3b29Sdan 7135f3f3b29Sdan 7 { 7145f3f3b29Sdan INSERT INTO t1 VALUES('Karl'); 7155f3f3b29Sdan SELECT * FROM t1; 7165f3f3b29Sdan } {Leonard Arthur {Julius Henry} Karl} { } 7175f3f3b29Sdan 7185f3f3b29Sdan 8 { 7195f3f3b29Sdan PRAGMA locking_mode = normal 7205f3f3b29Sdan } {normal} { } 7215f3f3b29Sdan 7225f3f3b29Sdan 9 { 7235f3f3b29Sdan SELECT * FROM t1 ORDER BY x 724d0864087Sdan } {Arthur {Julius Henry} Karl Leonard} $READMARK1_READ 7255f3f3b29Sdan 726d0864087Sdan 10 { DELETE FROM t1 } {} $READMARK1_WRITE 7275f3f3b29Sdan 7285f3f3b29Sdan 11 { 7295f3f3b29Sdan SELECT * FROM t1 7305f3f3b29Sdan } {} { 7315f3f3b29Sdan $READMARK1_SET 7325f3f3b29Sdan $READMARK1_READ 7335f3f3b29Sdan } 7345f3f3b29Sdan} { 7355f3f3b29Sdan 7365f3f3b29Sdan set L [list] 7375f3f3b29Sdan foreach el [subst $expected_locks] { lappend L $el } 7385f3f3b29Sdan 7395f3f3b29Sdan set S "" 7405f3f3b29Sdan foreach sq [split $sql "\n"] { 7415f3f3b29Sdan set sq [string trim $sq] 7425f3f3b29Sdan if {[string match {#*} $sq]==0} {append S "$sq\n"} 7435543759bSdan } 7445543759bSdan 7455543759bSdan set ::locks [list] 7465f3f3b29Sdan do_test wal2-6.4.$tn.1 { execsql $S } $res 7475f3f3b29Sdan do_test wal2-6.4.$tn.2 { set ::locks } $L 7485543759bSdan} 7495f3f3b29Sdan 7505543759bSdandb close 751ed36020dSdantvfs delete 752ed36020dSdan 753ed36020dSdando_test wal2-6.5.1 { 754ed36020dSdan sqlite3 db test.db 755ed36020dSdan execsql { 7567fa65fbfSdan PRAGMA auto_vacuum = 0; 757ed36020dSdan PRAGMA journal_mode = wal; 758ed36020dSdan PRAGMA locking_mode = exclusive; 759ed36020dSdan CREATE TABLE t2(a, b); 760ed36020dSdan PRAGMA wal_checkpoint; 761ed36020dSdan INSERT INTO t2 VALUES('I', 'II'); 762ed36020dSdan PRAGMA journal_mode; 763ed36020dSdan } 7640774bb59Sdan} {wal exclusive 0 2 2 wal} 76514740f1cSdando_test wal2-6.5.2 { 76614740f1cSdan execsql { 76714740f1cSdan PRAGMA locking_mode = normal; 76814740f1cSdan INSERT INTO t2 VALUES('III', 'IV'); 76914740f1cSdan PRAGMA locking_mode = exclusive; 77014740f1cSdan SELECT * FROM t2; 77114740f1cSdan } 77214740f1cSdan} {normal exclusive I II III IV} 77314740f1cSdando_test wal2-6.5.3 { 77414740f1cSdan execsql { PRAGMA wal_checkpoint } 7750774bb59Sdan} {0 2 2} 776ed36020dSdandb close 7775543759bSdan 7783cac5dc9Sdanproc lock_control {method filename handle spec} { 7793cac5dc9Sdan foreach {start n op type} $spec break 7803cac5dc9Sdan if {$op == "lock"} { return SQLITE_IOERR } 7813cac5dc9Sdan return SQLITE_OK 7823cac5dc9Sdan} 7833cac5dc9Sdando_test wal2-6.6.1 { 7843cac5dc9Sdan testvfs T 7853cac5dc9Sdan T script lock_control 7863cac5dc9Sdan T filter {} 7873cac5dc9Sdan sqlite3 db test.db -vfs T 7888c408004Sdan execsql { SELECT * FROM sqlite_master } 7893cac5dc9Sdan execsql { PRAGMA locking_mode = exclusive } 7903cac5dc9Sdan execsql { INSERT INTO t2 VALUES('V', 'VI') } 7913cac5dc9Sdan} {} 7923cac5dc9Sdando_test wal2-6.6.2 { 7933cac5dc9Sdan execsql { PRAGMA locking_mode = normal } 7943cac5dc9Sdan T filter xShmLock 7953cac5dc9Sdan execsql { INSERT INTO t2 VALUES('VII', 'VIII') } 7963cac5dc9Sdan} {} 7973cac5dc9Sdando_test wal2-6.6.3 { 7983cac5dc9Sdan # At this point the connection should still be in exclusive-mode, even 7993cac5dc9Sdan # though it tried to exit exclusive-mode when committing the INSERT 8003cac5dc9Sdan # statement above. To exit exclusive mode, SQLite has to take a read-lock 8013cac5dc9Sdan # on the WAL file using xShmLock(). Since that call failed, it remains 8023cac5dc9Sdan # in exclusive mode. 8033cac5dc9Sdan # 8043cac5dc9Sdan sqlite3 db2 test.db -vfs T 8053cac5dc9Sdan catchsql { SELECT * FROM t2 } db2 8063cac5dc9Sdan} {1 {database is locked}} 8073cac5dc9Sdando_test wal2-6.6.2 { 8083cac5dc9Sdan db2 close 8093cac5dc9Sdan T filter {} 8103cac5dc9Sdan execsql { INSERT INTO t2 VALUES('IX', 'X') } 8113cac5dc9Sdan} {} 8128c408004Sdando_test wal2-6.6.4 { 8133cac5dc9Sdan # This time, we have successfully exited exclusive mode. So the second 8143cac5dc9Sdan # connection can read the database. 8153cac5dc9Sdan sqlite3 db2 test.db -vfs T 8163cac5dc9Sdan catchsql { SELECT * FROM t2 } db2 8173cac5dc9Sdan} {0 {I II III IV V VI VII VIII IX X}} 8183cac5dc9Sdan 8193cac5dc9Sdandb close 8203cac5dc9Sdandb2 close 8213cac5dc9SdanT delete 8223cac5dc9Sdan 8236f150148Sdan#------------------------------------------------------------------------- 8246f150148Sdan# Test a theory about the checksum algorithm. Theory was false and this 8256f150148Sdan# test did not provoke a bug. 8268067adbcSdan# 827fda06befSmistachkinforcedelete test.db test.db-wal test.db-journal 8286f150148Sdando_test wal2-7.1.1 { 8296f150148Sdan sqlite3 db test.db 8306f150148Sdan execsql { 8316f150148Sdan PRAGMA page_size = 4096; 8326f150148Sdan PRAGMA journal_mode = WAL; 8336f150148Sdan CREATE TABLE t1(a, b); 8346f150148Sdan } 8356f150148Sdan file size test.db 8366f150148Sdan} {4096} 8376f150148Sdando_test wal2-7.1.2 { 838fda06befSmistachkin forcecopy test.db test2.db 839fda06befSmistachkin forcecopy test.db-wal test2.db-wal 840e03d7625Sdan # The first 32 bytes of the WAL file contain the WAL header. Offset 48 841e03d7625Sdan # is the first byte of the checksum for the first frame in the WAL. 842e03d7625Sdan # The following three lines replaces the contents of that byte with 843e03d7625Sdan # a different value. 844e03d7625Sdan set newval FF 845e03d7625Sdan if {$newval == [hexio_read test2.db-wal 48 1]} { set newval 00 } 846e03d7625Sdan hexio_write test2.db-wal 48 $newval 8476f150148Sdan} {1} 8486f150148Sdando_test wal2-7.1.3 { 8496f150148Sdan sqlite3 db2 test2.db 8506f150148Sdan execsql { PRAGMA wal_checkpoint } db2 8516f150148Sdan execsql { SELECT * FROM sqlite_master } db2 8526f150148Sdan} {} 853a1a889ecSshanehdb close 8546f150148Sdandb2 close 855fda06befSmistachkinforcedelete test.db test.db-wal test.db-journal 8568067adbcSdando_test wal2-8.1.2 { 8578067adbcSdan sqlite3 db test.db 8588067adbcSdan execsql { 859c2857bf2Sdrh PRAGMA auto_vacuum=OFF; 8608067adbcSdan PRAGMA page_size = 1024; 8618067adbcSdan PRAGMA journal_mode = WAL; 8628067adbcSdan CREATE TABLE t1(x); 8638067adbcSdan INSERT INTO t1 VALUES(zeroblob(8188*1020)); 8648067adbcSdan CREATE TABLE t2(y); 865bdd9af0fSdan PRAGMA wal_checkpoint; 8668067adbcSdan } 8678067adbcSdan execsql { 86847ee386fSdan SELECT rootpage>=8192 FROM sqlite_master WHERE tbl_name = 't2'; 8698067adbcSdan } 87047ee386fSdan} {1} 8718067adbcSdando_test wal2-8.1.3 { 8728067adbcSdan execsql { 8738067adbcSdan PRAGMA cache_size = 10; 8748067adbcSdan CREATE TABLE t3(z); 8758067adbcSdan BEGIN; 8768067adbcSdan INSERT INTO t3 VALUES(randomblob(900)); 8778067adbcSdan INSERT INTO t3 SELECT randomblob(900) FROM t3; 8788067adbcSdan INSERT INTO t2 VALUES('hello'); 8798067adbcSdan INSERT INTO t3 SELECT randomblob(900) FROM t3; 8808067adbcSdan INSERT INTO t3 SELECT randomblob(900) FROM t3; 8818067adbcSdan INSERT INTO t3 SELECT randomblob(900) FROM t3; 8828067adbcSdan INSERT INTO t3 SELECT randomblob(900) FROM t3; 8838067adbcSdan INSERT INTO t3 SELECT randomblob(900) FROM t3; 8848067adbcSdan INSERT INTO t3 SELECT randomblob(900) FROM t3; 8858067adbcSdan ROLLBACK; 8868067adbcSdan } 8878067adbcSdan execsql { 8888067adbcSdan INSERT INTO t2 VALUES('goodbye'); 8898067adbcSdan INSERT INTO t3 SELECT randomblob(900) FROM t3; 8908067adbcSdan INSERT INTO t3 SELECT randomblob(900) FROM t3; 8918067adbcSdan } 8928067adbcSdan} {} 8938067adbcSdando_test wal2-8.1.4 { 8948067adbcSdan sqlite3 db2 test.db 8958067adbcSdan execsql { SELECT * FROM t2 } 8968067adbcSdan} {goodbye} 8978067adbcSdandb2 close 89823dced35Sdandb close 8998067adbcSdan 90023dced35Sdan#------------------------------------------------------------------------- 90123dced35Sdan# Test that even if the checksums for both are valid, if the two copies 90223dced35Sdan# of the wal-index header in the wal-index do not match, the client 90323dced35Sdan# runs (or at least tries to run) database recovery. 90423dced35Sdan# 90523f71920Sdan# 90623f71920Sdanproc get_name {method args} { set ::filename [lindex $args 0] ; tvfs filter {} } 90723dced35Sdantestvfs tvfs 90823dced35Sdantvfs script get_name 90923dced35Sdantvfs filter xShmOpen 91023dced35Sdan 911fda06befSmistachkinforcedelete test.db test.db-wal test.db-journal 91223dced35Sdando_test wal2-9.1 { 91323dced35Sdan sqlite3 db test.db -vfs tvfs 91423dced35Sdan execsql { 91523dced35Sdan PRAGMA journal_mode = WAL; 91623dced35Sdan CREATE TABLE x(y); 91723dced35Sdan INSERT INTO x VALUES('Barton'); 91823dced35Sdan INSERT INTO x VALUES('Deakin'); 91923dced35Sdan } 92023f71920Sdan 92123f71920Sdan # Set $wih(1) to the contents of the wal-index header after 92223f71920Sdan # the frames associated with the first two rows in table 'x' have 92323f71920Sdan # been inserted. Then insert one more row and set $wih(2) 92423f71920Sdan # to the new value of the wal-index header. 92523f71920Sdan # 92623f71920Sdan # If the $wih(1) is written into the wal-index before running 92723f71920Sdan # a read operation, the client will see only the first two rows. If 92823f71920Sdan # $wih(2) is written into the wal-index, the client will see 92923f71920Sdan # three rows. If an invalid header is written into the wal-index, then 93023f71920Sdan # the client will run recovery and see three rows. 93123f71920Sdan # 93223f71920Sdan set wih(1) [set_tvfs_hdr $::filename] 93323dced35Sdan execsql { INSERT INTO x VALUES('Watson') } 93423f71920Sdan set wih(2) [set_tvfs_hdr $::filename] 93523f71920Sdan 93623dced35Sdan sqlite3 db2 test.db -vfs tvfs 93723dced35Sdan execsql { SELECT * FROM x } db2 93823dced35Sdan} {Barton Deakin Watson} 93923f71920Sdan 94023f71920Sdanforeach {tn hdr1 hdr2 res} [list \ 94123f71920Sdan 3 $wih(1) $wih(1) {Barton Deakin} \ 94223f71920Sdan 4 $wih(1) $wih(2) {Barton Deakin Watson} \ 94323f71920Sdan 5 $wih(2) $wih(1) {Barton Deakin Watson} \ 94423f71920Sdan 6 $wih(2) $wih(2) {Barton Deakin Watson} \ 94523f71920Sdan 7 $wih(1) $wih(1) {Barton Deakin} \ 94610f5a50eSdan 8 {0 0 0 0 0 0 0 0 0 0 0 0} {0 0 0 0 0 0 0 0 0 0 0 0} {Barton Deakin Watson} 94723f71920Sdan] { 94823f71920Sdan do_test wal2-9.$tn { 94923f71920Sdan set_tvfs_hdr $::filename $hdr1 $hdr2 95023dced35Sdan execsql { SELECT * FROM x } db2 95123f71920Sdan } $res 95223f71920Sdan} 95323dced35Sdan 95423dced35Sdandb2 close 95523dced35Sdandb close 9568067adbcSdan 95710f5a50eSdan#------------------------------------------------------------------------- 95810f5a50eSdan# This block of tests - wal2-10.* - focus on the libraries response to 95910f5a50eSdan# new versions of the wal or wal-index formats. 96010f5a50eSdan# 96110f5a50eSdan# wal2-10.1.*: Test that the library refuses to "recover" a new WAL 96210f5a50eSdan# format. 96310f5a50eSdan# 96410f5a50eSdan# wal2-10.2.*: Test that the library refuses to read or write a database 96510f5a50eSdan# if the wal-index version is newer than it understands. 96610f5a50eSdan# 96710f5a50eSdan# At time of writing, the only versions of the wal and wal-index formats 96810f5a50eSdan# that exist are versions 3007000 (corresponding to SQLite version 3.7.0, 96910f5a50eSdan# the first version of SQLite to feature wal mode). 97010f5a50eSdan# 97110f5a50eSdando_test wal2-10.1.1 { 97210f5a50eSdan faultsim_delete_and_reopen 97310f5a50eSdan execsql { 97410f5a50eSdan PRAGMA journal_mode = WAL; 97510f5a50eSdan CREATE TABLE t1(a, b); 97610f5a50eSdan PRAGMA wal_checkpoint; 97710f5a50eSdan INSERT INTO t1 VALUES(1, 2); 97810f5a50eSdan INSERT INTO t1 VALUES(3, 4); 97910f5a50eSdan } 98010f5a50eSdan faultsim_save_and_close 98110f5a50eSdan} {} 98210f5a50eSdando_test wal2-10.1.2 { 98310f5a50eSdan faultsim_restore_and_reopen 98410f5a50eSdan execsql { SELECT * FROM t1 } 98510f5a50eSdan} {1 2 3 4} 98610f5a50eSdando_test wal2-10.1.3 { 98710f5a50eSdan faultsim_restore_and_reopen 98810f5a50eSdan set hdr [wal_set_walhdr test.db-wal] 98910f5a50eSdan lindex $hdr 1 99010f5a50eSdan} {3007000} 99110f5a50eSdando_test wal2-10.1.4 { 99210f5a50eSdan lset hdr 1 3007001 99310f5a50eSdan wal_set_walhdr test.db-wal $hdr 99410f5a50eSdan catchsql { SELECT * FROM t1 } 99510f5a50eSdan} {1 {unable to open database file}} 99610f5a50eSdan 99710f5a50eSdantestvfs tvfs -default 1 99810f5a50eSdando_test wal2-10.2.1 { 99910f5a50eSdan faultsim_restore_and_reopen 100010f5a50eSdan execsql { SELECT * FROM t1 } 100110f5a50eSdan} {1 2 3 4} 100210f5a50eSdando_test wal2-10.2.2 { 100310f5a50eSdan set hdr [set_tvfs_hdr $::filename] 100410f5a50eSdan lindex $hdr 0 100510f5a50eSdan} {3007000} 100610f5a50eSdando_test wal2-10.2.3 { 100710f5a50eSdan lset hdr 0 3007001 100810f5a50eSdan wal_fix_walindex_cksum hdr 100910f5a50eSdan set_tvfs_hdr $::filename $hdr 101010f5a50eSdan catchsql { SELECT * FROM t1 } 101110f5a50eSdan} {1 {unable to open database file}} 1012c3857934Sdandb close 1013c3857934Sdantvfs delete 1014c3857934Sdan 1015c3857934Sdan#------------------------------------------------------------------------- 1016c3857934Sdan# This block of tests - wal2-11.* - tests that it is not possible to put 1017c3857934Sdan# the library into an infinite loop by presenting it with a corrupt 1018c3857934Sdan# hash table (one that appears to contain a single chain of infinite 1019c3857934Sdan# length). 1020c3857934Sdan# 1021c3857934Sdan# wal2-11.1.*: While reading the hash-table. 1022c3857934Sdan# 1023c3857934Sdan# wal2-11.2.*: While writing the hash-table. 1024c3857934Sdan# 1025c3857934Sdantestvfs tvfs -default 1 1026c3857934Sdando_test wal2-11.0 { 1027c3857934Sdan faultsim_delete_and_reopen 1028c3857934Sdan execsql { 1029c3857934Sdan PRAGMA journal_mode = WAL; 1030c3857934Sdan CREATE TABLE t1(a, b, c); 1031c3857934Sdan INSERT INTO t1 VALUES(1, 2, 3); 1032c3857934Sdan INSERT INTO t1 VALUES(4, 5, 6); 1033c3857934Sdan INSERT INTO t1 VALUES(7, 8, 9); 1034c3857934Sdan SELECT * FROM t1; 1035c3857934Sdan } 1036c3857934Sdan} {wal 1 2 3 4 5 6 7 8 9} 1037c3857934Sdan 1038c3857934Sdando_test wal2-11.1.1 { 1039c3857934Sdan sqlite3 db2 test.db 1040c3857934Sdan execsql { SELECT name FROM sqlite_master } db2 1041c3857934Sdan} {t1} 1042c3857934Sdan 10439e5f1074Sdrhif {$::tcl_version>=8.5} { 1044e84322e5Sdan # Set all zeroed slots in the first hash table to invalid values. 1045e84322e5Sdan # 1046e84322e5Sdan set blob [string range [tvfs shm $::filename] 0 16383] 1047e84322e5Sdan set I [string range [tvfs shm $::filename] 16384 end] 1048e84322e5Sdan binary scan $I t* L 1049e84322e5Sdan set I [list] 1050e84322e5Sdan foreach p $L { 1051e84322e5Sdan lappend I [expr $p ? $p : 400] 1052e84322e5Sdan } 1053e84322e5Sdan append blob [binary format t* $I] 1054e84322e5Sdan tvfs shm $::filename $blob 1055e84322e5Sdan do_test wal2-11.2 { 1056e84322e5Sdan catchsql { INSERT INTO t1 VALUES(10, 11, 12) } 1057e84322e5Sdan } {1 {database disk image is malformed}} 1058e84322e5Sdan 1059c3857934Sdan # Fill up the hash table on the first page of shared memory with 0x55 bytes. 1060c3857934Sdan # 1061c3857934Sdan set blob [string range [tvfs shm $::filename] 0 16383] 1062e84322e5Sdan append blob [string repeat [binary format c 55] 16384] 1063c3857934Sdan tvfs shm $::filename $blob 1064e84322e5Sdan do_test wal2-11.3 { 1065c3857934Sdan catchsql { SELECT * FROM t1 } db2 1066c3857934Sdan } {1 {database disk image is malformed}} 10679e5f1074Sdrh} 1068c3857934Sdan 1069c3857934Sdandb close 1070c3857934Sdandb2 close 1071c3857934Sdantvfs delete 107210f5a50eSdan 1073ddb0ac4bSdan#------------------------------------------------------------------------- 1074ddb0ac4bSdan# If a connection is required to create a WAL or SHM file, it creates 1075ddb0ac4bSdan# the new files with the same file-system permissions as the database 1076ddb0ac4bSdan# file itself. Test this. 1077ddb0ac4bSdan# 1078ddb0ac4bSdanif {$::tcl_platform(platform) == "unix"} { 1079ddb0ac4bSdan faultsim_delete_and_reopen 10808c815d14Sdrh # Changed on 2012-02-13: umask is deliberately ignored for -wal files. 10818c815d14Sdrh #set umask [exec /bin/sh -c umask] 10828c815d14Sdrh set umask 0 10838c815d14Sdrh 108450833e32Sdan 1085ddb0ac4bSdan do_test wal2-12.1 { 1086ddb0ac4bSdan sqlite3 db test.db 1087ddb0ac4bSdan execsql { 1088ddb0ac4bSdan CREATE TABLE tx(y, z); 1089ddb0ac4bSdan PRAGMA journal_mode = WAL; 1090ddb0ac4bSdan } 1091ddb0ac4bSdan db close 1092ddb0ac4bSdan list [file exists test.db-wal] [file exists test.db-shm] 1093ddb0ac4bSdan } {0 0} 1094ddb0ac4bSdan 1095ddb0ac4bSdan foreach {tn permissions} { 1096ddb0ac4bSdan 1 00644 1097ddb0ac4bSdan 2 00666 1098ddb0ac4bSdan 3 00600 1099ddb0ac4bSdan 4 00755 1100ddb0ac4bSdan } { 1101ddb0ac4bSdan set effective [format %.5o [expr $permissions & ~$umask]] 1102ddb0ac4bSdan do_test wal2-12.2.$tn.1 { 1103ddb0ac4bSdan file attributes test.db -permissions $permissions 1104158931abSdrh string map {o 0} [file attributes test.db -permissions] 1105ddb0ac4bSdan } $permissions 1106ddb0ac4bSdan do_test wal2-12.2.$tn.2 { 1107ddb0ac4bSdan list [file exists test.db-wal] [file exists test.db-shm] 1108ddb0ac4bSdan } {0 0} 1109ddb0ac4bSdan do_test wal2-12.2.$tn.3 { 1110ddb0ac4bSdan sqlite3 db test.db 1111ddb0ac4bSdan execsql { INSERT INTO tx DEFAULT VALUES } 1112ddb0ac4bSdan list [file exists test.db-wal] [file exists test.db-shm] 1113ddb0ac4bSdan } {1 1} 1114ddb0ac4bSdan do_test wal2-12.2.$tn.4 { 1115158931abSdrh set x [list [file attr test.db-wal -perm] [file attr test.db-shm -perm]] 1116158931abSdrh string map {o 0} $x 1117ddb0ac4bSdan } [list $effective $effective] 1118ddb0ac4bSdan do_test wal2-12.2.$tn.5 { 1119ddb0ac4bSdan db close 1120ddb0ac4bSdan list [file exists test.db-wal] [file exists test.db-shm] 1121ddb0ac4bSdan } {0 0} 1122ddb0ac4bSdan } 1123ddb0ac4bSdan} 1124ddb0ac4bSdan 112550833e32Sdan#------------------------------------------------------------------------- 112650833e32Sdan# Test the libraries response to discovering that one or more of the 112750833e32Sdan# database, wal or shm files cannot be opened, or can only be opened 112850833e32Sdan# read-only. 112950833e32Sdan# 113050833e32Sdanif {$::tcl_platform(platform) == "unix"} { 113150833e32Sdan proc perm {} { 113250833e32Sdan set L [list] 113350833e32Sdan foreach f {test.db test.db-wal test.db-shm} { 113450833e32Sdan if {[file exists $f]} { 113550833e32Sdan lappend L [file attr $f -perm] 113650833e32Sdan } else { 113750833e32Sdan lappend L {} 113850833e32Sdan } 113950833e32Sdan } 114050833e32Sdan set L 114150833e32Sdan } 114250833e32Sdan 114350833e32Sdan faultsim_delete_and_reopen 114450833e32Sdan execsql { 114550833e32Sdan PRAGMA journal_mode = WAL; 114650833e32Sdan CREATE TABLE t1(a, b); 114750833e32Sdan PRAGMA wal_checkpoint; 114850833e32Sdan INSERT INTO t1 VALUES('3.14', '2.72'); 114950833e32Sdan } 115050833e32Sdan do_test wal2-13.1.1 { 115150833e32Sdan list [file exists test.db-shm] [file exists test.db-wal] 115250833e32Sdan } {1 1} 115350833e32Sdan faultsim_save_and_close 115450833e32Sdan 115550833e32Sdan foreach {tn db_perm wal_perm shm_perm can_open can_read can_write} { 115650833e32Sdan 2 00644 00644 00644 1 1 1 11571e5de5a1Sdan 3 00644 00400 00644 1 1 0 1158f12ba66cSdan 4 00644 00644 00400 1 1 0 115950833e32Sdan 5 00400 00644 00644 1 1 0 116050833e32Sdan 116150833e32Sdan 7 00644 00000 00644 1 0 0 116250833e32Sdan 8 00644 00644 00000 1 0 0 116350833e32Sdan 9 00000 00644 00644 0 0 0 116450833e32Sdan } { 116550833e32Sdan faultsim_restore 116650833e32Sdan do_test wal2-13.$tn.1 { 116750833e32Sdan file attr test.db -perm $db_perm 116850833e32Sdan file attr test.db-wal -perm $wal_perm 116950833e32Sdan file attr test.db-shm -perm $shm_perm 117050833e32Sdan 117150833e32Sdan set L [file attr test.db -perm] 117250833e32Sdan lappend L [file attr test.db-wal -perm] 117350833e32Sdan lappend L [file attr test.db-shm -perm] 1174158931abSdrh string map {o 0} $L 117550833e32Sdan } [list $db_perm $wal_perm $shm_perm] 117650833e32Sdan 117750833e32Sdan # If $can_open is true, then it should be possible to open a database 117850833e32Sdan # handle. Otherwise, if $can_open is 0, attempting to open the db 117950833e32Sdan # handle throws an "unable to open database file" exception. 118050833e32Sdan # 118150833e32Sdan set r(1) {0 ok} 118250833e32Sdan set r(0) {1 {unable to open database file}} 118350833e32Sdan do_test wal2-13.$tn.2 { 118450833e32Sdan list [catch {sqlite3 db test.db ; set {} ok} msg] $msg 118550833e32Sdan } $r($can_open) 118650833e32Sdan 118750833e32Sdan if {$can_open} { 118850833e32Sdan 118950833e32Sdan # If $can_read is true, then the client should be able to read from 119050833e32Sdan # the database file. If $can_read is false, attempting to read should 119150833e32Sdan # throw the "unable to open database file" exception. 119250833e32Sdan # 119350833e32Sdan set a(0) {1 {unable to open database file}} 119450833e32Sdan set a(1) {0 {3.14 2.72}} 119550833e32Sdan do_test wal2-13.$tn.3 { 119650833e32Sdan catchsql { SELECT * FROM t1 } 119750833e32Sdan } $a($can_read) 119850833e32Sdan 119950833e32Sdan # Now try to write to the db file. If the client can read but not 120050833e32Sdan # write, then it should throw the familiar "unable to open db file" 120150833e32Sdan # exception. If it can read but not write, the exception should 120250833e32Sdan # be "attempt to write a read only database". 120350833e32Sdan # 120450833e32Sdan # If the client can read and write, the operation should succeed. 120550833e32Sdan # 120650833e32Sdan set b(0,0) {1 {unable to open database file}} 120750833e32Sdan set b(1,0) {1 {attempt to write a readonly database}} 120850833e32Sdan set b(1,1) {0 {}} 120950833e32Sdan do_test wal2-13.$tn.4 { 121050833e32Sdan catchsql { INSERT INTO t1 DEFAULT VALUES } 121150833e32Sdan } $b($can_read,$can_write) 121250833e32Sdan } 121350833e32Sdan catch { db close } 121450833e32Sdan } 121550833e32Sdan} 121611f273fcSdan 121711f273fcSdan#------------------------------------------------------------------------- 121811f273fcSdan# Test that "PRAGMA checkpoint_fullsync" appears to be working. 121911f273fcSdan# 122011f273fcSdanforeach {tn sql reslist} { 12214eb02a45Sdrh 1 { } {10 0 4 0 6 0} 1222daaae7b9Sdrh 2 { PRAGMA checkpoint_fullfsync = 1 } {10 6 4 3 6 3} 12234eb02a45Sdrh 3 { PRAGMA checkpoint_fullfsync = 0 } {10 0 4 0 6 0} 122411f273fcSdan} { 1225108e5a9aSdrh ifcapable default_ckptfullfsync { 1226108e5a9aSdrh if {[string trim $sql]==""} continue 1227108e5a9aSdrh } 122811f273fcSdan faultsim_delete_and_reopen 122911f273fcSdan 1230e243de5cSdrh execsql {PRAGMA auto_vacuum = 0; PRAGMA synchronous = FULL;} 123111f273fcSdan execsql $sql 12320774bb59Sdan do_execsql_test wal2-14.$tn.0 { PRAGMA page_size = 4096 } {} 123311f273fcSdan do_execsql_test wal2-14.$tn.1 { PRAGMA journal_mode = WAL } {wal} 123411f273fcSdan 123511f273fcSdan set sqlite_sync_count 0 123611f273fcSdan set sqlite_fullsync_count 0 123711f273fcSdan 123811f273fcSdan do_execsql_test wal2-14.$tn.2 { 123911f273fcSdan PRAGMA wal_autocheckpoint = 10; 124011f273fcSdan CREATE TABLE t1(a, b); -- 2 wal syncs 12414eb02a45Sdrh INSERT INTO t1 VALUES(1, 2); -- 2 wal sync 124211f273fcSdan PRAGMA wal_checkpoint; -- 1 wal sync, 1 db sync 124311f273fcSdan BEGIN; 124411f273fcSdan INSERT INTO t1 VALUES(3, 4); 124511f273fcSdan INSERT INTO t1 VALUES(5, 6); 12464eb02a45Sdrh COMMIT; -- 2 wal sync 124711f273fcSdan PRAGMA wal_checkpoint; -- 1 wal sync, 1 db sync 12480774bb59Sdan } {10 0 3 3 0 1 1} 124911f273fcSdan 125011f273fcSdan do_test wal2-14.$tn.3 { 12519dd6e080Sshaneh cond_incr_sync_count 1 125211f273fcSdan list $sqlite_sync_count $sqlite_fullsync_count 125311f273fcSdan } [lrange $reslist 0 1] 125411f273fcSdan 125511f273fcSdan set sqlite_sync_count 0 125611f273fcSdan set sqlite_fullsync_count 0 125711f273fcSdan 125811f273fcSdan do_test wal2-14.$tn.4 { 125911f273fcSdan execsql { INSERT INTO t1 VALUES(7, zeroblob(12*4096)) } 126011f273fcSdan list $sqlite_sync_count $sqlite_fullsync_count 126111f273fcSdan } [lrange $reslist 2 3] 126211f273fcSdan 126311f273fcSdan set sqlite_sync_count 0 126411f273fcSdan set sqlite_fullsync_count 0 126511f273fcSdan 126611f273fcSdan do_test wal2-14.$tn.5 { 126711f273fcSdan execsql { PRAGMA wal_autocheckpoint = 1000 } 126811f273fcSdan execsql { INSERT INTO t1 VALUES(9, 10) } 126911f273fcSdan execsql { INSERT INTO t1 VALUES(11, 12) } 127011f273fcSdan execsql { INSERT INTO t1 VALUES(13, 14) } 127111f273fcSdan db close 127211f273fcSdan list $sqlite_sync_count $sqlite_fullsync_count 127311f273fcSdan } [lrange $reslist 4 5] 127411f273fcSdan} 127511f273fcSdan 127618826195Sdancatch { db close } 127718826195Sdan 127818826195Sdan# PRAGMA checkpoint_fullsync 127918826195Sdan# PRAGMA fullfsync 128018826195Sdan# PRAGMA synchronous 128118826195Sdan# 12824eb02a45Sdrhforeach {tn settings restart_sync commit_sync ckpt_sync} { 12834eb02a45Sdrh 1 {0 0 off} {0 0} {0 0} {0 0} 12844eb02a45Sdrh 2 {0 0 normal} {1 0} {0 0} {2 0} 12854eb02a45Sdrh 3 {0 0 full} {2 0} {1 0} {2 0} 128618826195Sdan 12874eb02a45Sdrh 4 {0 1 off} {0 0} {0 0} {0 0} 12884eb02a45Sdrh 5 {0 1 normal} {0 1} {0 0} {0 2} 12894eb02a45Sdrh 6 {0 1 full} {0 2} {0 1} {0 2} 129018826195Sdan 12914eb02a45Sdrh 7 {1 0 off} {0 0} {0 0} {0 0} 1292daaae7b9Sdrh 8 {1 0 normal} {0 1} {0 0} {0 2} 1293daaae7b9Sdrh 9 {1 0 full} {1 1} {1 0} {0 2} 129418826195Sdan 12954eb02a45Sdrh 10 {1 1 off} {0 0} {0 0} {0 0} 12964eb02a45Sdrh 11 {1 1 normal} {0 1} {0 0} {0 2} 12974eb02a45Sdrh 12 {1 1 full} {0 2} {0 1} {0 2} 129818826195Sdan} { 129918826195Sdan forcedelete test.db 130018826195Sdan 130118826195Sdan testvfs tvfs -default 1 130218826195Sdan tvfs filter xSync 130318826195Sdan tvfs script xSyncCb 130418826195Sdan proc xSyncCb {method file fileid flags} { 130518826195Sdan incr ::sync($flags) 130618826195Sdan } 130718826195Sdan 130818826195Sdan sqlite3 db test.db 130918826195Sdan do_execsql_test 15.$tn.1 " 13100774bb59Sdan PRAGMA page_size = 4096; 131118826195Sdan CREATE TABLE t1(x); 13124eb02a45Sdrh PRAGMA wal_autocheckpoint = OFF; 131318826195Sdan PRAGMA journal_mode = WAL; 131418826195Sdan PRAGMA checkpoint_fullfsync = [lindex $settings 0]; 131518826195Sdan PRAGMA fullfsync = [lindex $settings 1]; 131618826195Sdan PRAGMA synchronous = [lindex $settings 2]; 13174eb02a45Sdrh " {0 wal} 131818826195Sdan 131918826195Sdan do_test 15.$tn.2 { 132018826195Sdan set sync(normal) 0 132118826195Sdan set sync(full) 0 132218826195Sdan execsql { INSERT INTO t1 VALUES('abc') } 132318826195Sdan list $::sync(normal) $::sync(full) 13244eb02a45Sdrh } $restart_sync 132518826195Sdan 132618826195Sdan do_test 15.$tn.3 { 132718826195Sdan set sync(normal) 0 132818826195Sdan set sync(full) 0 13294eb02a45Sdrh execsql { INSERT INTO t1 VALUES('abc') } 13304eb02a45Sdrh list $::sync(normal) $::sync(full) 13314eb02a45Sdrh } $commit_sync 13324eb02a45Sdrh 13334eb02a45Sdrh do_test 15.$tn.4 { 13344eb02a45Sdrh set sync(normal) 0 13354eb02a45Sdrh set sync(full) 0 133618826195Sdan execsql { INSERT INTO t1 VALUES('def') } 133718826195Sdan list $::sync(normal) $::sync(full) 133818826195Sdan } $commit_sync 133918826195Sdan 13404eb02a45Sdrh do_test 15.$tn.5 { 134118826195Sdan set sync(normal) 0 134218826195Sdan set sync(full) 0 134318826195Sdan execsql { PRAGMA wal_checkpoint } 134418826195Sdan list $::sync(normal) $::sync(full) 134518826195Sdan } $ckpt_sync 134618826195Sdan 134718826195Sdan db close 134818826195Sdan tvfs delete 134918826195Sdan} 135018826195Sdan 135111f273fcSdan 135250833e32Sdan 13539a6b4e9aSdanfinish_test 1354