]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fixes for problems with small caches and SAVEPOINT rollback in WAL mode.
authordan <dan@noemail.net>
Mon, 26 Apr 2010 16:57:10 +0000 (16:57 +0000)
committerdan <dan@noemail.net>
Mon, 26 Apr 2010 16:57:10 +0000 (16:57 +0000)
FossilOrigin-Name: 6a944f028d4a070bef29e1fbc6fbef481ebcd34c

manifest
manifest.uuid
src/pager.c
src/wal.c
src/wal.h
test/permutations.test
test/savepoint6.test
test/wal.test

index 3e8c4278aebf93b95398e6a1ecf62360134ef4af..9451cdd82f4ea0809ae9c334c62b857a07350ca4 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Add\sthe\s"wal"\spermutation\sto\srun\sexisting\stest\sfiles\ssavepoint.test\sand\ssavepoint2.test\sin\sWAL\smode.
-D 2010-04-26T12:39:04
+C Fixes\sfor\sproblems\swith\ssmall\scaches\sand\sSAVEPOINT\srollback\sin\sWAL\smode.
+D 2010-04-26T16:57:10
 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
 F Makefile.in d83a0ffef3dcbfb08b410a6c6dd6c009ec9167fb
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -152,7 +152,7 @@ F src/os_common.h 240c88b163b02c21a9f21f87d49678a0aa21ff30
 F src/os_os2.c 082884dc2a20a2f1fddc404f3606ec2abe907b56
 F src/os_unix.c 1acc854259b045cf029c6f95828a5f4b84f361c7
 F src/os_win.c 607b40e40662c6c74ff2400ff03e7f42521d5c75
-F src/pager.c 5924538fb99f62774419bfae882debb0d65bc3c8
+F src/pager.c b4a41030860229e80295fa1f37addab24d21799c
 F src/pager.h cee4487ab4f0911dd9f22a40e3cd55afdb7ef444
 F src/parse.y ace5c7a125d9f2a410e431ee3209034105045f7e
 F src/pcache.c ace8f6a5ecd4711cc66a1b23053be7109bd437cf
@@ -221,8 +221,8 @@ F src/vdbeblob.c 5327132a42a91e8b7acfb60b9d2c3b1c5c863e0e
 F src/vdbemem.c 2a82f455f6ca6f78b59fb312f96054c04ae0ead1
 F src/vdbetrace.c 864cef96919323482ebd9986f2132435115e9cc2
 F src/vtab.c a0f8a40274e4261696ef57aa806de2776ab72cda
-F src/wal.c f93ce8968d6e86378aa2d465f592027e02929a7a
-F src/wal.h 1a34bb71642b46af5e6d51c2f69ae0f55268df81
+F src/wal.c ce03bdd759c7b949188c0b75c46777fe0f7f105e
+F src/wal.h 812101dd76610401fbcd44114e7e8b7ce0224645
 F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
 F src/where.c faadd9c2bf08868e5135192b44e0d753e363a885
 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
@@ -532,7 +532,7 @@ F test/pageropt.test 3ee6578891baaca967f0bd349e4abfa736229e1a
 F test/pagesize.test 76aa9f23ecb0741a4ed9d2e16c5fa82671f28efb
 F test/pcache.test eebc4420b37cb07733ae9b6e99c9da7c40dd6d58
 F test/pcache2.test 0d85f2ab6963aee28c671d4c71bec038c00a1d16
-F test/permutations.test e9a9070862e3c675f0844815054cfd2ed4ed9c66
+F test/permutations.test 0730dc6c028b620a15c38a0a7d07238da088ecd3
 F test/pragma.test 6960f9efbce476f70ba9ee2171daf5042f9e3d8a
 F test/pragma2.test 5364893491b9231dd170e3459bfc2e2342658b47
 F test/printf.test 05970cde31b1a9f54bd75af60597be75a5c54fea
@@ -553,7 +553,7 @@ F test/savepoint2.test 9b8543940572a2f01a18298c3135ad0c9f4f67d7
 F test/savepoint3.test e328085853b14898d78ceea00dfe7db18bb6a9ec
 F test/savepoint4.test c8f8159ade6d2acd9128be61e1230f1c1edc6cc0
 F test/savepoint5.test 0735db177e0ebbaedc39812c8d065075d563c4fd
