-C Adjust\sthe\sprevious\scheck-in,\swhich\smodified\sthe\sWin32\sVFS,\sso\sthat\sit\sworks\swith\sSQLITE_OMIT_WAL.
-D 2018-02-05T21:02:47.090
+C When\sthe\sfinal\sconnection\sdisconnects\sfrom\sa\swal\smode\sdatabase,\scheck\sthat\sthe\ndatabase\sfile\shas\snot\sbeen\smoved\sor\sunlinked\sbefore\sdeleting\sthe\swal\sand\sshm\nfiles.
+D 2018-02-07T16:14:41.573
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F Makefile.in 7a3f714b4fcf793108042b7b0a5c720b0b310ec84314d61ba7f3f49f27e550ea
F src/os_unix.c ce491421b3a54b63094a155eeac668a3bc8e5b86a5a58551d906e5b5affb443f
F src/os_win.c eb03c6d52f893bcd7fdd4c6006674c13c1b5e49543fec98d605201af2997171c
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
-F src/pager.c cd194a8793ce061e184ddc369fadbc1020c6f431014d22093f6c5e55c9234033
+F src/pager.c a3834a40acc2f3ab247d846f850d8c9313587d9c99c57a4dc194f2d4d7bf9d15
F src/pager.h 581698f2177e8bd4008fe4760898ce20b6133d1df22139b9101b5155f900df7a
F src/parse.y 4e750e1b261ff9f1d0b6b5d40a829c66d691899f48953fde839d8b52d41aa148
F src/pcache.c 7ae91a4557a43d77d449accbfdc68846e6516f8e2eda46e8bbe4536fb669b201
F test/mutex1.test ea2cc74d97f077b9e74c84cbd024f14d79a8126f
F test/mutex2.test bfeaeac2e73095b2ac32285d2756e3a65e681660
F test/nan.test 437d40e6d0778b050d7750726c0cbd2c9936b81962926e8f8c48ca698f00f4d1
-F test/nockpt.test 9a436a7213ba5ef7a32304998d386d3ea3f76c9d
+F test/nockpt.test d291d618c934a453683cb2eff95f633d406f7147fa0403e10055db19dcc3842a
F test/nolock.test f196cf8b8fbea4e2ca345140a2b3f3b0da45c76e
F test/normalize.test 501630ab49b0b26b65c74124bf03e3374c1b57fa97aae750f84803609141d167
F test/notify1.test 669b2b743618efdc18ca4b02f45423d5d2304abf
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 535ed0ac5e8728ec91fc0a4cb54b820923d161cfd4e0e6aed6df6cdae365bc7d
-R 610345e12e18345d79d861c16dfe01d9
-U mistachkin
-Z 7a54a037e46133481e56c9143fb3122e
+P 36c2e67e82626f8d0a187c6c286c133ed659889e3b577469261b9dcd3b3ab75b
+R ed31a2562d55c76884009a210d222cf0
+U dan
+Z 0e612251c296ff4ce7a47fbd872de74d
-36c2e67e82626f8d0a187c6c286c133ed659889e3b577469261b9dcd3b3ab75b
\ No newline at end of file
+4761db83b6d3d57f281370899403c102e39ad0021d315dd6a6912d250436782a
\ No newline at end of file
}
}
+/* Verify that the database file has not be deleted or renamed out from
+** under the pager. Return SQLITE_OK if the database is still were it ought
+** to be on disk. Return non-zero (SQLITE_READONLY_DBMOVED or some other error
+** code from sqlite3OsAccess()) if the database has gone missing.
+*/
+static int databaseIsUnmoved(Pager *pPager){
+ int bHasMoved = 0;
+ int rc;
+
+ if( pPager->tempFile ) return SQLITE_OK;
+ if( pPager->dbSize==0 ) return SQLITE_OK;
+ assert( pPager->zFilename && pPager->zFilename[0] );
+ rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_HAS_MOVED, &bHasMoved);
+ if( rc==SQLITE_NOTFOUND ){
+ /* If the HAS_MOVED file-control is unimplemented, assume that the file
+ ** has not been moved. That is the historical behavior of SQLite: prior to
+ ** version 3.8.3, it never checked */
+ rc = SQLITE_OK;
+ }else if( rc==SQLITE_OK && bHasMoved ){
+ rc = SQLITE_READONLY_DBMOVED;
+ }
+ return rc;
+}
+
/*
** Shutdown the page cache. Free all memory and close all files.
** to the caller.
*/
int sqlite3PagerClose(Pager *pPager, sqlite3 *db){
- u8 *pTmp = (u8 *)pPager->pTmpSpace;
-
+ u8 *pTmp = (u8*)pPager->pTmpSpace;
assert( db || pagerUseWal(pPager)==0 );
assert( assert_pager_state(pPager) );
disable_simulated_io_errors();
/* pPager->errCode = 0; */
pPager->exclusiveMode = 0;
#ifndef SQLITE_OMIT_WAL
- assert( db || pPager->pWal==0 );
- sqlite3WalClose(pPager->pWal, db, pPager->walSyncFlags, pPager->pageSize,
- (db && (db->flags & SQLITE_NoCkptOnClose) ? 0 : pTmp)
- );
- pPager->pWal = 0;
+ {
+ u8 *a = 0;
+ assert( db || pPager->pWal==0 );
+ if( db && 0==(db->flags & SQLITE_NoCkptOnClose)
+ && SQLITE_OK==databaseIsUnmoved(pPager)
+ ){
+ a = pTmp;
+ }
+ sqlite3WalClose(pPager->pWal, db, pPager->walSyncFlags, pPager->pageSize,a);
+ pPager->pWal = 0;
+ }
#endif
pager_reset(pPager);
if( MEMDB ){
}
-/* Verify that the database file has not be deleted or renamed out from
-** under the pager. Return SQLITE_OK if the database is still were it ought
-** to be on disk. Return non-zero (SQLITE_READONLY_DBMOVED or some other error
-** code from sqlite3OsAccess()) if the database has gone missing.
-*/
-static int databaseIsUnmoved(Pager *pPager){
- int bHasMoved = 0;
- int rc;
-
- if( pPager->tempFile ) return SQLITE_OK;
- if( pPager->dbSize==0 ) return SQLITE_OK;
- assert( pPager->zFilename && pPager->zFilename[0] );
- rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_HAS_MOVED, &bHasMoved);
- if( rc==SQLITE_NOTFOUND ){
- /* If the HAS_MOVED file-control is unimplemented, assume that the file
- ** has not been moved. That is the historical behavior of SQLite: prior to
- ** version 3.8.3, it never checked */
- rc = SQLITE_OK;
- }else if( rc==SQLITE_OK && bHasMoved ){
- rc = SQLITE_READONLY_DBMOVED;
- }
- return rc;
-}
-
/*
** This function is called after transitioning from PAGER_UNLOCK to
do_execsql_test 1.14 { PRAGMA main.journal_mode = delete } {delete}
do_test 1.15 { file exists test.db-wal } {0}
+#-------------------------------------------------------------------------
+# Test an unusual scenario:
+#
+# 1. A wal mode db is opened and written. Then sqlite3_close_v2() used
+# to close the db handle while there is still an unfinalized
+# statement (so the db handle stays open).
+#
+# 2. The db, wal and *-shm files are deleted from the file system.
+#
+# 3. Another connection creates a new wal mode db at the same file-system
+# location as the previous one.
+#
+# 4. The statement left unfinalized in (1) is finalized.
+#
+# The test is to ensure that the connection left open in step (1) does
+# not try to delete the wal file from the file-system as part of step
+# 4.
+#
+reset_db
+db close
+
+# Open a connection on a wal database. Write to it a bit. Then prepare
+# a statement and call sqlite3_close_v2() (so that the statement handle
+# holds the db connection open).
+#
+set ::db1 [sqlite3_open_v2 test.db SQLITE_OPEN_READWRITE ""]
+do_test 2.0 {
+ lindex [
+ sqlite3_exec $::db1 {
+ PRAGMA journal_mode = wal;
+ CREATE TABLE t1(x PRIMARY KEY, y UNIQUE, z);
+ INSERT INTO t1 VALUES(1, 2, 3);
+ PRAGMA wal_checkpoint;
+ }] 0
+} {0}
+set ::stmt [sqlite3_prepare $::db1 "SELECT * FROM t1" -1 dummy]
+sqlite3_close_v2 $::db1
+
+# Delete the database, wal and shm files.
+#
+forcedelete test.db test.db-wal test.db-shm
+
+# Open and populate a new database file at the same file-system location
+# as the one just deleted. Contrive a partial checkpoint on it.
+#
+sqlite3 db test.db
+sqlite3 db2 test.db
+do_execsql_test 2.1 {
+ PRAGMA journal_mode = wal;
+ CREATE TABLE y1(a PRIMARY KEY, b UNIQUE, c);
+ INSERT INTO y1 VALUES('a', 'b', 'c');
+ INSERT INTO y1 VALUES('d', 'e', 'f');
+} {wal}
+do_execsql_test -db db2 2.2 {
+ BEGIN;
+ SELECT * FROM y1;
+} {a b c d e f}
+do_execsql_test 2.3 {
+ UPDATE y1 SET c='g' WHERE a='d';
+ PRAGMA wal_checkpoint;
+} {0 11 10}
+do_execsql_test -db db2 2.4 {
+ COMMIT
+}
+
+# Finalize the statement handle, causing the first connection to be
+# closed. Test that this has not corrupted the database file by
+# deleting the new wal file from the file-system. If it has, this
+# test should fail with an IO or corruption error.
+#
+do_test 2.5 {
+ sqlite3_finalize $::stmt
+ sqlite3 db3 test.db
+ execsql {
+ PRAGMA integrity_check;
+ SELECT * FROM y1;
+ } db3
+} {ok a b c d e g}
finish_test