mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-07 02:42:48 +03:00
Fixes for problems with small caches and SAVEPOINT rollback in WAL mode.
FossilOrigin-Name: 6a944f028d4a070bef29e1fbc6fbef481ebcd34c
This commit is contained in:
22
manifest
22
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
|
||||
|
@@ -1 +1 @@
|
||||
205e5d8ac08f7d7853427b4cd235fca125155d2d
|
||||
6a944f028d4a070bef29e1fbc6fbef481ebcd34c
|
21
src/pager.c
21
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.
|
||||
*/
|
||||
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. */
|
||||
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. */
|
||||
|
25
src/wal.c
25
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 */
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -761,6 +761,7 @@ run_tests "wal" -description {
|
||||
} -include {
|
||||
savepoint.test
|
||||
savepoint2.test
|
||||
savepoint6.test
|
||||
}
|
||||
|
||||
# End of tests
|
||||
|
@@ -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
|
||||
|
@@ -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]]
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
|
Reference in New Issue
Block a user