]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fixes for OOM and IO error handling with temp file databases.
authordan <dan@noemail.net>
Mon, 11 Apr 2016 18:07:47 +0000 (18:07 +0000)
committerdan <dan@noemail.net>
Mon, 11 Apr 2016 18:07:47 +0000 (18:07 +0000)
FossilOrigin-Name: 4eb06e843af60d5e533793618c6e0e9b7ef7a1a6

manifest
manifest.uuid
src/pager.c
test/cffault.test
test/tempfault.test [new file with mode: 0644]

index 2cc562547468868e7cd111fbc1ad6777b31c87fd..1c7823a2ff4a9d08872337ece0bc596a1d237eae 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Update\sthis\sbranch\swith\sthe\slatest\schanges\sfrom\sthe\strunk.
-D 2016-04-11T09:39:25.021
+C Fixes\sfor\sOOM\sand\sIO\serror\shandling\swith\stemp\sfile\sdatabases.
+D 2016-04-11T18:07:47.205
 F Makefile.in eba680121821b8a60940a81454316f47a341487a
 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
 F Makefile.msc 1f123a0757f6f04f0341accb46457e116817159a
@@ -362,7 +362,7 @@ F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa
 F src/os_unix.c bde4844f0849cab5924c6a81178f8500774ce76b
 F src/os_win.c b3ba9573d8d893e70a6a8015bbee572ecf7ffbef
 F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca
-F src/pager.c 91d7462aa2429e30d64c705f75ba36cace90c241
+F src/pager.c 4cc8a5b3979db65725eaa03650a6d54219122b8d
 F src/pager.h e1d38a2f14849e219df0f91f8323504d134c8a56
 F src/parse.y 52cdeb4f37634d0ccd2998aab099b7bbb690b0d3
 F src/pcache.c e9c00846d3dcdaa75b288c6f16238c2fe2177823
@@ -551,7 +551,7 @@ F test/capi3c.test 0b9edb0c2156a964b9271cd5ea7ae56736cc2fcb
 F test/capi3d.test 485048dc5cd07bc68011e4917ad035ad6047ab82
 F test/capi3e.test 3d49c01ef2a1a55f41d73cba2b23b5059ec460fe
 F test/cast.test 4c275cbdc8202d6f9c54a3596701719868ac7dc3
-F test/cffault.test aadc1f61f8811cb600e3e069acbf8796f472a096
+F test/cffault.test 9d6b20606afe712374952eec4f8fd74b1a8097ef
 F test/check.test 85a84bfc4be0e83f668747211c7cd45a6721d485
 F test/close.test 83947daf3b700631f90f4850ddaab455be4af73d
 F test/closure01.test b1703ba40639cfc9b295cf478d70739415eec6a4
@@ -1109,6 +1109,7 @@ F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126
 F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
 F test/tclsqlite.test e1306001a0ca92250b691ea6d3cecaca5b6342aa
 F test/tempdb.test bd92eba8f20e16a9136e434e20b280794de3cdb6
+F test/tempfault.test 0c80f23c651cf6452c27cacf09f4c2ee9527a912
 F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
 F test/temptable2.test 707c01c00b4a8fd050e0db5dcef448e998b9ddb5
 F test/temptrigger.test 8ec228b0db5d7ebc4ee9b458fc28cb9e7873f5e1
@@ -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 84c557010c211595d2ec80b62c63af1c7f4714bd ef1966c2469a0f5dbdb31a0287bd37badb2b8f28
-R 95ac2720b81ae4f698b1e227fe8fc71b
+P 982b753d0b6a3ed9fba33ed41523b2cd42280276
+R 46e56336ea4184d65ce3043234f11f03
 U dan
-Z 4e2c4b80dd3173e2cb79a80f72f7a7a8
+Z 58afa17a4e51610cdca345488b854923
index 9b0cbf0915b5829980d3620c28849689b231822f..9e8a4101e2f349cfa80ef6d6255f254ce5e6b6b7 100644 (file)
@@ -1 +1 @@
-982b753d0b6a3ed9fba33ed41523b2cd42280276
\ No newline at end of file
+4eb06e843af60d5e533793618c6e0e9b7ef7a1a6
\ No newline at end of file
index 79dbaec5c27365623602377f2de9ae2f76bd716a..9baddc29863b73489c246dc2213e054bf20508b7 100644 (file)
@@ -958,7 +958,7 @@ static int assert_pager_state(Pager *p){
       ** back to OPEN state.
       */
       assert( pPager->errCode!=SQLITE_OK );
-      assert( sqlite3PcacheRefCount(pPager->pPCache)>0 );
+      assert( sqlite3PcacheRefCount(pPager->pPCache)>0 || pPager->tempFile );
       break;
   }
 
