From: drh Date: Thu, 1 Jul 2010 19:45:34 +0000 (+0000) Subject: If you delete a database file but not its *-wal file, then open the database X-Git-Tag: version-3.7.2~209 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=32f29643907cf278c627fc5df1b884b6d524694d;p=thirdparty%2Fsqlite.git If you delete a database file but not its *-wal file, then open the database (thus creating a new empty database file) the *-wal file is automatically deleted. FossilOrigin-Name: 95c69dfbddaf4367cd699dfe8fcf8e06030c1f53 --- diff --git a/manifest b/manifest index 304145c057..eed809a962 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,8 @@ -C Add\stests\sto\spager1.test\sand\spagerfault.test. -D 2010-07-01T19:01:56 +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA1 + +C If\syou\sdelete\sa\sdatabase\sfile\sbut\snot\sits\s*-wal\sfile,\sthen\sopen\sthe\sdatabase\n(thus\screating\sa\snew\sempty\sdatabase\sfile)\sthe\s*-wal\sfile\sis\sautomatically\ndeleted. +D 2010-07-01T19:45:35 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 F Makefile.in a5cad1f8f3e021356bfcc6c77dc16f6f1952bbc3 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -156,7 +159,7 @@ F src/os_common.h a8f95b81eca8a1ab8593d23e94f8a35f35d4078f F src/os_os2.c 665876d5eec7585226b0a1cf5e18098de2b2da19 F src/os_unix.c ec7c7f7ca224ce2ff58736eebf804b48a75f9946 F src/os_win.c 48f67798969ba983487fed5691059ade7fff2ef7 -F src/pager.c 19975354882e9ac8d361bb3c1c434fd3aa9b0928 +F src/pager.c 2ce3612ab02a87b3c59c30bd412facc0bcc76ee9 F src/pager.h 879fdde5a102d2f21a3135d6f647530b21c2796c F src/parse.y ace5c7a125d9f2a410e431ee3209034105045f7e F src/pcache.c 1e9aa2dbc0845b52e1b51cc39753b6d1e041cb07 @@ -776,6 +779,7 @@ F test/vtab_shared.test 0eff9ce4f19facbe0a3e693f6c14b80711a4222d F test/wal.test 1891e6f72dd437a1c2a48091aa9182ba17a8f780 F test/wal2.test 9f2c2a00358b1466bc38feda85f105a4fb52f251 F test/wal3.test bb3bc0be06411c2d147c1d1d636b6208fbe0349d +F test/wal4.test 640be93f5422df37203aa5e7c06b24fb5e4a2439 F test/wal_common.tcl 875ee2118cd7b292ba22fb9bfa66a984b5226b13 F test/walbak.test e5632adde03fbb0533b9928a89468566ef78a710 F test/walcksum.test a37b36375c595e61bdb7e1ec49b5f0979b6fc7ce @@ -829,7 +833,14 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P a8f6341d3b12d64ef56ed05226e3b4f183b8957d -R b06840e637f43962c2afd5444d532e11 -U dan -Z fe3e1bcbb9bcaec1df9d747e7acac3b7 +P c6e75950928954fbb1590f952e3cdbcb0753b745 +R f7186a46c1dcd52609a2789564f69cd8 +U drh +Z 3a354030eb2816ac63480d6e68d82e49 +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.4.6 (GNU/Linux) + +iD8DBQFMLPBjoxKgR168RlERAqIFAJ9cSOQ6YZOm/Gu4IvyKKa1xG8xpCgCggbR1 +xxpDAqZSMt9gn5sgaTshVfc= +=eCFs +-----END PGP SIGNATURE----- diff --git a/manifest.uuid b/manifest.uuid index cdb996725e..79b10eed33 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c6e75950928954fbb1590f952e3cdbcb0753b745 \ No newline at end of file +95c69dfbddaf4367cd699dfe8fcf8e06030c1f53 \ No newline at end of file diff --git a/src/pager.c b/src/pager.c index b2e1487126..f7fcd61721 100644 --- a/src/pager.c +++ b/src/pager.c @@ -2414,12 +2414,19 @@ static int pagerBeginReadTransaction(Pager *pPager){ } /* -** Check if the *-wal file that corresponds to the database opened by pPager -** exists. Assuming no error occurs, set *pExists to 1 if the file exists, -** or 0 otherwise and return SQLITE_OK. If an IO or OOM error occurs, return +** Check for the existence of or delete the *-wal file that corresponds to +** the database opened by pPager. +** +** When pExists!=NULL, set *pExists to 1 if the *-wal file exists, or 0 +** if the *-wal file does not exist. +** +** When pExists==NULL, delete the *-wal file if it exists, or the do +** nothing if the *-wal file does not exist. +** +** Return SQLITE_OK on success. If on an IO or OOM error occurs, return ** an SQLite error code. */ -static int pagerHasWAL(Pager *pPager, int *pExists){ +static int pagerCheckForOrDeleteWAL(Pager *pPager, int *pExists){ int rc; /* Return code */ char *zWal; /* Name of the WAL file */ @@ -2428,7 +2435,11 @@ static int pagerHasWAL(Pager *pPager, int *pExists){ if( !zWal ){ rc = SQLITE_NOMEM; }else{ - rc = sqlite3OsAccess(pPager->pVfs, zWal, SQLITE_ACCESS_EXISTS, pExists); + if( pExists ){ + rc = sqlite3OsAccess(pPager->pVfs, zWal, SQLITE_ACCESS_EXISTS, pExists); + }else{ + rc = sqlite3OsDelete(pPager->pVfs, zWal, 0); + } sqlite3_free(zWal); } return rc; @@ -2436,22 +2447,38 @@ static int pagerHasWAL(Pager *pPager, int *pExists){ /* ** Check if the *-wal file that corresponds to the database opened by pPager -** exists. If it does, open the pager in WAL mode. Otherwise, if no error -** occurs, make sure Pager.journalMode is not set to PAGER_JOURNALMODE_WAL. -** If an IO or OOM error occurs, return an SQLite error code. +** exists if the database is not empy, or verify that the *-wal file does +** not exist (by deleting it) if the database file is empty. +** +** If the database is not empty and the *-wal file exists, open the pager +** in WAL mode. If the database is empty or if no *-wal file exists and +** if no error occurs, make sure Pager.journalMode is not set to +** PAGER_JOURNALMODE_WAL. +** +** Return SQLITE_OK or an error code. ** ** If the WAL file is opened, also open a snapshot (read transaction). ** ** The caller must hold a SHARED lock on the database file to call this ** function. Because an EXCLUSIVE lock on the db file is required to delete -** a WAL, this ensures there is no race condition between the xAccess() -** below and an xDelete() being executed by some other connection. +** a WAL on a none-empty database, this ensures there is no race condition +** between the xAccess() below and an xDelete() being executed by some +** other connection. */ static int pagerOpenWalIfPresent(Pager *pPager){ int rc = SQLITE_OK; if( !pPager->tempFile ){ int isWal; /* True if WAL file exists */ - rc = pagerHasWAL(pPager, &isWal); + int nPage; /* Size of the database file */ + assert( pPager->state>=SHARED_LOCK ); + rc = sqlite3PagerPagecount(pPager, &nPage); + if( rc ) return rc; + if( nPage==0 ){ + rc = pagerCheckForOrDeleteWAL(pPager, 0); + isWal = 0; + }else{ + rc = pagerCheckForOrDeleteWAL(pPager, &isWal); + } if( rc==SQLITE_OK ){ if( isWal ){ pager_reset(pPager); @@ -6071,7 +6098,7 @@ int sqlite3PagerCloseWal(Pager *pPager){ int logexists = 0; rc = sqlite3OsLock(pPager->fd, SQLITE_LOCK_SHARED); if( rc==SQLITE_OK ){ - rc = pagerHasWAL(pPager, &logexists); + rc = pagerCheckForOrDeleteWAL(pPager, &logexists); } if( rc==SQLITE_OK && logexists ){ rc = sqlite3WalOpen(pPager->pVfs, pPager->fd, diff --git a/test/wal4.test b/test/wal4.test new file mode 100644 index 0000000000..c255182cc2 --- /dev/null +++ b/test/wal4.test @@ -0,0 +1,52 @@ +# 2010 July 1 +# +# 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. +# +#*********************************************************************** +# Verify that an empty database and a non-empty WAL file do not +# result in database corruption +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +source $testdir/malloc_common.tcl +ifcapable !wal {finish_test ; return } + +do_test wal4-1.1 { + db close + file delete -force wal4.db wal4.db-journal wal4.db-wal wal4.db-shm + file delete -force test.db test.db-journal test.db-wal test.db-shm + sqlite3 db2 wal4.db + db2 eval { + PRAGMA journal_mode=WAL; + CREATE TABLE t1(x); + INSERT INTO t1 VALUES(1); + INSERT INTO t1 VALUES(2); + SELECT x FROM t1 ORDER BY x; + } +} {wal 1 2} +do_test wal4-1.2 { + file delete -force test.db test.db-journal test.db-wal + file copy wal4.db-wal test.db-wal + sqlite3 db test.db + catchsql { + SELECT * FROM t1; + } +} {1 {no such table: t1}} + +do_malloc_test wal4-2.0 -tclprep { + db close + file delete -force test.db test.db-journal test.db-wal + file copy wal4.db-wal test.db-wal + sqlite3 db test.db +} -sqlbody { + SELECT name FROM sqlite_master +} + + +finish_test