-F test/savepoint6.test 2df1d093e59e78d688c64eb20e0457aaea7d08f9
+F test/savepoint6.test 8e871226bcd20241c0ee7da28166f5c525d7cba9
 F test/schema.test 8f7999be894260f151adf15c2c7540f1c6d6a481
 F test/schema2.test 906408621ea881fdb496d878b1822572a34e32c5
 F test/securedel.test 328d2921c0ca49bdd3352e516b0377fc07143254
@@ -758,7 +758,7 @@ F test/vtabE.test 7c4693638d7797ce2eda17af74292b97e705cc61
 F test/vtab_alter.test 9e374885248f69e251bdaacf480b04a197f125e5
 F test/vtab_err.test 0d4d8eb4def1d053ac7c5050df3024fd47a3fbd8
 F test/vtab_shared.test 0eff9ce4f19facbe0a3e693f6c14b80711a4222d
-F test/wal.test 7d44c2ee327e86a7c26052795789dd2d472bd1d4
+F test/wal.test b5d5fe1b3171eefb25355758e0dc689096bc1f87
 F test/walbak.test f6fde9a5f59d0c697cb1f4af7876178c2f69a7ba
 F test/walcrash.test f022cee7eb7baa5fb898726120a6a4073dd831d1
 F test/walhook.test 76a559e262f0715c470bade4a8d8333035f8ee47
@@ -808,7 +808,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
-P 3d159939cc2beb18c4ca0c8e9a99a75d4107e6e4
-R 9cdc568754b75f48338d755d9a93a206
+P 205e5d8ac08f7d7853427b4cd235fca125155d2d
+R f3447c8eaaa2559454ba677c09b3ac47
 U dan
-Z e32fb56774989323e02682dddebb9008
+Z 1f4eebc47ae413fc016108c1a59ad1db
index a4610645139dac4bc421d30641354d04b6eb8e90..c54915524665256cfa2a4fbd01bd4cdc3083eff1 100644 (file)
@@ -1 +1 @@
-205e5d8ac08f7d7853427b4cd235fca125155d2d
\ No newline at end of file
+6a944f028d4a070bef29e1fbc6fbef481ebcd34c
\ No newline at end of file
index 171b584573d4df972987994c3e91c09c1b5b2855..bd704fa7c7960af5ebdb7a458b985294d088a359 100644 (file)
@@ -221,6 +221,7 @@ struct PagerSavepoint {
   Bitvec *pInSavepoint;        /* Set of pages in this savepoint */
   Pgno nOrig;                  /* Original number of pages in file */
   Pgno iSubRec;                /* Index of first record in sub-journal */
+  u32 iFrame;                  /* Last frame in WAL when savepoint opened */
 };
 
 /*
@@ -1539,6 +1540,7 @@ static int pager_playback_one_page(
 
   aData = pPager->pTmpSpace;
   assert( aData );         /* Temp storage must have already been allocated */
+  assert( pagerUseLog(pPager)==0 || (!isMainJrnl && isSavepnt) );
 
   /* Read the page number and page data from the journal or sub-journal
   ** file. Return an error code to the caller if an IO error occurs.
@@ -1608,7 +1610,11 @@ static int pager_playback_one_page(
   ** is possible to fail a statement on a database that does not yet exist.
   ** Do not attempt to write if database file has never been opened.
   */