@@ -1819,11 +1819,14 @@ static void pager_unlock(Pager *pPager){
   ** trusted. Now that there are no outstanding references to the pager,
   ** it can safely move back to PAGER_OPEN state. This happens in both
   ** normal and exclusive-locking mode.
-  */
-  if( pPager->errCode ){
-    assert( !MEMDB );
+  **
+  ** Exception: There is no way out of the error state for temp files.
+  ** This is because it is not possible to call pager_reset() on a temp
+  ** file pager (as this may discard the only copy of some data).  */
+  assert( pPager->errCode==SQLITE_OK || !MEMDB );
+  if( pPager->tempFile==0 && pPager->errCode ){
     pager_reset(pPager);
-    pPager->changeCountDone = pPager->tempFile;
+    pPager->changeCountDone = 0;
     pPager->eState = PAGER_OPEN;
     pPager->errCode = SQLITE_OK;
     if( USEFETCH(pPager) ) sqlite3OsUnfetch(pPager->fd, 0, 0);
@@ -5034,8 +5037,8 @@ int sqlite3PagerSharedLock(Pager *pPager){
   */
   assert( sqlite3PcacheRefCount(pPager->pPCache)==0 );
   assert( assert_pager_state(pPager) );
+  if( pPager->tempFile && pPager->errCode ) { return pPager->errCode; }
   assert( pPager->eState==PAGER_OPEN || pPager->eState==PAGER_READER );
-  if( NEVER(MEMDB && pPager->errCode) ){ return pPager->errCode; }
 
   if( !pagerUseWal(pPager) && pPager->eState==PAGER_OPEN ){
     int bHotJournal = 1;          /* True if there exists a hot journal-file */
index 79cefd24c4946655f2c890312181d7615c1a7f51..0d029ece37d8f70e116e27bb2808bf719223f707 100644 (file)
@@ -15,7 +15,7 @@
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
-set testprefix cacheflush
+set testprefix cffault
 source $testdir/malloc_common.tcl
 
 # Run the supplied SQL on a copy of the database currently stored on 
diff --git a/test/tempfault.test b/test/tempfault.test
new file mode 100644 (file)
index 0000000..da1ae12
--- /dev/null
@@ -0,0 +1,114 @@
+# 2016 April 11
+#
+# 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 tests for fault-injection when SQLite is used with
+# a temp file database.
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+source $testdir/malloc_common.tcl
+set testprefix tempfault
+
+sqlite3_memdebug_vfs_oom_test 0
+
+do_faultsim_test 1 -faults oom* -prep {
+  sqlite3 db ""
+  db eval {
+    PRAGMA page_size = 1024;
+    CREATE TABLE t1(a, b);
+    INSERT INTO t1 VALUES(1, 2);
+    INSERT INTO t1 VALUES(3, 4);
+  }
+} -body {
+  execsql { INSERT INTO t1 VALUES(5, 6) }
+} -test {
+  faultsim_test_result {0 {}}
+  set rc [catch { execsql { SELECT * FROM t1 } } msg]
+  if {$rc==0 && $msg != "1 2 3 4 5 6" && $msg != "1 2 3 4"} {
+    error "data mismatch 1: $msg"
+  }
+  if {$testrc==0 && $msg != "1 2 3 4 5 6"} {
+    error "data mismatch 2: $msg"
+  }
+  faultsim_integrity_check
+}
+
+do_faultsim_test 2 -faults oom* -prep {
+  sqlite3 db ""
+  db eval {
+    PRAGMA page_size = 1024;
+    PRAGMA cache_size = 10;
+    CREATE TABLE t1(a, b);
+    CREATE INDEX i1 ON t1(b, a);
+    WITH x(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<50)
+    INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM x;
+  }
+} -body {
+  execsql { UPDATE t1 SET a = randomblob(99) }
+} -test {
+  faultsim_test_result {0 {}}
+  faultsim_integrity_check db
+}
+
+do_faultsim_test 3 -faults oom* -prep {
+  sqlite3 db ""
+  db eval {
+    PRAGMA page_size = 1024;
+    PRAGMA cache_size = 10;
+    CREATE TABLE t1(a, b);
+    CREATE INDEX i1 ON t1(b, a);
+    WITH x(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<50)
+    INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM x;
+  }
+} -body {
+  execsql { 
+    BEGIN;
+      UPDATE t1 SET a = randomblob(99);
+      SAVEPOINT abc;
+        UPDATE t1 SET a = randomblob(98) WHERE (rowid%10)==0;
+      ROLLBACK TO abc;
+        UPDATE t1 SET a = randomblob(97) WHERE (rowid%5)==0;
+      ROLLBACK TO abc;
+    COMMIT;
+  }
+} -test {
+  faultsim_test_result {0 {}}
+  faultsim_integrity_check db
+}
+
+do_faultsim_test 4 -faults * -prep {
+  sqlite3 db ""
+  db eval {
+    PRAGMA page_size = 1024;
+    PRAGMA cache_size = 10;
+    CREATE TABLE t1(a, b);
+    CREATE INDEX i1 ON t1(b, a);
+    WITH x(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<50)
+    INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM x;
+  }
+} -body {
+  execsql { 
+    BEGIN;
+      UPDATE t1 SET a = randomblob(99);
+      SAVEPOINT abc;
+        UPDATE t1 SET a = randomblob(98) WHERE (rowid%10)==0;
+      ROLLBACK TO abc;
+        UPDATE t1 SET a = randomblob(97) WHERE (rowid%5)==0;
+      ROLLBACK TO abc;
+    COMMIT;
+  }
+} -test {
+  faultsim_test_result {0 {}}
+}
+
+sqlite3_memdebug_vfs_oom_test 1
+finish_test