mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-14 00:22:38 +03:00
Add a version number to the wal-index header. If SQLite encounters a version number in either the wal or wal-index files that it does not understand, the operation is abandoned and SQLITE_CANTOPEN returned.
FossilOrigin-Name: 8d0f8a7f70d6fb42369411a934b30f8c8ca8322f
This commit is contained in:
@@ -18,6 +18,8 @@
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
do_not_use_codec
|
||||
|
||||
ifcapable !trigger||!view { finish_test ; return }
|
||||
|
||||
# Fill a database with test data.
|
||||
|
||||
@@ -500,30 +500,32 @@ datetest 13.34 {date('2001-01-01','-1.5 years')} {1999-07-02}
|
||||
# Put a floating point number in the database so that we can manipulate
|
||||
# raw bits using the hexio interface.
|
||||
#
|
||||
do_test date-14.1 {
|
||||
execsql {
|
||||
PRAGMA auto_vacuum=OFF;
|
||||
PRAGMA page_size = 1024;
|
||||
CREATE TABLE t1(x);
|
||||
INSERT INTO t1 VALUES(1.1);
|
||||
if {0==[sqlite3 -has-codec]} {
|
||||
do_test date-14.1 {
|
||||
execsql {
|
||||
PRAGMA auto_vacuum=OFF;
|
||||
PRAGMA page_size = 1024;
|
||||
CREATE TABLE t1(x);
|
||||
INSERT INTO t1 VALUES(1.1);
|
||||
}
|
||||
db close
|
||||
hexio_write test.db 2040 4142ba32bffffff9
|
||||
sqlite3 db test.db
|
||||
db eval {SELECT * FROM t1}
|
||||
} {2454629.5}
|
||||
|
||||
# Changing the least significant byte of the floating point value between
|
||||
# 00 and FF should always generate a time of either 23:59:59 or 00:00:00,
|
||||
# never 24:00:00
|
||||
#
|
||||
for {set i 0} {$i<=255} {incr i} {
|
||||
db close
|
||||
hexio_write test.db 2047 [format %02x $i]
|
||||
sqlite3 db test.db
|
||||
do_test date-14.2.$i {
|
||||
set date [db one {SELECT datetime(x) FROM t1}]
|
||||
expr {$date eq "2008-06-12 00:00:00" || $date eq "2008-06-11 23:59:59"}
|
||||
} {1}
|
||||
}
|
||||
db close
|
||||
hexio_write test.db 2040 4142ba32bffffff9
|
||||
sqlite3 db test.db
|
||||
db eval {SELECT * FROM t1}
|
||||
} {2454629.5}
|
||||
|
||||
# Changing the least significant byte of the floating point value between
|
||||
# 00 and FF should always generate a time of either 23:59:59 or 00:00:00,
|
||||
# never 24:00:00
|
||||
#
|
||||
for {set i 0} {$i<=255} {incr i} {
|
||||
db close
|
||||
hexio_write test.db 2047 [format %02x $i]
|
||||
sqlite3 db test.db
|
||||
do_test date-14.2.$i {
|
||||
set date [db one {SELECT datetime(x) FROM t1}]
|
||||
expr {$date eq "2008-06-12 00:00:00" || $date eq "2008-06-11 23:59:59"}
|
||||
} {1}
|
||||
}
|
||||
finish_test
|
||||
|
||||
@@ -556,6 +556,10 @@ do_execsql_test pager1.4.5.2 {
|
||||
# journal. Check that the first record in the transaction is
|
||||
# played back, but not the second.
|
||||
#
|
||||
# pager1-4.5.6: Restore the file-system. Try to open the database with a
|
||||
# readonly connection. This should fail, as a read-only
|
||||
# connection cannot roll back the database file.
|
||||
#
|
||||
faultsim_restore_and_reopen
|
||||
do_execsql_test pager1.4.5.3 {
|
||||
SELECT * FROM t1;
|
||||
@@ -574,6 +578,14 @@ do_execsql_test pager1.4.5.5 {
|
||||
SELECT * FROM t2;
|
||||
} {I II III IV 3 4}
|
||||
|
||||
faultsim_restore_and_reopen
|
||||
db close
|
||||
sqlite3 db test.db -readonly 1
|
||||
do_catchsql_test pager1.4.5.6 {
|
||||
SELECT * FROM t1;
|
||||
SELECT * FROM t2;
|
||||
} {1 {disk I/O error}}
|
||||
|
||||
db close
|
||||
tv delete
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
source $testdir/lock_common.tcl
|
||||
source $testdir/malloc_common.tcl
|
||||
source $testdir/wal_common.tcl
|
||||
|
||||
ifcapable !wal {finish_test ; return }
|
||||
|
||||
@@ -41,10 +42,6 @@ proc sqlite3_wal {args} {
|
||||
[lindex $args 0] function blob blob
|
||||
}
|
||||
|
||||
proc log_file_size {nFrame pgsz} {
|
||||
expr {24 + ($pgsz+24)*$nFrame}
|
||||
}
|
||||
|
||||
proc log_deleted {logfile} {
|
||||
return [expr [file exists $logfile]==0]
|
||||
}
|
||||
@@ -87,7 +84,7 @@ do_test wal-1.1 {
|
||||
do_test wal-1.2 {
|
||||
# There are now two pages in the log.
|
||||
file size test.db-wal
|
||||
} [log_file_size 2 1024]
|
||||
} [wal_file_size 2 1024]
|
||||
|
||||
do_test wal-1.3 {
|
||||
execsql { SELECT * FROM sqlite_master }
|
||||
@@ -366,11 +363,11 @@ do_test wal-7.1 {
|
||||
INSERT INTO t1 VALUES(1, 2);
|
||||
}
|
||||
list [file size test.db] [file size test.db-wal]
|
||||
} [list 1024 [log_file_size 3 1024]]
|
||||
} [list 1024 [wal_file_size 3 1024]]
|
||||
do_test wal-7.2 {
|
||||
execsql { PRAGMA wal_checkpoint }
|
||||
list [file size test.db] [file size test.db-wal]
|
||||
} [list 2048 [log_file_size 3 1024]]
|
||||
} [list 2048 [wal_file_size 3 1024]]
|
||||
|
||||
# Execute some transactions in auto-vacuum mode to test database file
|
||||
# truncation.
|
||||
@@ -685,11 +682,11 @@ do_test wal-11.1 {
|
||||
do_test wal-11.2 {
|
||||
execsql { PRAGMA wal_checkpoint }
|
||||
list [expr [file size test.db]/1024] [file size test.db-wal]
|
||||
} [list 3 [log_file_size 3 1024]]
|
||||
} [list 3 [wal_file_size 3 1024]]
|
||||
do_test wal-11.3 {
|
||||
execsql { INSERT INTO t1 VALUES( blob(900) ) }
|
||||
list [expr [file size test.db]/1024] [file size test.db-wal]
|
||||
} [list 3 [log_file_size 4 1024]]
|
||||
} [list 3 [wal_file_size 4 1024]]
|
||||
|
||||
do_test wal-11.4 {
|
||||
execsql {
|
||||
@@ -700,7 +697,7 @@ do_test wal-11.4 {
|
||||
INSERT INTO t1 SELECT blob(900) FROM t1; -- 16
|
||||
}
|
||||
list [expr [file size test.db]/1024] [file size test.db-wal]
|
||||
} [list 3 [log_file_size 32 1024]]
|
||||
} [list 3 [wal_file_size 32 1024]]
|
||||
do_test wal-11.5 {
|
||||
execsql {
|
||||
SELECT count(*) FROM t1;
|
||||
@@ -710,7 +707,7 @@ do_test wal-11.5 {
|
||||
do_test wal-11.6 {
|
||||
execsql COMMIT
|
||||
list [expr [file size test.db]/1024] [file size test.db-wal]
|
||||
} [list 3 [log_file_size 41 1024]]
|
||||
} [list 3 [wal_file_size 41 1024]]
|
||||
do_test wal-11.7 {
|
||||
execsql {
|
||||
SELECT count(*) FROM t1;
|
||||
@@ -720,7 +717,7 @@ do_test wal-11.7 {
|
||||
do_test wal-11.8 {
|
||||
execsql { PRAGMA wal_checkpoint }
|
||||
list [expr [file size test.db]/1024] [file size test.db-wal]
|
||||
} [list 37 [log_file_size 41 1024]]
|
||||
} [list 37 [wal_file_size 41 1024]]
|
||||
do_test wal-11.9 {
|
||||
db close
|
||||
list [expr [file size test.db]/1024] [log_deleted test.db-wal]
|
||||
@@ -734,7 +731,7 @@ do_test wal-11.10 {
|
||||
SELECT count(*) FROM t1;
|
||||
}
|
||||
list [expr [file size test.db]/1024] [file size test.db-wal]
|
||||
} [list 37 [log_file_size 37 1024]]
|
||||
} [list 37 [wal_file_size 37 1024]]
|
||||
do_test wal-11.11 {
|
||||
execsql {
|
||||
SELECT count(*) FROM t1;
|
||||
@@ -744,7 +741,7 @@ do_test wal-11.11 {
|
||||
} {32 16}
|
||||
do_test wal-11.12 {
|
||||
list [expr [file size test.db]/1024] [file size test.db-wal]
|
||||
} [list 37 [log_file_size 37 1024]]
|
||||
} [list 37 [wal_file_size 37 1024]]
|
||||
do_test wal-11.13 {
|
||||
execsql {
|
||||
INSERT INTO t1 VALUES( blob(900) );
|
||||
@@ -754,7 +751,7 @@ do_test wal-11.13 {
|
||||
} {17 ok}
|
||||
do_test wal-11.14 {
|
||||
list [expr [file size test.db]/1024] [file size test.db-wal]
|
||||
} [list 37 [log_file_size 37 1024]]
|
||||
} [list 37 [wal_file_size 37 1024]]
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
@@ -771,7 +768,7 @@ do_test wal-12.1 {
|
||||
INSERT INTO t1 VALUES('A', 1);
|
||||
}
|
||||
list [expr [file size test.db]/1024] [file size test.db-wal]
|
||||
} [list 1 [log_file_size 5 1024]]
|
||||
} [list 1 [wal_file_size 5 1024]]
|
||||
do_test wal-12.2 {
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
@@ -865,7 +862,7 @@ do_test wal-13.2.2 {
|
||||
execsql { SELECT count(*) FROM t2 }
|
||||
} [expr int(pow(2, 16))]
|
||||
do_test wal-13.2.3 {
|
||||
expr [file size test.db-wal] > [log_file_size 33000 1024]
|
||||
expr [file size test.db-wal] > [wal_file_size 33000 1024]
|
||||
} 1
|
||||
|
||||
do_multiclient_test tn {
|
||||
@@ -1067,20 +1064,20 @@ foreach {tn ckpt_cmd ckpt_res ckpt_main ckpt_aux} {
|
||||
}
|
||||
|
||||
list [file size test.db] [file size test.db-wal]
|
||||
} [list [expr 1*1024] [log_file_size 10 1024]]
|
||||
} [list [expr 1*1024] [wal_file_size 10 1024]]
|
||||
do_test wal-16.$tn.3 {
|
||||
list [file size test2.db] [file size test2.db-wal]
|
||||
} [list [expr 1*1024] [log_file_size 16 1024]]
|
||||
} [list [expr 1*1024] [wal_file_size 16 1024]]
|
||||
|
||||
do_test wal-16.$tn.4 [list eval $ckpt_cmd] $ckpt_res
|
||||
|
||||
do_test wal-16.$tn.5 {
|
||||
list [file size test.db] [file size test.db-wal]
|
||||
} [list [expr ($ckpt_main ? 7 : 1)*1024] [log_file_size 10 1024]]
|
||||
} [list [expr ($ckpt_main ? 7 : 1)*1024] [wal_file_size 10 1024]]
|
||||
|
||||
do_test wal-16.$tn.6 {
|
||||
list [file size test2.db] [file size test2.db-wal]
|
||||
} [list [expr ($ckpt_aux ? 7 : 1)*1024] [log_file_size 16 1024]]
|
||||
} [list [expr ($ckpt_aux ? 7 : 1)*1024] [wal_file_size 16 1024]]
|
||||
|
||||
catch { db close }
|
||||
}
|
||||
@@ -1094,7 +1091,7 @@ foreach {tn ckpt_cmd ckpt_res ckpt_main ckpt_aux} {
|
||||
# a transaction that modifies 171 pages. In synchronous=NORMAL mode, this
|
||||
# produces a log file of:
|
||||
#
|
||||
# 24 + (24+512)*171 = 90312 bytes.
|
||||
# 32 + (24+512)*171 = 90312 bytes.
|
||||
#
|
||||
# Slightly larger than 11*8192 = 90112 bytes.
|
||||
#
|
||||
@@ -1106,15 +1103,15 @@ foreach {tn ckpt_cmd ckpt_res ckpt_main ckpt_aux} {
|
||||
#
|
||||
set old_pending_byte [sqlite3_test_control_pending_byte 0x10000000]
|
||||
catch { db close }
|
||||
foreach {tn sectorsize logsize} {
|
||||
1 128 92216
|
||||
2 256 92216
|
||||
3 512 92216
|
||||
4 1024 92216
|
||||
5 2048 92216
|
||||
6 4096 94360
|
||||
7 8192 98648
|
||||
} {
|
||||
foreach {tn sectorsize logsize} "
|
||||
1 128 [wal_file_size 172 512]
|
||||
2 256 [wal_file_size 172 512]
|
||||
3 512 [wal_file_size 172 512]
|
||||
4 1024 [wal_file_size 172 512]
|
||||
5 2048 [wal_file_size 172 512]
|
||||
6 4096 [wal_file_size 176 512]
|
||||
7 8192 [wal_file_size 184 512]
|
||||
" {
|
||||
file delete -force test.db test.db-wal test.db-journal
|
||||
sqlite3_simulate_device -sectorsize $sectorsize
|
||||
sqlite3 db test.db -vfs devsym
|
||||
@@ -1181,7 +1178,7 @@ do_test wal-18.0 {
|
||||
file copy -force test.db-wal testX.db-wal
|
||||
db close
|
||||
list [file size testX.db] [file size testX.db-wal]
|
||||
} [list [expr 3*1024] [log_file_size 6 1024]]
|
||||
} [list [expr 3*1024] [wal_file_size 6 1024]]
|
||||
|
||||
unset -nocomplain nFrame result
|
||||
foreach {nFrame result} {
|
||||
@@ -1280,6 +1277,8 @@ foreach {tn pgsz works} {
|
||||
set c1 0
|
||||
set c2 0
|
||||
logcksum c1 c2 $walhdr
|
||||
|
||||
append walhdr [binary format II $c1 $c2]
|
||||
logcksum c1 c2 [string range $framehdr 0 7]
|
||||
logcksum c1 c2 $framebody
|
||||
set framehdr [binary format IIIIII $pg 5 22 23 $c1 $c2]
|
||||
@@ -1292,7 +1291,7 @@ foreach {tn pgsz works} {
|
||||
close $fd
|
||||
|
||||
file size test.db-wal
|
||||
} [log_file_size 1 $pgsz]
|
||||
} [wal_file_size 1 $pgsz]
|
||||
|
||||
do_test wal-18.2.$tn.$pg.5 {
|
||||
sqlite3 db test.db
|
||||
@@ -1414,10 +1413,9 @@ integrity_check wal-20.5
|
||||
|
||||
catch { db2 close }
|
||||
catch { db close }
|
||||
file delete -force test.db test.db-wal test.db-journal
|
||||
|
||||
do_test wal-21.1 {
|
||||
sqlite3 db test.db
|
||||
faultsim_delete_and_reopen
|
||||
execsql {
|
||||
PRAGMA journal_mode = WAL;
|
||||
CREATE TABLE t1(a, b);
|
||||
|
||||
@@ -16,12 +16,15 @@
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
source $testdir/lock_common.tcl
|
||||
source $testdir/malloc_common.tcl
|
||||
source $testdir/wal_common.tcl
|
||||
|
||||
ifcapable !wal {finish_test ; return }
|
||||
|
||||
proc set_tvfs_hdr {file args} {
|
||||
|
||||
# Set $nHdr to the number of bytes in the wal-index header:
|
||||
set nHdr 40
|
||||
set nHdr 48
|
||||
set nInt [expr {$nHdr/4}]
|
||||
|
||||
if {[llength $args]>2} {
|
||||
@@ -880,7 +883,7 @@ foreach {tn hdr1 hdr2 res} [list \
|
||||
5 $wih(2) $wih(1) {Barton Deakin Watson} \
|
||||
6 $wih(2) $wih(2) {Barton Deakin Watson} \
|
||||
7 $wih(1) $wih(1) {Barton Deakin} \
|
||||
8 {0 0 0 0 0 0 0 0 0 0} {0 0 0 0 0 0 0 0 0 0} {Barton Deakin Watson} \
|
||||
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}
|
||||
] {
|
||||
do_test wal2-9.$tn {
|
||||
set_tvfs_hdr $::filename $hdr1 $hdr2
|
||||
@@ -891,4 +894,62 @@ foreach {tn hdr1 hdr2 res} [list \
|
||||
db2 close
|
||||
db close
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# This block of tests - wal2-10.* - focus on the libraries response to
|
||||
# new versions of the wal or wal-index formats.
|
||||
#
|
||||
# wal2-10.1.*: Test that the library refuses to "recover" a new WAL
|
||||
# format.
|
||||
#
|
||||
# wal2-10.2.*: Test that the library refuses to read or write a database
|
||||
# if the wal-index version is newer than it understands.
|
||||
#
|
||||
# At time of writing, the only versions of the wal and wal-index formats
|
||||
# that exist are versions 3007000 (corresponding to SQLite version 3.7.0,
|
||||
# the first version of SQLite to feature wal mode).
|
||||
#
|
||||
do_test wal2-10.1.1 {
|
||||
faultsim_delete_and_reopen
|
||||
execsql {
|
||||
PRAGMA journal_mode = WAL;
|
||||
CREATE TABLE t1(a, b);
|
||||
PRAGMA wal_checkpoint;
|
||||
INSERT INTO t1 VALUES(1, 2);
|
||||
INSERT INTO t1 VALUES(3, 4);
|
||||
}
|
||||
faultsim_save_and_close
|
||||
} {}
|
||||
do_test wal2-10.1.2 {
|
||||
faultsim_restore_and_reopen
|
||||
execsql { SELECT * FROM t1 }
|
||||
} {1 2 3 4}
|
||||
do_test wal2-10.1.3 {
|
||||
faultsim_restore_and_reopen
|
||||
set hdr [wal_set_walhdr test.db-wal]
|
||||
lindex $hdr 1
|
||||
} {3007000}
|
||||
do_test wal2-10.1.4 {
|
||||
lset hdr 1 3007001
|
||||
wal_set_walhdr test.db-wal $hdr
|
||||
catchsql { SELECT * FROM t1 }
|
||||
} {1 {unable to open database file}}
|
||||
|
||||
testvfs tvfs -default 1
|
||||
do_test wal2-10.2.1 {
|
||||
faultsim_restore_and_reopen
|
||||
execsql { SELECT * FROM t1 }
|
||||
} {1 2 3 4}
|
||||
do_test wal2-10.2.2 {
|
||||
set hdr [set_tvfs_hdr $::filename]
|
||||
lindex $hdr 0
|
||||
} {3007000}
|
||||
breakpoint
|
||||
do_test wal2-10.2.3 {
|
||||
lset hdr 0 3007001
|
||||
wal_fix_walindex_cksum hdr
|
||||
set_tvfs_hdr $::filename $hdr
|
||||
catchsql { SELECT * FROM t1 }
|
||||
} {1 {unable to open database file}}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -14,13 +14,77 @@
|
||||
#
|
||||
|
||||
proc wal_file_size {nFrame pgsz} {
|
||||
expr {24 + ($pgsz+24)*$nFrame}
|
||||
expr {32 + ($pgsz+24)*$nFrame}
|
||||
}
|
||||
|
||||
proc wal_frame_count {zFile pgsz} {
|
||||
set f [file size $zFile]
|
||||
expr {($f - 24) / ($pgsz+24)}
|
||||
expr {($f - 32) / ($pgsz+24)}
|
||||
}
|
||||
|
||||
proc wal_cksum_intlist {ckv1 ckv2 intlist} {
|
||||
upvar $ckv1 c1
|
||||
upvar $ckv2 c2
|
||||
foreach {v1 v2} $intlist {
|
||||
set c1 [expr {($c1 + $v1 + $c2)&0xFFFFFFFF}]
|
||||
set c2 [expr {($c2 + $v2 + $c1)&0xFFFFFFFF}]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# This proc calculates checksums in the same way as those used by SQLite
|
||||
# in WAL files. If the $endian argument is "big", then checksums are
|
||||
# calculated by interpreting data as an array of big-endian integers. If
|
||||
# it is "little", data is interpreted as an array of little-endian integers.
|
||||
#
|
||||
proc wal_cksum {endian ckv1 ckv2 blob} {
|
||||
upvar $ckv1 c1
|
||||
upvar $ckv2 c2
|
||||
|
||||
if {$endian!="big" && $endian!="little"} {
|
||||
return -error "Bad value \"$endian\" - must be \"big\" or \"little\""
|
||||
}
|
||||
set scanpattern I*
|
||||
if {$endian == "little"} { set scanpattern i* }
|
||||
|
||||
binary scan $blob $scanpattern values
|
||||
wal_cksum_intlist c1 c2 $values
|
||||
}
|
||||
|
||||
proc wal_set_walhdr {filename {intlist {}}} {
|
||||
if {[llength $intlist]==6} {
|
||||
set blob [binary format I6 $intlist]
|
||||
set endian little
|
||||
if {[lindex $intlist 0] & 0x00000001} { set endian big }
|
||||
set c1 0
|
||||
set c2 0
|
||||
wal_cksum $endian c1 c2 $blob
|
||||
append blob [binary format II $c1 $c2]
|
||||
|
||||
set fd [open $filename r+]
|
||||
fconfigure $fd -translation binary
|
||||
fconfigure $fd -encoding binary
|
||||
seek $fd 0
|
||||
puts -nonewline $fd $blob
|
||||
close $fd
|
||||
}
|
||||
|
||||
set fd [open $filename]
|
||||
fconfigure $fd -translation binary
|
||||
fconfigure $fd -encoding binary
|
||||
set blob [read $fd 24]
|
||||
|
||||
binary scan $blob I6 ints
|
||||
set ints
|
||||
}
|
||||
|
||||
proc wal_fix_walindex_cksum {hdrvar} {
|
||||
upvar $hdrvar hdr
|
||||
set c1 0
|
||||
set c2 0
|
||||
wal_cksum_intlist c1 c2 [lrange $hdr 0 9]
|
||||
lset hdr 10 $c1
|
||||
lset hdr 11 $c2
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -15,12 +15,12 @@
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
source $testdir/wal_common.tcl
|
||||
|
||||
do_not_use_codec
|
||||
|
||||
ifcapable !wal {finish_test ; return }
|
||||
|
||||
proc log_file_size {nFrame pgsz} {
|
||||
expr {24 + ($pgsz+24)*$nFrame}
|
||||
}
|
||||
|
||||
# Test organization:
|
||||
#
|
||||
@@ -69,11 +69,11 @@ do_test walbak-1.4 {
|
||||
} {wal}
|
||||
do_test walbak-1.5 {
|
||||
list [file size test.db] [file size test.db-wal]
|
||||
} [list 1024 [log_file_size 6 1024]]
|
||||
} [list 1024 [wal_file_size 6 1024]]
|
||||
do_test walbak-1.6 {
|
||||
execsql { PRAGMA wal_checkpoint }
|
||||
list [file size test.db] [file size test.db-wal]
|
||||
} [list [expr 3*1024] [log_file_size 6 1024]]
|
||||
} [list [expr 3*1024] [wal_file_size 6 1024]]
|
||||
do_test walbak-1.7 {
|
||||
execsql {
|
||||
CREATE TABLE t2(a, b);
|
||||
@@ -81,15 +81,15 @@ do_test walbak-1.7 {
|
||||
DROP TABLE t1;
|
||||
}
|
||||
list [file size test.db] [file size test.db-wal]
|
||||
} [list [expr 3*1024] [log_file_size 6 1024]]
|
||||
} [list [expr 3*1024] [wal_file_size 6 1024]]
|
||||
do_test walbak-1.8 {
|
||||
execsql { VACUUM }
|
||||
list [file size test.db] [file size test.db-wal]
|
||||
} [list [expr 3*1024] [log_file_size 8 1024]]
|
||||
} [list [expr 3*1024] [wal_file_size 8 1024]]
|
||||
do_test walbak-1.9 {
|
||||
execsql { PRAGMA wal_checkpoint }
|
||||
list [file size test.db] [file size test.db-wal]
|
||||
} [list [expr 2*1024] [log_file_size 8 1024]]
|
||||
} [list [expr 2*1024] [wal_file_size 8 1024]]
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Backups when the source db is modified mid-backup.
|
||||
|
||||
@@ -13,35 +13,10 @@
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
source $testdir/lock_common.tcl
|
||||
source $testdir/wal_common.tcl
|
||||
|
||||
ifcapable !wal {finish_test ; return }
|
||||
|
||||
# This proc calculates checksums in the same way as those used by SQLite
|
||||
# in WAL files. If the $endian argument is "big", then checksums are
|
||||
# calculated by interpreting data as an array of big-endian integers. If
|
||||
# it is "little", data is interpreted as an array of little-endian integers.
|
||||
#
|
||||
proc log_cksum {endian ckv1 ckv2 blob} {
|
||||
upvar $ckv1 c1
|
||||
upvar $ckv2 c2
|
||||
|
||||
if {$endian!="big" && $endian!="little"} {
|
||||
return -error "Bad value \"$endian\" - must be \"big\" or \"little\""
|
||||
}
|
||||
set scanpattern I*
|
||||
if {$endian == "little"} { set scanpattern i* }
|
||||
|
||||
binary scan $blob $scanpattern values
|
||||
foreach {v1 v2} $values {
|
||||
set c1 [expr {($c1 + $v1 + $c2)&0xFFFFFFFF}]
|
||||
set c2 [expr {($c2 + $v2 + $c1)&0xFFFFFFFF}]
|
||||
}
|
||||
}
|
||||
|
||||
proc log_file_size {nFrame pgsz} {
|
||||
expr {24 + ($pgsz+24)*$nFrame}
|
||||
}
|
||||
|
||||
# Read and return the contents of file $filename. Treat the content as
|
||||
# binary data.
|
||||
#
|
||||
@@ -72,7 +47,6 @@ proc log_checksum_verify {filename iFrame endian} {
|
||||
expr {$c1==$expect1 && $c2==$expect2}
|
||||
}
|
||||
|
||||
#
|
||||
# File $filename must be a WAL file on disk. Compute the checksum for frame
|
||||
# $iFrame in the file by interpreting data as $endian-endian integers
|
||||
# ($endian must be either "big" or "little"). Then write the computed
|
||||
@@ -92,21 +66,38 @@ proc log_checksum_write {filename iFrame endian} {
|
||||
close $fd
|
||||
}
|
||||
|
||||
# Calculate and return the checksum for a particular frame in a WAL.
|
||||
#
|
||||
# Arguments are:
|
||||
#
|
||||
# $data Blob containing the entire contents of a WAL.
|
||||
#
|
||||
# $iFrame Frame number within the $data WAL. Frames are numbered
|
||||
# starting at 1.
|
||||
#
|
||||
# $endian One of "big" or "little".
|
||||
#
|
||||
# Returns a list of three elements, as follows:
|
||||
#
|
||||
# * The byte offset of the checksum belonging to frame $iFrame in the WAL.
|
||||
# * The first integer in the calculated version of the checksum.
|
||||
# * The second integer in the calculated version of the checksum.
|
||||
#
|
||||
proc log_checksum_calc {data iFrame endian} {
|
||||
|
||||
binary scan [string range $data 8 11] I pgsz
|
||||
if {$iFrame > 1} {
|
||||
set n [log_file_size [expr $iFrame-2] $pgsz]
|
||||
set n [wal_file_size [expr $iFrame-2] $pgsz]
|
||||
binary scan [string range $data [expr $n+16] [expr $n+23]] II c1 c2
|
||||
} else {
|
||||
set c1 0
|
||||
set c2 0
|
||||
log_cksum $endian c1 c2 [string range $data 0 23]
|
||||
wal_cksum $endian c1 c2 [string range $data 0 23]
|
||||
}
|
||||
|
||||
set n [log_file_size [expr $iFrame-1] $pgsz]
|
||||
log_cksum $endian c1 c2 [string range $data $n [expr $n+7]]
|
||||
log_cksum $endian c1 c2 [string range $data [expr $n+24] [expr $n+24+$pgsz-1]]
|
||||
set n [wal_file_size [expr $iFrame-1] $pgsz]
|
||||
wal_cksum $endian c1 c2 [string range $data $n [expr $n+7]]
|
||||
wal_cksum $endian c1 c2 [string range $data [expr $n+24] [expr $n+24+$pgsz-1]]
|
||||
|
||||
list [expr $n+16] $c1 $c2
|
||||
}
|
||||
@@ -116,6 +107,9 @@ proc log_checksum_calc {data iFrame endian} {
|
||||
# WAL header to indicate that checksums are $endian-endian ($endian must be
|
||||
# either "big" or "little").
|
||||
#
|
||||
# Also update the wal header checksum (since the wal header contents may
|
||||
# have changed).
|
||||
#
|
||||
proc log_checksum_writemagic {filename endian} {
|
||||
set val [expr {0x377f0682 | ($endian == "big" ? 1 : 0)}]
|
||||
set bin [binary format I $val]
|
||||
@@ -123,6 +117,15 @@ proc log_checksum_writemagic {filename endian} {
|
||||
fconfigure $fd -encoding binary
|
||||
fconfigure $fd -translation binary
|
||||
puts -nonewline $fd $bin
|
||||
|
||||
seek $fd 0
|
||||
set blob [read $fd 24]
|
||||
set c1 0
|
||||
set c2 0
|
||||
wal_cksum $endian c1 c2 $blob
|
||||
seek $fd 24
|
||||
puts -nonewline $fd [binary format II $c1 $c2]
|
||||
|
||||
close $fd
|
||||
}
|
||||
|
||||
@@ -174,7 +177,7 @@ foreach endian {big little} {
|
||||
db close
|
||||
|
||||
list [file size test2.db] [file size test2.db-wal]
|
||||
} [list [expr 1024*3] [log_file_size 6 1024]]
|
||||
} [list [expr 1024*3] [wal_file_size 6 1024]]
|
||||
|
||||
# Verify that the checksums are valid for all frames and that they
|
||||
# are calculated by interpreting data in native byte-order.
|
||||
@@ -211,7 +214,7 @@ foreach endian {big little} {
|
||||
INSERT INTO t1 VALUES(34, 'thirtyfour');
|
||||
}
|
||||
list [file size test.db] [file size test.db-wal]
|
||||
} [list [expr 1024*3] [log_file_size 8 1024]]
|
||||
} [list [expr 1024*3] [wal_file_size 8 1024]]
|
||||
for {set f 1} {$f <= 8} {incr f} {
|
||||
do_test walcksum-1.$endian.5.$f {
|
||||
log_checksum_verify test.db-wal $f $endian
|
||||
@@ -235,7 +238,7 @@ foreach endian {big little} {
|
||||
INSERT INTO t1 VALUES(55, 'fiftyfive');
|
||||
} db2
|
||||
list [file size test.db] [file size test.db-wal]
|
||||
} [list [expr 1024*3] [log_file_size 10 1024]]
|
||||
} [list [expr 1024*3] [wal_file_size 10 1024]]
|
||||
for {set f 1} {$f <= 10} {incr f} {
|
||||
do_test walcksum-1.$endian.7.$f {
|
||||
log_checksum_verify test.db-wal $f $endian
|
||||
@@ -351,7 +354,7 @@ do_test walcksum-3.1 {
|
||||
}
|
||||
|
||||
file size test.db-wal
|
||||
} [log_file_size 1 1024]
|
||||
} [wal_file_size 1 1024]
|
||||
do_test walcksum-3.2 {
|
||||
file copy -force test.db-wal test2.db-wal
|
||||
file copy -force test.db test2.db
|
||||
@@ -365,7 +368,7 @@ file copy -force test.db test2.db
|
||||
foreach incr {1 2 3 20 40 60 80 100 120 140 160 180 200 220 240 253 254 255} {
|
||||
do_test walcksum-3.3.$incr {
|
||||
set FAIL 0
|
||||
for {set iOff 0} {$iOff < [log_file_size 1 1024]} {incr iOff} {
|
||||
for {set iOff 0} {$iOff < [wal_file_size 1 1024]} {incr iOff} {
|
||||
|
||||
file copy -force test.db-wal test2.db-wal
|
||||
set fd [open test2.db-wal r+]
|
||||
|
||||
@@ -14,11 +14,9 @@
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
source $testdir/lock_common.tcl
|
||||
source $testdir/wal_common.tcl
|
||||
ifcapable !wal {finish_test ; return }
|
||||
|
||||
proc wal_file_size {nFrame pgsz} {
|
||||
expr {24 + ($pgsz+24)*$nFrame}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# This test case demonstrates a flaw in the wal-index manipulation that
|
||||
|
||||
@@ -19,13 +19,10 @@
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
source $testdir/wal_common.tcl
|
||||
|
||||
ifcapable !wal {finish_test ; return }
|
||||
|
||||
proc log_file_size {nFrame pgsz} {
|
||||
expr {24 + ($pgsz+24)*$nFrame}
|
||||
}
|
||||
|
||||
set ::wal_hook [list]
|
||||
proc wal_hook {zDb nEntry} {
|
||||
lappend ::wal_hook $zDb $nEntry
|
||||
@@ -104,7 +101,7 @@ foreach {tn sql dbpages logpages} {
|
||||
do_test walhook-2.$tn {
|
||||
execsql $sql
|
||||
list [file size test.db] [file size test.db-wal]
|
||||
} [list [expr $dbpages*1024] [log_file_size $logpages 1024]]
|
||||
} [list [expr $dbpages*1024] [wal_file_size $logpages 1024]]
|
||||
}
|
||||
|
||||
catch { db2 close }
|
||||
|
||||
Reference in New Issue
Block a user