summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVasu Nori <vnori@google.com>2010-07-07 14:29:44 -0700
committerVasu Nori <vnori@google.com>2010-07-07 14:29:44 -0700
commitebc6b24ff37b903195b37f143a5791c9f02be8df (patch)
treef0a5a461bd590906db4209a720eff2abe1ff0789
parent176bf03af2edfb2a45b66dcb5daf822cc50c499e (diff)
latest sqlite with fix for WAL-caued corruption
Change-Id: I40056f72e4eecf8cbc39d91933cc604ab0c361c1
-rw-r--r--dist/shell.c1
-rw-r--r--dist/sqlite3.c462
-rw-r--r--dist/sqlite3.c.orig462
-rw-r--r--dist/sqlite3.h18
4 files changed, 568 insertions, 375 deletions
diff --git a/dist/shell.c b/dist/shell.c
index 8879b36..9c21103 100644
--- a/dist/shell.c
+++ b/dist/shell.c
@@ -24,7 +24,6 @@
#include "sqlite3.h"
#include <ctype.h>
#include <stdarg.h>
-
// Begin Android Add
#ifndef NO_ANDROID_FUNCS
#include <sqlite3_android.h>
diff --git a/dist/sqlite3.c b/dist/sqlite3.c
index 121fc93..bbe4d1e 100644
--- a/dist/sqlite3.c
+++ b/dist/sqlite3.c
@@ -516,6 +516,13 @@ SQLITE_PRIVATE void sqlite3Coverage(int);
#endif
/*
+** Return true (non-zero) if the input is a integer that is too large
+** to fit in 32-bits. This macro is used inside of various testcase()
+** macros to verify that we have tested SQLite for large-file support.
+*/
+#define IS_BIG_INT(X) (((X)&(i64)0xffffffff)!=0)
+
+/*
** The macro unlikely() is a hint that surrounds a boolean
** expression that is usually false. Macro likely() surrounds
** a boolean expression that is usually true. GCC is able to
@@ -642,7 +649,7 @@ extern "C" {
*/
#define SQLITE_VERSION "3.7.0"
#define SQLITE_VERSION_NUMBER 3007000
-#define SQLITE_SOURCE_ID "2010-06-28 10:15:20 4932f22848b3d15a2b6dc5fa2cd69ce19182e2a4"
+#define SQLITE_SOURCE_ID "2010-07-07 14:45:41 8eefc287265443ec043bdab629597e79c9d22006"
/*
** CAPI3REF: Run-Time Library Version Numbers
@@ -1365,16 +1372,23 @@ typedef struct sqlite3_mutex sqlite3_mutex;
** handled as a fatal error by SQLite, vfs implementations should endeavor
** to prevent this by setting mxPathname to a sufficiently large value.
**
-** The xRandomness(), xSleep(), and xCurrentTime() interfaces
-** are not strictly a part of the filesystem, but they are
+** The xRandomness(), xSleep(), xCurrentTime(), and xCurrentTimeInt64()
+** interfaces are not strictly a part of the filesystem, but they are
** included in the VFS structure for completeness.
** The xRandomness() function attempts to return nBytes bytes
** of good-quality randomness into zOut. The return value is
** the actual number of bytes of randomness obtained.
** The xSleep() method causes the calling thread to sleep for at
** least the number of microseconds given. The xCurrentTime()
-** method returns a Julian Day Number for the current date and time.
-**
+** method returns a Julian Day Number for the current date and time as
+** a floating point value.
+** The xCurrentTimeInt64() method returns, as an integer, the Julian
+** Day Number multipled by 86400000 (the number of milliseconds in
+** a 24-hour day).
+** ^SQLite will use the xCurrentTimeInt64() method to get the current
+** date and time if that method is available (if iVersion is 2 or
+** greater and the function pointer is not NULL) and will fall back
+** to xCurrentTime() if xCurrentTimeInt64() is unavailable.
*/
typedef struct sqlite3_vfs sqlite3_vfs;
struct sqlite3_vfs {
@@ -1401,7 +1415,6 @@ struct sqlite3_vfs {
** The methods above are in version 1 of the sqlite_vfs object
** definition. Those that follow are added in version 2 or later
*/
- int (*xRename)(sqlite3_vfs*, const char *zOld, const char *zNew, int dirSync);
int (*xCurrentTimeInt64)(sqlite3_vfs*, sqlite3_int64*);
/*
** The methods above are in versions 1 and 2 of the sqlite_vfs object.
@@ -11333,9 +11346,11 @@ static const char * const azCompileOpt[] = {
#ifdef SQLITE_OMIT_CHECK
"OMIT_CHECK",
#endif
-#ifdef SQLITE_OMIT_COMPILEOPTION_DIAGS
- "OMIT_COMPILEOPTION_DIAGS",
-#endif
+/* // redundant
+** #ifdef SQLITE_OMIT_COMPILEOPTION_DIAGS
+** "OMIT_COMPILEOPTION_DIAGS",
+** #endif
+*/
#ifdef SQLITE_OMIT_COMPLETE
"OMIT_COMPLETE",
#endif
@@ -11369,9 +11384,6 @@ static const char * const azCompileOpt[] = {
#ifdef SQLITE_OMIT_GET_TABLE
"OMIT_GET_TABLE",
#endif
-#ifdef SQLITE_OMIT_GLOBALRECOVER
- "OMIT_GLOBALRECOVER",
-#endif
#ifdef SQLITE_OMIT_INCRBLOB
"OMIT_INCRBLOB",
#endif
@@ -11450,6 +11462,9 @@ static const char * const azCompileOpt[] = {
#ifdef SQLITE_OMIT_VIRTUALTABLE
"OMIT_VIRTUALTABLE",
#endif
+#ifdef SQLITE_OMIT_WAL
+ "OMIT_WAL",
+#endif
#ifdef SQLITE_OMIT_WSD
"OMIT_WSD",
#endif
@@ -12801,8 +12816,10 @@ SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void){
** sqlite3OsLock()
**
*/
-#if defined(SQLITE_TEST) && (SQLITE_OS_WIN==0)
- #define DO_OS_MALLOC_TEST(x) if (!x || !sqlite3IsMemJournal(x)) { \
+#if defined(SQLITE_TEST)
+SQLITE_API int sqlite3_memdebug_vfs_oom_test = 1;
+ #define DO_OS_MALLOC_TEST(x) \
+ if (sqlite3_memdebug_vfs_oom_test && (!x || !sqlite3IsMemJournal(x))) { \
void *pTstAlloc = sqlite3Malloc(10); \
if (!pTstAlloc) return SQLITE_IOERR_NOMEM; \
sqlite3_free(pTstAlloc); \
@@ -27490,7 +27507,7 @@ static int proxyGetLockPath(const char *dbPath, char *lPath, size_t maxLen){
/* transform the db path to a unique cache name */
dbLen = (int)strlen(dbPath);
- for( i=0; i<dbLen && (i+len+7)<maxLen; i++){
+ for( i=0; i<dbLen && (i+len+7)<(int)maxLen; i++){
char c = dbPath[i];
lPath[i+len] = (c=='/')?'_':c;
}
@@ -27631,6 +27648,9 @@ SQLITE_API int sqlite3_hostid_num = 0;
#define PROXY_HOSTIDLEN 16 /* conch file host id length */
+/* Not always defined in the headers as it ought to be */
+extern int gethostuuid(uuid_t id, const struct timespec *wait);
+
/* get the host ID via gethostuuid(), pHostID must point to PROXY_HOSTIDLEN
** bytes of writable memory.
*/
@@ -27680,6 +27700,7 @@ static int proxyBreakConchLock(unixFile *pFile, uuid_t myHostID){
char errmsg[64] = "";
int fd = -1;
int rc = -1;
+ UNUSED_PARAMETER(myHostID);
/* create a new path by replace the trailing '-conch' with '-break' */
pathLen = strlcpy(tPath, cPath, MAXPATHLEN);
@@ -27700,7 +27721,7 @@ static int proxyBreakConchLock(unixFile *pFile, uuid_t myHostID){
sprintf(errmsg, "create failed (%d)", errno);
goto end_breaklock;
}
- if( pwrite(fd, buf, readLen, 0) != readLen ){
+ if( pwrite(fd, buf, readLen, 0) != (ssize_t)readLen ){
sprintf(errmsg, "write failed (%d)", errno);
goto end_breaklock;
}
@@ -28503,7 +28524,6 @@ SQLITE_API int sqlite3_os_init(void){
unixSleep, /* xSleep */ \
unixCurrentTime, /* xCurrentTime */ \
unixGetLastError, /* xGetLastError */ \
- 0, /* xRename */ \
unixCurrentTimeInt64, /* xCurrentTimeInt64 */ \
}
@@ -29497,7 +29517,11 @@ static int winWrite(
rc = SetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN);
if( rc==INVALID_SET_FILE_POINTER && (error=GetLastError())!=NO_ERROR ){
pFile->lastErrno = error;
- return SQLITE_FULL;
+ if( pFile->lastErrno==ERROR_HANDLE_DISK_FULL ){
+ return SQLITE_FULL;
+ }else{
+ return SQLITE_IOERR_WRITE;
+ }
}
assert( amt>0 );
while(
@@ -29510,7 +29534,11 @@ static int winWrite(
}
if( !rc || amt>(int)wrote ){
pFile->lastErrno = GetLastError();
- return SQLITE_FULL;
+ if( pFile->lastErrno==ERROR_HANDLE_DISK_FULL ){
+ return SQLITE_FULL;
+ }else{
+ return SQLITE_IOERR_WRITE;
+ }
}
return SQLITE_OK;
}
@@ -30197,6 +30225,9 @@ static int winShmOpen(
*/
if( winShmSystemLock(pShmNode, _SHM_WRLCK, WIN_SHM_DMS, 1)==SQLITE_OK ){
rc = winTruncate((sqlite3_file *)&pShmNode->hFile, 0);
+ if( rc!=SQLITE_OK ){
+ rc = SQLITE_IOERR_SHMOPEN;
+ }
}
if( rc==SQLITE_OK ){
winShmSystemLock(pShmNode, _SHM_UNLCK, WIN_SHM_DMS, 1);
@@ -30423,6 +30454,7 @@ static int winShmLock(
static void winShmBarrier(
sqlite3_file *fd /* Database holding the shared memory */
){
+ UNUSED_PARAMETER(fd);
/* MemoryBarrier(); // does not work -- do not know why not */
winShmEnterMutex();
winShmLeaveMutex();
@@ -30834,13 +30866,38 @@ static int winAccess(
){
DWORD attr;
int rc = 0;
- void *zConverted = convertUtf8Filename(zFilename);
+ void *zConverted;
UNUSED_PARAMETER(pVfs);
+
+ SimulateIOError( return SQLITE_IOERR_ACCESS; );
+ zConverted = convertUtf8Filename(zFilename);
if( zConverted==0 ){
return SQLITE_NOMEM;
}
if( isNT() ){
- attr = GetFileAttributesW((WCHAR*)zConverted);
+ WIN32_FILE_ATTRIBUTE_DATA sAttrData;
+ memset(&sAttrData, 0, sizeof(sAttrData));
+ if( GetFileAttributesExW((WCHAR*)zConverted,
+ GetFileExInfoStandard,
+ &sAttrData) ){
+ /* For an SQLITE_ACCESS_EXISTS query, treat a zero-length file
+ ** as if it does not exist.
+ */
+ if( flags==SQLITE_ACCESS_EXISTS
+ && sAttrData.nFileSizeHigh==0
+ && sAttrData.nFileSizeLow==0 ){
+ attr = INVALID_FILE_ATTRIBUTES;
+ }else{
+ attr = sAttrData.dwFileAttributes;
+ }
+ }else{
+ if( GetLastError()!=ERROR_FILE_NOT_FOUND ){
+ free(zConverted);
+ return SQLITE_IOERR_ACCESS;
+ }else{
+ attr = INVALID_FILE_ATTRIBUTES;
+ }
+ }
/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
** Since the ASCII version of these Windows API do not exist for WINCE,
** it's important to not reference them for WINCE builds.
@@ -31240,7 +31297,6 @@ SQLITE_API int sqlite3_os_init(void){
winSleep, /* xSleep */
winCurrentTime, /* xCurrentTime */
winGetLastError, /* xGetLastError */
- 0, /* xRename */
winCurrentTimeInt64, /* xCurrentTimeInt64 */
};
@@ -33510,13 +33566,14 @@ SQLITE_PRIVATE int sqlite3RowSetTest(RowSet *pRowSet, u8 iBatch, sqlite3_int64 i
# define sqlite3WalRead(v,w,x,y,z) 0
# define sqlite3WalDbsize(y,z)
# define sqlite3WalBeginWriteTransaction(y) 0
-# define sqlite3WalEndWRiteTransaction(x) 0
+# define sqlite3WalEndWriteTransaction(x) 0
# define sqlite3WalUndo(x,y,z) 0
# define sqlite3WalSavepoint(y,z)
# define sqlite3WalSavepointUndo(y,z) 0
# define sqlite3WalFrames(u,v,w,x,y,z) 0
# define sqlite3WalCheckpoint(u,v,w,x) 0
# define sqlite3WalCallback(z) 0
+# define sqlite3WalExclusiveMode(y,z) 0
#else
#define WAL_SAVEPOINT_NDATA 4
@@ -33790,7 +33847,9 @@ 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 */
+#ifndef SQLITE_OMIT_WAL
u32 aWalData[WAL_SAVEPOINT_NDATA]; /* WAL savepoint context */
+#endif
};
/*
@@ -33974,6 +34033,7 @@ struct Pager {
sqlite3_backup *pBackup; /* Pointer to list of ongoing backup processes */
#ifndef SQLITE_OMIT_WAL
Wal *pWal; /* Write-ahead log used by "journal_mode=wal" */
+ char *zWal; /* File name for write-ahead log */
#endif
};
@@ -35085,6 +35145,21 @@ static u32 pager_cksum(Pager *pPager, const u8 *aData){
}
/*
+** Report the current page size and number of reserved bytes back
+** to the codec.
+*/
+#ifdef SQLITE_HAS_CODEC
+static void pagerReportSize(Pager *pPager){
+ if( pPager->xCodecSizeChng ){
+ pPager->xCodecSizeChng(pPager->pCodec, pPager->pageSize,
+ (int)pPager->nReserve);
+ }
+}
+#else
+# define pagerReportSize(X) /* No-op if we do not support a codec */
+#endif
+
+/*
** Read a single page from either the journal file (if isMainJrnl==1) or
** from the sub-journal (if isMainJrnl==0) and playback that page.
** The page begins at offset *pOffset into the file. The *pOffset
@@ -35176,12 +35251,21 @@ static int pager_playback_one_page(
}
}
+ /* If this page has already been played by before during the current
+ ** rollback, then don't bother to play it back again.
+ */
if( pDone && (rc = sqlite3BitvecSet(pDone, pgno))!=SQLITE_OK ){
return rc;
}
-
assert( pPager->state==PAGER_RESERVED || pPager->state>=PAGER_EXCLUSIVE );
+ /* When playing back page 1, restore the nReserve setting
+ */
+ if( pgno==1 && pPager->nReserve!=((u8*)aData)[20] ){
+ pPager->nReserve = ((u8*)aData)[20];
+ pagerReportSize(pPager);
+ }
+
/* If the pager is in RESERVED state, then there must be a copy of this
** page in the pager cache. In this case just update the pager cache,
** not the database file. The page is left marked dirty in this case.
@@ -35982,43 +36066,40 @@ static int pagerBeginReadTransaction(Pager *pPager){
/*
** Check if the *-wal file that corresponds to the database opened by pPager
-** exists. Assuming no error occurs, set *pExists to 1 if the file exists,
-** or 0 otherwise and return SQLITE_OK. If an IO or OOM error occurs, return
-** an SQLite error code.
-*/
-static int pagerHasWAL(Pager *pPager, int *pExists){
- int rc; /* Return code */
- char *zWal; /* Name of the WAL file */
-
- assert( !pPager->tempFile );
- zWal = sqlite3_mprintf("%s-wal", pPager->zFilename);
- if( !zWal ){
- rc = SQLITE_NOMEM;
- }else{
- rc = sqlite3OsAccess(pPager->pVfs, zWal, SQLITE_ACCESS_EXISTS, pExists);
- sqlite3_free(zWal);
- }
- return rc;
-}
-
-/*
-** Check if the *-wal file that corresponds to the database opened by pPager
-** exists. If it does, open the pager in WAL mode. Otherwise, if no error
-** occurs, make sure Pager.journalMode is not set to PAGER_JOURNALMODE_WAL.
-** If an IO or OOM error occurs, return an SQLite error code.
+** exists if the database is not empy, or verify that the *-wal file does
+** not exist (by deleting it) if the database file is empty.
+**
+** If the database is not empty and the *-wal file exists, open the pager
+** in WAL mode. If the database is empty or if no *-wal file exists and
+** if no error occurs, make sure Pager.journalMode is not set to
+** PAGER_JOURNALMODE_WAL.
+**
+** Return SQLITE_OK or an error code.
**
** If the WAL file is opened, also open a snapshot (read transaction).
**
** The caller must hold a SHARED lock on the database file to call this
** function. Because an EXCLUSIVE lock on the db file is required to delete
-** a WAL, this ensures there is no race condition between the xAccess()
-** below and an xDelete() being executed by some other connection.
+** a WAL on a none-empty database, this ensures there is no race condition
+** between the xAccess() below and an xDelete() being executed by some
+** other connection.
*/
static int pagerOpenWalIfPresent(Pager *pPager){
int rc = SQLITE_OK;
if( !pPager->tempFile ){
int isWal; /* True if WAL file exists */
- rc = pagerHasWAL(pPager, &isWal);
+ int nPage; /* Size of the database file */
+ assert( pPager->state>=SHARED_LOCK );
+ rc = sqlite3PagerPagecount(pPager, &nPage);
+ if( rc ) return rc;
+ if( nPage==0 ){
+ rc = sqlite3OsDelete(pPager->pVfs, pPager->zWal, 0);
+ isWal = 0;
+ }else{
+ rc = sqlite3OsAccess(
+ pPager->pVfs, pPager->zWal, SQLITE_ACCESS_EXISTS, &isWal
+ );
+ }
if( rc==SQLITE_OK ){
if( isWal ){
pager_reset(pPager);
@@ -36292,21 +36373,6 @@ SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(
}
/*
-** Report the current page size and number of reserved bytes back
-** to the codec.
-*/
-#ifdef SQLITE_HAS_CODEC
-static void pagerReportSize(Pager *pPager){
- if( pPager->xCodecSizeChng ){
- pPager->xCodecSizeChng(pPager->pCodec, pPager->pageSize,
- (int)pPager->nReserve);
- }
-}
-#else
-# define pagerReportSize(X) /* No-op if we do not support a codec */
-#endif
-
-/*
** Change the page size used by the Pager object. The new page size
** is passed in *pPageSize.
**
@@ -36392,7 +36458,7 @@ SQLITE_PRIVATE int sqlite3PagerMaxPageCount(Pager *pPager, int mxPage){
}
if( pPager->state!=PAGER_UNLOCK ){
sqlite3PagerPagecount(pPager, &nPage);
- assert( pPager->mxPgno>=nPage );
+ assert( (int)pPager->mxPgno>=nPage );
}
return pPager->mxPgno;
}
@@ -36445,15 +36511,6 @@ SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager *pPager, int N, unsigned cha
** to WAL mode yet.
*/
assert( !pagerUseWal(pPager) );
-#if 0
- if( pagerUseWal(pPager) ){
- int isInWal = 0;
- rc = sqlite3WalRead(pPager->pWal, 1, &isInWal, N, pDest);
- if( rc!=SQLITE_OK || isInWal ){
- return rc;
- }
- }
-#endif
if( isOpen(pPager->fd) ){
IOTRACE(("DBHDR %p 0 %d\n", pPager, N))
@@ -36897,13 +36954,9 @@ static int syncJournal(Pager *pPager){
** occurs, an IO error code is returned. Or, if the EXCLUSIVE lock cannot
** be obtained, SQLITE_BUSY is returned.
*/
-static int pager_write_pagelist(PgHdr *pList){
- Pager *pPager; /* Pager object */
+static int pager_write_pagelist(Pager *pPager, PgHdr *pList){
int rc; /* Return code */
- if( NEVER(pList==0) ) return SQLITE_OK;
- pPager = pList->pPager;
-
/* At this point there may be either a RESERVED or EXCLUSIVE lock on the
** database file. If there is already an EXCLUSIVE lock, the following
** call is a no-op.
@@ -36920,7 +36973,7 @@ static int pager_write_pagelist(PgHdr *pList){
** EXCLUSIVE, it means the database file has been changed and any rollback
** will require a journal playback.
*/
- assert( !pagerUseWal(pList->pPager) );
+ assert( !pagerUseWal(pPager) );
assert( pPager->state>=PAGER_RESERVED );
rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
@@ -37165,7 +37218,7 @@ static int pagerStress(void *p, PgHdr *pPg){
/* Write the contents of the page out to the database file. */
if( rc==SQLITE_OK ){
- rc = pager_write_pagelist(pPg);
+ rc = pager_write_pagelist(pPager, pPg);
}
}
@@ -37305,6 +37358,9 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
journalFileSize * 2 + /* The two journal files */
nPathname + 1 + /* zFilename */
nPathname + 8 + 1 /* zJournal */
+#ifndef SQLITE_OMIT_WAL
+ + nPathname + 4 + 1 /* zWal */
+#endif
);
assert( EIGHT_BYTE_ALIGNMENT(SQLITE_INT_TO_PTR(journalFileSize)) );
if( !pPtr ){
@@ -37325,7 +37381,16 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
memcpy(pPager->zFilename, zPathname, nPathname);
memcpy(pPager->zJournal, zPathname, nPathname);
memcpy(&pPager->zJournal[nPathname], "-journal", 8);
- if( pPager->zFilename[0]==0 ) pPager->zJournal[0] = 0;
+ if( pPager->zFilename[0]==0 ){
+ pPager->zJournal[0] = 0;
+ }
+#ifndef SQLITE_OMIT_WAL
+ else{
+ pPager->zWal = &pPager->zJournal[nPathname+8+1];
+ memcpy(pPager->zWal, zPathname, nPathname);
+ memcpy(&pPager->zWal[nPathname], "-wal", 4);
+ }
+#endif
sqlite3_free(zPathname);
}
pPager->pVfs = pVfs;
@@ -38201,30 +38266,19 @@ SQLITE_PRIVATE int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory
** we might save the work of creating a file if the transaction
** ends up being a no-op.
*/
- }else if( isOpen(pPager->jfd) && pPager->journalOff==0 ){
- /* This happens when the pager was in exclusive-access mode the last
- ** time a (read or write) transaction was successfully concluded
- ** by this connection. Instead of deleting the journal file it was
- ** kept open and either was truncated to 0 bytes or its header was
- ** overwritten with zeros.
- */
- assert( pagerUseWal(pPager)==0 );
- assert( pPager->nRec==0 );
- assert( pPager->dbOrigSize==0 );
- assert( pPager->pInJournal==0 );
- rc = pager_open_journal(pPager);
+
+ if( rc!=SQLITE_OK ){
+ assert( !pPager->dbModified );
+ /* Ignore any IO error that occurs within pager_end_transaction(). The
+ ** purpose of this call is to reset the internal state of the pager
+ ** sub-system. It doesn't matter if the journal-file is not properly
+ ** finalized at this point (since it is not a valid journal file anyway).
+ */
+ pager_end_transaction(pPager, 0);
+ }
}
PAGERTRACE(("TRANSACTION %d\n", PAGERID(pPager)));
- if( rc!=SQLITE_OK ){
- assert( !pPager->dbModified );
- /* Ignore any IO error that occurs within pager_end_transaction(). The
- ** purpose of this call is to reset the internal state of the pager
- ** sub-system. It doesn't matter if the journal-file is not properly
- ** finalized at this point (since it is not a valid journal file anyway).
- */
- pager_end_transaction(pPager, 0);
- }
return rc;
}
@@ -38275,10 +38329,7 @@ static int pager_write(PgHdr *pPg){
** which means they have acquired the necessary locks but the rollback
** journal might not yet be open.
*/
- rc = sqlite3PagerBegin(pPager, 0, pPager->subjInMemory);
- if( rc!=SQLITE_OK ){
- return rc;
- }
+ assert( pPager->state>=RESERVED_LOCK );
if( pPager->pInJournal==0
&& pPager->journalMode!=PAGER_JOURNALMODE_OFF
&& !pagerUseWal(pPager)
@@ -38719,7 +38770,10 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(
*/
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
PgHdr *pPg;
- assert( isOpen(pPager->jfd) || pPager->journalMode==PAGER_JOURNALMODE_OFF );
+ assert( isOpen(pPager->jfd)
+ || pPager->journalMode==PAGER_JOURNALMODE_OFF
+ || pPager->journalMode==PAGER_JOURNALMODE_WAL
+ );
if( !zMaster && isOpen(pPager->jfd)
&& pPager->journalOff==jrnlBufferSize(pPager)
&& pPager->dbSize>=pPager->dbFileSize
@@ -38793,7 +38847,7 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(
if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
/* Write all dirty pages to the database file. */
- rc = pager_write_pagelist(sqlite3PcacheDirtyList(pPager->pPCache));
+ rc = pager_write_pagelist(pPager,sqlite3PcacheDirtyList(pPager->pPCache));
if( rc!=SQLITE_OK ){
assert( rc!=SQLITE_IOERR_BLOCKED );
goto commit_phase_one_exit;
@@ -38853,7 +38907,7 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager *pPager){
** fails - make it so that we never reach this point if we do not hold
** all necessary locks.
*/
- if( pPager->state<PAGER_RESERVED ) return SQLITE_ERROR;
+ if( NEVER(pPager->state<PAGER_RESERVED) ) return SQLITE_ERROR;
/* An optimization. If the database was not actually modified during
** this transaction, the pager is running in exclusive-mode and is
@@ -38869,7 +38923,7 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager *pPager){
if( pPager->dbModified==0 && pPager->exclusiveMode
&& pPager->journalMode==PAGER_JOURNALMODE_PERSIST
){
- assert( pPager->journalOff==JOURNAL_HDR_SZ(pPager) );
+ assert( pPager->journalOff==JOURNAL_HDR_SZ(pPager) || !pPager->journalOff );
return SQLITE_OK;
}
@@ -39203,7 +39257,7 @@ SQLITE_PRIVATE int sqlite3PagerNosync(Pager *pPager){
/*
** Set or retrieve the codec for this pager
*/
-static void sqlite3PagerSetCodec(
+SQLITE_PRIVATE void sqlite3PagerSetCodec(
Pager *pPager,
void *(*xCodec)(void*,void*,Pgno,int),
void (*xCodecSizeChng)(void*,int,int),
@@ -39217,7 +39271,7 @@ static void sqlite3PagerSetCodec(
pPager->pCodec = pCodec;
pagerReportSize(pPager);
}
-static void *sqlite3PagerGetCodec(Pager *pPager){
+SQLITE_PRIVATE void *sqlite3PagerGetCodec(Pager *pPager){
return pPager->pCodec;
}
#endif
@@ -39541,7 +39595,7 @@ SQLITE_PRIVATE int sqlite3PagerGetJournalMode(Pager *pPager){
*/
SQLITE_PRIVATE int sqlite3PagerOkToChangeJournalMode(Pager *pPager){
if( pPager->dbModified ) return 0;
- if( isOpen(pPager->jfd) && pPager->journalOff>0 ) return 0;
+ if( NEVER(isOpen(pPager->jfd) && pPager->journalOff>0) ) return 0;
return 1;
}
@@ -39598,25 +39652,37 @@ SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager){
}
/*
-** Open a connection to the write-ahead log file for pager pPager. If
-** the log connection is already open, this function is a no-op.
-**
** The caller must be holding a SHARED lock on the database file to call
** this function.
+**
+** If the pager passed as the first argument is open on a real database
+** file (not a temp file or an in-memory database), and the WAL file
+** is not already open, make an attempt to open it now. If successful,
+** return SQLITE_OK. If an error occurs or the VFS used by the pager does
+** not support the xShmXXX() methods, return an error code. *pisOpen is
+** not modified in either case.
+**
+** If the pager is open on a temp-file (or in-memory database), or if
+** the WAL file is already open, set *pisOpen to 1 and return SQLITE_OK
+** without doing anything.
*/
-SQLITE_PRIVATE int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen){
+SQLITE_PRIVATE int sqlite3PagerOpenWal(
+ Pager *pPager, /* Pager object */
+ int *pisOpen /* OUT: Set to true if call is a no-op */
+){
int rc = SQLITE_OK; /* Return code */
assert( pPager->state>=PAGER_SHARED );
- if( !pPager->pWal ){
+ assert( (pisOpen==0 && !pPager->tempFile && !pPager->pWal) || *pisOpen==0 );
+
+ if( !pPager->tempFile && !pPager->pWal ){
if( !sqlite3PagerWalSupported(pPager) ) return SQLITE_CANTOPEN;
/* Open the connection to the log file. If this operation fails,
** (e.g. due to malloc() failure), unlock the database file and
** return an error code.
*/
- rc = sqlite3WalOpen(pPager->pVfs, pPager->fd,
- pPager->zFilename, &pPager->pWal);
+ rc = sqlite3WalOpen(pPager->pVfs, pPager->fd, pPager->zWal, &pPager->pWal);
if( rc==SQLITE_OK ){
pPager->journalMode = PAGER_JOURNALMODE_WAL;
}
@@ -39649,11 +39715,13 @@ SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager){
int logexists = 0;
rc = sqlite3OsLock(pPager->fd, SQLITE_LOCK_SHARED);
if( rc==SQLITE_OK ){
- rc = pagerHasWAL(pPager, &logexists);
+ rc = sqlite3OsAccess(
+ pPager->pVfs, pPager->zWal, SQLITE_ACCESS_EXISTS, &logexists
+ );
}
if( rc==SQLITE_OK && logexists ){
rc = sqlite3WalOpen(pPager->pVfs, pPager->fd,
- pPager->zFilename, &pPager->pWal);
+ pPager->zWal, &pPager->pWal);
}
}
@@ -40095,7 +40163,7 @@ struct WalCkptInfo {
** is to the start of the write-ahead log frame-header.
*/
#define walFrameOffset(iFrame, szPage) ( \
- WAL_HDRSIZE + ((iFrame)-1)*((szPage)+WAL_FRAME_HDRSIZE) \
+ WAL_HDRSIZE + ((iFrame)-1)*(i64)((szPage)+WAL_FRAME_HDRSIZE) \
)
/*
@@ -40116,7 +40184,7 @@ struct Wal {
u8 writeLock; /* True if in a write transaction */
u8 ckptLock; /* True if holding a checkpoint lock */
WalIndexHdr hdr; /* Wal-index header for current transaction */
- char *zWalName; /* Name of WAL file */
+ const char *zWalName; /* Name of WAL file */
u32 nCkpt; /* Checkpoint sequence counter in the wal-header */
#ifdef SQLITE_DEBUG
u8 lockError; /* True if a locking error has occurred */
@@ -40196,12 +40264,12 @@ static int walIndexPage(Wal *pWal, int iPage, volatile u32 **ppPage){
if( pWal->nWiData<=iPage ){
int nByte = sizeof(u32 *)*(iPage+1);
volatile u32 **apNew;
- apNew = (volatile u32 **)sqlite3_realloc(pWal->apWiData, nByte);
+ apNew = (volatile u32 **)sqlite3_realloc((void *)pWal->apWiData, nByte);
if( !apNew ){
*ppPage = 0;
return SQLITE_NOMEM;
}
- memset(&apNew[pWal->nWiData], 0, sizeof(u32 *)*(iPage+1-pWal->nWiData));
+ memset((void *)&apNew[pWal->nWiData], 0, sizeof(u32 *)*(iPage+1-pWal->nWiData));
pWal->apWiData = apNew;
pWal->nWiData = iPage+1;
}
@@ -40436,7 +40504,7 @@ static int walLockShared(Wal *pWal, int lockIdx){
SQLITE_SHM_LOCK | SQLITE_SHM_SHARED);
WALTRACE(("WAL%p: acquire SHARED-%s %s\n", pWal,
walLockName(lockIdx), rc ? "failed" : "ok"));
- VVA_ONLY( pWal->lockError = (rc!=SQLITE_OK && rc!=SQLITE_BUSY); )
+ VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && rc!=SQLITE_BUSY); )
return rc;
}
static void walUnlockShared(Wal *pWal, int lockIdx){
@@ -40452,7 +40520,7 @@ static int walLockExclusive(Wal *pWal, int lockIdx, int n){
SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE);
WALTRACE(("WAL%p: acquire EXCLUSIVE-%s cnt=%d %s\n", pWal,
walLockName(lockIdx), n, rc ? "failed" : "ok"));
- VVA_ONLY( pWal->lockError = (rc!=SQLITE_OK && rc!=SQLITE_BUSY); )
+ VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && rc!=SQLITE_BUSY); )
return rc;
}
static void walUnlockExclusive(Wal *pWal, int lockIdx, int n){
@@ -40600,7 +40668,7 @@ static void walCleanupHash(Wal *pWal){
/* Zero the entries in the aPgno array that correspond to frames with
** frame numbers greater than pWal->hdr.mxFrame.
*/
- nByte = ((char *)aHash - (char *)&aPgno[iLimit+1]);
+ nByte = (int)((char *)aHash - (char *)&aPgno[iLimit+1]);
memset((void *)&aPgno[iLimit+1], 0, nByte);
#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
@@ -40648,7 +40716,7 @@ static int walIndexAppend(Wal *pWal, u32 iFrame, u32 iPage){
** entire hash table and aPgno[] array before proceding.
*/
if( idx==1 ){
- int nByte = (u8 *)&aHash[HASHTABLE_NSLOT] - (u8 *)&aPgno[1];
+ int nByte = (int)((u8 *)&aHash[HASHTABLE_NSLOT] - (u8 *)&aPgno[1]);
memset((void*)&aPgno[1], 0, nByte);
}
@@ -40668,7 +40736,7 @@ static int walIndexAppend(Wal *pWal, u32 iFrame, u32 iPage){
assert( nCollide++ < idx );
}
aPgno[idx] = iPage;
- aHash[iKey] = idx;
+ aHash[iKey] = (ht_slot)idx;
#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
/* Verify that the number of entries in the hash table exactly equals
@@ -40776,8 +40844,8 @@ static int walIndexRecover(Wal *pWal){
){
goto finished;
}
- pWal->hdr.bigEndCksum = (magic&0x00000001);
- pWal->szPage = szPage;
+ pWal->hdr.bigEndCksum = (u8)(magic&0x00000001);
+ pWal->szPage = (u16)szPage;
pWal->nCkpt = sqlite3Get4byte(&aBuf[12]);
memcpy(&pWal->hdr.aSalt, &aBuf[16], 8);
@@ -40827,7 +40895,7 @@ static int walIndexRecover(Wal *pWal){
if( nTruncate ){
pWal->hdr.mxFrame = iFrame;
pWal->hdr.nPage = nTruncate;
- pWal->hdr.szPage = szPage;
+ pWal->hdr.szPage = (u16)szPage;
aFrameCksum[0] = pWal->hdr.aFrameCksum[0];
aFrameCksum[1] = pWal->hdr.aFrameCksum[1];
}
@@ -40871,8 +40939,9 @@ static void walIndexClose(Wal *pWal, int isDelete){
}
/*
-** Open a connection to the WAL file associated with database zDbName.
-** The database file must already be opened on connection pDbFd.
+** Open a connection to the WAL file zWalName. The database file must
+** already be opened on connection pDbFd. The buffer that zWalName points
+** to must remain valid for the lifetime of the returned Wal* handle.
**
** A SHARED lock should be held on the database file when this function
** is called. The purpose of this SHARED lock is to prevent any other
@@ -40887,16 +40956,14 @@ static void walIndexClose(Wal *pWal, int isDelete){
SQLITE_PRIVATE int sqlite3WalOpen(
sqlite3_vfs *pVfs, /* vfs module to open wal and wal-index */
sqlite3_file *pDbFd, /* The open database file */
- const char *zDbName, /* Name of the database file */
+ const char *zWalName, /* Name of the WAL file */
Wal **ppWal /* OUT: Allocated Wal handle */
){
int rc; /* Return Code */
Wal *pRet; /* Object to allocate and return */
int flags; /* Flags passed to OsOpen() */
- char *zWal; /* Name of write-ahead log file */
- int nWal; /* Length of zWal in bytes */
- assert( zDbName && zDbName[0] );
+ assert( zWalName && zWalName[0] );
assert( pDbFd );
/* In the amalgamation, the os_unix.c and os_win.c source files come before
@@ -40913,8 +40980,7 @@ SQLITE_PRIVATE int sqlite3WalOpen(
/* Allocate an instance of struct Wal to return. */
*ppWal = 0;
- nWal = sqlite3Strlen30(zDbName) + 5;
- pRet = (Wal*)sqlite3MallocZero(sizeof(Wal) + pVfs->szOsFile + nWal);
+ pRet = (Wal*)sqlite3MallocZero(sizeof(Wal) + pVfs->szOsFile);
if( !pRet ){
return SQLITE_NOMEM;
}
@@ -40924,15 +40990,14 @@ SQLITE_PRIVATE int sqlite3WalOpen(
pRet->pDbFd = pDbFd;
pRet->readLock = -1;
sqlite3_randomness(8, &pRet->hdr.aSalt);
- pRet->zWalName = zWal = pVfs->szOsFile + (char*)pRet->pWalFd;
- sqlite3_snprintf(nWal, zWal, "%s-wal", zDbName);
+ pRet->zWalName = zWalName;
rc = sqlite3OsShmOpen(pDbFd);
/* Open file handle on the write-ahead log file. */
if( rc==SQLITE_OK ){
pRet->isWIndexOpen = 1;
flags = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_MAIN_JOURNAL);
- rc = sqlite3OsOpen(pVfs, zWal, pRet->pWalFd, flags, &flags);
+ rc = sqlite3OsOpen(pVfs, zWalName, pRet->pWalFd, flags, &flags);
}
if( rc!=SQLITE_OK ){
@@ -41155,12 +41220,12 @@ static int walIteratorInit(Wal *pWal, WalIterator **pp){
ht_slot *aIndex; /* Sorted index for this segment */
aPgno++;
- nEntry = ((i+1)==nSegment)?(int)(iLast-iZero):(u32 *)aHash-(u32 *)aPgno;
+ nEntry = (int)(((i+1)==nSegment)?(int)(iLast-iZero):(u32 *)aHash-(u32 *)aPgno);
aIndex = &((ht_slot *)&p->aSegment[p->nSegment])[iZero];
iZero++;
for(j=0; j<nEntry; j++){
- aIndex[j] = j;
+ aIndex[j] = (ht_slot)j;
}
walMergesort((u32 *)aPgno, aTmp, aIndex, &nEntry);
p->aSegment[i].iZero = iZero;
@@ -41274,20 +41339,25 @@ static int walCheckpoint(
/* Iterate through the contents of the WAL, copying data to the db file. */
while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){
+ i64 iOffset;
assert( walFramePgno(pWal, iFrame)==iDbpage );
if( iFrame<=nBackfill || iFrame>mxSafeFrame ) continue;
- rc = sqlite3OsRead(pWal->pWalFd, zBuf, szPage,
- walFrameOffset(iFrame, szPage) + WAL_FRAME_HDRSIZE
- );
+ iOffset = walFrameOffset(iFrame, szPage) + WAL_FRAME_HDRSIZE;
+ /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL file */
+ rc = sqlite3OsRead(pWal->pWalFd, zBuf, szPage, iOffset);
if( rc!=SQLITE_OK ) break;
- rc = sqlite3OsWrite(pWal->pDbFd, zBuf, szPage, (iDbpage-1)*szPage);
+ iOffset = (iDbpage-1)*(i64)szPage;
+ testcase( IS_BIG_INT(iOffset) );
+ rc = sqlite3OsWrite(pWal->pDbFd, zBuf, szPage, iOffset);
if( rc!=SQLITE_OK ) break;
}
/* If work was actually accomplished... */
if( rc==SQLITE_OK ){
if( mxSafeFrame==walIndexHdr(pWal)->mxFrame ){
- rc = sqlite3OsTruncate(pWal->pDbFd, ((i64)pWal->hdr.nPage*(i64)szPage));
+ i64 szDb = pWal->hdr.nPage*(i64)szPage;
+ testcase( IS_BIG_INT(szDb) );
+ rc = sqlite3OsTruncate(pWal->pDbFd, szDb);
if( rc==SQLITE_OK && sync_flags ){
rc = sqlite3OsSync(pWal->pDbFd, sync_flags);
}
@@ -41347,7 +41417,7 @@ SQLITE_PRIVATE int sqlite3WalClose(
sqlite3OsDelete(pWal->pVfs, pWal->zWalName, 0);
}
WALTRACE(("WAL%p: closed\n", pWal));
- sqlite3_free(pWal->apWiData);
+ sqlite3_free((void *)pWal->apWiData);
sqlite3_free(pWal);
}
return rc;
@@ -41683,7 +41753,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
return WAL_RETRY;
}else{
assert( mxReadMark<=pWal->hdr.mxFrame );
- pWal->readLock = mxI;
+ pWal->readLock = (i16)mxI;
}
}
return rc;
@@ -41825,6 +41895,7 @@ SQLITE_PRIVATE int sqlite3WalRead(
if( iRead ){
i64 iOffset = walFrameOffset(iRead, pWal->hdr.szPage) + WAL_FRAME_HDRSIZE;
*pInWal = 1;
+ /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL */
return sqlite3OsRead(pWal->pWalFd, pOut, nOut, iOffset);
}
@@ -42096,7 +42167,7 @@ SQLITE_PRIVATE int sqlite3WalFrames(
sqlite3Put4byte(&aWalHdr[24], aCksum[0]);
sqlite3Put4byte(&aWalHdr[28], aCksum[1]);
- pWal->szPage = szPage;
+ pWal->szPage = (u16)szPage;
pWal->hdr.bigEndCksum = SQLITE_BIGENDIAN;
pWal->hdr.aFrameCksum[0] = aCksum[0];
pWal->hdr.aFrameCksum[1] = aCksum[1];
@@ -42115,8 +42186,8 @@ SQLITE_PRIVATE int sqlite3WalFrames(
i64 iOffset; /* Write offset in log file */
void *pData;
-
iOffset = walFrameOffset(++iFrame, szPage);
+ /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL */
/* Populate and write the frame header */
nDbsize = (isCommit && p->pDirty==0) ? nTruncate : 0;
@@ -42156,6 +42227,7 @@ SQLITE_PRIVATE int sqlite3WalFrames(
pData = pLast->pData;
#endif
walEncodeFrame(pWal, pLast->pgno, nTruncate, pData, aFrame);
+ /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL */
rc = sqlite3OsWrite(pWal->pWalFd, aFrame, sizeof(aFrame), iOffset);
if( rc!=SQLITE_OK ){
return rc;
@@ -42190,7 +42262,7 @@ SQLITE_PRIVATE int sqlite3WalFrames(
if( rc==SQLITE_OK ){
/* Update the private copy of the header. */
- pWal->hdr.szPage = szPage;
+ pWal->hdr.szPage = (u16)szPage;
pWal->hdr.mxFrame = iFrame;
if( isCommit ){
pWal->hdr.iChange++;
@@ -44927,16 +44999,20 @@ static int getAndInitPage(
int rc;
assert( sqlite3_mutex_held(pBt->mutex) );
- if( pgno<=0 || pgno>btreePagecount(pBt) ){
- return SQLITE_CORRUPT_BKPT;
- }
- rc = btreeGetPage(pBt, pgno, ppPage, 0);
- if( rc==SQLITE_OK ){
- rc = btreeInitPage(*ppPage);
- if( rc!=SQLITE_OK ){
- releasePage(*ppPage);
+ if( pgno>btreePagecount(pBt) ){
+ rc = SQLITE_CORRUPT_BKPT;
+ }else{
+ rc = btreeGetPage(pBt, pgno, ppPage, 0);
+ if( rc==SQLITE_OK ){
+ rc = btreeInitPage(*ppPage);
+ if( rc!=SQLITE_OK ){
+ releasePage(*ppPage);
+ }
}
}
+
+ testcase( pgno==0 );
+ assert( pgno!=0 || rc==SQLITE_CORRUPT );
return rc;
}
@@ -45863,7 +45939,7 @@ SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag){
rc = querySharedCacheTableLock(p, MASTER_ROOT, READ_LOCK);
if( SQLITE_OK!=rc ) goto trans_begun;
- pBt->initiallyEmpty = pBt->nPage==0;
+ pBt->initiallyEmpty = (u8)(pBt->nPage==0);
do {
/* Call lockBtree() until either pBt->pPage1 is populated or
** lockBtree() returns something other than SQLITE_OK. lockBtree()
@@ -47586,7 +47662,6 @@ SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){
if( pCur->eState==CURSOR_INVALID ){
assert( pCur->apPage[pCur->iPage]->nCell==0 );
*pRes = 1;
- rc = SQLITE_OK;
}else{
assert( pCur->apPage[pCur->iPage]->nCell>0 );
*pRes = 0;
@@ -51351,7 +51426,7 @@ SQLITE_PRIVATE int sqlite3BtreeSetVersion(Btree *pBtree, int iVersion){
/* If setting the version fields to 1, do not automatically open the
** WAL connection, even if the version fields are currently set to 2.
*/
- pBt->doNotUseWAL = (iVersion==1);
+ pBt->doNotUseWAL = (u8)(iVersion==1);
rc = sqlite3BtreeBeginTrans(pBtree, 0);
if( rc==SQLITE_OK ){
@@ -51843,6 +51918,9 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
assert( rc2==SQLITE_OK );
}
+ if( rc==SQLITE_IOERR_NOMEM ){
+ rc = SQLITE_NOMEM;
+ }
p->rc = rc;
}
if( p->pDestDb ){
@@ -53965,7 +54043,9 @@ SQLITE_PRIVATE void sqlite3VdbeNoopComment(Vdbe *p, const char *zFormat, ...){
** check the value of p->nOp-1 before continuing.
*/
SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){
- static const VdbeOp dummy;
+ /* C89 specifies that the constant "dummy" will be initialized to all
+ ** zeros, which is correct. MSVC generates a warning, nevertheless. */
+ static const VdbeOp dummy; /* Ignore the MSVC warning about no initializer */
assert( p->magic==VDBE_MAGIC_INIT );
if( addr<0 ){
#ifdef SQLITE_OMIT_TRACE
@@ -62396,14 +62476,13 @@ case OP_Rewind: { /* jump */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
u.bl.pC = p->apCsr[pOp->p1];
assert( u.bl.pC!=0 );
+ u.bl.res = 1;
if( (u.bl.pCrsr = u.bl.pC->pCursor)!=0 ){
rc = sqlite3BtreeFirst(u.bl.pCrsr, &u.bl.res);
u.bl.pC->atFirst = u.bl.res==0 ?1:0;
u.bl.pC->deferredMoveto = 0;
u.bl.pC->cacheStatus = CACHE_STALE;
u.bl.pC->rowidIsValid = 0;
- }else{
- u.bl.res = 1;
}
u.bl.pC->nullRow = (u8)u.bl.res;
assert( pOp->p2>0 && pOp->p2<p->nOp );
@@ -63447,6 +63526,7 @@ case OP_Checkpoint: {
};
#endif
+#ifndef SQLITE_OMIT_PRAGMA
/* Opcode: JournalMode P1 P2 P3 * P5
**
** Change the journal mode of database P1 to P3. P3 must be one of the
@@ -63573,7 +63653,8 @@ case OP_JournalMode: { /* out2-prerelease */
pOut->enc = SQLITE_UTF8;
sqlite3VdbeChangeEncoding(pOut, encoding);
break;
-};
+};
+#endif /* SQLITE_OMIT_PRAGMA */
#if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH)
/* Opcode: Vacuum * * * * *
@@ -64757,7 +64838,12 @@ static struct sqlite3_io_methods JournalFileMethods = {
0, /* xCheckReservedLock */
0, /* xFileControl */
0, /* xSectorSize */
- 0 /* xDeviceCharacteristics */
+ 0, /* xDeviceCharacteristics */
+ 0, /* xShmOpen */
+ 0, /* xShmLock */
+ 0, /* xShmMap */
+ 0, /* xShmBarrier */
+ 0 /* xShmClose */
};
/*
@@ -83535,6 +83621,10 @@ SQLITE_PRIVATE void sqlite3Pragma(
if( sqlite3StrICmp(zLeft,"journal_mode")==0 ){
int eMode; /* One of the PAGER_JOURNALMODE_XXX symbols */
+ if( sqlite3ReadSchema(pParse) ){
+ goto pragma_out;
+ }
+
sqlite3VdbeSetNumCols(v, 1);
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "journal_mode", SQLITE_STATIC);
@@ -83543,7 +83633,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
}else{
const char *zMode;
int n = sqlite3Strlen30(zRight);
- for(eMode=0; (zMode = sqlite3JournalModename(eMode)); eMode++){
+ for(eMode=0; (zMode = sqlite3JournalModename(eMode))!=0; eMode++){
if( sqlite3StrNICmp(zRight, zMode, n)==0 ) break;
}
if( !zMode ){
@@ -84598,12 +84688,15 @@ SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char
*/
int rc;
sqlite3_stmt *pStmt;
+ TESTONLY(int rcp); /* Return code from sqlite3_prepare() */
assert( db->init.busy );
db->init.iDb = iDb;
db->init.newTnum = atoi(argv[1]);
db->init.orphanTrigger = 0;
- rc = sqlite3_prepare(db, argv[2], -1, &pStmt, 0);
+ TESTONLY(rcp = ) sqlite3_prepare(db, argv[2], -1, &pStmt, 0);
+ rc = db->errCode;
+ assert( (rc&0xFF)==(rcp&0xFF) );
db->init.iDb = 0;
if( SQLITE_OK!=rc ){
if( db->init.orphanTrigger ){
@@ -84612,7 +84705,7 @@ SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char
pData->rc = rc;
if( rc==SQLITE_NOMEM ){
db->mallocFailed = 1;
- }else if( rc!=SQLITE_INTERRUPT && rc!=SQLITE_LOCKED ){
+ }else if( rc!=SQLITE_INTERRUPT && (rc&0xFF)!=SQLITE_LOCKED ){
corruptSchema(pData, argv[0], sqlite3_errmsg(db));
}
}
@@ -94779,7 +94872,7 @@ static void constructAutomaticIndex(
}
}
}
- assert( n==pLevel->plan.nEq );
+ assert( (u32)n==pLevel->plan.nEq );
/* Add additional columns needed to make the automatic index into
** a covering index */
@@ -96373,7 +96466,7 @@ static Bitmask codeOneLoopStart(
** a forward order scan on a descending index, interchange the
** start and end terms (pRangeStart and pRangeEnd).
*/
- if( bRev==(pIdx->aSortOrder[nEq]==SQLITE_SO_ASC) ){
+ if( nEq<pIdx->nColumn && bRev==(pIdx->aSortOrder[nEq]==SQLITE_SO_ASC) ){
SWAP(WhereTerm *, pRangeEnd, pRangeStart);
}
@@ -104088,7 +104181,6 @@ SQLITE_API int sqlite3_collation_needed16(
}
#endif /* SQLITE_OMIT_UTF16 */
-#ifndef SQLITE_OMIT_GLOBALRECOVER
#ifndef SQLITE_OMIT_DEPRECATED
/*
** This function is now an anachronism. It used to be used to recover from a
@@ -104098,7 +104190,6 @@ SQLITE_API int sqlite3_global_recover(void){
return SQLITE_OK;
}
#endif
-#endif
/*
** Test to see whether or not the database connection is in autocommit
@@ -106073,6 +106164,9 @@ static int fts3CreateTables(Fts3Table *p){
** An sqlite3_exec() callback for fts3TableExists.
*/
static int fts3TableExistsCallback(void *pArg, int n, char **pp1, char **pp2){
+ UNUSED_PARAMETER(n);
+ UNUSED_PARAMETER(pp1);
+ UNUSED_PARAMETER(pp2);
*(int*)pArg = 1;
return 1;
}
@@ -106098,7 +106192,7 @@ static void fts3TableExists(
);
rc = sqlite3_exec(db, zSql, fts3TableExistsCallback, &res, 0);
sqlite3_free(zSql);
- *pResult = res & 0xff;
+ *pResult = (u8)(res & 0xff);
if( rc!=SQLITE_ABORT ) *pRc = rc;
}
diff --git a/dist/sqlite3.c.orig b/dist/sqlite3.c.orig
index 5058edf..2ac17c8 100644
--- a/dist/sqlite3.c.orig
+++ b/dist/sqlite3.c.orig
@@ -512,6 +512,13 @@ SQLITE_PRIVATE void sqlite3Coverage(int);
#endif
/*
+** Return true (non-zero) if the input is a integer that is too large
+** to fit in 32-bits. This macro is used inside of various testcase()
+** macros to verify that we have tested SQLite for large-file support.
+*/
+#define IS_BIG_INT(X) (((X)&(i64)0xffffffff)!=0)
+
+/*
** The macro unlikely() is a hint that surrounds a boolean
** expression that is usually false. Macro likely() surrounds
** a boolean expression that is usually true. GCC is able to
@@ -638,7 +645,7 @@ extern "C" {
*/
#define SQLITE_VERSION "3.7.0"
#define SQLITE_VERSION_NUMBER 3007000
-#define SQLITE_SOURCE_ID "2010-06-28 10:15:20 4932f22848b3d15a2b6dc5fa2cd69ce19182e2a4"
+#define SQLITE_SOURCE_ID "2010-07-07 14:45:41 8eefc287265443ec043bdab629597e79c9d22006"
/*
** CAPI3REF: Run-Time Library Version Numbers
@@ -1361,16 +1368,23 @@ typedef struct sqlite3_mutex sqlite3_mutex;
** handled as a fatal error by SQLite, vfs implementations should endeavor
** to prevent this by setting mxPathname to a sufficiently large value.
**
-** The xRandomness(), xSleep(), and xCurrentTime() interfaces
-** are not strictly a part of the filesystem, but they are
+** The xRandomness(), xSleep(), xCurrentTime(), and xCurrentTimeInt64()
+** interfaces are not strictly a part of the filesystem, but they are
** included in the VFS structure for completeness.
** The xRandomness() function attempts to return nBytes bytes
** of good-quality randomness into zOut. The return value is
** the actual number of bytes of randomness obtained.
** The xSleep() method causes the calling thread to sleep for at
** least the number of microseconds given. The xCurrentTime()
-** method returns a Julian Day Number for the current date and time.
-**
+** method returns a Julian Day Number for the current date and time as
+** a floating point value.
+** The xCurrentTimeInt64() method returns, as an integer, the Julian
+** Day Number multipled by 86400000 (the number of milliseconds in
+** a 24-hour day).
+** ^SQLite will use the xCurrentTimeInt64() method to get the current
+** date and time if that method is available (if iVersion is 2 or
+** greater and the function pointer is not NULL) and will fall back
+** to xCurrentTime() if xCurrentTimeInt64() is unavailable.
*/
typedef struct sqlite3_vfs sqlite3_vfs;
struct sqlite3_vfs {
@@ -1397,7 +1411,6 @@ struct sqlite3_vfs {
** The methods above are in version 1 of the sqlite_vfs object
** definition. Those that follow are added in version 2 or later
*/
- int (*xRename)(sqlite3_vfs*, const char *zOld, const char *zNew, int dirSync);
int (*xCurrentTimeInt64)(sqlite3_vfs*, sqlite3_int64*);
/*
** The methods above are in versions 1 and 2 of the sqlite_vfs object.
@@ -11329,9 +11342,11 @@ static const char * const azCompileOpt[] = {
#ifdef SQLITE_OMIT_CHECK
"OMIT_CHECK",
#endif
-#ifdef SQLITE_OMIT_COMPILEOPTION_DIAGS
- "OMIT_COMPILEOPTION_DIAGS",
-#endif
+/* // redundant
+** #ifdef SQLITE_OMIT_COMPILEOPTION_DIAGS
+** "OMIT_COMPILEOPTION_DIAGS",
+** #endif
+*/
#ifdef SQLITE_OMIT_COMPLETE
"OMIT_COMPLETE",
#endif
@@ -11365,9 +11380,6 @@ static const char * const azCompileOpt[] = {
#ifdef SQLITE_OMIT_GET_TABLE
"OMIT_GET_TABLE",
#endif
-#ifdef SQLITE_OMIT_GLOBALRECOVER
- "OMIT_GLOBALRECOVER",
-#endif
#ifdef SQLITE_OMIT_INCRBLOB
"OMIT_INCRBLOB",
#endif
@@ -11446,6 +11458,9 @@ static const char * const azCompileOpt[] = {
#ifdef SQLITE_OMIT_VIRTUALTABLE
"OMIT_VIRTUALTABLE",
#endif
+#ifdef SQLITE_OMIT_WAL
+ "OMIT_WAL",
+#endif
#ifdef SQLITE_OMIT_WSD
"OMIT_WSD",
#endif
@@ -12797,8 +12812,10 @@ SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void){
** sqlite3OsLock()
**
*/
-#if defined(SQLITE_TEST) && (SQLITE_OS_WIN==0)
- #define DO_OS_MALLOC_TEST(x) if (!x || !sqlite3IsMemJournal(x)) { \
+#if defined(SQLITE_TEST)
+SQLITE_API int sqlite3_memdebug_vfs_oom_test = 1;
+ #define DO_OS_MALLOC_TEST(x) \
+ if (sqlite3_memdebug_vfs_oom_test && (!x || !sqlite3IsMemJournal(x))) { \
void *pTstAlloc = sqlite3Malloc(10); \
if (!pTstAlloc) return SQLITE_IOERR_NOMEM; \
sqlite3_free(pTstAlloc); \
@@ -27486,7 +27503,7 @@ static int proxyGetLockPath(const char *dbPath, char *lPath, size_t maxLen){
/* transform the db path to a unique cache name */
dbLen = (int)strlen(dbPath);
- for( i=0; i<dbLen && (i+len+7)<maxLen; i++){
+ for( i=0; i<dbLen && (i+len+7)<(int)maxLen; i++){
char c = dbPath[i];
lPath[i+len] = (c=='/')?'_':c;
}
@@ -27627,6 +27644,9 @@ SQLITE_API int sqlite3_hostid_num = 0;
#define PROXY_HOSTIDLEN 16 /* conch file host id length */
+/* Not always defined in the headers as it ought to be */
+extern int gethostuuid(uuid_t id, const struct timespec *wait);
+
/* get the host ID via gethostuuid(), pHostID must point to PROXY_HOSTIDLEN
** bytes of writable memory.
*/
@@ -27676,6 +27696,7 @@ static int proxyBreakConchLock(unixFile *pFile, uuid_t myHostID){
char errmsg[64] = "";
int fd = -1;
int rc = -1;
+ UNUSED_PARAMETER(myHostID);
/* create a new path by replace the trailing '-conch' with '-break' */
pathLen = strlcpy(tPath, cPath, MAXPATHLEN);
@@ -27696,7 +27717,7 @@ static int proxyBreakConchLock(unixFile *pFile, uuid_t myHostID){
sprintf(errmsg, "create failed (%d)", errno);
goto end_breaklock;
}
- if( pwrite(fd, buf, readLen, 0) != readLen ){
+ if( pwrite(fd, buf, readLen, 0) != (ssize_t)readLen ){
sprintf(errmsg, "write failed (%d)", errno);
goto end_breaklock;
}
@@ -28499,7 +28520,6 @@ SQLITE_API int sqlite3_os_init(void){
unixSleep, /* xSleep */ \
unixCurrentTime, /* xCurrentTime */ \
unixGetLastError, /* xGetLastError */ \
- 0, /* xRename */ \
unixCurrentTimeInt64, /* xCurrentTimeInt64 */ \
}
@@ -29493,7 +29513,11 @@ static int winWrite(
rc = SetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN);
if( rc==INVALID_SET_FILE_POINTER && (error=GetLastError())!=NO_ERROR ){
pFile->lastErrno = error;
- return SQLITE_FULL;
+ if( pFile->lastErrno==ERROR_HANDLE_DISK_FULL ){
+ return SQLITE_FULL;
+ }else{
+ return SQLITE_IOERR_WRITE;
+ }
}
assert( amt>0 );
while(
@@ -29506,7 +29530,11 @@ static int winWrite(
}
if( !rc || amt>(int)wrote ){
pFile->lastErrno = GetLastError();
- return SQLITE_FULL;
+ if( pFile->lastErrno==ERROR_HANDLE_DISK_FULL ){
+ return SQLITE_FULL;
+ }else{
+ return SQLITE_IOERR_WRITE;
+ }
}
return SQLITE_OK;
}
@@ -30193,6 +30221,9 @@ static int winShmOpen(
*/
if( winShmSystemLock(pShmNode, _SHM_WRLCK, WIN_SHM_DMS, 1)==SQLITE_OK ){
rc = winTruncate((sqlite3_file *)&pShmNode->hFile, 0);
+ if( rc!=SQLITE_OK ){
+ rc = SQLITE_IOERR_SHMOPEN;
+ }
}
if( rc==SQLITE_OK ){
winShmSystemLock(pShmNode, _SHM_UNLCK, WIN_SHM_DMS, 1);
@@ -30419,6 +30450,7 @@ static int winShmLock(
static void winShmBarrier(
sqlite3_file *fd /* Database holding the shared memory */
){
+ UNUSED_PARAMETER(fd);
/* MemoryBarrier(); // does not work -- do not know why not */
winShmEnterMutex();
winShmLeaveMutex();
@@ -30830,13 +30862,38 @@ static int winAccess(
){
DWORD attr;
int rc = 0;
- void *zConverted = convertUtf8Filename(zFilename);
+ void *zConverted;
UNUSED_PARAMETER(pVfs);
+
+ SimulateIOError( return SQLITE_IOERR_ACCESS; );
+ zConverted = convertUtf8Filename(zFilename);
if( zConverted==0 ){
return SQLITE_NOMEM;
}
if( isNT() ){
- attr = GetFileAttributesW((WCHAR*)zConverted);
+ WIN32_FILE_ATTRIBUTE_DATA sAttrData;
+ memset(&sAttrData, 0, sizeof(sAttrData));
+ if( GetFileAttributesExW((WCHAR*)zConverted,
+ GetFileExInfoStandard,
+ &sAttrData) ){
+ /* For an SQLITE_ACCESS_EXISTS query, treat a zero-length file
+ ** as if it does not exist.
+ */
+ if( flags==SQLITE_ACCESS_EXISTS
+ && sAttrData.nFileSizeHigh==0
+ && sAttrData.nFileSizeLow==0 ){
+ attr = INVALID_FILE_ATTRIBUTES;
+ }else{
+ attr = sAttrData.dwFileAttributes;
+ }
+ }else{
+ if( GetLastError()!=ERROR_FILE_NOT_FOUND ){
+ free(zConverted);
+ return SQLITE_IOERR_ACCESS;
+ }else{
+ attr = INVALID_FILE_ATTRIBUTES;
+ }
+ }
/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
** Since the ASCII version of these Windows API do not exist for WINCE,
** it's important to not reference them for WINCE builds.
@@ -31236,7 +31293,6 @@ SQLITE_API int sqlite3_os_init(void){
winSleep, /* xSleep */
winCurrentTime, /* xCurrentTime */
winGetLastError, /* xGetLastError */
- 0, /* xRename */
winCurrentTimeInt64, /* xCurrentTimeInt64 */
};
@@ -33506,13 +33562,14 @@ SQLITE_PRIVATE int sqlite3RowSetTest(RowSet *pRowSet, u8 iBatch, sqlite3_int64 i
# define sqlite3WalRead(v,w,x,y,z) 0
# define sqlite3WalDbsize(y,z)
# define sqlite3WalBeginWriteTransaction(y) 0
-# define sqlite3WalEndWRiteTransaction(x) 0
+# define sqlite3WalEndWriteTransaction(x) 0
# define sqlite3WalUndo(x,y,z) 0
# define sqlite3WalSavepoint(y,z)
# define sqlite3WalSavepointUndo(y,z) 0
# define sqlite3WalFrames(u,v,w,x,y,z) 0
# define sqlite3WalCheckpoint(u,v,w,x) 0
# define sqlite3WalCallback(z) 0
+# define sqlite3WalExclusiveMode(y,z) 0
#else
#define WAL_SAVEPOINT_NDATA 4
@@ -33786,7 +33843,9 @@ 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 */
+#ifndef SQLITE_OMIT_WAL
u32 aWalData[WAL_SAVEPOINT_NDATA]; /* WAL savepoint context */
+#endif
};
/*
@@ -33970,6 +34029,7 @@ struct Pager {
sqlite3_backup *pBackup; /* Pointer to list of ongoing backup processes */
#ifndef SQLITE_OMIT_WAL
Wal *pWal; /* Write-ahead log used by "journal_mode=wal" */
+ char *zWal; /* File name for write-ahead log */
#endif
};
@@ -35081,6 +35141,21 @@ static u32 pager_cksum(Pager *pPager, const u8 *aData){
}
/*
+** Report the current page size and number of reserved bytes back
+** to the codec.
+*/
+#ifdef SQLITE_HAS_CODEC
+static void pagerReportSize(Pager *pPager){
+ if( pPager->xCodecSizeChng ){
+ pPager->xCodecSizeChng(pPager->pCodec, pPager->pageSize,
+ (int)pPager->nReserve);
+ }
+}
+#else
+# define pagerReportSize(X) /* No-op if we do not support a codec */
+#endif
+
+/*
** Read a single page from either the journal file (if isMainJrnl==1) or
** from the sub-journal (if isMainJrnl==0) and playback that page.
** The page begins at offset *pOffset into the file. The *pOffset
@@ -35172,12 +35247,21 @@ static int pager_playback_one_page(
}
}
+ /* If this page has already been played by before during the current
+ ** rollback, then don't bother to play it back again.
+ */
if( pDone && (rc = sqlite3BitvecSet(pDone, pgno))!=SQLITE_OK ){
return rc;
}
-
assert( pPager->state==PAGER_RESERVED || pPager->state>=PAGER_EXCLUSIVE );
+ /* When playing back page 1, restore the nReserve setting
+ */
+ if( pgno==1 && pPager->nReserve!=((u8*)aData)[20] ){
+ pPager->nReserve = ((u8*)aData)[20];
+ pagerReportSize(pPager);
+ }
+
/* If the pager is in RESERVED state, then there must be a copy of this
** page in the pager cache. In this case just update the pager cache,
** not the database file. The page is left marked dirty in this case.
@@ -35978,43 +36062,40 @@ static int pagerBeginReadTransaction(Pager *pPager){
/*
** Check if the *-wal file that corresponds to the database opened by pPager
-** exists. Assuming no error occurs, set *pExists to 1 if the file exists,
-** or 0 otherwise and return SQLITE_OK. If an IO or OOM error occurs, return
-** an SQLite error code.
-*/
-static int pagerHasWAL(Pager *pPager, int *pExists){
- int rc; /* Return code */
- char *zWal; /* Name of the WAL file */
-
- assert( !pPager->tempFile );
- zWal = sqlite3_mprintf("%s-wal", pPager->zFilename);
- if( !zWal ){
- rc = SQLITE_NOMEM;
- }else{
- rc = sqlite3OsAccess(pPager->pVfs, zWal, SQLITE_ACCESS_EXISTS, pExists);
- sqlite3_free(zWal);
- }
- return rc;
-}
-
-/*
-** Check if the *-wal file that corresponds to the database opened by pPager
-** exists. If it does, open the pager in WAL mode. Otherwise, if no error
-** occurs, make sure Pager.journalMode is not set to PAGER_JOURNALMODE_WAL.
-** If an IO or OOM error occurs, return an SQLite error code.
+** exists if the database is not empy, or verify that the *-wal file does
+** not exist (by deleting it) if the database file is empty.
+**
+** If the database is not empty and the *-wal file exists, open the pager
+** in WAL mode. If the database is empty or if no *-wal file exists and
+** if no error occurs, make sure Pager.journalMode is not set to
+** PAGER_JOURNALMODE_WAL.
+**
+** Return SQLITE_OK or an error code.
**
** If the WAL file is opened, also open a snapshot (read transaction).
**
** The caller must hold a SHARED lock on the database file to call this
** function. Because an EXCLUSIVE lock on the db file is required to delete
-** a WAL, this ensures there is no race condition between the xAccess()
-** below and an xDelete() being executed by some other connection.
+** a WAL on a none-empty database, this ensures there is no race condition
+** between the xAccess() below and an xDelete() being executed by some
+** other connection.
*/
static int pagerOpenWalIfPresent(Pager *pPager){
int rc = SQLITE_OK;
if( !pPager->tempFile ){
int isWal; /* True if WAL file exists */
- rc = pagerHasWAL(pPager, &isWal);
+ int nPage; /* Size of the database file */
+ assert( pPager->state>=SHARED_LOCK );
+ rc = sqlite3PagerPagecount(pPager, &nPage);
+ if( rc ) return rc;
+ if( nPage==0 ){
+ rc = sqlite3OsDelete(pPager->pVfs, pPager->zWal, 0);
+ isWal = 0;
+ }else{
+ rc = sqlite3OsAccess(
+ pPager->pVfs, pPager->zWal, SQLITE_ACCESS_EXISTS, &isWal
+ );
+ }
if( rc==SQLITE_OK ){
if( isWal ){
pager_reset(pPager);
@@ -36288,21 +36369,6 @@ SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(
}
/*
-** Report the current page size and number of reserved bytes back
-** to the codec.
-*/
-#ifdef SQLITE_HAS_CODEC
-static void pagerReportSize(Pager *pPager){
- if( pPager->xCodecSizeChng ){
- pPager->xCodecSizeChng(pPager->pCodec, pPager->pageSize,
- (int)pPager->nReserve);
- }
-}
-#else
-# define pagerReportSize(X) /* No-op if we do not support a codec */
-#endif
-
-/*
** Change the page size used by the Pager object. The new page size
** is passed in *pPageSize.
**
@@ -36388,7 +36454,7 @@ SQLITE_PRIVATE int sqlite3PagerMaxPageCount(Pager *pPager, int mxPage){
}
if( pPager->state!=PAGER_UNLOCK ){
sqlite3PagerPagecount(pPager, &nPage);
- assert( pPager->mxPgno>=nPage );
+ assert( (int)pPager->mxPgno>=nPage );
}
return pPager->mxPgno;
}
@@ -36441,15 +36507,6 @@ SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager *pPager, int N, unsigned cha
** to WAL mode yet.
*/
assert( !pagerUseWal(pPager) );
-#if 0
- if( pagerUseWal(pPager) ){
- int isInWal = 0;
- rc = sqlite3WalRead(pPager->pWal, 1, &isInWal, N, pDest);
- if( rc!=SQLITE_OK || isInWal ){
- return rc;
- }
- }
-#endif
if( isOpen(pPager->fd) ){
IOTRACE(("DBHDR %p 0 %d\n", pPager, N))
@@ -36893,13 +36950,9 @@ static int syncJournal(Pager *pPager){
** occurs, an IO error code is returned. Or, if the EXCLUSIVE lock cannot
** be obtained, SQLITE_BUSY is returned.
*/
-static int pager_write_pagelist(PgHdr *pList){
- Pager *pPager; /* Pager object */
+static int pager_write_pagelist(Pager *pPager, PgHdr *pList){
int rc; /* Return code */
- if( NEVER(pList==0) ) return SQLITE_OK;
- pPager = pList->pPager;
-
/* At this point there may be either a RESERVED or EXCLUSIVE lock on the
** database file. If there is already an EXCLUSIVE lock, the following
** call is a no-op.
@@ -36916,7 +36969,7 @@ static int pager_write_pagelist(PgHdr *pList){
** EXCLUSIVE, it means the database file has been changed and any rollback
** will require a journal playback.
*/
- assert( !pagerUseWal(pList->pPager) );
+ assert( !pagerUseWal(pPager) );
assert( pPager->state>=PAGER_RESERVED );
rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
@@ -37161,7 +37214,7 @@ static int pagerStress(void *p, PgHdr *pPg){
/* Write the contents of the page out to the database file. */
if( rc==SQLITE_OK ){
- rc = pager_write_pagelist(pPg);
+ rc = pager_write_pagelist(pPager, pPg);
}
}
@@ -37301,6 +37354,9 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
journalFileSize * 2 + /* The two journal files */
nPathname + 1 + /* zFilename */
nPathname + 8 + 1 /* zJournal */
+#ifndef SQLITE_OMIT_WAL
+ + nPathname + 4 + 1 /* zWal */
+#endif
);
assert( EIGHT_BYTE_ALIGNMENT(SQLITE_INT_TO_PTR(journalFileSize)) );
if( !pPtr ){
@@ -37321,7 +37377,16 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
memcpy(pPager->zFilename, zPathname, nPathname);
memcpy(pPager->zJournal, zPathname, nPathname);
memcpy(&pPager->zJournal[nPathname], "-journal", 8);
- if( pPager->zFilename[0]==0 ) pPager->zJournal[0] = 0;
+ if( pPager->zFilename[0]==0 ){
+ pPager->zJournal[0] = 0;
+ }
+#ifndef SQLITE_OMIT_WAL
+ else{
+ pPager->zWal = &pPager->zJournal[nPathname+8+1];
+ memcpy(pPager->zWal, zPathname, nPathname);
+ memcpy(&pPager->zWal[nPathname], "-wal", 4);
+ }
+#endif
sqlite3_free(zPathname);
}
pPager->pVfs = pVfs;
@@ -38197,30 +38262,19 @@ SQLITE_PRIVATE int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory
** we might save the work of creating a file if the transaction
** ends up being a no-op.
*/
- }else if( isOpen(pPager->jfd) && pPager->journalOff==0 ){
- /* This happens when the pager was in exclusive-access mode the last
- ** time a (read or write) transaction was successfully concluded
- ** by this connection. Instead of deleting the journal file it was
- ** kept open and either was truncated to 0 bytes or its header was
- ** overwritten with zeros.
- */
- assert( pagerUseWal(pPager)==0 );
- assert( pPager->nRec==0 );
- assert( pPager->dbOrigSize==0 );
- assert( pPager->pInJournal==0 );
- rc = pager_open_journal(pPager);
+
+ if( rc!=SQLITE_OK ){
+ assert( !pPager->dbModified );
+ /* Ignore any IO error that occurs within pager_end_transaction(). The
+ ** purpose of this call is to reset the internal state of the pager
+ ** sub-system. It doesn't matter if the journal-file is not properly
+ ** finalized at this point (since it is not a valid journal file anyway).
+ */
+ pager_end_transaction(pPager, 0);
+ }
}
PAGERTRACE(("TRANSACTION %d\n", PAGERID(pPager)));
- if( rc!=SQLITE_OK ){
- assert( !pPager->dbModified );
- /* Ignore any IO error that occurs within pager_end_transaction(). The
- ** purpose of this call is to reset the internal state of the pager
- ** sub-system. It doesn't matter if the journal-file is not properly
- ** finalized at this point (since it is not a valid journal file anyway).
- */
- pager_end_transaction(pPager, 0);
- }
return rc;
}
@@ -38271,10 +38325,7 @@ static int pager_write(PgHdr *pPg){
** which means they have acquired the necessary locks but the rollback
** journal might not yet be open.
*/
- rc = sqlite3PagerBegin(pPager, 0, pPager->subjInMemory);
- if( rc!=SQLITE_OK ){
- return rc;
- }
+ assert( pPager->state>=RESERVED_LOCK );
if( pPager->pInJournal==0
&& pPager->journalMode!=PAGER_JOURNALMODE_OFF
&& !pagerUseWal(pPager)
@@ -38715,7 +38766,10 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(
*/
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
PgHdr *pPg;
- assert( isOpen(pPager->jfd) || pPager->journalMode==PAGER_JOURNALMODE_OFF );
+ assert( isOpen(pPager->jfd)
+ || pPager->journalMode==PAGER_JOURNALMODE_OFF
+ || pPager->journalMode==PAGER_JOURNALMODE_WAL
+ );
if( !zMaster && isOpen(pPager->jfd)
&& pPager->journalOff==jrnlBufferSize(pPager)
&& pPager->dbSize>=pPager->dbFileSize
@@ -38789,7 +38843,7 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(
if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
/* Write all dirty pages to the database file. */
- rc = pager_write_pagelist(sqlite3PcacheDirtyList(pPager->pPCache));
+ rc = pager_write_pagelist(pPager,sqlite3PcacheDirtyList(pPager->pPCache));
if( rc!=SQLITE_OK ){
assert( rc!=SQLITE_IOERR_BLOCKED );
goto commit_phase_one_exit;
@@ -38849,7 +38903,7 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager *pPager){
** fails - make it so that we never reach this point if we do not hold
** all necessary locks.
*/
- if( pPager->state<PAGER_RESERVED ) return SQLITE_ERROR;
+ if( NEVER(pPager->state<PAGER_RESERVED) ) return SQLITE_ERROR;
/* An optimization. If the database was not actually modified during
** this transaction, the pager is running in exclusive-mode and is
@@ -38865,7 +38919,7 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager *pPager){
if( pPager->dbModified==0 && pPager->exclusiveMode
&& pPager->journalMode==PAGER_JOURNALMODE_PERSIST
){
- assert( pPager->journalOff==JOURNAL_HDR_SZ(pPager) );
+ assert( pPager->journalOff==JOURNAL_HDR_SZ(pPager) || !pPager->journalOff );
return SQLITE_OK;
}
@@ -39199,7 +39253,7 @@ SQLITE_PRIVATE int sqlite3PagerNosync(Pager *pPager){
/*
** Set or retrieve the codec for this pager
*/
-static void sqlite3PagerSetCodec(
+SQLITE_PRIVATE void sqlite3PagerSetCodec(
Pager *pPager,
void *(*xCodec)(void*,void*,Pgno,int),
void (*xCodecSizeChng)(void*,int,int),
@@ -39213,7 +39267,7 @@ static void sqlite3PagerSetCodec(
pPager->pCodec = pCodec;
pagerReportSize(pPager);
}
-static void *sqlite3PagerGetCodec(Pager *pPager){
+SQLITE_PRIVATE void *sqlite3PagerGetCodec(Pager *pPager){
return pPager->pCodec;
}
#endif
@@ -39537,7 +39591,7 @@ SQLITE_PRIVATE int sqlite3PagerGetJournalMode(Pager *pPager){
*/
SQLITE_PRIVATE int sqlite3PagerOkToChangeJournalMode(Pager *pPager){
if( pPager->dbModified ) return 0;
- if( isOpen(pPager->jfd) && pPager->journalOff>0 ) return 0;
+ if( NEVER(isOpen(pPager->jfd) && pPager->journalOff>0) ) return 0;
return 1;
}
@@ -39594,25 +39648,37 @@ SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager){
}
/*
-** Open a connection to the write-ahead log file for pager pPager. If
-** the log connection is already open, this function is a no-op.
-**
** The caller must be holding a SHARED lock on the database file to call
** this function.
+**
+** If the pager passed as the first argument is open on a real database
+** file (not a temp file or an in-memory database), and the WAL file
+** is not already open, make an attempt to open it now. If successful,
+** return SQLITE_OK. If an error occurs or the VFS used by the pager does
+** not support the xShmXXX() methods, return an error code. *pisOpen is
+** not modified in either case.
+**
+** If the pager is open on a temp-file (or in-memory database), or if
+** the WAL file is already open, set *pisOpen to 1 and return SQLITE_OK
+** without doing anything.
*/
-SQLITE_PRIVATE int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen){
+SQLITE_PRIVATE int sqlite3PagerOpenWal(
+ Pager *pPager, /* Pager object */
+ int *pisOpen /* OUT: Set to true if call is a no-op */
+){
int rc = SQLITE_OK; /* Return code */
assert( pPager->state>=PAGER_SHARED );
- if( !pPager->pWal ){
+ assert( (pisOpen==0 && !pPager->tempFile && !pPager->pWal) || *pisOpen==0 );
+
+ if( !pPager->tempFile && !pPager->pWal ){
if( !sqlite3PagerWalSupported(pPager) ) return SQLITE_CANTOPEN;
/* Open the connection to the log file. If this operation fails,
** (e.g. due to malloc() failure), unlock the database file and
** return an error code.
*/
- rc = sqlite3WalOpen(pPager->pVfs, pPager->fd,
- pPager->zFilename, &pPager->pWal);
+ rc = sqlite3WalOpen(pPager->pVfs, pPager->fd, pPager->zWal, &pPager->pWal);
if( rc==SQLITE_OK ){
pPager->journalMode = PAGER_JOURNALMODE_WAL;
}
@@ -39645,11 +39711,13 @@ SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager){
int logexists = 0;
rc = sqlite3OsLock(pPager->fd, SQLITE_LOCK_SHARED);
if( rc==SQLITE_OK ){
- rc = pagerHasWAL(pPager, &logexists);
+ rc = sqlite3OsAccess(
+ pPager->pVfs, pPager->zWal, SQLITE_ACCESS_EXISTS, &logexists
+ );
}
if( rc==SQLITE_OK && logexists ){
rc = sqlite3WalOpen(pPager->pVfs, pPager->fd,
- pPager->zFilename, &pPager->pWal);
+ pPager->zWal, &pPager->pWal);
}
}
@@ -40091,7 +40159,7 @@ struct WalCkptInfo {
** is to the start of the write-ahead log frame-header.
*/
#define walFrameOffset(iFrame, szPage) ( \
- WAL_HDRSIZE + ((iFrame)-1)*((szPage)+WAL_FRAME_HDRSIZE) \
+ WAL_HDRSIZE + ((iFrame)-1)*(i64)((szPage)+WAL_FRAME_HDRSIZE) \
)
/*
@@ -40112,7 +40180,7 @@ struct Wal {
u8 writeLock; /* True if in a write transaction */
u8 ckptLock; /* True if holding a checkpoint lock */
WalIndexHdr hdr; /* Wal-index header for current transaction */
- char *zWalName; /* Name of WAL file */
+ const char *zWalName; /* Name of WAL file */
u32 nCkpt; /* Checkpoint sequence counter in the wal-header */
#ifdef SQLITE_DEBUG
u8 lockError; /* True if a locking error has occurred */
@@ -40192,12 +40260,12 @@ static int walIndexPage(Wal *pWal, int iPage, volatile u32 **ppPage){
if( pWal->nWiData<=iPage ){
int nByte = sizeof(u32 *)*(iPage+1);
volatile u32 **apNew;
- apNew = (volatile u32 **)sqlite3_realloc(pWal->apWiData, nByte);
+ apNew = (volatile u32 **)sqlite3_realloc((void *)pWal->apWiData, nByte);
if( !apNew ){
*ppPage = 0;
return SQLITE_NOMEM;
}
- memset(&apNew[pWal->nWiData], 0, sizeof(u32 *)*(iPage+1-pWal->nWiData));
+ memset((void *)&apNew[pWal->nWiData], 0, sizeof(u32 *)*(iPage+1-pWal->nWiData));
pWal->apWiData = apNew;
pWal->nWiData = iPage+1;
}
@@ -40432,7 +40500,7 @@ static int walLockShared(Wal *pWal, int lockIdx){
SQLITE_SHM_LOCK | SQLITE_SHM_SHARED);
WALTRACE(("WAL%p: acquire SHARED-%s %s\n", pWal,
walLockName(lockIdx), rc ? "failed" : "ok"));
- VVA_ONLY( pWal->lockError = (rc!=SQLITE_OK && rc!=SQLITE_BUSY); )
+ VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && rc!=SQLITE_BUSY); )
return rc;
}
static void walUnlockShared(Wal *pWal, int lockIdx){
@@ -40448,7 +40516,7 @@ static int walLockExclusive(Wal *pWal, int lockIdx, int n){
SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE);
WALTRACE(("WAL%p: acquire EXCLUSIVE-%s cnt=%d %s\n", pWal,
walLockName(lockIdx), n, rc ? "failed" : "ok"));
- VVA_ONLY( pWal->lockError = (rc!=SQLITE_OK && rc!=SQLITE_BUSY); )
+ VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && rc!=SQLITE_BUSY); )
return rc;
}
static void walUnlockExclusive(Wal *pWal, int lockIdx, int n){
@@ -40596,7 +40664,7 @@ static void walCleanupHash(Wal *pWal){
/* Zero the entries in the aPgno array that correspond to frames with
** frame numbers greater than pWal->hdr.mxFrame.
*/
- nByte = ((char *)aHash - (char *)&aPgno[iLimit+1]);
+ nByte = (int)((char *)aHash - (char *)&aPgno[iLimit+1]);
memset((void *)&aPgno[iLimit+1], 0, nByte);
#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
@@ -40644,7 +40712,7 @@ static int walIndexAppend(Wal *pWal, u32 iFrame, u32 iPage){
** entire hash table and aPgno[] array before proceding.
*/
if( idx==1 ){
- int nByte = (u8 *)&aHash[HASHTABLE_NSLOT] - (u8 *)&aPgno[1];
+ int nByte = (int)((u8 *)&aHash[HASHTABLE_NSLOT] - (u8 *)&aPgno[1]);
memset((void*)&aPgno[1], 0, nByte);
}
@@ -40664,7 +40732,7 @@ static int walIndexAppend(Wal *pWal, u32 iFrame, u32 iPage){
assert( nCollide++ < idx );
}
aPgno[idx] = iPage;
- aHash[iKey] = idx;
+ aHash[iKey] = (ht_slot)idx;
#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
/* Verify that the number of entries in the hash table exactly equals
@@ -40772,8 +40840,8 @@ static int walIndexRecover(Wal *pWal){
){
goto finished;
}
- pWal->hdr.bigEndCksum = (magic&0x00000001);
- pWal->szPage = szPage;
+ pWal->hdr.bigEndCksum = (u8)(magic&0x00000001);
+ pWal->szPage = (u16)szPage;
pWal->nCkpt = sqlite3Get4byte(&aBuf[12]);
memcpy(&pWal->hdr.aSalt, &aBuf[16], 8);
@@ -40823,7 +40891,7 @@ static int walIndexRecover(Wal *pWal){
if( nTruncate ){
pWal->hdr.mxFrame = iFrame;
pWal->hdr.nPage = nTruncate;
- pWal->hdr.szPage = szPage;
+ pWal->hdr.szPage = (u16)szPage;
aFrameCksum[0] = pWal->hdr.aFrameCksum[0];
aFrameCksum[1] = pWal->hdr.aFrameCksum[1];
}
@@ -40867,8 +40935,9 @@ static void walIndexClose(Wal *pWal, int isDelete){
}
/*
-** Open a connection to the WAL file associated with database zDbName.
-** The database file must already be opened on connection pDbFd.
+** Open a connection to the WAL file zWalName. The database file must
+** already be opened on connection pDbFd. The buffer that zWalName points
+** to must remain valid for the lifetime of the returned Wal* handle.
**
** A SHARED lock should be held on the database file when this function
** is called. The purpose of this SHARED lock is to prevent any other
@@ -40883,16 +40952,14 @@ static void walIndexClose(Wal *pWal, int isDelete){
SQLITE_PRIVATE int sqlite3WalOpen(
sqlite3_vfs *pVfs, /* vfs module to open wal and wal-index */
sqlite3_file *pDbFd, /* The open database file */
- const char *zDbName, /* Name of the database file */
+ const char *zWalName, /* Name of the WAL file */
Wal **ppWal /* OUT: Allocated Wal handle */
){
int rc; /* Return Code */
Wal *pRet; /* Object to allocate and return */
int flags; /* Flags passed to OsOpen() */
- char *zWal; /* Name of write-ahead log file */
- int nWal; /* Length of zWal in bytes */
- assert( zDbName && zDbName[0] );
+ assert( zWalName && zWalName[0] );
assert( pDbFd );
/* In the amalgamation, the os_unix.c and os_win.c source files come before
@@ -40909,8 +40976,7 @@ SQLITE_PRIVATE int sqlite3WalOpen(
/* Allocate an instance of struct Wal to return. */
*ppWal = 0;
- nWal = sqlite3Strlen30(zDbName) + 5;
- pRet = (Wal*)sqlite3MallocZero(sizeof(Wal) + pVfs->szOsFile + nWal);
+ pRet = (Wal*)sqlite3MallocZero(sizeof(Wal) + pVfs->szOsFile);
if( !pRet ){
return SQLITE_NOMEM;
}
@@ -40920,15 +40986,14 @@ SQLITE_PRIVATE int sqlite3WalOpen(
pRet->pDbFd = pDbFd;
pRet->readLock = -1;
sqlite3_randomness(8, &pRet->hdr.aSalt);
- pRet->zWalName = zWal = pVfs->szOsFile + (char*)pRet->pWalFd;
- sqlite3_snprintf(nWal, zWal, "%s-wal", zDbName);
+ pRet->zWalName = zWalName;
rc = sqlite3OsShmOpen(pDbFd);
/* Open file handle on the write-ahead log file. */
if( rc==SQLITE_OK ){
pRet->isWIndexOpen = 1;
flags = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_MAIN_JOURNAL);
- rc = sqlite3OsOpen(pVfs, zWal, pRet->pWalFd, flags, &flags);
+ rc = sqlite3OsOpen(pVfs, zWalName, pRet->pWalFd, flags, &flags);
}
if( rc!=SQLITE_OK ){
@@ -41151,12 +41216,12 @@ static int walIteratorInit(Wal *pWal, WalIterator **pp){
ht_slot *aIndex; /* Sorted index for this segment */
aPgno++;
- nEntry = ((i+1)==nSegment)?(int)(iLast-iZero):(u32 *)aHash-(u32 *)aPgno;
+ nEntry = (int)(((i+1)==nSegment)?(int)(iLast-iZero):(u32 *)aHash-(u32 *)aPgno);
aIndex = &((ht_slot *)&p->aSegment[p->nSegment])[iZero];
iZero++;
for(j=0; j<nEntry; j++){
- aIndex[j] = j;
+ aIndex[j] = (ht_slot)j;
}
walMergesort((u32 *)aPgno, aTmp, aIndex, &nEntry);
p->aSegment[i].iZero = iZero;
@@ -41270,20 +41335,25 @@ static int walCheckpoint(
/* Iterate through the contents of the WAL, copying data to the db file. */
while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){
+ i64 iOffset;
assert( walFramePgno(pWal, iFrame)==iDbpage );
if( iFrame<=nBackfill || iFrame>mxSafeFrame ) continue;
- rc = sqlite3OsRead(pWal->pWalFd, zBuf, szPage,
- walFrameOffset(iFrame, szPage) + WAL_FRAME_HDRSIZE
- );
+ iOffset = walFrameOffset(iFrame, szPage) + WAL_FRAME_HDRSIZE;
+ /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL file */
+ rc = sqlite3OsRead(pWal->pWalFd, zBuf, szPage, iOffset);
if( rc!=SQLITE_OK ) break;
- rc = sqlite3OsWrite(pWal->pDbFd, zBuf, szPage, (iDbpage-1)*szPage);
+ iOffset = (iDbpage-1)*(i64)szPage;
+ testcase( IS_BIG_INT(iOffset) );
+ rc = sqlite3OsWrite(pWal->pDbFd, zBuf, szPage, iOffset);
if( rc!=SQLITE_OK ) break;
}
/* If work was actually accomplished... */
if( rc==SQLITE_OK ){
if( mxSafeFrame==walIndexHdr(pWal)->mxFrame ){
- rc = sqlite3OsTruncate(pWal->pDbFd, ((i64)pWal->hdr.nPage*(i64)szPage));
+ i64 szDb = pWal->hdr.nPage*(i64)szPage;
+ testcase( IS_BIG_INT(szDb) );
+ rc = sqlite3OsTruncate(pWal->pDbFd, szDb);
if( rc==SQLITE_OK && sync_flags ){
rc = sqlite3OsSync(pWal->pDbFd, sync_flags);
}
@@ -41343,7 +41413,7 @@ SQLITE_PRIVATE int sqlite3WalClose(
sqlite3OsDelete(pWal->pVfs, pWal->zWalName, 0);
}
WALTRACE(("WAL%p: closed\n", pWal));
- sqlite3_free(pWal->apWiData);
+ sqlite3_free((void *)pWal->apWiData);
sqlite3_free(pWal);
}
return rc;
@@ -41679,7 +41749,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
return WAL_RETRY;
}else{
assert( mxReadMark<=pWal->hdr.mxFrame );
- pWal->readLock = mxI;
+ pWal->readLock = (i16)mxI;
}
}
return rc;
@@ -41821,6 +41891,7 @@ SQLITE_PRIVATE int sqlite3WalRead(
if( iRead ){
i64 iOffset = walFrameOffset(iRead, pWal->hdr.szPage) + WAL_FRAME_HDRSIZE;
*pInWal = 1;
+ /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL */
return sqlite3OsRead(pWal->pWalFd, pOut, nOut, iOffset);
}
@@ -42092,7 +42163,7 @@ SQLITE_PRIVATE int sqlite3WalFrames(
sqlite3Put4byte(&aWalHdr[24], aCksum[0]);
sqlite3Put4byte(&aWalHdr[28], aCksum[1]);
- pWal->szPage = szPage;
+ pWal->szPage = (u16)szPage;
pWal->hdr.bigEndCksum = SQLITE_BIGENDIAN;
pWal->hdr.aFrameCksum[0] = aCksum[0];
pWal->hdr.aFrameCksum[1] = aCksum[1];
@@ -42111,8 +42182,8 @@ SQLITE_PRIVATE int sqlite3WalFrames(
i64 iOffset; /* Write offset in log file */
void *pData;
-
iOffset = walFrameOffset(++iFrame, szPage);
+ /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL */
/* Populate and write the frame header */
nDbsize = (isCommit && p->pDirty==0) ? nTruncate : 0;
@@ -42152,6 +42223,7 @@ SQLITE_PRIVATE int sqlite3WalFrames(
pData = pLast->pData;
#endif
walEncodeFrame(pWal, pLast->pgno, nTruncate, pData, aFrame);
+ /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL */
rc = sqlite3OsWrite(pWal->pWalFd, aFrame, sizeof(aFrame), iOffset);
if( rc!=SQLITE_OK ){
return rc;
@@ -42186,7 +42258,7 @@ SQLITE_PRIVATE int sqlite3WalFrames(
if( rc==SQLITE_OK ){
/* Update the private copy of the header. */
- pWal->hdr.szPage = szPage;
+ pWal->hdr.szPage = (u16)szPage;
pWal->hdr.mxFrame = iFrame;
if( isCommit ){
pWal->hdr.iChange++;
@@ -44923,16 +44995,20 @@ static int getAndInitPage(
int rc;
assert( sqlite3_mutex_held(pBt->mutex) );
- if( pgno<=0 || pgno>btreePagecount(pBt) ){
- return SQLITE_CORRUPT_BKPT;
- }
- rc = btreeGetPage(pBt, pgno, ppPage, 0);
- if( rc==SQLITE_OK ){
- rc = btreeInitPage(*ppPage);
- if( rc!=SQLITE_OK ){
- releasePage(*ppPage);
+ if( pgno>btreePagecount(pBt) ){
+ rc = SQLITE_CORRUPT_BKPT;
+ }else{
+ rc = btreeGetPage(pBt, pgno, ppPage, 0);
+ if( rc==SQLITE_OK ){
+ rc = btreeInitPage(*ppPage);
+ if( rc!=SQLITE_OK ){
+ releasePage(*ppPage);
+ }
}
}
+
+ testcase( pgno==0 );
+ assert( pgno!=0 || rc==SQLITE_CORRUPT );
return rc;
}
@@ -45859,7 +45935,7 @@ SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag){
rc = querySharedCacheTableLock(p, MASTER_ROOT, READ_LOCK);
if( SQLITE_OK!=rc ) goto trans_begun;
- pBt->initiallyEmpty = pBt->nPage==0;
+ pBt->initiallyEmpty = (u8)(pBt->nPage==0);
do {
/* Call lockBtree() until either pBt->pPage1 is populated or
** lockBtree() returns something other than SQLITE_OK. lockBtree()
@@ -47582,7 +47658,6 @@ SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){
if( pCur->eState==CURSOR_INVALID ){
assert( pCur->apPage[pCur->iPage]->nCell==0 );
*pRes = 1;
- rc = SQLITE_OK;
}else{
assert( pCur->apPage[pCur->iPage]->nCell>0 );
*pRes = 0;
@@ -51347,7 +51422,7 @@ SQLITE_PRIVATE int sqlite3BtreeSetVersion(Btree *pBtree, int iVersion){
/* If setting the version fields to 1, do not automatically open the
** WAL connection, even if the version fields are currently set to 2.
*/
- pBt->doNotUseWAL = (iVersion==1);
+ pBt->doNotUseWAL = (u8)(iVersion==1);
rc = sqlite3BtreeBeginTrans(pBtree, 0);
if( rc==SQLITE_OK ){
@@ -51839,6 +51914,9 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
assert( rc2==SQLITE_OK );
}
+ if( rc==SQLITE_IOERR_NOMEM ){
+ rc = SQLITE_NOMEM;
+ }
p->rc = rc;
}
if( p->pDestDb ){
@@ -53961,7 +54039,9 @@ SQLITE_PRIVATE void sqlite3VdbeNoopComment(Vdbe *p, const char *zFormat, ...){
** check the value of p->nOp-1 before continuing.
*/
SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){
- static const VdbeOp dummy;
+ /* C89 specifies that the constant "dummy" will be initialized to all
+ ** zeros, which is correct. MSVC generates a warning, nevertheless. */
+ static const VdbeOp dummy; /* Ignore the MSVC warning about no initializer */
assert( p->magic==VDBE_MAGIC_INIT );
if( addr<0 ){
#ifdef SQLITE_OMIT_TRACE
@@ -62392,14 +62472,13 @@ case OP_Rewind: { /* jump */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
u.bl.pC = p->apCsr[pOp->p1];
assert( u.bl.pC!=0 );
+ u.bl.res = 1;
if( (u.bl.pCrsr = u.bl.pC->pCursor)!=0 ){
rc = sqlite3BtreeFirst(u.bl.pCrsr, &u.bl.res);
u.bl.pC->atFirst = u.bl.res==0 ?1:0;
u.bl.pC->deferredMoveto = 0;
u.bl.pC->cacheStatus = CACHE_STALE;
u.bl.pC->rowidIsValid = 0;
- }else{
- u.bl.res = 1;
}
u.bl.pC->nullRow = (u8)u.bl.res;
assert( pOp->p2>0 && pOp->p2<p->nOp );
@@ -63443,6 +63522,7 @@ case OP_Checkpoint: {
};
#endif
+#ifndef SQLITE_OMIT_PRAGMA
/* Opcode: JournalMode P1 P2 P3 * P5
**
** Change the journal mode of database P1 to P3. P3 must be one of the
@@ -63569,7 +63649,8 @@ case OP_JournalMode: { /* out2-prerelease */
pOut->enc = SQLITE_UTF8;
sqlite3VdbeChangeEncoding(pOut, encoding);
break;
-};
+};
+#endif /* SQLITE_OMIT_PRAGMA */
#if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH)
/* Opcode: Vacuum * * * * *
@@ -64753,7 +64834,12 @@ static struct sqlite3_io_methods JournalFileMethods = {
0, /* xCheckReservedLock */
0, /* xFileControl */
0, /* xSectorSize */
- 0 /* xDeviceCharacteristics */
+ 0, /* xDeviceCharacteristics */
+ 0, /* xShmOpen */
+ 0, /* xShmLock */
+ 0, /* xShmMap */
+ 0, /* xShmBarrier */
+ 0 /* xShmClose */
};
/*
@@ -83531,6 +83617,10 @@ SQLITE_PRIVATE void sqlite3Pragma(
if( sqlite3StrICmp(zLeft,"journal_mode")==0 ){
int eMode; /* One of the PAGER_JOURNALMODE_XXX symbols */
+ if( sqlite3ReadSchema(pParse) ){
+ goto pragma_out;
+ }
+
sqlite3VdbeSetNumCols(v, 1);
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "journal_mode", SQLITE_STATIC);
@@ -83539,7 +83629,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
}else{
const char *zMode;
int n = sqlite3Strlen30(zRight);
- for(eMode=0; (zMode = sqlite3JournalModename(eMode)); eMode++){
+ for(eMode=0; (zMode = sqlite3JournalModename(eMode))!=0; eMode++){
if( sqlite3StrNICmp(zRight, zMode, n)==0 ) break;
}
if( !zMode ){
@@ -84594,12 +84684,15 @@ SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char
*/
int rc;
sqlite3_stmt *pStmt;
+ TESTONLY(int rcp); /* Return code from sqlite3_prepare() */
assert( db->init.busy );
db->init.iDb = iDb;
db->init.newTnum = atoi(argv[1]);
db->init.orphanTrigger = 0;
- rc = sqlite3_prepare(db, argv[2], -1, &pStmt, 0);
+ TESTONLY(rcp = ) sqlite3_prepare(db, argv[2], -1, &pStmt, 0);
+ rc = db->errCode;
+ assert( (rc&0xFF)==(rcp&0xFF) );
db->init.iDb = 0;
if( SQLITE_OK!=rc ){
if( db->init.orphanTrigger ){
@@ -84608,7 +84701,7 @@ SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char
pData->rc = rc;
if( rc==SQLITE_NOMEM ){
db->mallocFailed = 1;
- }else if( rc!=SQLITE_INTERRUPT && rc!=SQLITE_LOCKED ){
+ }else if( rc!=SQLITE_INTERRUPT && (rc&0xFF)!=SQLITE_LOCKED ){
corruptSchema(pData, argv[0], sqlite3_errmsg(db));
}
}
@@ -94775,7 +94868,7 @@ static void constructAutomaticIndex(
}
}
}
- assert( n==pLevel->plan.nEq );
+ assert( (u32)n==pLevel->plan.nEq );
/* Add additional columns needed to make the automatic index into
** a covering index */
@@ -96369,7 +96462,7 @@ static Bitmask codeOneLoopStart(
** a forward order scan on a descending index, interchange the
** start and end terms (pRangeStart and pRangeEnd).
*/
- if( bRev==(pIdx->aSortOrder[nEq]==SQLITE_SO_ASC) ){
+ if( nEq<pIdx->nColumn && bRev==(pIdx->aSortOrder[nEq]==SQLITE_SO_ASC) ){
SWAP(WhereTerm *, pRangeEnd, pRangeStart);
}
@@ -104069,7 +104162,6 @@ SQLITE_API int sqlite3_collation_needed16(
}
#endif /* SQLITE_OMIT_UTF16 */
-#ifndef SQLITE_OMIT_GLOBALRECOVER
#ifndef SQLITE_OMIT_DEPRECATED
/*
** This function is now an anachronism. It used to be used to recover from a
@@ -104079,7 +104171,6 @@ SQLITE_API int sqlite3_global_recover(void){
return SQLITE_OK;
}
#endif
-#endif
/*
** Test to see whether or not the database connection is in autocommit
@@ -106054,6 +106145,9 @@ static int fts3CreateTables(Fts3Table *p){
** An sqlite3_exec() callback for fts3TableExists.
*/
static int fts3TableExistsCallback(void *pArg, int n, char **pp1, char **pp2){
+ UNUSED_PARAMETER(n);
+ UNUSED_PARAMETER(pp1);
+ UNUSED_PARAMETER(pp2);
*(int*)pArg = 1;
return 1;
}
@@ -106079,7 +106173,7 @@ static void fts3TableExists(
);
rc = sqlite3_exec(db, zSql, fts3TableExistsCallback, &res, 0);
sqlite3_free(zSql);
- *pResult = res & 0xff;
+ *pResult = (u8)(res & 0xff);
if( rc!=SQLITE_ABORT ) *pRc = rc;
}
diff --git a/dist/sqlite3.h b/dist/sqlite3.h
index 9ad6e39..9268b20 100644
--- a/dist/sqlite3.h
+++ b/dist/sqlite3.h
@@ -109,7 +109,7 @@ extern "C" {
*/
#define SQLITE_VERSION "3.7.0"
#define SQLITE_VERSION_NUMBER 3007000
-#define SQLITE_SOURCE_ID "2010-06-28 10:15:20 4932f22848b3d15a2b6dc5fa2cd69ce19182e2a4"
+#define SQLITE_SOURCE_ID "2010-07-07 14:45:41 8eefc287265443ec043bdab629597e79c9d22006"
/*
** CAPI3REF: Run-Time Library Version Numbers
@@ -832,16 +832,23 @@ typedef struct sqlite3_mutex sqlite3_mutex;
** handled as a fatal error by SQLite, vfs implementations should endeavor
** to prevent this by setting mxPathname to a sufficiently large value.
**
-** The xRandomness(), xSleep(), and xCurrentTime() interfaces
-** are not strictly a part of the filesystem, but they are
+** The xRandomness(), xSleep(), xCurrentTime(), and xCurrentTimeInt64()
+** interfaces are not strictly a part of the filesystem, but they are
** included in the VFS structure for completeness.
** The xRandomness() function attempts to return nBytes bytes
** of good-quality randomness into zOut. The return value is
** the actual number of bytes of randomness obtained.
** The xSleep() method causes the calling thread to sleep for at
** least the number of microseconds given. The xCurrentTime()
-** method returns a Julian Day Number for the current date and time.
-**
+** method returns a Julian Day Number for the current date and time as
+** a floating point value.
+** The xCurrentTimeInt64() method returns, as an integer, the Julian
+** Day Number multipled by 86400000 (the number of milliseconds in
+** a 24-hour day).
+** ^SQLite will use the xCurrentTimeInt64() method to get the current
+** date and time if that method is available (if iVersion is 2 or
+** greater and the function pointer is not NULL) and will fall back
+** to xCurrentTime() if xCurrentTimeInt64() is unavailable.
*/
typedef struct sqlite3_vfs sqlite3_vfs;
struct sqlite3_vfs {
@@ -868,7 +875,6 @@ struct sqlite3_vfs {
** The methods above are in version 1 of the sqlite_vfs object
** definition. Those that follow are added in version 2 or later
*/
- int (*xRename)(sqlite3_vfs*, const char *zOld, const char *zNew, int dirSync);
int (*xCurrentTimeInt64)(sqlite3_vfs*, sqlite3_int64*);
/*
** The methods above are in versions 1 and 2 of the sqlite_vfs object.