aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backup.c3
-rw-r--r--src/build.c2
-rw-r--r--src/pager.c98
-rw-r--r--src/pager.h8
-rw-r--r--src/vacuum.c4
-rw-r--r--src/vdbe.c88
6 files changed, 120 insertions, 83 deletions
diff --git a/src/backup.c b/src/backup.c
index 3e2cba5ff..1478a991b 100644
--- a/src/backup.c
+++ b/src/backup.c
@@ -335,8 +335,7 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
** and the page sizes are different between source and destination */
pgszSrc = sqlite3BtreeGetPageSize(p->pSrc);
pgszDest = sqlite3BtreeGetPageSize(p->pDest);
- destMode = sqlite3PagerJournalMode(sqlite3BtreePager(p->pDest),
- PAGER_JOURNALMODE_QUERY);
+ destMode = sqlite3PagerGetJournalMode(sqlite3BtreePager(p->pDest));
if( SQLITE_OK==rc && destMode==PAGER_JOURNALMODE_WAL && pgszSrc!=pgszDest ){
rc = SQLITE_READONLY;
}
diff --git a/src/build.c b/src/build.c
index 38166ce7f..4c00e398e 100644
--- a/src/build.c
+++ b/src/build.c
@@ -3422,7 +3422,7 @@ int sqlite3OpenTempDatabase(Parse *pParse){
db->mallocFailed = 1;
return 1;
}
- sqlite3PagerJournalMode(sqlite3BtreePager(pBt), db->dfltJournalMode);
+ sqlite3PagerSetJournalMode(sqlite3BtreePager(pBt), db->dfltJournalMode);
}
return 0;
}
diff --git a/src/pager.c b/src/pager.c
index 9e1ea7aa8..2b102fbea 100644
--- a/src/pager.c
+++ b/src/pager.c
@@ -5815,9 +5815,8 @@ int sqlite3PagerLockingMode(Pager *pPager, int eMode){
}
/*
-** Get/set the journal-mode for this pager. Parameter eMode must be one of:
+** Set the journal-mode for this pager. Parameter eMode must be one of:
**
-** PAGER_JOURNALMODE_QUERY
** PAGER_JOURNALMODE_DELETE
** PAGER_JOURNALMODE_TRUNCATE
** PAGER_JOURNALMODE_PERSIST
@@ -5825,56 +5824,95 @@ int sqlite3PagerLockingMode(Pager *pPager, int eMode){
** PAGER_JOURNALMODE_MEMORY
** PAGER_JOURNALMODE_WAL
**
-** If the parameter is not _QUERY, then the journal_mode is set to the
-** value specified if the change is allowed. The change may be disallowed
-** for the following reasons:
+** The journalmode is set to the value specified if the change is allowed.
+** The change may be disallowed for the following reasons:
**
** * An in-memory database can only have its journal_mode set to _OFF
** or _MEMORY.
**
-** * The journal mode may not be changed while a transaction is active.
+** * Temporary databases cannot have _WAL journalmode.
**
** The returned indicate the current (possibly updated) journal-mode.
*/
-int sqlite3PagerJournalMode(Pager *pPager, int eMode){
- assert( eMode==PAGER_JOURNALMODE_QUERY
- || eMode==PAGER_JOURNALMODE_DELETE
+int sqlite3PagerSetJournalMode(Pager *pPager, int eMode){
+ u8 eOld = pPager->journalMode; /* Prior journalmode */
+
+ /* The eMode parameter is always valid */
+ assert( eMode==PAGER_JOURNALMODE_DELETE
|| eMode==PAGER_JOURNALMODE_TRUNCATE
|| eMode==PAGER_JOURNALMODE_PERSIST
|| eMode==PAGER_JOURNALMODE_OFF
|| eMode==PAGER_JOURNALMODE_WAL
|| eMode==PAGER_JOURNALMODE_MEMORY );
- assert( PAGER_JOURNALMODE_QUERY<0 );
- if( eMode==PAGER_JOURNALMODE_WAL
- && pPager->journalMode==PAGER_JOURNALMODE_DELETE
- ){
- pPager->journalMode = PAGER_JOURNALMODE_WAL;
- }else if( eMode>=0
- && (pPager->tempFile==0 || eMode!=PAGER_JOURNALMODE_WAL)
- && (!MEMDB || eMode==PAGER_JOURNALMODE_MEMORY||eMode==PAGER_JOURNALMODE_OFF)
- && !pPager->dbModified
- && (!isOpen(pPager->jfd) || 0==pPager->journalOff)
- ){
- if( isOpen(pPager->jfd) ){
- sqlite3OsClose(pPager->jfd);
+ /* Do not allow the journalmode of a TEMP database to be changed to WAL
+ */
+ if( pPager->tempFile && eMode==PAGER_JOURNALMODE_WAL ){
+ assert( eOld!=PAGER_JOURNALMODE_WAL );
+ eMode = eOld;
+ }
+
+ /* Do allow the journalmode of an in-memory database to be set to
+ ** anything other than MEMORY or OFF
+ */
+ if( MEMDB ){
+ assert( eOld==PAGER_JOURNALMODE_MEMORY || eOld==PAGER_JOURNALMODE_OFF );
+ if( eMode!=PAGER_JOURNALMODE_MEMORY && eMode!=PAGER_JOURNALMODE_OFF ){
+ eMode = eOld;
}
- assert( (PAGER_JOURNALMODE_TRUNCATE & 1)==1 );
- assert( (PAGER_JOURNALMODE_PERSIST & 1)==1 );
- assert( (PAGER_JOURNALMODE_DELETE & 1)==0 );
- assert( (PAGER_JOURNALMODE_MEMORY & 1)==0 );
- assert( (PAGER_JOURNALMODE_OFF & 1)==0 );
- if( (pPager->journalMode & 1)==1 && (eMode & 1)==0
- && !pPager->exclusiveMode ){
- sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0);
+ }
+
+ if( eMode!=eOld ){
+ /* When changing between rollback modes, close the journal file prior
+ ** to the change. But when changing from a rollback mode to WAL, keep
+ ** the journal open since there is a rollback-style transaction in play
+ ** used to convert the version numbers in the btree header.
+ */
+ if( isOpen(pPager->jfd) && eMode!=PAGER_JOURNALMODE_WAL ){
+ sqlite3OsClose(pPager->jfd);
}
+ /* Change the journal mode. */
pPager->journalMode = (u8)eMode;
+
+ /* When transistioning from TRUNCATE or PERSIST to any other journal
+ ** mode (and we are not in locking_mode=EXCLUSIVE) then delete the
+ ** journal file.
+ */
+ assert( (PAGER_JOURNALMODE_TRUNCATE & 5)==1 );
+ assert( (PAGER_JOURNALMODE_PERSIST & 5)==1 );
+ assert( (PAGER_JOURNALMODE_DELETE & 5)!=1 );
+ assert( (PAGER_JOURNALMODE_MEMORY & 5)!=1 );
+ assert( (PAGER_JOURNALMODE_OFF & 5)!=1 );
+ assert( (PAGER_JOURNALMODE_WAL & 5)!=1 );
+ if( (eOld & 5)==1 && (eMode & 5)!=1 && !pPager->exclusiveMode ){
+ sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0);
+ }
}
+
+ /* Return the new journal mode */
return (int)pPager->journalMode;
}
/*
+** Return the current journal mode.
+*/
+int sqlite3PagerGetJournalMode(Pager *pPager){
+ return (int)pPager->journalMode;
+}
+
+/*
+** Return TRUE if the pager is in a state where it is OK to change the
+** journalmode. Journalmode changes can only happen when the database
+** is unmodified.
+*/
+int sqlite3PagerOkToChangeJournalMode(Pager *pPager){
+ if( pPager->dbModified ) return 0;
+ if( isOpen(pPager->jfd) && pPager->journalOff>0 ) return 0;
+ return 1;
+}
+
+/*
** Get/set the size-limit used for persistent journal files.
**
** Setting the size limit to -1 means no limit is enforced.
diff --git a/src/pager.h b/src/pager.h
index 57ceb0463..9f77cde07 100644
--- a/src/pager.h
+++ b/src/pager.h
@@ -68,9 +68,9 @@ typedef struct PgHdr DbPage;
#define PAGER_LOCKINGMODE_EXCLUSIVE 1
/*
-** Valid values for the second argument to sqlite3PagerJournalMode().
+** Numeric constants that encode the journalmode.
*/
-#define PAGER_JOURNALMODE_QUERY -1
+#define PAGER_JOURNALMODE_QUERY (-1) /* Query the value of journalmode */
#define PAGER_JOURNALMODE_DELETE 0 /* Commit by deleting journal file */
#define PAGER_JOURNALMODE_PERSIST 1 /* Commit by zeroing journal header */
#define PAGER_JOURNALMODE_OFF 2 /* Journal omitted. */
@@ -104,7 +104,9 @@ int sqlite3PagerMaxPageCount(Pager*, int);
void sqlite3PagerSetCachesize(Pager*, int);
void sqlite3PagerSetSafetyLevel(Pager*,int,int);
int sqlite3PagerLockingMode(Pager *, int);
-int sqlite3PagerJournalMode(Pager *, int);
+int sqlite3PagerSetJournalMode(Pager *, int);
+int sqlite3PagerGetJournalMode(Pager*);
+int sqlite3PagerOkToChangeJournalMode(Pager*);
i64 sqlite3PagerJournalSizeLimit(Pager *, i64);
sqlite3_backup **sqlite3PagerBackupPtr(Pager*);
diff --git a/src/vacuum.c b/src/vacuum.c
index e95b4aa90..a0bf1ebfe 100644
--- a/src/vacuum.c
+++ b/src/vacuum.c
@@ -173,8 +173,8 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
#endif
/* Do not attempt to change the page size for a WAL database */
- if( sqlite3PagerJournalMode(sqlite3BtreePager(pMain),
- PAGER_JOURNALMODE_QUERY)==PAGER_JOURNALMODE_WAL ){
+ if( sqlite3PagerGetJournalMode(sqlite3BtreePager(pMain))
+ ==PAGER_JOURNALMODE_WAL ){
db->nextPagesize = 0;
}
diff --git a/src/vdbe.c b/src/vdbe.c
index 89a8c340b..14785d35d 100644
--- a/src/vdbe.c
+++ b/src/vdbe.c
@@ -5176,7 +5176,6 @@ case OP_JournalMode: { /* out2-prerelease */
Pager *pPager; /* Pager associated with pBt */
int eNew; /* New journal mode */
int eOld; /* The old journal mode */
- const sqlite3_vfs *pVfs; /* The VFS of pPager */
const char *zFilename; /* Name of database file for pPager */
eNew = pOp->p3;
@@ -5211,10 +5210,12 @@ case OP_JournalMode: { /* out2-prerelease */
pBt = db->aDb[pOp->p1].pBt;
pPager = sqlite3BtreePager(pBt);
+ eOld = sqlite3PagerGetJournalMode(pPager);
+ if( eNew==PAGER_JOURNALMODE_QUERY ) eNew = eOld;
+ if( !sqlite3PagerOkToChangeJournalMode(pPager) ) eNew = eOld;
#ifndef SQLITE_OMIT_WAL
zFilename = sqlite3PagerFilename(pPager);
- pVfs = sqlite3PagerVfs(pPager);
/* Do not allow a transition to journal_mode=WAL for a database
** in temporary storage or if the VFS does not support xShmOpen.
@@ -5223,59 +5224,56 @@ case OP_JournalMode: { /* out2-prerelease */
&& (zFilename[0]==0 /* Temp file */
|| !sqlite3PagerWalSupported(pPager)) /* No xShmOpen support */
){
- eNew = PAGER_JOURNALMODE_QUERY;
+ eNew = eOld;
}
- if( eNew!=PAGER_JOURNALMODE_QUERY ){
- eOld = sqlite3PagerJournalMode(pPager, PAGER_JOURNALMODE_QUERY);
- if( (eNew!=eOld)
- && (eOld==PAGER_JOURNALMODE_WAL || eNew==PAGER_JOURNALMODE_WAL)
- ){
- if( !db->autoCommit || db->activeVdbeCnt>1 ){
- rc = SQLITE_ERROR;
- sqlite3SetString(&p->zErrMsg, db,
- "cannot change %s wal mode from within a transaction",
- (eNew==PAGER_JOURNALMODE_WAL ? "into" : "out of")
- );
- break;
- }else{
-
- if( eOld==PAGER_JOURNALMODE_WAL ){
- /* If leaving WAL mode, close the log file. If successful, the call
- ** to PagerCloseWal() checkpoints and deletes the write-ahead-log
- ** file. An EXCLUSIVE lock may still be held on the database file
- ** after a successful return.
- */
- rc = sqlite3PagerCloseWal(pPager);
- if( rc==SQLITE_OK ){
- sqlite3PagerJournalMode(pPager, eNew);
- }else if( rc==SQLITE_BUSY && pOp->p5==0 ){
- goto abort_due_to_error;
- }
- }else{
- sqlite3PagerJournalMode(pPager, PAGER_JOURNALMODE_DELETE);
- rc = SQLITE_OK;
- }
-
- /* Open a transaction on the database file. Regardless of the journal
- ** mode, this transaction always uses a rollback journal.
+ if( (eNew!=eOld)
+ && (eOld==PAGER_JOURNALMODE_WAL || eNew==PAGER_JOURNALMODE_WAL)
+ ){
+ if( !db->autoCommit || db->activeVdbeCnt>1 ){
+ rc = SQLITE_ERROR;
+ sqlite3SetString(&p->zErrMsg, db,
+ "cannot change %s wal mode from within a transaction",
+ (eNew==PAGER_JOURNALMODE_WAL ? "into" : "out of")
+ );
+ break;
+ }else{
+
+ if( eOld==PAGER_JOURNALMODE_WAL ){
+ /* If leaving WAL mode, close the log file. If successful, the call
+ ** to PagerCloseWal() checkpoints and deletes the write-ahead-log
+ ** file. An EXCLUSIVE lock may still be held on the database file
+ ** after a successful return.
*/
- assert( sqlite3BtreeIsInTrans(pBt)==0 );
+ rc = sqlite3PagerCloseWal(pPager);
if( rc==SQLITE_OK ){
- rc = sqlite3BtreeSetVersion(pBt,
- (eNew==PAGER_JOURNALMODE_WAL ? 2 : 1));
- if( rc==SQLITE_BUSY && pOp->p5==0 ) goto abort_due_to_error;
- }
- if( rc==SQLITE_BUSY ){
- eNew = PAGER_JOURNALMODE_QUERY;
- rc = SQLITE_OK;
+ sqlite3PagerSetJournalMode(pPager, eNew);
+ }else if( rc==SQLITE_BUSY && pOp->p5==0 ){
+ goto abort_due_to_error;
}
+ }else{
+ sqlite3PagerSetJournalMode(pPager, PAGER_JOURNALMODE_DELETE);
+ rc = SQLITE_OK;
+ }
+
+ /* Open a transaction on the database file. Regardless of the journal
+ ** mode, this transaction always uses a rollback journal.
+ */
+ assert( sqlite3BtreeIsInTrans(pBt)==0 );
+ if( rc==SQLITE_OK ){
+ rc = sqlite3BtreeSetVersion(pBt,
+ (eNew==PAGER_JOURNALMODE_WAL ? 2 : 1));
+ if( rc==SQLITE_BUSY && pOp->p5==0 ) goto abort_due_to_error;
+ }
+ if( rc==SQLITE_BUSY ){
+ eNew = eOld;
+ rc = SQLITE_OK;
}
}
}
#endif /* ifndef SQLITE_OMIT_WAL */
- eNew = sqlite3PagerJournalMode(pPager, eNew);
+ eNew = sqlite3PagerSetJournalMode(pPager, eNew);
pOut = &aMem[pOp->p2];
pOut->flags = MEM_Str|MEM_Static|MEM_Term;
pOut->z = (char *)sqlite3JournalModename(eNew);