-  pPg = pager_lookup(pPager, pgno);
+  if( pagerUseLog(pPager) ){
+    pPg = 0;
+  }else{
+    pPg = pager_lookup(pPager, pgno);
+  }
   assert( pPg || !MEMDB );
   PAGERTRACE(("PLAYBACK %d page %d hash(%08x) %s\n",
            PAGERID(pPager), pgno, pager_datahash(pPager->pageSize, (u8*)aData),
@@ -1625,6 +1631,7 @@ static int pager_playback_one_page(
   ){
     i64 ofst = (pgno-1)*(i64)pPager->pageSize;
     testcase( !isSavepnt && pPg!=0 && (pPg->flags&PGHDR_NEED_SYNC)!=0 );
+    assert( !pagerUseLog(pPager) );
     rc = sqlite3OsWrite(pPager->fd, (u8*)aData, pPager->pageSize, ofst);
     if( pgno>pPager->dbFileSize ){
       pPager->dbFileSize = pgno;
@@ -1689,6 +1696,7 @@ static int pager_playback_one_page(
       ** segment is synced. If a crash occurs during or following this,
       ** database corruption may ensue.
       */
+      assert( !pagerUseLog(pPager) );
       sqlite3PcacheMakeClean(pPg);
     }
 #ifdef SQLITE_CHECK_PAGES
@@ -2428,6 +2436,10 @@ static int pagerPlaybackSavepoint(Pager *pPager, PagerSavepoint *pSavepoint){
   if( pSavepoint ){
     u32 ii;            /* Loop counter */
     i64 offset = pSavepoint->iSubRec*(4+pPager->pageSize);
+
+    if( pagerUseLog(pPager) ){
+      rc = sqlite3WalSavepointUndo(pPager->pLog, pSavepoint->iFrame);
+    }
     for(ii=pSavepoint->iSubRec; rc==SQLITE_OK && ii<pPager->nSubRec; ii++){
       assert( offset==ii*(4+pPager->pageSize) );
       rc = pager_playback_one_page(pPager, &offset, pDone, 0, 1);
@@ -2439,6 +2451,7 @@ static int pagerPlaybackSavepoint(Pager *pPager, PagerSavepoint *pSavepoint){
   if( rc==SQLITE_OK ){
     pPager->journalOff = szJ;
   }
+
   return rc;
 }
 
@@ -3326,7 +3339,12 @@ static int pagerStress(void *p, PgHdr *pPg){
   pPg->pDirty = 0;
   if( pagerUseLog(pPager) ){
     /* Write a single frame for this page to the log. */
-    rc = pagerLogFrames(pPager, pPg, 0, 0, 0);
+    if( subjRequiresPage(pPg) ){ 
+      rc = subjournalPage(pPg); 
+    }
+    if( rc==SQLITE_OK ){
+      rc = pagerLogFrames(pPager, pPg, 0, 0, 0);
+    }
   }else{
     /* The doNotSync flag is set by the sqlite3PagerWrite() function while it
     ** is journalling a set of two or more database pages that are stored
@@ -5342,6 +5360,9 @@ int sqlite3PagerOpenSavepoint(Pager *pPager, int nSavepoint){
       if( !aNew[ii].pInSavepoint ){
         return SQLITE_NOMEM;
       }
+      if( pagerUseLog(pPager) ){
+        aNew[ii].iFrame = sqlite3WalSavepoint(pPager->pLog);
+      }
     }
 
     /* Open the sub-journal, if it is not already opened. */
index 0797822f8a49f5d48f33b2b6f1d93c133ff844ad..8c6878a1a497891ab167d42cff8f04210008d6cb 100644 (file)
--- a/src/wal.c
+++ b/src/wal.c
@@ -1669,6 +1669,27 @@ int sqlite3WalUndo(Log *pLog, int (*xUndo)(void *, Pgno), void *pUndoCtx){
   return rc;
 }
 
+u32 sqlite3WalSavepoint(Log *pLog){
+  assert( pLog->isWriteLocked );
+  return pLog->hdr.iLastPg;
+}
+
+int sqlite3WalSavepointUndo(Log *pLog, u32 iFrame){
+  int rc = SQLITE_OK;
+  u8 aCksum[8];
+  assert( pLog->isWriteLocked );
+
+  pLog->hdr.iLastPg = iFrame;
+  if( iFrame>0 ){
+    i64 iOffset = logFrameOffset(iFrame, pLog->hdr.pgsz) + sizeof(u32)*2;
+    rc = sqlite3OsRead(pLog->pFd, aCksum, sizeof(aCksum), iOffset);
+    pLog->hdr.iCheck1 = sqlite3Get4byte(&aCksum[0]);
+    pLog->hdr.iCheck2 = sqlite3Get4byte(&aCksum[4]);
+  }
+
+  return rc;
+}
+
 /* 
 ** Return true if data has been written but not committed to the log file. 
 */
@@ -1678,8 +1699,8 @@ int sqlite3WalDirty(Log *pLog){
 }
 
 /* 
-** Write a set of frames to the log. The caller must hold at least a
-** RESERVED lock on the database file.
+** Write a set of frames to the log. The caller must hold the write-lock
+** on the log file (obtained using sqlite3WalWriteLock()).
 */
 int sqlite3WalFrames(
   Log *pLog,                      /* Log handle to write to */
index c53e41d5eaca29a83921a86cc626241e63b39552..64067ce09b8403334fd85bb646871df8f1fa56d9 100644 (file)
--- a/src/wal.h
+++ b/src/wal.h
@@ -40,6 +40,9 @@ int sqlite3WalWriteLock(Log *pLog, int op);
 /* Undo any frames written (but not committed) to the log */
 int sqlite3WalUndo(Log *pLog, int (*xUndo)(void *, Pgno), void *pUndoCtx);
 
+u32 sqlite3WalSavepoint(Log *pLog);
+int sqlite3WalSavepointUndo(Log *pLog, u32 iFrame);
+
 /* Return true if data has been written but not committed to the log file. */
 int sqlite3WalDirty(Log *pLog);
 
index f11bb661e533cd66e4b386bcfd1c9d8bab200c87..e4c47a3650ad4bfac66e83a7b04120f4bc92af1e 100644 (file)
@@ -761,6 +761,7 @@ run_tests "wal" -description {
 } -include {
   savepoint.test
   savepoint2.test
+  savepoint6.test
 }
 
 # End of tests
index 33758b8648e72cc1160a77784e21c75e736d0e9e..ae866e215a9d4c576542d28159a6738fab4027bc 100644 (file)
@@ -222,6 +222,7 @@ foreach zSetup [list {
   set testname normal
   sqlite3 db test.db
 } {
+  if {[wal_is_wal_mode]} continue
   set testname tempdb
   sqlite3 db ""
 } {
@@ -241,10 +242,12 @@ foreach zSetup [list {
   unset -nocomplain ::aEntry
 
   catch { db close }
-  file delete -force test.db
+  file delete -force test.db test.db-wal test.db-journal
   eval $zSetup
   sql $DATABASE_SCHEMA
 
+  wal_set_journal_mode
+
   do_test savepoint6-$testname.setup {
     savepoint one
     insert_rows [random_integers 100 1000]
@@ -252,7 +255,7 @@ foreach zSetup [list {
     checkdb
   } {ok}
   
-  for {set i 0} {$i < 1000} {incr i} {
+  for {set i 0} {$i < 50} {incr i} {
     do_test savepoint6-$testname.$i.1 {
       savepoint_op
       checkdb
@@ -264,6 +267,8 @@ foreach zSetup [list {
       checkdb
     } {ok}
   }
+
+  wal_check_journal_mode savepoint6-$testname.walok
 }
 
 unset -nocomplain ::lSavepoint
index 1398ffd3ac106addbc02920216782bfe8763bf4d..d533f9e0c7829a7ff453e37ffeb3a5185f78ec2c 100644 (file)
@@ -166,13 +166,13 @@ do_test wal-4.3 {
   }
 } {a b}
 
-do_test wal-4.4 {
+do_test wal-4.4.1 {
   db close
   sqlite3 db test.db
   db func blob blob
   list [execsql { SELECT * FROM t1 }] [file size test.db-wal]
 } {{a b} 0}
-do_test wal-4.5 {
+do_test wal-4.4.2 {
   execsql { PRAGMA cache_size = 10 }
   execsql {
     CREATE TABLE t2(a, b);
@@ -191,10 +191,10 @@ do_test wal-4.5 {
       SELECT count(*) FROM t2;
   }
 } {32}
-do_test wal-4.6 {
+do_test wal-4.4.3 {
   execsql { ROLLBACK TO tr }
 } {}
-do_test wal-4.7 {
+do_test wal-4.4.4 {
   set logsize [file size test.db-wal]
   execsql {
       INSERT INTO t1 VALUES('x', 'y');
@@ -202,20 +202,82 @@ do_test wal-4.7 {
   }
   expr { $logsize == [file size test.db-wal] }
 } {1}
-do_test wal-4.8 {
+do_test wal-4.4.5 {
   execsql { SELECT count(*) FROM t2 }
 } {1}
-do_test wal-4.9 {
+do_test wal-4.4.6 {
   file copy -force test.db test2.db
   file copy -force test.db-wal test2.db-wal
   sqlite3 db2 test2.db
   execsql { SELECT count(*) FROM t2 ; SELECT count(*) FROM t1 } db2
 } {1 2}
-do_test wal-4.10 {
+do_test wal-4.4.7 {
   execsql { PRAGMA integrity_check } db2
 } {ok}
 db2 close
 
+do_test wal-4.5.1 {
+  reopen_db
+  db func blob blob
+  execsql {
+    PRAGMA journal_mode = WAL;
+    CREATE TABLE t1(a, b);
+    INSERT INTO t1 VALUES('a', 'b');
+  }
+  sqlite3 db test.db
+  db func blob blob
+  list [execsql { SELECT * FROM t1 }] [file size test.db-wal]
+} {{a b} 0}
+do_test wal-4.5.2 {
+  execsql { PRAGMA cache_size = 10 }
+  execsql {
+    CREATE TABLE t2(a, b);
+    BEGIN;
+    INSERT INTO t2 VALUES(blob(400), blob(400));
+    SAVEPOINT tr;
+      INSERT INTO t2 SELECT blob(400), blob(400) FROM t2; /*  2 */
+      INSERT INTO t2 SELECT blob(400), blob(400) FROM t2; /*  4 */
+      INSERT INTO t2 SELECT blob(400), blob(400) FROM t2; /*  8 */
+      INSERT INTO t2 SELECT blob(400), blob(400) FROM t2; /* 16 */
+      INSERT INTO t2 SELECT blob(400), blob(400) FROM t2; /* 32 */
+      INSERT INTO t1 SELECT blob(400), blob(400) FROM t1; /*  2 */
+      INSERT INTO t1 SELECT blob(400), blob(400) FROM t1; /*  4 */
+      INSERT INTO t1 SELECT blob(400), blob(400) FROM t1; /*  8 */
+      INSERT INTO t1 SELECT blob(400), blob(400) FROM t1; /* 16 */
+      INSERT INTO t1 SELECT blob(400), blob(400) FROM t1; /* 32 */
+      SELECT count(*) FROM t2;
+  }
+} {32}
+do_test wal-4.5.3 {
+breakpoint
+  execsql { ROLLBACK TO tr }
+} {}
+do_test wal-4.5.4 {
+  set logsize [file size test.db-wal]
+breakpoint
+  execsql {
+      INSERT INTO t1 VALUES('x', 'y');
+    RELEASE tr;
+    COMMIT;
+  }
+  expr { $logsize == [file size test.db-wal] }
+} {1}
+do_test wal-4.5.5 {
+  execsql { SELECT count(*) FROM t2 ; SELECT count(*) FROM t1 }
+} {1 2}
+do_test wal-4.5.6 {
+  file copy -force test.db test2.db
+  file copy -force test.db-wal test2.db-wal
+  sqlite3 db2 test2.db
+breakpoint
+  execsql { SELECT count(*) FROM t2 ; SELECT count(*) FROM t1 } db2
+} {1 2}
+do_test wal-4.5.7 {
+  execsql { PRAGMA integrity_check } db2
+} {ok}
+db2 close
+
+
 reopen_db
 do_test wal-5.1 {
   execsql {
@@ -680,7 +742,7 @@ do_test wal-11.10 {
       SELECT count(*) FROM t1;
   }
   list [expr [file size test.db]/1024] [file size test.db-wal]
-} [list 37 [log_file_size 35 1024]]
+} [list 37 [log_file_size 37 1024]]
 do_test wal-11.11 {
   execsql {
       SELECT count(*) FROM t1;
@@ -690,7 +752,7 @@ do_test wal-11.11 {
 } {32 16}
 do_test wal-11.12 {
   list [expr [file size test.db]/1024] [file size test.db-wal]
-} [list 37 [log_file_size 35 1024]]
+} [list 37 [log_file_size 37 1024]]
 do_test wal-11.13 {
   execsql {
     INSERT INTO t1 VALUES( blob(900) );
@@ -700,7 +762,7 @@ do_test wal-11.13 {
 } {17 ok}
 do_test wal-11.14 {
   list [expr [file size test.db]/1024] [file size test.db-wal]
-} [list 37 [log_file_size 35 1024]]
+} [list 37 [log_file_size 37 1024]]
 
 
 #-------------------------------------------------------------------------