diff --git a/manifest b/manifest index c85376b665..5a1ef56a4d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Increase\sthe\smaximum\spage\ssize\sfrom\s32k\sto\s64k. -D 2010-08-12T02:41:12 +C Add\scoverage\stests\sfor\spager.c. +D 2010-08-12T11:25:48 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in ec08dc838fd8110fe24c92e5130bcd91cbb1ff2e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -156,7 +156,7 @@ F src/os_common.h a8f95b81eca8a1ab8593d23e94f8a35f35d4078f F src/os_os2.c 72d0b2e562952a2464308c4ce5f7913ac10bef3e F src/os_unix.c 11194cbcf6a57456e58022dc537ab8c3497d9bb9 F src/os_win.c 51cb62f76262d961ea4249489383d714501315a7 -F src/pager.c 39be42c3234a4ea51ddf185a47a91f31a0439fd1 +F src/pager.c ff51a76c802c51dc5b36645a2d9202d2a9462897 F src/pager.h 985a83d35b0cfa8e1c23ef91ed5cdb9bde73695a F src/parse.y 12b7ebd61ea54f0e1b1083ff69cc2c8ce9353d58 F src/pcache.c 1e9aa2dbc0845b52e1b51cc39753b6d1e041cb07 @@ -222,7 +222,7 @@ F src/vdbe.c 66c262a923915e596379b1d597178e04c5d719e4 F src/vdbe.h 4de0efb4b0fdaaa900cf419b35c458933ef1c6d2 F src/vdbeInt.h ffd68c4d4229227a5089bec53a1c635146177abc F src/vdbeapi.c d0f4407e465f261780ad725c1caece7d66a6aa35 -F src/vdbeaux.c e18a42d0bdac405565f2d258a82457fd10db133d +F src/vdbeaux.c c73bcefcebfd3d2cf91bf6a41ef0fb0d884814c6 F src/vdbeblob.c 258a6010ba7a82b72b327fb24c55790655689256 F src/vdbemem.c e5673f81a2381b35c60e73ef0a8502be2ab1041e F src/vdbetrace.c 864cef96919323482ebd9986f2132435115e9cc2 @@ -489,7 +489,7 @@ F test/lock4.test c82268c031d39345d05efa672f80b025481b3ae5 F test/lock5.test b2abb5e711bc59b0eae00f6c97a36ec9f458fada F test/lock6.test 8df56060f396151777390982422c800d026e1722 F test/lock7.test 64006c84c1c616657e237c7ad6532b765611cf64 -F test/lock_common.tcl e7013c6208f5fa818735c324eb0249b4c0f317cf +F test/lock_common.tcl 57727421a6a850443944cbadfdf5a6dd9e4ac81c F test/lookaside.test 382e7bc2fab23d902c8eafb1b9ed7ababfff75a6 F test/main.test 9d7bbfcc1b52c88ba7b2ba6554068ecf9939f252 F test/make-where7.tcl 05c16b5d4f5d6512881dfec560cb793915932ef9 @@ -539,10 +539,10 @@ F test/notify3.test d60923e186e0900f4812a845fcdfd8eea096e33a F test/notnull.test cc7c78340328e6112a13c3e311a9ab3127114347 F test/null.test a8b09b8ed87852742343b33441a9240022108993 F test/openv2.test af02ed0a9cbc0d2a61b8f35171d4d117e588e4ec -F test/pager1.test 9a7650f95bc84ef2fa4c2db87f9676d2641f9829 -F test/pager2.test 9edc1584cbc8ecd3b34dbcc8e86467bf05caa27f +F test/pager1.test 8b6e57d8cdf4c9f5c31ddcd048e81b026b225f0c +F test/pager2.test 0fbb6b6dc40ce1fecfe758c555a748ad2e9beaa3 F test/pager3.test 3856d9c80839be0668efee1b74811b1b7f7fc95f -F test/pagerfault.test 495ab0a0ed30aebe7e4278fcee148986085d4c8b +F test/pagerfault.test c08abb54b591ba704c913af9278428fa3cce42d5 F test/pagerfault2.test 1f79ea40d1133b2683a2f811b00f2399f7ec2401 F test/pageropt.test 8146bf448cf09e87bb1867c2217b921fb5857806 F test/pagesize.test 76aa9f23ecb0741a4ed9d2e16c5fa82671f28efb @@ -843,7 +843,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 2fa05d01b6b11788a5b73d203fcac9d4a4ba9fd8 -R 68189c2924cc1a955c4daa7396f7f071 -U drh -Z ea2561c5cb1a509ae1c92e5b10fbf288 +P 45362437d491fbe0f033a67b398f8ba68cbf1b3b +R 38d53c0088d37a8bc9ce3834465ac451 +U dan +Z ebb8f906eccfa5df91e15cf73afafb56 diff --git a/manifest.uuid b/manifest.uuid index fe0d59964d..c33d8e70ba 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -45362437d491fbe0f033a67b398f8ba68cbf1b3b \ No newline at end of file +228c5b16af80c22e97d9d4deb351e0d3f4523f89 \ No newline at end of file diff --git a/src/pager.c b/src/pager.c index 12f45b5c18..3a7afd17cf 100644 --- a/src/pager.c +++ b/src/pager.c @@ -4126,7 +4126,7 @@ static int pagerStress(void *p, PgHdr *pPg){ sqlite3PcacheMakeClean(pPg); } - return pager_error(pPager, rc); + return pager_error(pPager, rc); } @@ -5701,9 +5701,6 @@ int sqlite3PagerCommitPhaseOne( ** that it took at the start of the transaction. Otherwise, the ** calls to sqlite3PagerGet() return zeroed pages instead of ** reading data from the database file. - ** - ** When journal_mode==OFF the dbOrigSize is always zero, so this - ** block never runs if journal_mode=OFF. */ #ifndef SQLITE_OMIT_AUTOVACUUM if( pPager->dbSizedbOrigSize @@ -6425,6 +6422,7 @@ int sqlite3PagerSetJournalMode(Pager *pPager, int eMode){ }else{ int rc = SQLITE_OK; int state = pPager->eState; + assert( state==PAGER_OPEN || state==PAGER_READER ); if( state==PAGER_OPEN ){ rc = sqlite3PagerSharedLock(pPager); } diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 7729a85d45..5a4ad84975 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -2061,8 +2061,17 @@ int sqlite3VdbeHalt(Vdbe *p){ isSpecialError = mrc==SQLITE_NOMEM || mrc==SQLITE_IOERR || mrc==SQLITE_INTERRUPT || mrc==SQLITE_FULL; if( isSpecialError ){ - /* If the query was read-only, we need do no rollback at all. Otherwise, - ** proceed with the special handling. + /* If the query was read-only and the error code is SQLITE_INTERRUPT, + ** no rollback is necessary. Otherwise, at least a savepoint + ** transaction must be rolled back to restore the database to a + ** consistent state. + ** + ** Even if the statement is read-only, it is important to perform + ** a statement or transaction rollback operation. If the error + ** occured while writing to the journal, sub-journal or database + ** file as part of an effort to free up cache space (see function + ** pagerStress() in pager.c), the rollback is required to restore + ** the pager to a consistent state. */ if( !p->readOnly || mrc!=SQLITE_INTERRUPT ){ if( (mrc==SQLITE_NOMEM || mrc==SQLITE_FULL) && p->usesStmtJournal ){ diff --git a/test/lock_common.tcl b/test/lock_common.tcl index 4fe08e0882..b2ff76fdb2 100644 --- a/test/lock_common.tcl +++ b/test/lock_common.tcl @@ -27,6 +27,8 @@ proc do_multiclient_test {varname script} { set tn 2 }] { faultsim_delete_and_reopen + + proc code1 {tcl} { uplevel #0 $tcl } # Open connections [db2] and [db3]. Depending on which iteration this # is, the connections may be created in this interpreter, or in diff --git a/test/pager1.test b/test/pager1.test index 9ddc6987cb..e469caf3d2 100644 --- a/test/pager1.test +++ b/test/pager1.test @@ -15,7 +15,7 @@ source $testdir/tester.tcl source $testdir/lock_common.tcl source $testdir/malloc_common.tcl source $testdir/wal_common.tcl - + # Do not use a codec for tests in this file, as the database file is # manipulated directly using tcl scripts (using the [hexio_write] command). # @@ -2273,4 +2273,60 @@ do_multiclient_test tn { sql1 { INSERT INTO t1 VALUES('c', 'd'); COMMIT } } {} } + +#------------------------------------------------------------------------- +# Normally, when changing from journal_mode=PERSIST to DELETE the pager +# attempts to delete the journal file. However, if it cannot obtain a +# RESERVED lock on the database file, this step is skipped. +# +do_multiclient_test tn { + do_test pager1-28.$tn.1 { + sql1 { + PRAGMA journal_mode = PERSIST; + CREATE TABLE t1(a, b); + INSERT INTO t1 VALUES('a', 'b'); + } + } {persist} + do_test pager1-28.$tn.2 { file exists test.db-journal } 1 + do_test pager1-28.$tn.3 { sql1 { PRAGMA journal_mode = DELETE } } delete + do_test pager1-28.$tn.4 { file exists test.db-journal } 0 + + do_test pager1-28.$tn.5 { + sql1 { + PRAGMA journal_mode = PERSIST; + INSERT INTO t1 VALUES('c', 'd'); + } + } {persist} + do_test pager1-28.$tn.6 { file exists test.db-journal } 1 + do_test pager1-28.$tn.7 { + sql2 { BEGIN; INSERT INTO t1 VALUES('e', 'f'); } + } {} + do_test pager1-28.$tn.8 { file exists test.db-journal } 1 + do_test pager1-28.$tn.9 { sql1 { PRAGMA journal_mode = DELETE } } delete + do_test pager1-28.$tn.10 { file exists test.db-journal } 1 + + do_test pager1-28.$tn.11 { sql2 COMMIT } {} + do_test pager1-28.$tn.12 { file exists test.db-journal } 0 + + do_test pager1-28-$tn.13 { + code1 { set channel [db incrblob -readonly t1 a 2] } + sql1 { + PRAGMA journal_mode = PERSIST; + INSERT INTO t1 VALUES('g', 'h'); + } + } {persist} + do_test pager1-28.$tn.14 { file exists test.db-journal } 1 + do_test pager1-28.$tn.15 { + sql2 { BEGIN; INSERT INTO t1 VALUES('e', 'f'); } + } {} + do_test pager1-28.$tn.16 { sql1 { PRAGMA journal_mode = DELETE } } delete + do_test pager1-28.$tn.17 { file exists test.db-journal } 1 + + do_test pager1-28.$tn.17 { csql2 { COMMIT } } {1 {database is locked}} + do_test pager1-28-$tn.18 { code1 { read $channel } } c + do_test pager1-28-$tn.19 { code1 { close $channel } } {} + do_test pager1-28.$tn.20 { sql2 { COMMIT } } {} +} + + finish_test diff --git a/test/pager2.test b/test/pager2.test index 780aec5274..06389f5d9f 100644 --- a/test/pager2.test +++ b/test/pager2.test @@ -118,9 +118,11 @@ tv delete #------------------------------------------------------------------------- -# Test a ROLLBACK with journal_mode=off. # -breakpoint +# pager2-2.1: Test a ROLLBACK with journal_mode=off. +# pager2-2.2: Test shrinking the database (auto-vacuum) with +# journal_mode=off +# do_test pager2-2.1 { faultsim_delete_and_reopen execsql { @@ -132,5 +134,18 @@ do_test pager2-2.1 { SELECT * FROM t1; } } {off 1 2} +do_test pager2-2.2 { + faultsim_delete_and_reopen + execsql { + PRAGMA auto_vacuum = incremental; + PRAGMA page_size = 1024; + PRAGMA journal_mode = off; + CREATE TABLE t1(a, b); + INSERT INTO t1 VALUES(zeroblob(5000), zeroblob(5000)); + DELETE FROM t1; + PRAGMA incremental_vacuum; + } + file size test.db +} {3072} finish_test diff --git a/test/pagerfault.test b/test/pagerfault.test index 363bc3b7fa..521e76b727 100644 --- a/test/pagerfault.test +++ b/test/pagerfault.test @@ -28,6 +28,8 @@ proc a_string {n} { } db func a_string a_string +if 1 { + #------------------------------------------------------------------------- # Test fault-injection while rolling back a hot-journal file. # @@ -1117,11 +1119,54 @@ do_faultsim_test pagerfault-24 -prep { } -body { execsql { CREATE TEMP TABLE t1(a, b) } } -test { - faultsim_test_result {0 {}} {1 {unable to open a temporary database file for storing temporary tables}} + faultsim_test_result {0 {}} \ + {1 {unable to open a temporary database file for storing temporary tables}} set ic [db eval { PRAGMA temp.integrity_check }] if {$ic != "ok"} { error "Integrity check: $ic" } } +} + +proc lockrows {n} { + if {$n==0} { return "" } + db eval { SELECT * FROM t1 WHERE oid = $n } { + return [lockrows [expr {$n-1}]] + } +} + +do_test pagerfault-25-pre1 { + faultsim_delete_and_reopen + db func a_string a_string + execsql { + PRAGMA page_size = 1024; + PRAGMA auto_vacuum = 0; + CREATE TABLE t1(a); + INSERT INTO t1 VALUES(a_string(500)); + INSERT INTO t1 SELECT a_string(500) FROM t1; + INSERT INTO t1 SELECT a_string(500) FROM t1; + INSERT INTO t1 SELECT a_string(500) FROM t1; + INSERT INTO t1 SELECT a_string(500) FROM t1; + INSERT INTO t1 SELECT a_string(500) FROM t1; + } + faultsim_save_and_close +} {} +do_faultsim_test pagerfault-25 -faults full -prep { + faultsim_restore_and_reopen + db func a_string a_string + set ::channel [db incrblob -readonly t1 a 1] + execsql { + PRAGMA cache_size = 10; + BEGIN; + INSERT INTO t1 VALUES(a_string(3000)); + INSERT INTO t1 VALUES(a_string(3000)); + } +} -body { + lockrows 30 +} -test { + catch { lockrows 30 } + close $::channel + faultsim_test_result {0 {}} +} finish_test