mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-01 06:27:03 +03:00
Add "pragma journal_mode=memory". Change the way rollback works for in-memory databases so that it reuses the journal_mode=memory code. (CVS 5830)
FossilOrigin-Name: 39ebf01addf9d0867daafd06a38719e725128f9c
This commit is contained in:
2
main.mk
2
main.mk
@ -57,6 +57,7 @@ LIBOBJ+= alter.o analyze.o attach.o auth.o \
|
||||
func.o global.o hash.o \
|
||||
icu.o insert.o journal.o legacy.o loadext.o \
|
||||
main.o malloc.o mem1.o mem2.o mem3.o mem4.o mem5.o mem6.o \
|
||||
memjournal.o \
|
||||
mutex.o mutex_noop.o mutex_os2.o mutex_unix.o mutex_w32.o \
|
||||
opcodes.o os.o os_os2.o os_unix.o os_win.o \
|
||||
pager.o parse.o pcache.o pragma.o prepare.o printf.o \
|
||||
@ -104,6 +105,7 @@ SRC = \
|
||||
$(TOP)/src/mem4.c \
|
||||
$(TOP)/src/mem5.c \
|
||||
$(TOP)/src/mem6.c \
|
||||
$(TOP)/src/memjournal.c \
|
||||
$(TOP)/src/mutex.c \
|
||||
$(TOP)/src/mutex.h \
|
||||
$(TOP)/src/mutex_noop.c \
|
||||
|
38
manifest
38
manifest
@ -1,5 +1,5 @@
|
||||
C Fix\sa\stypo\sin\sdocumentation.\s\sTicket\s#3447.\s(CVS\s5829)
|
||||
D 2008-10-17T15:10:37
|
||||
C Add\s"pragma\sjournal_mode=memory".\sChange\sthe\sway\srollback\sworks\sfor\sin-memory\sdatabases\sso\sthat\sit\sreuses\sthe\sjournal_mode=memory\scode.\s(CVS\s5830)
|
||||
D 2008-10-17T18:51:52
|
||||
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
|
||||
F Makefile.in 2014e5a4010ad5ebbcaedff98240b3d14ee83838
|
||||
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
||||
@ -79,7 +79,7 @@ F ext/rtree/tkt3363.test 6662237ea75bb431cd5d262dfc9535e1023315fc
|
||||
F ext/rtree/viewrtree.tcl 09526398dae87a5a87c5aac2b3854dbaf8376869
|
||||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895
|
||||
F ltmain.sh 09fe5815427dc7d0abb188bbcdf0e34896577210
|
||||
F main.mk 725b8b0ee2c1a7e53adb172984c43165eca61be1
|
||||
F main.mk c0baa7e57584ce3666a854015ad8743c5fe38dec
|
||||
F mkdll.sh 7d09b23c05d56532e9d44a50868eb4b12ff4f74a
|
||||
F mkextu.sh 416f9b7089d80e5590a29692c9d9280a10dbad9f
|
||||
F mkextw.sh 4123480947681d9b434a5e7b1ee08135abe409ac
|
||||
@ -138,12 +138,12 @@ F src/os_common.h 24525d8b7bce66c374dfc1810a6c9043f3359b60
|
||||
F src/os_os2.c 24221ff5ab20cf3472e3ec7eec595f759de55298
|
||||
F src/os_unix.c 5e3b3c9a54546249c1317cff5343e965192f7f2b
|
||||
F src/os_win.c 13bed718f62d64031b17bb3685adcf994dbf0232
|
||||
F src/pager.c d98f56128e849083f2f612196efebd982c491fea
|
||||
F src/pager.h 9c1917be28fff58118e1fe0ddbc7adfb8dd4f44d
|
||||
F src/pager.c fd11076a5a2f46a831688f036f03c57bd730dff5
|
||||
F src/pager.h 4a57b219c0765fe1870238064e3f46e4eb2cf5af
|
||||
F src/parse.y f4620f42b5e0141e20243b5f963d0fc9c180ab9b
|
||||
F src/pcache.c f8d7beceba164a34441ac37e88abb3a404f968a7
|
||||
F src/pcache.h 974d8ba609c7069af7c050cd3de698cadd090405
|
||||
F src/pragma.c f0f48d0d50e9d8fa785178fc2410244c06f6a287
|
||||
F src/pcache.c 5b80676e664019c1ebc8356cc25332dd69da6269
|
||||
F src/pcache.h 2caf2deb6cbaa75c423b8b96fc1411069ee77c75
|
||||
F src/pragma.c 10d61f211d819acd97174a41acc56394bd5bde7e
|
||||
F src/prepare.c c7e00ed1b0bdcf699b1aad651247d4dc3d281b0b
|
||||
F src/printf.c 785f87120589c1db672e37c6eb1087c456e6f84d
|
||||
F src/random.c a87afbd598aa877e23ac676ee92fd8ee5c786a51
|
||||
@ -152,7 +152,7 @@ F src/select.c d910d7350df0d918e22286c5bfd39d4ea68ec813
|
||||
F src/shell.c d83b578a8ccdd3e0e7fef4388a0887ce9f810967
|
||||
F src/sqlite.h.in ee95eeed2196e5fa98fdad007301b8d5d3733b6d
|
||||
F src/sqlite3ext.h 1db7d63ab5de4b3e6b83dd03d1a4e64fef6d2a17
|
||||
F src/sqliteInt.h 69ad0023756cc738d2a5f9def8a0b21d90350667
|
||||
F src/sqliteInt.h e5e3909f565fb020a820ccce11abca040902f075
|
||||
F src/sqliteLimit.h f435e728c6b620ef7312814d660a81f9356eb5c8
|
||||
F src/status.c 237b193efae0cf6ac3f0817a208de6c6c6ef6d76
|
||||
F src/table.c 22744786199c9195720c15a7a42cb97b2e2728d8
|
||||
@ -393,7 +393,7 @@ F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0
|
||||
F test/join4.test 1a352e4e267114444c29266ce79e941af5885916
|
||||
F test/join5.test 86675fc2919269aa923c84dd00ee4249b97990fe
|
||||
F test/journal1.test 36f2d1bb9bf03f790f43fbdb439e44c0657fab19
|
||||
F test/jrnlmode.test 54469696db41e185a37aed3b3848998cca4e0c37
|
||||
F test/jrnlmode.test c2e8212a6f6d32f8fd8f869b93553154eaf2244c
|
||||
F test/lastinsert.test 474d519c68cb79d07ecae56a763aa7f322c72f51
|
||||
F test/laststmtchanges.test 18ead86c8a87ade949a1d5658f6dc4bb111d1b02
|
||||
F test/like.test fef924922828d5a2a5bff80b9bdd9ff57a1ca500
|
||||
@ -450,14 +450,14 @@ F test/nan.test c627d79b3d36ea892563fd67584b3e8a18f0618a
|
||||
F test/notnull.test 44d600f916b770def8b095a9962dbe3be5a70d82
|
||||
F test/null.test a8b09b8ed87852742343b33441a9240022108993
|
||||
F test/openv2.test f5dd6b23e4dce828eb211649b600763c42a668df
|
||||
F test/pager.test 1e1832795e9e07a359c959ffdddcf7275a88f54c
|
||||
F test/pager2.test 070983b89a308adaba525a2f9c1ba0592c72fa3d
|
||||
F test/pager.test fd3f5009985728ef7bf0dfe32a1bbc112e6895c5
|
||||
F test/pager2.test d84c59ae4a803e03d19d72cbb5b14c71850c6163
|
||||
F test/pager3.test 2323bf27fd5bd887b580247e5bce500ceee994b4
|
||||
F test/pageropt.test 3ee6578891baaca967f0bd349e4abfa736229e1a
|
||||
F test/pagesize.test 0d9ff3fedfce6e5ffe8fa7aca9b6d3433a2e843b
|
||||
F test/pcache.test 515b4c26e9f57660357dfff5b6b697acac1abc5f
|
||||
F test/pcache2.test e2260293e892190be65de89526dbc4f92c8b5a7c
|
||||
F test/permutations.test a80a319ed2e825fa828af086d322b47fc9d9c664
|
||||
F test/permutations.test 3f24cf55e9646b138a6980f78f18190f318af9a3
|
||||
F test/pragma.test 583937903d01cad823ae195573d90c02ea945717
|
||||
F test/pragma2.test 5364893491b9231dd170e3459bfc2e2342658b47
|
||||
F test/printf.test 262a5acd3158f788e9bdf7f18d718f3af32ff6ef
|
||||
@ -467,7 +467,7 @@ F test/quick.test 70695607082b3e1ca54023b2c856991604b07703
|
||||
F test/quote.test 215897dbe8de1a6f701265836d6601cc6ed103e6
|
||||
F test/rdonly.test bd054831f8a3078e765a0657e247182486f0cb47
|
||||
F test/reindex.test 44edd3966b474468b823d481eafef0c305022254
|
||||
F test/rollback.test d67022e8f99fdb1f115de7e8ea65139263b4bd40
|
||||
F test/rollback.test 1f70ab4301d8d105d41438a436cad1fc8897f5e5
|
||||
F test/rowid.test 1c8fc43c60d273e6ea44dfb992db587f3164312c
|
||||
F test/rtree.test b85fd4f0861a40ca366ac195e363be2528dcfadf
|
||||
F test/safety.test b69e2b2dd5d52a3f78e216967086884bbc1a09c6
|
||||
@ -633,7 +633,7 @@ F tool/memleak3.tcl 7707006ee908cffff210c98158788d85bb3fcdbf
|
||||
F tool/mkkeywordhash.c c219ee2b8b5b8e7011cccfa1caec62d9812e82e7
|
||||
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e x
|
||||
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
|
||||
F tool/mksqlite3c.tcl 8aff2d49beb7d94a63841e86f3ffd4770e5054aa
|
||||
F tool/mksqlite3c.tcl ab98a8321f292b4871e362bb4435be234993d46b
|
||||
F tool/mksqlite3internalh.tcl 7b43894e21bcb1bb39e11547ce7e38a063357e87
|
||||
F tool/omittest.tcl 27d6f6e3b1e95aeb26a1c140e6eb57771c6d794a
|
||||
F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c
|
||||
@ -648,7 +648,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81
|
||||
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
||||
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
||||
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
||||
P 8065a92f705dfa04863ba4a828f5bd2803901be8
|
||||
R 4bd0b87e5fdde7ed86abc759091ffc21
|
||||
U drh
|
||||
Z 9251407651b2b71ae84b77628eaaa866
|
||||
P 5ce2ddffea807d45318619cc9e259a99dfa14346
|
||||
R d3d208ea9f507cd99d0a55a9424ad33c
|
||||
U danielk1977
|
||||
Z e1e732a777069a84074d19c41d686a93
|
||||
|
@ -1 +1 @@
|
||||
5ce2ddffea807d45318619cc9e259a99dfa14346
|
||||
39ebf01addf9d0867daafd06a38719e725128f9c
|
169
src/pager.c
169
src/pager.c
@ -18,7 +18,7 @@
|
||||
** file simultaneously, or one process from reading the database while
|
||||
** another is writing.
|
||||
**
|
||||
** @(#) $Id: pager.c,v 1.497 2008/10/07 11:51:20 danielk1977 Exp $
|
||||
** @(#) $Id: pager.c,v 1.498 2008/10/17 18:51:52 danielk1977 Exp $
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_DISKIO
|
||||
#include "sqliteInt.h"
|
||||
@ -309,12 +309,8 @@ static const unsigned char aJournalMagic[] = {
|
||||
*/
|
||||
static int pageInStatement(PgHdr *pPg){
|
||||
Pager *pPager = pPg->pPager;
|
||||
if( MEMDB ){
|
||||
return pPg->apSave[1]!=0;
|
||||
}else{
|
||||
return sqlite3BitvecTest(pPager->pInStmt, pPg->pgno);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Read a 32-bit integer from the given file descriptor. Store the integer
|
||||
@ -470,7 +466,7 @@ static u32 pager_set_pagehash(PgHdr *pPage){
|
||||
#define CHECK_PAGE(x) checkPage(x)
|
||||
static void checkPage(PgHdr *pPg){
|
||||
Pager *pPager = pPg->pPager;
|
||||
assert( !pPg->pageHash || pPager->errCode || MEMDB
|
||||
assert( !pPg->pageHash || pPager->errCode
|
||||
|| (pPg->flags&PGHDR_DIRTY) || pPg->pageHash==pager_pagehash(pPg) );
|
||||
}
|
||||
|
||||
@ -664,7 +660,7 @@ static int writeJournalHdr(Pager *pPager){
|
||||
** that garbage data is never appended to the journal file.
|
||||
*/
|
||||
assert(pPager->fd->pMethods||pPager->noSync);
|
||||
if( (pPager->noSync)
|
||||
if( (pPager->noSync) || (pPager->journalMode==PAGER_JOURNALMODE_MEMORY)
|
||||
|| (sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_SAFE_APPEND)
|
||||
){
|
||||
put32bits(&zHeader[sizeof(aJournalMagic)], 0xffffffff);
|
||||
@ -797,6 +793,7 @@ static int writeMasterJournal(Pager *pPager, const char *zMaster){
|
||||
char zBuf[sizeof(aJournalMagic)+2*4];
|
||||
|
||||
if( !zMaster || pPager->setMaster ) return SQLITE_OK;
|
||||
if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ) return SQLITE_OK;
|
||||
pPager->setMaster = 1;
|
||||
|
||||
len = strlen(zMaster);
|
||||
@ -880,7 +877,6 @@ static void pager_reset(Pager *pPager){
|
||||
*/
|
||||
static void pager_unlock(Pager *pPager){
|
||||
if( !pPager->exclusiveMode ){
|
||||
if( !MEMDB ){
|
||||
int rc = osUnlock(pPager->fd, NO_LOCK);
|
||||
if( rc ) pPager->errCode = rc;
|
||||
pPager->dbSize = -1;
|
||||
@ -918,14 +914,11 @@ static void pager_unlock(Pager *pPager){
|
||||
pPager->stmtAutoopen = 0;
|
||||
pPager->origDbSize = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if( !MEMDB || pPager->errCode==SQLITE_OK ){
|
||||
pPager->state = PAGER_UNLOCK;
|
||||
pPager->changeCountDone = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Execute a rollback if a transaction is active and unlock the
|
||||
@ -961,7 +954,6 @@ static void pagerUnlockAndRollback(Pager *p){
|
||||
static int pager_end_transaction(Pager *pPager, int hasMaster){
|
||||
int rc = SQLITE_OK;
|
||||
int rc2 = SQLITE_OK;
|
||||
assert( !MEMDB );
|
||||
if( pPager->state<PAGER_RESERVED ){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@ -971,7 +963,14 @@ static int pager_end_transaction(Pager *pPager, int hasMaster){
|
||||
pPager->stmtOpen = 0;
|
||||
}
|
||||
if( pPager->journalOpen ){
|
||||
if( pPager->journalMode==PAGER_JOURNALMODE_TRUNCATE
|
||||
if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ){
|
||||
int isMemoryJournal = sqlite3IsMemJournal(pPager->jfd);
|
||||
sqlite3OsClose(pPager->jfd);
|
||||
pPager->journalOpen = 0;
|
||||
if( !isMemoryJournal ){
|
||||
rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0);
|
||||
}
|
||||
}else if( pPager->journalMode==PAGER_JOURNALMODE_TRUNCATE
|
||||
&& (rc = sqlite3OsTruncate(pPager->jfd, 0))==SQLITE_OK ){
|
||||
pPager->journalOff = 0;
|
||||
pPager->journalStarted = 0;
|
||||
@ -1017,7 +1016,9 @@ static int pager_end_transaction(Pager *pPager, int hasMaster){
|
||||
pPager->setMaster = 0;
|
||||
pPager->needSync = 0;
|
||||
/* lruListSetFirstSynced(pPager); */
|
||||
if( !MEMDB ){
|
||||
pPager->dbSize = -1;
|
||||
}
|
||||
pPager->dbModified = 0;
|
||||
|
||||
return (rc==SQLITE_OK?rc2:rc);
|
||||
@ -1667,7 +1668,7 @@ void sqlite3PagerSetCachesize(Pager *pPager, int mxPage){
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_PAGER_PRAGMAS
|
||||
void sqlite3PagerSetSafetyLevel(Pager *pPager, int level, int bFullFsync){
|
||||
pPager->noSync = level==1 || pPager->tempFile || MEMDB;
|
||||
pPager->noSync = level==1 || pPager->tempFile;
|
||||
pPager->fullSync = level==3 && !pPager->tempFile;
|
||||
pPager->sync_flags = (bFullFsync?SQLITE_SYNC_FULL:SQLITE_SYNC_NORMAL);
|
||||
if( pPager->noSync ) pPager->needSync = 0;
|
||||
@ -1741,12 +1742,18 @@ int sqlite3PagerOpen(
|
||||
int readOnly = 0;
|
||||
int useJournal = (flags & PAGER_OMIT_JOURNAL)==0;
|
||||
int noReadlock = (flags & PAGER_NO_READLOCK)!=0;
|
||||
int journalFileSize = sqlite3JournalSize(pVfs);
|
||||
int journalFileSize;
|
||||
int pcacheSize = sqlite3PcacheSize();
|
||||
int szPageDflt = SQLITE_DEFAULT_PAGE_SIZE;
|
||||
char *zPathname = 0;
|
||||
int nPathname = 0;
|
||||
|
||||
if( sqlite3JournalSize(pVfs)>sqlite3MemJournalSize() ){
|
||||
journalFileSize = sqlite3JournalSize(pVfs);
|
||||
}else{
|
||||
journalFileSize = sqlite3MemJournalSize();
|
||||
}
|
||||
|
||||
/* The default return is a NULL pointer */
|
||||
*ppPager = 0;
|
||||
|
||||
@ -1764,7 +1771,6 @@ int sqlite3PagerOpen(
|
||||
if( strcmp(zFilename,":memory:")==0 ){
|
||||
memDb = 1;
|
||||
zPathname[0] = 0;
|
||||
useJournal = 0;
|
||||
}else
|
||||
#endif
|
||||
{
|
||||
@ -1782,7 +1788,8 @@ int sqlite3PagerOpen(
|
||||
sizeof(*pPager) + /* Pager structure */
|
||||
pcacheSize + /* PCache object */
|
||||
journalFileSize + /* The journal file structure */
|
||||
pVfs->szOsFile * 3 + /* The main db and two journal files */
|
||||
pVfs->szOsFile + /* The main db file */
|
||||
journalFileSize * 2 + /* The two journal files */
|
||||
3*nPathname + 40 /* zFilename, zDirectory, zJournal */
|
||||
);
|
||||
if( !pPager ){
|
||||
@ -1793,9 +1800,9 @@ int sqlite3PagerOpen(
|
||||
pPtr = ((u8 *)&pPager[1]) + pcacheSize;
|
||||
pPager->vfsFlags = vfsFlags;
|
||||
pPager->fd = (sqlite3_file*)&pPtr[pVfs->szOsFile*0];
|
||||
pPager->stfd = (sqlite3_file*)&pPtr[pVfs->szOsFile*1];
|
||||
pPager->jfd = (sqlite3_file*)&pPtr[pVfs->szOsFile*2];
|
||||
pPager->zFilename = (char*)&pPtr[pVfs->szOsFile*2+journalFileSize];
|
||||
pPager->stfd = (sqlite3_file*)&pPtr[pVfs->szOsFile];
|
||||
pPager->jfd = (sqlite3_file*)&pPtr[pVfs->szOsFile+journalFileSize];
|
||||
pPager->zFilename = (char*)&pPtr[pVfs->szOsFile+2*journalFileSize];
|
||||
pPager->zDirectory = &pPager->zFilename[nPathname+1];
|
||||
pPager->zJournal = &pPager->zDirectory[nPathname+1];
|
||||
pPager->pVfs = pVfs;
|
||||
@ -1845,10 +1852,14 @@ int sqlite3PagerOpen(
|
||||
}
|
||||
}
|
||||
}
|
||||
}else if( !memDb ){
|
||||
}else{
|
||||
/* If a temporary file is requested, it is not opened immediately.
|
||||
** In this case we accept the default page size and delay actually
|
||||
** opening the file until the first call to OsWrite().
|
||||
**
|
||||
** This branch is also run for an in-memory database. An in-memory
|
||||
** database is the same as a temp-file that is never written out to
|
||||
** disk and uses an in-memory rollback journal.
|
||||
*/
|
||||
tempFile = 1;
|
||||
pPager->state = PAGER_EXCLUSIVE;
|
||||
@ -1920,9 +1931,10 @@ int sqlite3PagerOpen(
|
||||
/* pPager->pLast = 0; */
|
||||
pPager->nExtra = nExtra;
|
||||
pPager->journalSizeLimit = SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT;
|
||||
assert(pPager->fd->pMethods||memDb||tempFile);
|
||||
if( !memDb ){
|
||||
assert(pPager->fd->pMethods||tempFile);
|
||||
setSectorSize(pPager);
|
||||
if( memDb ){
|
||||
pPager->journalMode = PAGER_JOURNALMODE_MEMORY;
|
||||
}
|
||||
/* pPager->pBusyHandler = 0; */
|
||||
/* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */
|
||||
@ -2043,7 +2055,7 @@ void enable_simulated_io_errors(void){
|
||||
int sqlite3PagerReadFileheader(Pager *pPager, int N, unsigned char *pDest){
|
||||
int rc = SQLITE_OK;
|
||||
memset(pDest, 0, N);
|
||||
assert(MEMDB||pPager->fd->pMethods||pPager->tempFile);
|
||||
assert(pPager->fd->pMethods||pPager->tempFile);
|
||||
if( pPager->fd->pMethods ){
|
||||
IOTRACE(("DBHDR %p 0 %d\n", pPager, N))
|
||||
rc = sqlite3OsRead(pPager->fd, pDest, N, 0);
|
||||
@ -2139,7 +2151,7 @@ static int pager_wait_on_lock(Pager *pPager, int locktype){
|
||||
assert( PAGER_EXCLUSIVE==EXCLUSIVE_LOCK );
|
||||
|
||||
/* If the file is currently unlocked then the size must be unknown */
|
||||
assert( pPager->state>=PAGER_SHARED || pPager->dbSize<0 || MEMDB );
|
||||
assert( pPager->state>=PAGER_SHARED || pPager->dbSize<0 );
|
||||
|
||||
if( pPager->state>=locktype ){
|
||||
rc = SQLITE_OK;
|
||||
@ -2161,17 +2173,12 @@ static int pager_wait_on_lock(Pager *pPager, int locktype){
|
||||
*/
|
||||
int sqlite3PagerTruncate(Pager *pPager, Pgno nPage){
|
||||
int rc = SQLITE_OK;
|
||||
assert( pPager->state>=PAGER_SHARED || MEMDB );
|
||||
|
||||
assert( pPager->state>=PAGER_SHARED );
|
||||
|
||||
sqlite3PagerPagecount(pPager, 0);
|
||||
if( pPager->errCode ){
|
||||
rc = pPager->errCode;
|
||||
}else if( nPage<(unsigned)pPager->dbSize ){
|
||||
if( MEMDB ){
|
||||
pPager->dbSize = nPage;
|
||||
pager_truncate_cache(pPager);
|
||||
}else{
|
||||
rc = syncJournal(pPager);
|
||||
if( rc==SQLITE_OK ){
|
||||
/* Get an exclusive lock on the database before truncating. */
|
||||
@ -2181,7 +2188,6 @@ int sqlite3PagerTruncate(Pager *pPager, Pgno nPage){
|
||||
rc = pager_truncate(pPager, nPage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
@ -2207,7 +2213,9 @@ int sqlite3PagerClose(Pager *pPager){
|
||||
pPager->errCode = 0;
|
||||
pPager->exclusiveMode = 0;
|
||||
pager_reset(pPager);
|
||||
if( !MEMDB ){
|
||||
pagerUnlockAndRollback(pPager);
|
||||
}
|
||||
enable_simulated_io_errors();
|
||||
sqlite3EndBenignMalloc();
|
||||
PAGERTRACE2("CLOSE %d\n", PAGERID(pPager));
|
||||
@ -2283,7 +2291,8 @@ static int syncJournal(Pager *pPager){
|
||||
** (assuming there is a journal and it needs to be synced.)
|
||||
*/
|
||||
if( pPager->needSync ){
|
||||
if( !pPager->tempFile ){
|
||||
assert( !pPager->tempFile );
|
||||
if( pPager->journalMode!=PAGER_JOURNALMODE_MEMORY ){
|
||||
int iDc = sqlite3OsDeviceCharacteristics(pPager->fd);
|
||||
assert( pPager->journalOpen );
|
||||
|
||||
@ -2439,6 +2448,7 @@ static int pagerStress(void *p, PgHdr *pPg){
|
||||
if( pPg->flags&PGHDR_NEED_SYNC ){
|
||||
rc = syncJournal(pPager);
|
||||
if( rc==SQLITE_OK && pPager->fullSync &&
|
||||
!(pPager->journalMode==PAGER_JOURNALMODE_MEMORY) &&
|
||||
!(sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_SAFE_APPEND)
|
||||
){
|
||||
pPager->nRec = 0;
|
||||
@ -2572,7 +2582,7 @@ static int pagerSharedLock(Pager *pPager){
|
||||
|
||||
if( pPager->state==PAGER_UNLOCK || isErrorReset ){
|
||||
sqlite3_vfs *pVfs = pPager->pVfs;
|
||||
if( !MEMDB ){
|
||||
assert( !MEMDB );
|
||||
int isHotJournal;
|
||||
assert( sqlite3PcacheRefCount(pPager->pPCache)==0 );
|
||||
if( !pPager->noReadlock ){
|
||||
@ -2707,7 +2717,6 @@ static int pagerSharedLock(Pager *pPager){
|
||||
pager_reset(pPager);
|
||||
}
|
||||
}
|
||||
}
|
||||
assert( pPager->exclusiveMode || pPager->state<=PAGER_SHARED );
|
||||
if( pPager->state==PAGER_UNLOCK ){
|
||||
pPager->state = PAGER_SHARED;
|
||||
@ -2845,7 +2854,6 @@ int sqlite3PagerAcquire(
|
||||
PAGER_INCR(pPager->nMiss);
|
||||
pPg->pPager = pPager;
|
||||
if( sqlite3BitvecTest(pPager->pInJournal, pgno) ){
|
||||
assert( !MEMDB );
|
||||
pPg->flags |= PGHDR_IN_JOURNAL;
|
||||
}
|
||||
memset(pPg->pExtra, 0, pPager->nExtra);
|
||||
@ -2948,7 +2956,6 @@ static int pager_open_journal(Pager *pPager){
|
||||
int flags = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_EXCLUSIVE|SQLITE_OPEN_CREATE);
|
||||
|
||||
int rc;
|
||||
assert( !MEMDB );
|
||||
assert( pPager->state>=PAGER_RESERVED );
|
||||
assert( pPager->useJournal );
|
||||
assert( pPager->pInJournal==0 );
|
||||
@ -2965,6 +2972,10 @@ static int pager_open_journal(Pager *pPager){
|
||||
}else{
|
||||
flags |= (SQLITE_OPEN_MAIN_JOURNAL);
|
||||
}
|
||||
if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ){
|
||||
sqlite3MemJournalOpen(pPager->jfd);
|
||||
rc = SQLITE_OK;
|
||||
}else{
|
||||
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
|
||||
rc = sqlite3JournalOpen(
|
||||
pVfs, pPager->zJournal, pPager->jfd, flags, jrnlBufferSize(pPager)
|
||||
@ -2972,6 +2983,7 @@ static int pager_open_journal(Pager *pPager){
|
||||
#else
|
||||
rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, flags, 0);
|
||||
#endif
|
||||
}
|
||||
assert( rc!=SQLITE_OK || pPager->jfd->pMethods );
|
||||
pPager->journalOff = 0;
|
||||
pPager->setMaster = 0;
|
||||
@ -3046,11 +3058,8 @@ int sqlite3PagerBegin(DbPage *pPg, int exFlag){
|
||||
assert( pPager->state!=PAGER_UNLOCK );
|
||||
if( pPager->state==PAGER_SHARED ){
|
||||
assert( pPager->pInJournal==0 );
|
||||
assert( !MEMDB );
|
||||
sqlite3PcacheAssertFlags(pPager->pPCache, 0, PGHDR_IN_JOURNAL);
|
||||
if( MEMDB ){
|
||||
pPager->state = PAGER_EXCLUSIVE;
|
||||
pPager->origDbSize = pPager->dbSize;
|
||||
}else{
|
||||
rc = sqlite3OsLock(pPager->fd, RESERVED_LOCK);
|
||||
if( rc==SQLITE_OK ){
|
||||
pPager->state = PAGER_RESERVED;
|
||||
@ -3067,7 +3076,6 @@ int sqlite3PagerBegin(DbPage *pPg, int exFlag){
|
||||
&& pPager->journalMode!=PAGER_JOURNALMODE_OFF ){
|
||||
rc = pager_open_journal(pPager);
|
||||
}
|
||||
}
|
||||
}else if( pPager->journalOpen && pPager->journalOff==0 ){
|
||||
/* This happens when the pager was in exclusive-access mode the last
|
||||
** time a (read or write) transaction was successfully concluded
|
||||
@ -3192,15 +3200,8 @@ static int pager_write(PgHdr *pPg){
|
||||
** EXCLUSIVE lock on the main database file. Write the current page to
|
||||
** the transaction journal if it is not there already.
|
||||
*/
|
||||
if( !(pPg->flags&PGHDR_IN_JOURNAL) && (pPager->journalOpen || MEMDB) ){
|
||||
if( !(pPg->flags&PGHDR_IN_JOURNAL) && pPager->journalOpen ){
|
||||
if( (int)pPg->pgno <= pPager->origDbSize ){
|
||||
if( MEMDB ){
|
||||
PAGERTRACE3("JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno);
|
||||
rc = sqlite3PcachePreserve(pPg, 0);
|
||||
if( rc!=SQLITE_OK ){
|
||||
return rc;
|
||||
}
|
||||
}else{
|
||||
u32 cksum;
|
||||
char *pData2;
|
||||
|
||||
@ -3243,7 +3244,6 @@ static int pager_write(PgHdr *pPg){
|
||||
if( pPager->stmtInUse ){
|
||||
sqlite3BitvecSet(pPager->pInStmt, pPg->pgno);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
if( !pPager->journalStarted && !pPager->noSync ){
|
||||
pPg->flags |= PGHDR_NEED_SYNC;
|
||||
@ -3269,13 +3269,6 @@ static int pager_write(PgHdr *pPg){
|
||||
){
|
||||
assert( (pPg->flags&PGHDR_IN_JOURNAL)
|
||||
|| (int)pPg->pgno>pPager->origDbSize );
|
||||
if( MEMDB ){
|
||||
rc = sqlite3PcachePreserve(pPg, 1);
|
||||
if( rc!=SQLITE_OK ){
|
||||
return rc;
|
||||
}
|
||||
PAGERTRACE3("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno);
|
||||
}else{
|
||||
i64 offset = pPager->stmtNRec*(4+pPager->pageSize);
|
||||
char *pData2 = CODEC2(pPager, pData, pPg->pgno, 7);
|
||||
rc = write32bits(pPager->stfd, offset, pPg->pgno);
|
||||
@ -3291,14 +3284,13 @@ static int pager_write(PgHdr *pPg){
|
||||
sqlite3BitvecSet(pPager->pInStmt, pPg->pgno);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Update the database size and return.
|
||||
*/
|
||||
assert( pPager->state>=PAGER_SHARED );
|
||||
if( pPager->dbSize<(int)pPg->pgno ){
|
||||
pPager->dbSize = pPg->pgno;
|
||||
if( !MEMDB && pPager->dbSize==PENDING_BYTE/pPager->pageSize ){
|
||||
if( pPager->dbSize==PENDING_BYTE/pPager->pageSize ){
|
||||
pPager->dbSize++;
|
||||
}
|
||||
}
|
||||
@ -3322,7 +3314,7 @@ int sqlite3PagerWrite(DbPage *pDbPage){
|
||||
Pager *pPager = pPg->pPager;
|
||||
Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize);
|
||||
|
||||
if( !MEMDB && nPagePerSector>1 ){
|
||||
if( nPagePerSector>1 ){
|
||||
Pgno nPageCount; /* Total number of pages in database file */
|
||||
Pgno pg1; /* First page of the sector pPg is located on. */
|
||||
int nPage; /* Number of pages starting at pg1 to journal */
|
||||
@ -3332,6 +3324,7 @@ int sqlite3PagerWrite(DbPage *pDbPage){
|
||||
/* Set the doNotSync flag to 1. This is because we cannot allow a journal
|
||||
** header to be written between the pages journaled by this function.
|
||||
*/
|
||||
assert( !MEMDB );
|
||||
assert( pPager->doNotSync==0 );
|
||||
pPager->doNotSync = 1;
|
||||
|
||||
@ -3439,7 +3432,7 @@ int sqlite3PagerDontWrite(DbPage *pDbPage){
|
||||
Pager *pPager = pPg->pPager;
|
||||
int rc;
|
||||
|
||||
if( MEMDB || pPg->pgno>pPager->origDbSize ){
|
||||
if( pPg->pgno>pPager->origDbSize ){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
if( pPager->pAlwaysRollback==0 ){
|
||||
@ -3500,7 +3493,6 @@ void sqlite3PagerDontRollback(DbPage *pPg){
|
||||
){
|
||||
return;
|
||||
}
|
||||
assert( !MEMDB ); /* For a memdb, pPager->journalOpen is always 0 */
|
||||
|
||||
#ifdef SQLITE_SECURE_DELETE
|
||||
if( (pPg->flags & PGHDR_IN_JOURNAL)!=0 || (int)pPg->pgno>pPager->origDbSize ){
|
||||
@ -3792,16 +3784,9 @@ int sqlite3PagerCommitPhaseTwo(Pager *pPager){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
PAGERTRACE2("COMMIT %d\n", PAGERID(pPager));
|
||||
if( MEMDB ){
|
||||
sqlite3PcacheCommit(pPager->pPCache, 0);
|
||||
sqlite3PcacheCleanAll(pPager->pPCache);
|
||||
sqlite3PcacheAssertFlags(pPager->pPCache, 0, PGHDR_IN_JOURNAL);
|
||||
pPager->state = PAGER_SHARED;
|
||||
}else{
|
||||
assert( pPager->state==PAGER_SYNCED || !pPager->dirtyCache );
|
||||
assert( pPager->state==PAGER_SYNCED || MEMDB || !pPager->dirtyCache );
|
||||
rc = pager_end_transaction(pPager, pPager->setMaster);
|
||||
rc = pager_error(pPager, rc);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -3820,16 +3805,7 @@ int sqlite3PagerCommitPhaseTwo(Pager *pPager){
|
||||
int sqlite3PagerRollback(Pager *pPager){
|
||||
int rc = SQLITE_OK;
|
||||
PAGERTRACE2("ROLLBACK %d\n", PAGERID(pPager));
|
||||
if( MEMDB ){
|
||||
sqlite3PcacheRollback(pPager->pPCache, 1, pPager->xReiniter);
|
||||
sqlite3PcacheRollback(pPager->pPCache, 0, pPager->xReiniter);
|
||||
sqlite3PcacheCleanAll(pPager->pPCache);
|
||||
sqlite3PcacheAssertFlags(pPager->pPCache, 0, PGHDR_IN_JOURNAL);
|
||||
pPager->dbSize = pPager->origDbSize;
|
||||
pager_truncate_cache(pPager);
|
||||
pPager->stmtInUse = 0;
|
||||
pPager->state = PAGER_SHARED;
|
||||
}else if( !pPager->dirtyCache || !pPager->journalOpen ){
|
||||
if( !pPager->dirtyCache || !pPager->journalOpen ){
|
||||
rc = pager_end_transaction(pPager, pPager->setMaster);
|
||||
}else if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){
|
||||
if( pPager->state>=PAGER_EXCLUSIVE ){
|
||||
@ -3848,7 +3824,9 @@ int sqlite3PagerRollback(Pager *pPager){
|
||||
rc = pager_playback(pPager, 0);
|
||||
}
|
||||
|
||||
if( !MEMDB ){
|
||||
pPager->dbSize = -1;
|
||||
}
|
||||
|
||||
/* If an error occurs during a ROLLBACK, we can no longer trust the pager
|
||||
** cache. So call pager_error() on the way out to make any error
|
||||
@ -3918,11 +3896,6 @@ static int pagerStmtBegin(Pager *pPager){
|
||||
assert( pPager->state>=PAGER_SHARED );
|
||||
assert( pPager->dbSize>=0 );
|
||||
PAGERTRACE2("STMT-BEGIN %d\n", PAGERID(pPager));
|
||||
if( MEMDB ){
|
||||
pPager->stmtInUse = 1;
|
||||
pPager->stmtSize = pPager->dbSize;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
if( !pPager->journalOpen ){
|
||||
pPager->stmtAutoopen = 1;
|
||||
return SQLITE_OK;
|
||||
@ -3939,10 +3912,14 @@ static int pagerStmtBegin(Pager *pPager){
|
||||
pPager->stmtHdrOff = 0;
|
||||
pPager->stmtCksum = pPager->cksumInit;
|
||||
if( !pPager->stmtOpen ){
|
||||
if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ){
|
||||
sqlite3MemJournalOpen(pPager->stfd);
|
||||
}else{
|
||||
rc = sqlite3PagerOpentemp(pPager, pPager->stfd, SQLITE_OPEN_SUBJOURNAL);
|
||||
if( rc ){
|
||||
goto stmt_begin_failed;
|
||||
}
|
||||
}
|
||||
pPager->stmtOpen = 1;
|
||||
pPager->stmtNRec = 0;
|
||||
}
|
||||
@ -3968,14 +3945,13 @@ int sqlite3PagerStmtBegin(Pager *pPager){
|
||||
int sqlite3PagerStmtCommit(Pager *pPager){
|
||||
if( pPager->stmtInUse ){
|
||||
PAGERTRACE2("STMT-COMMIT %d\n", PAGERID(pPager));
|
||||
if( !MEMDB ){
|
||||
sqlite3BitvecDestroy(pPager->pInStmt);
|
||||
pPager->pInStmt = 0;
|
||||
}else{
|
||||
sqlite3PcacheCommit(pPager->pPCache, 1);
|
||||
}
|
||||
pPager->stmtNRec = 0;
|
||||
pPager->stmtInUse = 0;
|
||||
if( sqlite3IsMemJournal(pPager->stfd) ){
|
||||
sqlite3OsTruncate(pPager->stfd, 0);
|
||||
}
|
||||
}
|
||||
pPager->stmtAutoopen = 0;
|
||||
return SQLITE_OK;
|
||||
@ -3988,14 +3964,7 @@ int sqlite3PagerStmtRollback(Pager *pPager){
|
||||
int rc;
|
||||
if( pPager->stmtInUse ){
|
||||
PAGERTRACE2("STMT-ROLLBACK %d\n", PAGERID(pPager));
|
||||
if( MEMDB ){
|
||||
sqlite3PcacheRollback(pPager->pPCache, 1, pPager->xReiniter);
|
||||
pPager->dbSize = pPager->stmtSize;
|
||||
pager_truncate_cache(pPager);
|
||||
rc = SQLITE_OK;
|
||||
}else{
|
||||
rc = pager_stmt_playback(pPager);
|
||||
}
|
||||
sqlite3PagerStmtCommit(pPager);
|
||||
}else{
|
||||
rc = SQLITE_OK;
|
||||
@ -4124,7 +4093,6 @@ int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){
|
||||
pPg->flags |= (pPgOld->flags&PGHDR_NEED_SYNC);
|
||||
}
|
||||
if( sqlite3BitvecTest(pPager->pInJournal, pgno) ){
|
||||
assert( !MEMDB );
|
||||
pPg->flags |= PGHDR_IN_JOURNAL;
|
||||
}
|
||||
|
||||
@ -4233,17 +4201,20 @@ int sqlite3PagerLockingMode(Pager *pPager, int eMode){
|
||||
** journal-mode.
|
||||
*/
|
||||
int sqlite3PagerJournalMode(Pager *pPager, int eMode){
|
||||
if( !MEMDB ){
|
||||
assert( eMode==PAGER_JOURNALMODE_QUERY
|
||||
|| eMode==PAGER_JOURNALMODE_DELETE
|
||||
|| eMode==PAGER_JOURNALMODE_TRUNCATE
|
||||
|| eMode==PAGER_JOURNALMODE_PERSIST
|
||||
|| eMode==PAGER_JOURNALMODE_OFF );
|
||||
|| eMode==PAGER_JOURNALMODE_OFF
|
||||
|| eMode==PAGER_JOURNALMODE_MEMORY );
|
||||
assert( PAGER_JOURNALMODE_QUERY<0 );
|
||||
if( eMode>=0 ){
|
||||
pPager->journalMode = eMode;
|
||||
}else{
|
||||
assert( eMode==PAGER_JOURNALMODE_QUERY );
|
||||
}
|
||||
}
|
||||
return (int)pPager->journalMode;
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,7 @@
|
||||
** subsystem. The page cache subsystem reads and writes a file a page
|
||||
** at a time and provides a journal for rollback.
|
||||
**
|
||||
** @(#) $Id: pager.h,v 1.85 2008/09/29 11:49:48 danielk1977 Exp $
|
||||
** @(#) $Id: pager.h,v 1.86 2008/10/17 18:51:53 danielk1977 Exp $
|
||||
*/
|
||||
|
||||
#ifndef _PAGER_H_
|
||||
@ -66,6 +66,7 @@ typedef struct PgHdr DbPage;
|
||||
#define PAGER_JOURNALMODE_PERSIST 1 /* Commit by zeroing journal header */
|
||||
#define PAGER_JOURNALMODE_OFF 2 /* Journal omitted. */
|
||||
#define PAGER_JOURNALMODE_TRUNCATE 3 /* Commit by truncating journal */
|
||||
#define PAGER_JOURNALMODE_MEMORY 4 /* In-memory journal file */
|
||||
|
||||
/*
|
||||
** See source code comments for a detailed description of the following
|
||||
|
76
src/pcache.c
76
src/pcache.c
@ -11,7 +11,7 @@
|
||||
*************************************************************************
|
||||
** This file implements that page cache.
|
||||
**
|
||||
** @(#) $Id: pcache.c,v 1.33 2008/09/29 11:49:48 danielk1977 Exp $
|
||||
** @(#) $Id: pcache.c,v 1.34 2008/10/17 18:51:53 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@ -491,8 +491,6 @@ static void pcachePageFree(PgHdr *p){
|
||||
if( p->pCache->bPurgeable ){
|
||||
pcache_g.nCurrentPage--;
|
||||
}
|
||||
pcacheFree(p->apSave[0]);
|
||||
pcacheFree(p->apSave[1]);
|
||||
pcacheFree(p);
|
||||
}
|
||||
|
||||
@ -813,7 +811,6 @@ void sqlite3PcacheMakeDirty(PgHdr *p){
|
||||
|
||||
static void pcacheMakeClean(PgHdr *p){
|
||||
PCache *pCache = p->pCache;
|
||||
assert( p->apSave[0]==0 && p->apSave[1]==0 );
|
||||
assert( p->flags & PGHDR_DIRTY );
|
||||
pcacheRemoveFromList(&pCache->pDirty, p);
|
||||
pcacheAddToList(&pCache->pClean, p);
|
||||
@ -844,7 +841,6 @@ void sqlite3PcacheCleanAll(PCache *pCache){
|
||||
PgHdr *p;
|
||||
pcacheEnterMutex();
|
||||
while( (p = pCache->pDirty)!=0 ){
|
||||
assert( p->apSave[0]==0 && p->apSave[1]==0 );
|
||||
pcacheRemoveFromList(&pCache->pDirty, p);
|
||||
p->flags &= ~PGHDR_DIRTY;
|
||||
pcacheAddToList(&pCache->pClean, p);
|
||||
@ -869,10 +865,6 @@ void sqlite3PcacheMove(PgHdr *p, Pgno newPgno){
|
||||
pcacheRemoveFromHash(p);
|
||||
p->pgno = newPgno;
|
||||
if( newPgno==0 ){
|
||||
pcacheFree(p->apSave[0]);
|
||||
pcacheFree(p->apSave[1]);
|
||||
p->apSave[0] = 0;
|
||||
p->apSave[1] = 0;
|
||||
if( (p->flags & PGHDR_DIRTY) ){
|
||||
pcacheMakeClean(p);
|
||||
}
|
||||
@ -970,72 +962,6 @@ void sqlite3PcacheClose(PCache *pCache){
|
||||
pcacheExitMutex();
|
||||
}
|
||||
|
||||
/*
|
||||
** Preserve the content of the page. It is assumed that the content
|
||||
** has not been preserved already.
|
||||
**
|
||||
** If idJournal==0 then this is for the overall transaction.
|
||||
** If idJournal==1 then this is for the statement journal.
|
||||
**
|
||||
** This routine is used for in-memory databases only.
|
||||
**
|
||||
** Return SQLITE_OK or SQLITE_NOMEM if a memory allocation fails.
|
||||
*/
|
||||
int sqlite3PcachePreserve(PgHdr *p, int idJournal){
|
||||
void *x;
|
||||
int sz;
|
||||
assert( p->pCache->bPurgeable==0 );
|
||||
assert( p->apSave[idJournal]==0 );
|
||||
sz = p->pCache->szPage;
|
||||
p->apSave[idJournal] = x = sqlite3PageMalloc( sz );
|
||||
if( x==0 ) return SQLITE_NOMEM;
|
||||
memcpy(x, p->pData, sz);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Commit a change previously preserved.
|
||||
*/
|
||||
void sqlite3PcacheCommit(PCache *pCache, int idJournal){
|
||||
PgHdr *p;
|
||||
int mask = idJournal==0 ? ~PGHDR_IN_JOURNAL : 0xffffff;
|
||||
pcacheEnterMutex(); /* Mutex is required to call pcacheFree() */
|
||||
for(p=pCache->pDirty; p; p=p->pNext){
|
||||
if( p->apSave[idJournal] ){
|
||||
pcacheFree(p->apSave[idJournal]);
|
||||
p->apSave[idJournal] = 0;
|
||||
}
|
||||
p->flags &= mask;
|
||||
}
|
||||
pcacheExitMutex();
|
||||
}
|
||||
|
||||
/*
|
||||
** Rollback a change previously preserved.
|
||||
*/
|
||||
void sqlite3PcacheRollback(
|
||||
PCache *pCache, /* Pager cache */
|
||||
int idJournal, /* Which copy to rollback to */
|
||||
void (*xReiniter)(PgHdr*) /* Called on each rolled back page */
|
||||
){
|
||||
PgHdr *p;
|
||||
int sz;
|
||||
int mask = idJournal==0 ? ~PGHDR_IN_JOURNAL : 0xffffff;
|
||||
pcacheEnterMutex(); /* Mutex is required to call pcacheFree() */
|
||||
sz = pCache->szPage;
|
||||
for(p=pCache->pDirty; p; p=p->pNext){
|
||||
if( p->apSave[idJournal] ){
|
||||
memcpy(p->pData, p->apSave[idJournal], sz);
|
||||
pcacheFree(p->apSave[idJournal]);
|
||||
p->apSave[idJournal] = 0;
|
||||
if( xReiniter ){
|
||||
xReiniter(p);
|
||||
}
|
||||
}
|
||||
p->flags &= mask;
|
||||
}
|
||||
pcacheExitMutex();
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
/*
|
||||
|
@ -12,7 +12,7 @@
|
||||
** This header file defines the interface that the sqlite page cache
|
||||
** subsystem.
|
||||
**
|
||||
** @(#) $Id: pcache.h,v 1.13 2008/10/11 17:42:29 drh Exp $
|
||||
** @(#) $Id: pcache.h,v 1.14 2008/10/17 18:51:53 danielk1977 Exp $
|
||||
*/
|
||||
|
||||
#ifndef _PCACHE_H_
|
||||
@ -40,7 +40,7 @@ struct PgHdr {
|
||||
*/
|
||||
i16 nRef; /* Number of users of this page */
|
||||
PCache *pCache; /* Cache that owns this page */
|
||||
void *apSave[2]; /* Journal entries for in-memory databases */
|
||||
|
||||
/**********************************************************************
|
||||
** Elements above are accessible at any time by the owner of the cache
|
||||
** without the need for a mutex. The elements that follow can only be
|
||||
@ -109,11 +109,6 @@ void sqlite3PcacheMove(PgHdr*, Pgno);
|
||||
/* Remove all pages with pgno>x. Reset the cache if x==0 */
|
||||
void sqlite3PcacheTruncate(PCache*, Pgno x);
|
||||
|
||||
/* Routines used to implement transactions on memory-only databases. */
|
||||
int sqlite3PcachePreserve(PgHdr*, int); /* Preserve current page content */
|
||||
void sqlite3PcacheCommit(PCache*, int); /* Drop preserved copy */
|
||||
void sqlite3PcacheRollback(PCache*, int, void (*xReiniter)(PgHdr*));
|
||||
|
||||
/* Get a list of all dirty pages in the cache, sorted by page number */
|
||||
PgHdr *sqlite3PcacheDirtyList(PCache*);
|
||||
|
||||
|
11
src/pragma.c
11
src/pragma.c
@ -11,7 +11,7 @@
|
||||
*************************************************************************
|
||||
** This file contains code used to implement the PRAGMA command.
|
||||
**
|
||||
** $Id: pragma.c,v 1.189 2008/10/10 17:47:21 danielk1977 Exp $
|
||||
** $Id: pragma.c,v 1.190 2008/10/17 18:51:53 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include <ctype.h>
|
||||
@ -455,11 +455,13 @@ void sqlite3Pragma(
|
||||
|
||||
/*
|
||||
** PRAGMA [database.]journal_mode
|
||||
** PRAGMA [database.]journal_mode = (delete|persist|off)
|
||||
** PRAGMA [database.]journal_mode = (delete|persist|memory|off)
|
||||
*/
|
||||
if( sqlite3StrICmp(zLeft,"journal_mode")==0 ){
|
||||
int eMode;
|
||||
static char * const azModeName[] = {"delete", "persist", "off", "truncate"};
|
||||
static char * const azModeName[] = {
|
||||
"delete", "persist", "off", "truncate", "memory"
|
||||
};
|
||||
|
||||
if( zRight==0 ){
|
||||
eMode = PAGER_JOURNALMODE_QUERY;
|
||||
@ -503,7 +505,8 @@ void sqlite3Pragma(
|
||||
assert( eMode==PAGER_JOURNALMODE_DELETE
|
||||
|| eMode==PAGER_JOURNALMODE_TRUNCATE
|
||||
|| eMode==PAGER_JOURNALMODE_PERSIST
|
||||
|| eMode==PAGER_JOURNALMODE_OFF );
|
||||
|| eMode==PAGER_JOURNALMODE_OFF
|
||||
|| eMode==PAGER_JOURNALMODE_MEMORY );
|
||||
sqlite3VdbeSetNumCols(v, 1);
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "journal_mode", P4_STATIC);
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0,
|
||||
|
@ -11,7 +11,7 @@
|
||||
*************************************************************************
|
||||
** Internal interface definitions for SQLite.
|
||||
**
|
||||
** @(#) $Id: sqliteInt.h,v 1.784 2008/10/13 15:35:09 drh Exp $
|
||||
** @(#) $Id: sqliteInt.h,v 1.785 2008/10/17 18:51:53 danielk1977 Exp $
|
||||
*/
|
||||
#ifndef _SQLITEINT_H_
|
||||
#define _SQLITEINT_H_
|
||||
@ -2505,6 +2505,10 @@ int sqlite3FindInIndex(Parse *, Expr *, int*);
|
||||
#define sqlite3JournalSize(pVfs) ((pVfs)->szOsFile)
|
||||
#endif
|
||||
|
||||
void sqlite3MemJournalOpen(sqlite3_file *);
|
||||
int sqlite3MemJournalSize();
|
||||
int sqlite3IsMemJournal(sqlite3_file *);
|
||||
|
||||
#if SQLITE_MAX_EXPR_DEPTH>0
|
||||
void sqlite3ExprSetHeight(Parse *pParse, Expr *p);
|
||||
int sqlite3SelectExprHeight(Select *);
|
||||
|
@ -11,7 +11,7 @@
|
||||
# This file implements regression tests for SQLite library. The focus
|
||||
# of these tests is the journal mode pragma.
|
||||
#
|
||||
# $Id: jrnlmode.test,v 1.6 2008/09/26 21:08:08 drh Exp $
|
||||
# $Id: jrnlmode.test,v 1.7 2008/10/17 18:51:53 danielk1977 Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
@ -95,7 +95,7 @@ ifcapable attach {
|
||||
PRAGMA main.journal_mode;
|
||||
PRAGMA aux1.journal_mode;
|
||||
}
|
||||
} {persist persist}
|
||||
} {persist memory}
|
||||
do_test jrnlmode-1.10 {
|
||||
execsql {
|
||||
PRAGMA main.journal_mode = OFF;
|
||||
@ -105,7 +105,7 @@ ifcapable attach {
|
||||
PRAGMA temp.journal_mode;
|
||||
PRAGMA aux1.journal_mode;
|
||||
}
|
||||
} {off persist persist}
|
||||
} {off persist memory}
|
||||
do_test jrnlmode-1.11 {
|
||||
execsql {
|
||||
PRAGMA journal_mode;
|
||||
@ -120,8 +120,9 @@ ifcapable attach {
|
||||
PRAGMA aux1.journal_mode;
|
||||
PRAGMA aux2.journal_mode;
|
||||
}
|
||||
} {off persist persist}
|
||||
} {off memory memory}
|
||||
do_test jrnlmode-1.11 {
|
||||
# The journal-mode used by in-memory databases cannot be changed.
|
||||
execsql {
|
||||
PRAGMA aux1.journal_mode = DELETE;
|
||||
}
|
||||
@ -130,7 +131,7 @@ ifcapable attach {
|
||||
PRAGMA aux1.journal_mode;
|
||||
PRAGMA aux2.journal_mode;
|
||||
}
|
||||
} {off delete persist}
|
||||
} {off memory memory}
|
||||
do_test jrnlmode-1.12 {
|
||||
execsql {
|
||||
PRAGMA journal_mode = delete;
|
||||
@ -141,7 +142,7 @@ ifcapable attach {
|
||||
PRAGMA aux1.journal_mode;
|
||||
PRAGMA aux2.journal_mode;
|
||||
}
|
||||
} {delete delete delete delete}
|
||||
} {delete delete memory memory}
|
||||
do_test jrnlmode-1.13 {
|
||||
execsql {
|
||||
ATTACH ':memory:' as aux3;
|
||||
@ -153,7 +154,7 @@ ifcapable attach {
|
||||
PRAGMA aux2.journal_mode;
|
||||
PRAGMA aux3.journal_mode;
|
||||
}
|
||||
} {delete delete delete delete delete}
|
||||
} {delete delete memory memory memory}
|
||||
do_test jrnlmode-1.14 {
|
||||
execsql {
|
||||
PRAGMA journal_mode = TRUNCATE;
|
||||
@ -165,7 +166,7 @@ ifcapable attach {
|
||||
PRAGMA aux2.journal_mode;
|
||||
PRAGMA aux3.journal_mode;
|
||||
}
|
||||
} {truncate truncate truncate truncate truncate}
|
||||
} {truncate truncate memory memory memory}
|
||||
|
||||
do_test jrnlmode-1.99 {
|
||||
execsql {
|
||||
|
@ -11,7 +11,7 @@
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this script is page cache subsystem.
|
||||
#
|
||||
# $Id: pager.test,v 1.31 2008/08/20 14:49:25 danielk1977 Exp $
|
||||
# $Id: pager.test,v 1.32 2008/10/17 18:51:53 danielk1977 Exp $
|
||||
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
@ -415,12 +415,14 @@ ifcapable memorydb {
|
||||
pager_truncate $::p2 5
|
||||
} {}
|
||||
do_test pager-4.6.3 {
|
||||
set page1 [page_get $::p2 1]
|
||||
for {set i 1} {$i<5} {incr i} {
|
||||
set p [page_get $::p2 $i]
|
||||
page_write $p "Page $i"
|
||||
pager_commit $::p2
|
||||
page_unref $p
|
||||
}
|
||||
page_unref $page1
|
||||
# pager_truncate $::p2 3
|
||||
} {}
|
||||
do_test pager-4.6.4 {
|
||||
|
@ -11,7 +11,7 @@
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this script is page cache subsystem.
|
||||
#
|
||||
# $Id: pager2.test,v 1.7 2008/08/20 14:49:25 danielk1977 Exp $
|
||||
# $Id: pager2.test,v 1.8 2008/10/17 18:51:53 danielk1977 Exp $
|
||||
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
@ -33,13 +33,13 @@ do_test pager2-1.0 {
|
||||
} {0}
|
||||
do_test pager2-1.1 {
|
||||
pager_stats $::p1
|
||||
} {ref 0 page 0 max 10 size 0 state 0 err 0 hit 0 miss 0 ovfl 0}
|
||||
} {ref 0 page 0 max 10 size 0 state 4 err 0 hit 0 miss 0 ovfl 0}
|
||||
do_test pager2-1.2 {
|
||||
pager_pagecount $::p1
|
||||
} {0}
|
||||
do_test pager2-1.3 {
|
||||
pager_stats $::p1
|
||||
} {ref 0 page 0 max 10 size 0 state 0 err 0 hit 0 miss 0 ovfl 0}
|
||||
} {ref 0 page 0 max 10 size 0 state 4 err 0 hit 0 miss 0 ovfl 0}
|
||||
do_test pager2-1.4 {
|
||||
pager_close $::p1
|
||||
} {}
|
||||
@ -62,7 +62,7 @@ do_test pager2-2.3.1 {
|
||||
} {}
|
||||
do_test pager2-2.3.2 {
|
||||
pager_stats $::p1
|
||||
} {ref 0 page 0 max 10 size 0 state 0 err 0 hit 0 miss 0 ovfl 0}
|
||||
} {ref 0 page 0 max 10 size 0 state 4 err 0 hit 0 miss 0 ovfl 0}
|
||||
do_test pager2-2.3.3 {
|
||||
set v [catch {
|
||||
set ::g1 [page_get $::p1 1]
|
||||
@ -72,7 +72,7 @@ do_test pager2-2.3.3 {
|
||||
} {0}
|
||||
do_test pager2-2.3.3 {
|
||||
pager_stats $::p1
|
||||
} {ref 1 page 1 max 10 size 0 state 1 err 0 hit 0 miss 1 ovfl 0}
|
||||
} {ref 1 page 1 max 10 size 0 state 4 err 0 hit 0 miss 1 ovfl 0}
|
||||
do_test pager2-2.3.4 {
|
||||
set ::gx [page_lookup $::p1 1]
|
||||
page_unref $::gx
|
||||
@ -80,22 +80,22 @@ do_test pager2-2.3.4 {
|
||||
} {1}
|
||||
do_test pager2-2.3.5 {
|
||||
pager_stats $::p1
|
||||
} {ref 1 page 1 max 10 size 0 state 1 err 0 hit 0 miss 1 ovfl 0}
|
||||
} {ref 1 page 1 max 10 size 0 state 4 err 0 hit 0 miss 1 ovfl 0}
|
||||
do_test pager2-2.3.6 {
|
||||
expr {$::g1==$::gx}
|
||||
} {1}
|
||||
do_test pager2-2.3.7 {
|
||||
pager_stats $::p1
|
||||
} {ref 1 page 1 max 10 size 0 state 1 err 0 hit 0 miss 1 ovfl 0}
|
||||
} {ref 1 page 1 max 10 size 0 state 4 err 0 hit 0 miss 1 ovfl 0}
|
||||
do_test pager2-2.4 {
|
||||
pager_stats $::p1
|
||||
} {ref 1 page 1 max 10 size 0 state 1 err 0 hit 0 miss 1 ovfl 0}
|
||||
} {ref 1 page 1 max 10 size 0 state 4 err 0 hit 0 miss 1 ovfl 0}
|
||||
do_test pager2-2.5 {
|
||||
pager_pagecount $::p1
|
||||
} {0}
|
||||
do_test pager2-2.6 {
|
||||
pager_stats $::p1
|
||||
} {ref 1 page 1 max 10 size 0 state 1 err 0 hit 0 miss 1 ovfl 0}
|
||||
} {ref 1 page 1 max 10 size 0 state 4 err 0 hit 0 miss 1 ovfl 0}
|
||||
do_test pager2-2.7 {
|
||||
page_number $::g1
|
||||
} {1}
|
||||
@ -107,7 +107,7 @@ do_test pager2-2.9 {
|
||||
} {}
|
||||
do_test pager2-2.10 {
|
||||
pager_stats $::p1
|
||||
} {ref 0 page 1 max 10 size 0 state 0 err 0 hit 0 miss 1 ovfl 0}
|
||||
} {ref 0 page 1 max 10 size 0 state 4 err 0 hit 0 miss 1 ovfl 0}
|
||||
do_test pager2-2.11 {
|
||||
set ::g1 [page_get $::p1 1]
|
||||
expr {$::g1!=0}
|
||||
@ -117,7 +117,7 @@ do_test pager2-2.12 {
|
||||
} {1}
|
||||
do_test pager2-2.13 {
|
||||
pager_stats $::p1
|
||||
} {ref 1 page 1 max 10 size 0 state 1 err 0 hit 1 miss 1 ovfl 0}
|
||||
} {ref 1 page 1 max 10 size 0 state 4 err 0 hit 1 miss 1 ovfl 0}
|
||||
do_test pager2-2.14 {
|
||||
set v [catch {
|
||||
page_write $::g1 "Page-One"
|
||||
@ -138,19 +138,19 @@ do_test pager2-2.17 {
|
||||
} {0 {}}
|
||||
do_test pager2-2.20 {
|
||||
pager_stats $::p1
|
||||
} {ref 1 page 1 max 10 size 1 state 1 err 0 hit 1 miss 1 ovfl 0}
|
||||
} {ref 1 page 1 max 10 size 1 state 4 err 0 hit 1 miss 1 ovfl 0}
|
||||
do_test pager2-2.19 {
|
||||
pager_pagecount $::p1
|
||||
} {1}
|
||||
do_test pager2-2.21 {
|
||||
pager_stats $::p1
|
||||
} {ref 1 page 1 max 10 size 1 state 1 err 0 hit 1 miss 1 ovfl 0}
|
||||
} {ref 1 page 1 max 10 size 1 state 4 err 0 hit 1 miss 1 ovfl 0}
|
||||
do_test pager2-2.22 {
|
||||
page_unref $::g1
|
||||
} {}
|
||||
do_test pager2-2.23 {
|
||||
pager_stats $::p1
|
||||
} {ref 0 page 1 max 10 size 1 state 0 err 0 hit 1 miss 1 ovfl 0}
|
||||
} {ref 0 page 1 max 10 size 1 state 4 err 0 hit 1 miss 1 ovfl 0}
|
||||
do_test pager2-2.24 {
|
||||
set v [catch {
|
||||
page_get $::p1 1
|
||||
@ -215,14 +215,17 @@ do_test pager2-3.5 {
|
||||
page_unref $::g(1)
|
||||
} {}
|
||||
for {set i 2} {$i<=20} {incr i} {
|
||||
set page1 [page_get $::p1 1]
|
||||
do_test pager2-3.6.[expr {$i-1}] [subst {
|
||||
set gx \[page_get $::p1 $i\]
|
||||
set v \[page_read \$gx\]
|
||||
page_unref \$gx
|
||||
set v
|
||||
}] "Page-$i"
|
||||
page_unref $page1
|
||||
}
|
||||
for {set i 1} {$i<=20} {incr i} {
|
||||
set page1 [page_get $::p1 1]
|
||||
regsub -all CNT {
|
||||
set ::g1 [page_get $::p1 CNT]
|
||||
set ::g2 [page_get $::p1 CNT]
|
||||
@ -244,6 +247,7 @@ for {set i 1} {$i<=20} {incr i} {
|
||||
expr {$vy==$::vx}
|
||||
} $i body;
|
||||
do_test pager2-3.7.$i.3 $body {1}
|
||||
page_unref $page1
|
||||
}
|
||||
do_test pager2-3.99 {
|
||||
pager_close $::p1
|
||||
@ -281,7 +285,7 @@ do_test pager2-4.3 {
|
||||
} {ref 1}
|
||||
do_test pager2-4.4 {
|
||||
lrange [pager_stats $::p1] 8 9
|
||||
} {state 1}
|
||||
} {state 4}
|
||||
|
||||
for {set i 1} {$i<20} {incr i} {
|
||||
do_test pager2-4.5.$i.0 {
|
||||
@ -396,7 +400,7 @@ breakpoint
|
||||
do_test pager2-4.5.$i.10 {
|
||||
pager_commit $p1
|
||||
lrange [pager_stats $p1] 8 9
|
||||
} {state 1}
|
||||
} {state 4}
|
||||
}
|
||||
|
||||
do_test pager2-4.99 {
|
||||
|
@ -9,7 +9,7 @@
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# $Id: permutations.test,v 1.35 2008/10/11 17:04:04 danielk1977 Exp $
|
||||
# $Id: permutations.test,v 1.36 2008/10/17 18:51:53 danielk1977 Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
@ -448,6 +448,24 @@ run_tests "autovacuum_ioerr" -description {
|
||||
pragma auto_vacuum = 1
|
||||
} -include ioerr.test
|
||||
|
||||
# Run tests with an in-memory journal.
|
||||
#
|
||||
run_tests "inmemory_journal" -description {
|
||||
Run tests with an in-memory journal file.
|
||||
} -presql {
|
||||
pragma journal_mode = 'memory'
|
||||
} -exclude {
|
||||
# Exclude all tests that simulate IO errors.
|
||||
autovacuum_ioerr2.test incrvacuum_ioerr.test ioerr.test
|
||||
ioerr.test ioerr2.test ioerr3.test ioerr4.test ioerr5.test
|
||||
vacuum3.test incrblob_err.test diskfull.test
|
||||
|
||||
# Exclude test scripts that use tcl IO to access journal files or count
|
||||
# the number of fsync() calls.
|
||||
pager.test exclusive.test jrnlmode.test sync.test misc1.test
|
||||
journal1.test conflict.test
|
||||
}
|
||||
|
||||
ifcapable mem3 {
|
||||
run_tests "memsys3" -description {
|
||||
Run tests using the allocator in mem3.c.
|
||||
|
@ -13,7 +13,7 @@
|
||||
# caused by an ON CONFLICT ROLLBACK clause aborts any other pending
|
||||
# statements.
|
||||
#
|
||||
# $Id: rollback.test,v 1.9 2008/10/13 14:16:11 drh Exp $
|
||||
# $Id: rollback.test,v 1.10 2008/10/17 18:51:53 danielk1977 Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
@ -81,7 +81,10 @@ do_test rollback-1.9 {
|
||||
|
||||
set permutation ""
|
||||
catch {set permutation $::permutations_test_prefix}
|
||||
if {$tcl_platform(platform) == "unix" && $permutation ne "onefile"} {
|
||||
if {$tcl_platform(platform) == "unix"
|
||||
&& $permutation ne "onefile"
|
||||
&& $permutation ne "inmemory_journal"
|
||||
} {
|
||||
do_test rollback-2.1 {
|
||||
execsql {
|
||||
BEGIN;
|
||||
|
@ -247,6 +247,7 @@ foreach file {
|
||||
vdbe.c
|
||||
vdbeblob.c
|
||||
journal.c
|
||||
memjournal.c
|
||||
|
||||
walker.c
|
||||
resolve.c
|
||||
|
Reference in New Issue
Block a user