diff --git a/ext/rbu/rbufault3.test b/ext/rbu/rbufault3.test new file mode 100644 index 0000000000..e72eb14f7d --- /dev/null +++ b/ext/rbu/rbufault3.test @@ -0,0 +1,98 @@ +# 2016 April 20 +# +# 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 contains fault injection tests for RBU vacuum operations. +# + +source [file join [file dirname [info script]] rbu_common.tcl] +source $testdir/malloc_common.tcl +set ::testprefix rbufault3 + +foreach {fault errlist} { + oom-* { + {1 SQLITE_NOMEM} + {1 SQLITE_IOERR_NOMEM} + {1 {SQLITE_NOMEM - out of memory}} + } + + ioerr-* { + {1 {SQLITE_IOERR - disk I/O error}} + {1 SQLITE_IOERR} + {1 SQLITE_IOERR_WRITE} + {1 SQLITE_IOERR_FSYNC} + {1 SQLITE_IOERR_READ} + {1 {SQLITE_IOERR - unable to open database: test.db2}} + {1 {SQLITE_ERROR - unable to open database: test.db2}} + {1 {SQLITE_ERROR - SQL logic error or missing database}} + } + + cantopen* { + {1 {SQLITE_CANTOPEN - unable to open database: test.db2}} + {1 {SQLITE_CANTOPEN - unable to open database: test.db2}} + {1 {SQLITE_CANTOPEN - unable to open database file}} + {1 SQLITE_CANTOPEN} + } + +} { + + reset_db + do_execsql_test 0 { + CREATE TABLE target(x UNIQUE, y, z, PRIMARY KEY(y)); + INSERT INTO target VALUES(1, 2, 3); + INSERT INTO target VALUES(4, 5, 6); + INSERT INTO target VALUES(7, 8, 9); + CREATE INDEX i1 ON target(z); + } + faultsim_save_and_close + + do_faultsim_test 1 -faults $fault -prep { + faultsim_restore_and_reopen + forcedelete test.db2 + } -body { + sqlite3rbu_vacuum rbu test.db test.db2 + while {[rbu step]=="SQLITE_OK"} {} + rbu close + } -test { + eval [list faultsim_test_result {0 SQLITE_DONE} {*}$::errlist] + } + + do_faultsim_test 2 -faults $fault -prep { + faultsim_restore_and_reopen + forcedelete test.db2 + } -body { + sqlite3rbu_vacuum rbu test.db test.db2 + rbu step + rbu close + } -test { + eval [list faultsim_test_result {0 SQLITE_OK} {*}$::errlist] + } + + forcedelete test.db2 + sqlite3rbu_vacuum rbu test.db test.db2 + rbu step + rbu close + faultsim_save_and_close + + do_faultsim_test 3 -faults $fault -prep { + faultsim_restore_and_reopen + forcedelete test.db2 + } -body { + sqlite3rbu_vacuum rbu test.db test.db2 + rbu step + rbu close + } -test { + eval [list faultsim_test_result {0 SQLITE_OK} {*}$::errlist] + } + +} + +finish_test + diff --git a/ext/rbu/sqlite3rbu.c b/ext/rbu/sqlite3rbu.c index 8c7682abea..8a1b06dd62 100644 --- a/ext/rbu/sqlite3rbu.c +++ b/ext/rbu/sqlite3rbu.c @@ -2339,7 +2339,7 @@ static void rbuOpenDatabase(sqlite3rbu *p){ /* Open the RBU database */ p->dbRbu = rbuOpenDbhandle(p, p->zRbu, 1); - if( rbuIsVacuum(p) ){ + if( p->rc==SQLITE_OK && rbuIsVacuum(p) ){ sqlite3_file_control(p->dbRbu, "main", SQLITE_FCNTL_RBUCNT, (void*)p); } @@ -2355,11 +2355,13 @@ static void rbuOpenDatabase(sqlite3rbu *p){ /* If it has not already been created, create the rbu_state table */ rbuMPrintfExec(p, p->dbRbu, RBU_CREATE_STATE, p->zStateDb); - if( rbuIsVacuum(p) ){ + if( p->rc==SQLITE_OK && rbuIsVacuum(p) ){ int bOpen = 0; + int rc; p->nRbu = 0; p->pRbuFd = 0; - sqlite3_file_control(p->dbRbu, "main", SQLITE_FCNTL_RBUCNT, (void*)p); + rc = sqlite3_file_control(p->dbRbu, "main", SQLITE_FCNTL_RBUCNT, (void*)p); + if( rc!=SQLITE_NOTFOUND ) p->rc = rc; if( p->eStage>=RBU_STAGE_MOVE ){ bOpen = 1; }else{ @@ -3411,6 +3413,9 @@ static void rbuCreateTargetSchema(sqlite3rbu *p){ sqlite3_step(pInsert); p->rc = sqlite3_reset(pInsert); } + if( p->rc==SQLITE_OK ){ + p->rc = sqlite3_exec(p->dbMain, "PRAGMA writable_schema=0",0,0,&p->zErrmsg); + } rbuFinalize(p, pSql); rbuFinalize(p, pInsert); @@ -3511,7 +3516,9 @@ static sqlite3rbu *openRbuHandle( /* Open transactions both databases. The *-oal file is opened or ** created at this point. */ - p->rc = sqlite3_exec(db, "BEGIN IMMEDIATE", 0, 0, &p->zErrmsg); + if( p->rc==SQLITE_OK ){ + p->rc = sqlite3_exec(db, "BEGIN IMMEDIATE", 0, 0, &p->zErrmsg); + } if( p->rc==SQLITE_OK ){ p->rc = sqlite3_exec(p->dbRbu, "BEGIN", 0, 0, &p->zErrmsg); } @@ -3528,7 +3535,7 @@ static sqlite3rbu *openRbuHandle( /* If this is an RBU vacuum operation and the state table was empty ** when this handle was opened, create the target database schema. */ - if( pState->eStage==0 && rbuIsVacuum(p) ){ + if( p->rc==SQLITE_OK && pState->eStage==0 && rbuIsVacuum(p) ){ rbuCreateTargetSchema(p); rbuCopyPragma(p, "user_version"); rbuCopyPragma(p, "application_id"); @@ -3895,7 +3902,7 @@ static int rbuVfsRead( if( pRbu && rbuIsVacuum(pRbu) && rc==SQLITE_IOERR_SHORT_READ && iOfst==0 && (p->openFlags & SQLITE_OPEN_MAIN_DB) - && pRbu->pRbuFd->base.pMethods + && pRbu->rc==SQLITE_OK ){ sqlite3_file *pFd = (sqlite3_file*)pRbu->pRbuFd; rc = pFd->pMethods->xRead(pFd, zBuf, iAmt, iOfst); diff --git a/manifest b/manifest index d233334b3c..e640d710d0 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Updates\sto\sensure\sthe\svalues\sof\sPRAGMA\ssettings\slike\s"page_size",\s"auto_vacuum",\s"user_version"\sand\s"application_id"\sare\snot\slost\swhen\sa\sdatabase\sis\sRBU\svacuumed. -D 2016-04-19T19:27:09.289 +C Add\sfault\sinjection\stests\sfor\srbu\svacuum.\sFix\ssome\sproblems\srevealed\sby\sthe\ssame. +D 2016-04-20T17:47:52.967 F Makefile.in eba680121821b8a60940a81454316f47a341487a F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 71b8b16cf9393f68e2e2035486ca104872558836 @@ -243,11 +243,12 @@ F ext/rbu/rbucrash.test 8d2ed5d4b05fef6c00c2a6b5f7ead71fa172a695 F ext/rbu/rbudiff.test 2df0a8a7d998ecf81764c21eeda3cde5611c5091 F ext/rbu/rbufault.test cc0be8d5d392d98b0c2d6a51be377ea989250a89 F ext/rbu/rbufault2.test 9a7f19edd6ea35c4c9f807d8a3db0a03a5670c06 +F ext/rbu/rbufault3.test 54a399888ac4af44c68f9f58afbed23149428bca F ext/rbu/rbufts.test 828cd689da825f0a7b7c53ffc1f6f7fdb6fa5bda F ext/rbu/rbuprogress.test 2023a7df2c523e3df1cb532eff811cda385a789a F ext/rbu/rbusave.test 0f43b6686084f426ddd040b878426452fd2c2f48 F ext/rbu/rbuvacuum.test ecd7ce1cd8528d6230b56f4840bbb7188cee6946 -F ext/rbu/sqlite3rbu.c a6c02a67834f9e6c2adb18a9191aa0ae65057cfb +F ext/rbu/sqlite3rbu.c cc44505ef06053077f35b08c4ba11dc8bcf310dc F ext/rbu/sqlite3rbu.h 1342ab6121e715b8da59ec35c5b5c16060be7a6b F ext/rbu/test_rbu.c 430b8b9520c233505371d564d3561e0b554355f4 F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 @@ -1483,7 +1484,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P ca021ba88106500f347ed65199a4832bc9eb5ef8 -R 8122ed3aabc11f4475527c60a5badfa5 +P 74ffea76b8c9ddd7699ce6ca77dce005bd7922ac +R f86f4403b5c8adf842292353673eca81 U dan -Z 8cbed13b6f72dec5a4cc65417abbee63 +Z 6e60b344cf662b4bf49e9c442360b79f diff --git a/manifest.uuid b/manifest.uuid index 590abb9da7..ce2dab7023 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -74ffea76b8c9ddd7699ce6ca77dce005bd7922ac \ No newline at end of file +f042fdd1ea7febec7228e51efc2b0281805e196a \ No newline at end of file