diff options
-rw-r--r-- | dist/shell.c | 1 | ||||
-rw-r--r-- | dist/sqlite3.c | 462 | ||||
-rw-r--r-- | dist/sqlite3.c.orig | 462 | ||||
-rw-r--r-- | dist/sqlite3.h | 18 |
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. |