diff --git a/manifest b/manifest index 3e8c4278ae..9451cdd82f 100644 --- 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 diff --git a/manifest.uuid b/manifest.uuid index a461064513..c549155246 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -205e5d8ac08f7d7853427b4cd235fca125155d2d \ No newline at end of file +6a944f028d4a070bef29e1fbc6fbef481ebcd34c \ No newline at end of file diff --git a/src/pager.c b/src/pager.c index 171b584573..bd704fa7c7 100644 --- a/src/pager.c +++ b/src/pager.c @@ -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 && iinSubRec; 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. */ diff --git a/src/wal.c b/src/wal.c index 0797822f8a..8c6878a1a4 100644 --- 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 */ diff --git a/src/wal.h b/src/wal.h index c53e41d5ea..64067ce09b 100644 --- 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); diff --git a/test/permutations.test b/test/permutations.test index f11bb661e5..e4c47a3650 100644 --- a/test/permutations.test +++ b/test/permutations.test @@ -761,6 +761,7 @@ run_tests "wal" -description { } -include { savepoint.test savepoint2.test + savepoint6.test } # End of tests diff --git a/test/savepoint6.test b/test/savepoint6.test index 33758b8648..ae866e215a 100644 --- a/test/savepoint6.test +++ b/test/savepoint6.test @@ -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 diff --git a/test/wal.test b/test/wal.test index 1398ffd3ac..d533f9e0c7 100644 --- a/test/wal.test +++ b/test/wal.test @@ -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]] #-------------------------------------------------------------------------