diff --git a/manifest b/manifest index 0a38a292c6..3746475123 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\sfix\s[f80c3f922a]\swith\sexperimental\schanges. -D 2010-06-17T06:19:53 +C Merge\strunk\supdates\swith\sexperimental\sbranch. +D 2010-06-17T10:52:07 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 F Makefile.in a5cad1f8f3e021356bfcc6c77dc16f6f1952bbc3 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -156,7 +156,7 @@ F src/os_common.h a8f95b81eca8a1ab8593d23e94f8a35f35d4078f F src/os_os2.c 665876d5eec7585226b0a1cf5e18098de2b2da19 F src/os_unix.c ae173c9f6afaa58b2833a1c95c6cd32021755c42 F src/os_win.c dfde7d33c446e89dd9a277c036f2c4cc564b3138 -F src/pager.c 3b2527d9d65a43880a98546ea84559271bb6d970 +F src/pager.c 658e5063d2d1661336a1e269e1cc324dfa8a683a F src/pager.h ca1f23c0cf137ac26f8908df2427c8b308361efd F src/parse.y ace5c7a125d9f2a410e431ee3209034105045f7e F src/pcache.c 1e9aa2dbc0845b52e1b51cc39753b6d1e041cb07 @@ -466,8 +466,8 @@ F test/join4.test 1a352e4e267114444c29266ce79e941af5885916 F test/join5.test 86675fc2919269aa923c84dd00ee4249b97990fe F test/join6.test bf82cf3f979e9eade83ad0d056a66c5ed71d1901 F test/journal1.test 36f2d1bb9bf03f790f43fbdb439e44c0657fab19 -F test/journal2.test 0f867f26c7f30bda2b69dc0e6451caa8fed18ef1 -F test/jrnlmode.test 76f94d61528c5ff32102a12f8cf34f4cc36f7849 +F test/journal2.test 92653f42868b32272a9913c767324b0b3992a60b +F test/jrnlmode.test cd0c9c5b2555f3d5bb72ed8aa8d0ad16ecf77e7c F test/jrnlmode2.test fe79ea1f0375c926b8de0362ddf94f34a64135fd F test/jrnlmode3.test cfcdb12b90e640a23b92785a002d96c0624c8710 F test/keyword1.test a2400977a2e4fde43bf33754c2929fda34dbca05 @@ -636,6 +636,7 @@ F test/tkt-cbd054fa6b.test f14f97ea43662e6f70c9e63287081e8be5d9d589 F test/tkt-d82e3f3721.test 731359dfdcdb36fea0559cd33fec39dd0ceae8e6 F test/tkt-f777251dc7a.test 6f24c053bc5cdb7e1e19be9a72c8887cf41d5e87 F test/tkt-f973c7ac31.test 1da0ed15ec2c7749fb5ce2828cd69d07153ad9f4 +F test/tkt-fc62af4523.test 7db6d6bddcf5b2da60a7e242311fdb6f3a2d27b1 F test/tkt1435.test f8c52c41de6e5ca02f1845f3a46e18e25cadac00 F test/tkt1443.test bacc311da5c96a227bf8c167e77a30c99f8e8368 F test/tkt1444.test a9d72f9e942708bd82dde6c707da61c489e213e9 @@ -823,7 +824,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P bede8c8a148fb9be5ffbf38df7fa733e35cc68c3 f80c3f922a114e738613955a939db46cf0847038 -R 99e9ca5d85226de77fd66a29f7003e5a +P 20133e9ca98f5e6c42051ed3d65e4eb71d5366a5 1ec74591a93e8b27ad3ac739914a48a91972e82c +R 4f7b82137af7b10bc7d2278f04c82c2f U dan -Z b12621360876a83980ead5d940279e1b +Z 03dc90f484cb38d112214ba72ea54330 diff --git a/manifest.uuid b/manifest.uuid index 8726926b10..200362655a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -20133e9ca98f5e6c42051ed3d65e4eb71d5366a5 \ No newline at end of file +9f6ea1de5abab0ca28688e257ddf03c66413cf6e \ No newline at end of file diff --git a/src/pager.c b/src/pager.c index a35e9d71d3..8869802c54 100644 --- a/src/pager.c +++ b/src/pager.c @@ -5898,20 +5898,6 @@ int sqlite3PagerSetJournalMode(Pager *pPager, int eMode){ /* Change the journal mode. */ pPager->journalMode = (u8)eMode; - - /* When transistioning from TRUNCATE or PERSIST to any other journal - ** mode (and we are not in locking_mode=EXCLUSIVE) then delete the - ** journal file. - */ - assert( (PAGER_JOURNALMODE_TRUNCATE & 5)==1 ); - assert( (PAGER_JOURNALMODE_PERSIST & 5)==1 ); - assert( (PAGER_JOURNALMODE_DELETE & 5)!=1 ); - assert( (PAGER_JOURNALMODE_MEMORY & 5)!=1 ); - assert( (PAGER_JOURNALMODE_OFF & 5)!=1 ); - assert( (PAGER_JOURNALMODE_WAL & 5)!=1 ); - if( (eOld & 5)==1 && (eMode & 5)!=1 && !pPager->exclusiveMode ){ - sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0); - } } /* Return the new journal mode */ diff --git a/test/journal2.test b/test/journal2.test index 8104299d49..ad76a8173f 100644 --- a/test/journal2.test +++ b/test/journal2.test @@ -37,7 +37,6 @@ tvfs devchar safe_delete # tvfs filter {xOpen xClose xDelete} tvfs script journal_op_catcher - proc journal_op_catcher {method filename args} { # If global variable ::tvfs_error_on_write is defined, then return an @@ -45,31 +44,36 @@ proc journal_op_catcher {method filename args} { # SQLITE_OK. # if {[info exists ::tvfs_error_on_write]} { - if {$method == "xDelete" || $method == "xWrite" || $method == "xTruncate"} { + if {[lsearch {xDelete xWrite xTruncate} $method]>=0} { return SQLITE_IOERR } return SQLITE_OK } - if {[string match *journal* $filename]==0} return - + # The rest of this command only deals with xOpen(), xClose() and xDelete() + # operations on journal files. If this invocation does not represent such + # an operation, return with no further ado. + # set f [file tail $filename] + if {[string match *journal $f]==0} return + if {[lsearch {xOpen xDelete xClose} $method]<0} return + + # Append a record of this operation to global list variable $::oplog. + # lappend ::oplog $method $f + # If this is an attempt to delete a journal file for which there exists + # one ore more open handles, return an error. The code in test_vfs.c + # will not invoke the xDelete method of the "real" VFS in this case. + # if {[info exists ::open_journals($f)]==0} { set ::open_journals($f) 0 } switch -- $method { - xOpen { - incr ::open_journals($f) +1 - } - xClose { - incr ::open_journals($f) -1 - } - xDelete { - if {$::open_journals($f)>0} { return SQLITE_IOERR } - } + xOpen { incr ::open_journals($f) +1 } + xClose { incr ::open_journals($f) -1 } + xDelete { if {$::open_journals($f)>0} { puts EEE;return SQLITE_IOERR } } } - return + return "" } @@ -112,10 +116,7 @@ do_test journal2-1.8 { } {} do_test journal2-1.9 { execsql { SELECT * FROM t1 } } {1 2 3 4 5 6} -# Grow the database until it is reasonably large. Then, from a -# journal_mode=DELETE connection, attempt to commit a large transaction (one -# that involves upgrading to an exclusive lock and writing the database -# before the transaction is committed). +# Grow the database until it is reasonably large. # do_test journal2-1.10 { db2 close @@ -137,6 +138,15 @@ do_test journal2-1.11 { expr {$sz>120 && $sz<200} } 1 +# Using new connection [db2] (with journal_mode=DELETE), write a lot of +# data to the database. So that many pages within the database file are +# modified before the transaction is committed. +# +# Then, enable simulated IO errors in all calls to xDelete, xWrite +# and xTruncate before committing the transaction and closing the +# database file. From the point of view of other file-system users, it +# appears as if the process hosting [db2] unexpectedly exited. +# do_test journal2-1.12 { sqlite3 db2 test.db execsql { @@ -181,8 +191,39 @@ do_test journal2-1.20 { do_test journal2-1.21 { db2 close } {} - db close + +#------------------------------------------------------------------------- +# Test that it is possible to switch from journal_mode=truncate to +# journal_mode=WAL on a SAFE_DELETE file-system. SQLite should close and +# delete the journal file when committing the transaction that switches +# the system to WAL mode. +# +ifcapable wal { + do_test journal2-2.1 { + faultsim_delete_and_reopen + set ::oplog [list] + execsql { PRAGMA journal_mode = persist } + set ::oplog + } {} + do_test journal2-2.2 { + execsql { + CREATE TABLE t1(x); + INSERT INTO t1 VALUES(3.14159); + } + set ::oplog + } {xOpen test.db-journal} + do_test journal2-2.3 { + expr {[file size test.db-journal] > 512} + } {1} + do_test journal2-2.3 { + set ::oplog [list] + execsql { PRAGMA journal_mode = WAL } + set ::oplog + } {xClose test.db-journal xDelete test.db-journal} + db close +} + tvfs delete finish_test diff --git a/test/jrnlmode.test b/test/jrnlmode.test index fd3e59f12d..2a6338fc9e 100644 --- a/test/jrnlmode.test +++ b/test/jrnlmode.test @@ -484,7 +484,7 @@ ifcapable pragma { INSERT INTO t4 VALUES(3, 4); } file exists test.db-journal - } {0} + } {1} do_test jrnlmode-6.7 { execsql { COMMIT; @@ -493,7 +493,7 @@ ifcapable pragma { } {1 2 3 4} do_test jrnlmode-6.8 { file exists test.db-journal - } {0} + } {1} do_test jrnlmode-6.9 { execsql { PRAGMA journal_mode = DELETE; diff --git a/test/tkt-fc62af4523.test b/test/tkt-fc62af4523.test new file mode 100644 index 0000000000..e35c8c485d --- /dev/null +++ b/test/tkt-fc62af4523.test @@ -0,0 +1,85 @@ +# 2010 June 16 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# This file implements regression tests for SQLite library. Specifically, +# it tests that ticket [fc62af4523] has been resolved. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +source $testdir/lock_common.tcl +source $testdir/malloc_common.tcl + +do_test tkt-fc62af4523.1 { + execsql { + PRAGMA cache_size = 10; + PRAGMA journal_mode = persist; + CREATE TABLE t1(a UNIQUE, b UNIQUE); + INSERT INTO t1 SELECT randomblob(200), randomblob(300); + INSERT INTO t1 SELECT randomblob(200), randomblob(300) FROM t1; -- 2 + INSERT INTO t1 SELECT randomblob(200), randomblob(300) FROM t1; -- 4 + INSERT INTO t1 SELECT randomblob(200), randomblob(300) FROM t1; -- 8 + INSERT INTO t1 SELECT randomblob(200), randomblob(300) FROM t1; -- 16 + INSERT INTO t1 SELECT randomblob(200), randomblob(300) FROM t1; -- 32 + INSERT INTO t1 SELECT randomblob(200), randomblob(300) FROM t1; -- 64 + } + execsql { + PRAGMA integrity_check; + SELECT count(*) FROM t1; + } +} {ok 64} + +# Launch an external process. Have it write (but not commit) a large +# transaction to the database. +# +set ::chan [launch_testfixture] +proc buddy {code} { testfixture $::chan $code } +do_test tkt-fc62af4523.2 { + testfixture $::chan { + sqlite3 db test.db + db eval { + PRAGMA cache_size = 10; + BEGIN; + UPDATE t1 SET b = randomblob(400); + UPDATE t1 SET a = randomblob(200); + } + } + file exists test.db-journal +} {1} + +# Now do "PRAGMA journal_mode = DELETE" in this process. At one point +# this was causing SQLite to delete the journal file from the file-system, +# even though the external process is currently using it. +# +do_test tkt-fc62af4523.3 { execsql { PRAGMA journal_mode = DELETE } } {delete} +do_test tkt-fc62af4523.4 { file exists test.db-journal } {1} + +# Cause the external process to crash. Since it has already written +# uncommitted data into the database file, the next reader will have +# to do a hot-journal rollback to recover the database. +# +# Or, if this test is run in a version with the bug present, the journal +# file has already been deleted. In this case we are left with a corrupt +# database file and no hot-journal to fix it with. +# +do_test tkt-fc62af4523.5 { + testfixture $::chan sqlite_abort +} {ERROR: Child process hung up} +after 200 +do_test tkt-fc62af4523.6 { + execsql { + PRAGMA integrity_check; + SELECT count(*) FROM t1; + } +} {ok 64} + +catch { close $::chan } +finish_test +