]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Disable the PagerDontWrite() optimization for temp tables. It can cause database...
authordan <dan@noemail.net>
Wed, 4 May 2016 11:28:03 +0000 (11:28 +0000)
committerdan <dan@noemail.net>
Wed, 4 May 2016 11:28:03 +0000 (11:28 +0000)
FossilOrigin-Name: 6341ab2ffef298ca16b323358afbea4a4c1fb0e1

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

index b85ef558d9c6d40e59c6c29a83e7b0f8d47470d4..0570c6e3af472d62ba48eb21d3e41c2f6d57c99c 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Minor\sstyle\stweaks\sin\sthe\sMSVC\smakefile.
-D 2016-05-03T19:40:54.328
+C Disable\sthe\sPagerDontWrite()\soptimization\sfor\stemp\stables.\sIt\scan\scause\sdatabase\scorruption\sif\sa\spage\spassed\sto\sPagerDontWrite()\sis\sdirty\sat\sthe\sstart\sof\sa\stransaction\sthat\sis\ssubsequently\srolled\sback.
+D 2016-05-04T11:28:03.301
 F Makefile.in 9eda6e1c90d05c199c3ec8a7069b0682ad307657
 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
 F Makefile.msc db82b35aef27f412fef14d8534afc022138bcdfd
@@ -364,7 +364,7 @@ F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa
 F src/os_unix.c a9443cdab41d7f3cdf0df3a5aab62fd6e1c9b234
 F src/os_win.c 852fc2ff6084296348ed3739c548b2cf32df394e
 F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca
-F src/pager.c a8d30c49c231e9a20d05257613db922532588963
+F src/pager.c c512873311087cd22372f2b076fc869e090e8e16
 F src/pager.h 329bdf078a4e0a3b35084534d58625d21fd03681
 F src/parse.y 10eb2f3fb62341291528c7984498054731f9d31e
 F src/pcache.c b3230ecfc7f797063fbe167f2845da363e8f07f8
@@ -1111,6 +1111,7 @@ F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126
 F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
 F test/tclsqlite.test e1306001a0ca92250b691ea6d3cecaca5b6342aa
 F test/tempdb.test bd92eba8f20e16a9136e434e20b280794de3cdb6
+F test/tempdb2.test 4fc92055f2a3f7626c0f2eabbb637dc021b311d5
 F test/tempfault.test 0c0d349c9a99bf5f374655742577f8712c647900
 F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
 F test/temptable2.test cd396beb41117a5302fff61767c35fa4270a0d5e
@@ -1486,7 +1487,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 bcaa650e8796984b275eceba0ed477f360295d01
-R 962b079d2f6aa84ad32617180232ff75
-U mistachkin
-Z 45ce4bc83f501da24480cd14c4b0de07
+P 1b43358f8979c4f18519e824e0d5f6ef2250107c
+R ddb8134dc049c780758987466a2a1e86
+U dan
+Z 527ddc60688e8fba4830106202c052a2
index 1744b7bee1ef00c954c4de0667a3180c47ee418a..ae5eab176f50e6781217adc02b29ecd7daa99c26 100644 (file)
@@ -1 +1 @@
-1b43358f8979c4f18519e824e0d5f6ef2250107c
\ No newline at end of file
+6341ab2ffef298ca16b323358afbea4a4c1fb0e1
\ No newline at end of file
index d24337cd50e5d758c71a42cb64f240b96199fe45..8ef0492e571ffe4e44c50a0f8b32b4b35b462174 100644 (file)
@@ -6008,10 +6008,16 @@ int sqlite3PagerIswriteable(DbPage *pPg){
 **
 ** Tests show that this optimization can quadruple the speed of large 
 ** DELETE operations.
+**
+** This optimization cannot be used with a temp-file, as the page may
+** have been dirty at the start of the transaction. In that case, if
+** memory pressure forces page pPg out of the cache, the data does need 
+** to be written out to disk so that it may be read back in if the 
+** current transaction is rolled back.
 */
 void sqlite3PagerDontWrite(PgHdr *pPg){
   Pager *pPager = pPg->pPager;
-  if( (pPg->flags&PGHDR_DIRTY) && pPager->nSavepoint==0 ){
+  if( !pPager->tempFile && (pPg->flags&PGHDR_DIRTY) && pPager->nSavepoint==0 ){
     PAGERTRACE(("DONT_WRITE page %d of %d\n", pPg->pgno, PAGERID(pPager)));
     IOTRACE(("CLEAN %p %d\n", pPager, pPg->pgno))
     pPg->flags |= PGHDR_DONT_WRITE;
diff --git a/test/tempdb2.test b/test/tempdb2.test
new file mode 100644 (file)
index 0000000..bc2822e
--- /dev/null
@@ -0,0 +1,77 @@
+# 2016 March 3
+#
+# 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.
+#
+#***********************************************************************
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+set testprefix tempdb2
+
+db close
+sqlite3 db ""
+
+proc int2str {i} { string range [string repeat "$i." 450] 0 899 }
+db func int2str int2str
+
+#-------------------------------------------------------------------------
+#
+#  1.1: Write a big transaction to the db. One so large that it forces
+#       the file to be created and the cache flushed to disk on COMMIT.
+#
+#  1.2: Write a small transaction - one small enough that it remains in
+#       memory on COMMIT. All the pages of table [t1] are now dirty.
+#
+#  1.3: Delete the contents of [t1]. This moves all of its leaves to the
+#       free-list and causes the btree layer to call PagerDontWrite() on
+#       each of them.
+#
+#       Then do a big update on table [t2]. So big that the former leaves
+#       of [t1] are forced out of the cache. Then roll back the transaction.
+#       If the PagerDontWrite() calls are honoured and the data is not written
+#       to disk, the update made in test 1.2 will be lost at this point. Or, if
+#       they are ignored (as they should be for temp databases), the update
+#       will be safely written out to disk before the cache entries are
+#       discarded.
+#
+do_execsql_test 1.1 {
+  PRAGMA page_size=1024;
+  PRAGMA cache_size=50;
+
+  BEGIN;
+    CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
+    INSERT INTO t1 VALUES(1, int2str(1));
+    INSERT INTO t1 VALUES(2, int2str(1));
+    INSERT INTO t1 VALUES(3, int2str(1));
+
+    CREATE TABLE t2(a INTEGER PRIMARY KEY, b);
+    WITH c(x) AS ( VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100 ) 
+    INSERT INTO t2 SELECT x, int2str(x) FROM c;
+  COMMIT;
+
+  PRAGMA lock_status;
+} {main unlocked temp closed}
+
+do_execsql_test 1.2 {
+  UPDATE t1 SET b=int2str(2);
+  SELECT b=int2str(2) FROM t1
+} {1 1 1}
+
+do_execsql_test 1.3 {
+  BEGIN;
+    DELETE FROM t1;
+    UPDATE t2 SET b=int2str(a+1);
+  ROLLBACK;
+}
+
+do_execsql_test 1.4 {
+  SELECT b=int2str(2) FROM t1
+} {1 1 1}
+
+finish_test
+