commit 24531c8fa553c4e491c591313771b0b80b96fccb parent 97b41b22a8e3ab30c0d8949fa2f4aff9f41403cf Author: Cristina Horotan <chorotan@mozilla.com> Date: Sat, 15 Nov 2025 18:34:20 +0200 Revert "Bug 1998267 - Fix compilation of the carray SQLite extension. r=RyanVM,asuth" on request for causing Bug 1999921 This reverts commit 4cd49eb13b7db4af87558f8eeefd025c40063369. Revert "Bug 1998267 - Upgrade to SQLite 3.51.0. r=RyanVM" This reverts commit 30f9ab4ef3c1781378fe00a3afd1a15075c8643e. Revert "Bug 1998267 - Upgrade SQLite vendoring. r=RyanVM" This reverts commit ca26f4e880869b5373edca675c6dd4f05732801f. Diffstat:
17 files changed, 2156 insertions(+), 4758 deletions(-)
diff --git a/config/system-headers.mozbuild b/config/system-headers.mozbuild @@ -770,6 +770,7 @@ system_headers = [ "soundtouch/SoundTouch.h", "spawn.h", "sqlite3.h", + "sqlite3_static_ext.h", "sslerr.h", "ssl.h", "sslproto.h", diff --git a/storage/mozStorageBindingParams.cpp b/storage/mozStorageBindingParams.cpp @@ -13,6 +13,7 @@ #include "mozStoragePrivateHelpers.h" #include "mozStorageBindingParams.h" #include "Variant.h" +#include "sqlite3_static_ext.h" namespace mozilla::storage { diff --git a/storage/mozStorageConnection.cpp b/storage/mozStorageConnection.cpp @@ -42,6 +42,7 @@ #include "SQLCollations.h" #include "FileSystemModule.h" #include "mozStorageHelper.h" +#include "sqlite3_static_ext.h" #include "mozilla/Assertions.h" #include "mozilla/Logging.h" diff --git a/third_party/sqlite3/ext/fts5.c b/third_party/sqlite3/ext/fts5.c @@ -854,20 +854,27 @@ typedef sqlite3_uint64 u64; # define LARGEST_INT64 (0xffffffff|(((i64)0x7fffffff)<<32)) # define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64) -/* -** This macro is used in a single assert() within fts5 to check that an -** allocation is aligned to an 8-byte boundary. But it is a complicated -** macro to get right for multiple platforms without generating warnings. -** So instead of reproducing the entire definition from sqliteInt.h, we -** just do without this assert() for the rare non-amalgamation builds. +/* The uptr type is an unsigned integer large enough to hold a pointer */ -#define EIGHT_BYTE_ALIGNMENT(x) 1 +#if defined(HAVE_STDINT_H) + typedef uintptr_t uptr; +#elif SQLITE_PTRSIZE==4 + typedef u32 uptr; +#else + typedef u64 uptr; +#endif + +#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC +# define EIGHT_BYTE_ALIGNMENT(X) ((((uptr)(X) - (uptr)0)&3)==0) +#else +# define EIGHT_BYTE_ALIGNMENT(X) ((((uptr)(X) - (uptr)0)&7)==0) +#endif /* ** Macros needed to provide flexible arrays in a portable way */ #ifndef offsetof -# define offsetof(ST,M) ((size_t)((char*)&((ST*)0)->M - (char*)0)) +# define offsetof(STRUCTURE,FIELD) ((size_t)((char*)&((STRUCTURE*)0)->FIELD)) #endif #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) # define FLEXARRAY @@ -1609,7 +1616,7 @@ static int sqlite3Fts5ExprPattern( ** i64 iRowid = sqlite3Fts5ExprRowid(pExpr); ** } */ -static int sqlite3Fts5ExprFirst(Fts5Expr*, Fts5Index *pIdx, i64 iMin, i64, int bDesc); +static int sqlite3Fts5ExprFirst(Fts5Expr*, Fts5Index *pIdx, i64 iMin, int bDesc); static int sqlite3Fts5ExprNext(Fts5Expr*, i64 iMax); static int sqlite3Fts5ExprEof(Fts5Expr*); static i64 sqlite3Fts5ExprRowid(Fts5Expr*); @@ -7254,13 +7261,7 @@ static int fts5ExprNodeFirst(Fts5Expr *pExpr, Fts5ExprNode *pNode){ ** Return SQLITE_OK if successful, or an SQLite error code otherwise. It ** is not considered an error if the query does not match any documents. */ -static int sqlite3Fts5ExprFirst( - Fts5Expr *p, - Fts5Index *pIdx, - i64 iFirst, - i64 iLast, - int bDesc -){ +static int sqlite3Fts5ExprFirst(Fts5Expr *p, Fts5Index *pIdx, i64 iFirst, int bDesc){ Fts5ExprNode *pRoot = p->pRoot; int rc; /* Return code */ @@ -7282,9 +7283,6 @@ static int sqlite3Fts5ExprFirst( assert( pRoot->bEof==0 ); rc = fts5ExprNodeNext(p, pRoot, 0, 0); } - if( fts5RowidCmp(p, pRoot->iRowid, iLast)>0 ){ - pRoot->bEof = 1; - } return rc; } @@ -10139,36 +10137,6 @@ struct Fts5SegIter { u8 bDel; /* True if the delete flag is set */ }; -static int fts5IndexCorruptRowid(Fts5Index *pIdx, i64 iRowid){ - pIdx->rc = FTS5_CORRUPT; - sqlite3Fts5ConfigErrmsg(pIdx->pConfig, - "fts5: corruption found reading blob %lld from table \"%s\"", - iRowid, pIdx->pConfig->zName - ); - return SQLITE_CORRUPT_VTAB; -} -#define FTS5_CORRUPT_ROWID(pIdx, iRowid) fts5IndexCorruptRowid(pIdx, iRowid) - -static int fts5IndexCorruptIter(Fts5Index *pIdx, Fts5SegIter *pIter){ - pIdx->rc = FTS5_CORRUPT; - sqlite3Fts5ConfigErrmsg(pIdx->pConfig, - "fts5: corruption on page %d, segment %d, table \"%s\"", - pIter->iLeafPgno, pIter->pSeg->iSegid, pIdx->pConfig->zName - ); - return SQLITE_CORRUPT_VTAB; -} -#define FTS5_CORRUPT_ITER(pIdx, pIter) fts5IndexCorruptIter(pIdx, pIter) - -static int fts5IndexCorruptIdx(Fts5Index *pIdx){ - pIdx->rc = FTS5_CORRUPT; - sqlite3Fts5ConfigErrmsg(pIdx->pConfig, - "fts5: corruption in table \"%s\"", pIdx->pConfig->zName - ); - return SQLITE_CORRUPT_VTAB; -} -#define FTS5_CORRUPT_IDX(pIdx) fts5IndexCorruptIdx(pIdx) - - /* ** Array of tombstone pages. Reference counted. */ @@ -10458,13 +10426,13 @@ static Fts5Data *fts5DataRead(Fts5Index *p, i64 iRowid){ ** All the reasons those functions might return SQLITE_ERROR - missing ** table, missing row, non-blob/text in block column - indicate ** backing store corruption. */ - if( rc==SQLITE_ERROR ) rc = FTS5_CORRUPT_ROWID(p, iRowid); + if( rc==SQLITE_ERROR ) rc = FTS5_CORRUPT; if( rc==SQLITE_OK ){ u8 *aOut = 0; /* Read blob data into this buffer */ - i64 nByte = sqlite3_blob_bytes(p->pReader); - i64 szData = (sizeof(Fts5Data) + 7) & ~7; - i64 nAlloc = szData + nByte + FTS5_DATA_PADDING; + int nByte = sqlite3_blob_bytes(p->pReader); + int szData = (sizeof(Fts5Data) + 7) & ~7; + sqlite3_int64 nAlloc = szData + nByte + FTS5_DATA_PADDING; pRet = (Fts5Data*)sqlite3_malloc64(nAlloc); if( pRet ){ pRet->nn = nByte; @@ -10508,7 +10476,7 @@ static Fts5Data *fts5LeafRead(Fts5Index *p, i64 iRowid){ Fts5Data *pRet = fts5DataRead(p, iRowid); if( pRet ){ if( pRet->nn<4 || pRet->szLeaf>pRet->nn ){ - FTS5_CORRUPT_ROWID(p, iRowid); + p->rc = FTS5_CORRUPT; fts5DataRelease(pRet); pRet = 0; } @@ -10867,14 +10835,8 @@ static Fts5Structure *fts5StructureReadUncached(Fts5Index *p){ /* TODO: Do we need this if the leaf-index is appended? Probably... */ memset(&pData->p[pData->nn], 0, FTS5_DATA_PADDING); p->rc = fts5StructureDecode(pData->p, pData->nn, &iCookie, &pRet); - if( p->rc==SQLITE_OK ){ - if( (pConfig->pgsz==0 || pConfig->iCookie!=iCookie) ){ - p->rc = sqlite3Fts5ConfigLoad(pConfig, iCookie); - } - }else if( p->rc==SQLITE_CORRUPT_VTAB ){ - sqlite3Fts5ConfigErrmsg(p->pConfig, - "fts5: corrupt structure record for table \"%s\"", p->pConfig->zName - ); + if( p->rc==SQLITE_OK && (pConfig->pgsz==0 || pConfig->iCookie!=iCookie) ){ + p->rc = sqlite3Fts5ConfigLoad(pConfig, iCookie); } fts5DataRelease(pData); if( p->rc!=SQLITE_OK ){ @@ -11497,7 +11459,7 @@ static void fts5SegIterLoadRowid(Fts5Index *p, Fts5SegIter *pIter){ while( iOff>=pIter->pLeaf->szLeaf ){ fts5SegIterNextPage(p, pIter); if( pIter->pLeaf==0 ){ - if( p->rc==SQLITE_OK ) FTS5_CORRUPT_ITER(p, pIter); + if( p->rc==SQLITE_OK ) p->rc = FTS5_CORRUPT; return; } iOff = 4; @@ -11529,7 +11491,7 @@ static void fts5SegIterLoadTerm(Fts5Index *p, Fts5SegIter *pIter, int nKeep){ iOff += fts5GetVarint32(&a[iOff], nNew); if( iOff+nNew>pIter->pLeaf->szLeaf || nKeep>pIter->term.n || nNew==0 ){ - FTS5_CORRUPT_ITER(p, pIter); + p->rc = FTS5_CORRUPT; return; } pIter->term.n = nKeep; @@ -11724,7 +11686,7 @@ static void fts5SegIterReverseNewPage(Fts5Index *p, Fts5SegIter *pIter){ iRowidOff = fts5LeafFirstRowidOff(pNew); if( iRowidOff ){ if( iRowidOff>=pNew->szLeaf ){ - FTS5_CORRUPT_ITER(p, pIter); + p->rc = FTS5_CORRUPT; }else{ pIter->pLeaf = pNew; pIter->iLeafOffset = iRowidOff; @@ -11958,7 +11920,7 @@ static void fts5SegIterNext( } assert_nc( iOff<pLeaf->szLeaf ); if( iOff>pLeaf->szLeaf ){ - FTS5_CORRUPT_ITER(p, pIter); + p->rc = FTS5_CORRUPT; return; } } @@ -12066,20 +12028,18 @@ static void fts5SegIterReverse(Fts5Index *p, Fts5SegIter *pIter){ fts5DataRelease(pIter->pLeaf); pIter->pLeaf = pLast; pIter->iLeafPgno = pgnoLast; - if( p->rc==SQLITE_OK ){ - iOff = fts5LeafFirstRowidOff(pLast); - if( iOff>pLast->szLeaf ){ - FTS5_CORRUPT_ITER(p, pIter); - return; - } - iOff += fts5GetVarint(&pLast->p[iOff], (u64*)&pIter->iRowid); - pIter->iLeafOffset = iOff; + iOff = fts5LeafFirstRowidOff(pLast); + if( iOff>pLast->szLeaf ){ + p->rc = FTS5_CORRUPT; + return; + } + iOff += fts5GetVarint(&pLast->p[iOff], (u64*)&pIter->iRowid); + pIter->iLeafOffset = iOff; - if( fts5LeafIsTermless(pLast) ){ - pIter->iEndofDoclist = pLast->nn+1; - }else{ - pIter->iEndofDoclist = fts5LeafFirstTermOff(pLast); - } + if( fts5LeafIsTermless(pLast) ){ + pIter->iEndofDoclist = pLast->nn+1; + }else{ + pIter->iEndofDoclist = fts5LeafFirstTermOff(pLast); } } @@ -12149,7 +12109,7 @@ static void fts5LeafSeek( iPgidx += fts5GetVarint32(&a[iPgidx], iTermOff); iOff = iTermOff; if( iOff>n ){ - FTS5_CORRUPT_ITER(p, pIter); + p->rc = FTS5_CORRUPT; return; } @@ -12192,7 +12152,7 @@ static void fts5LeafSeek( iOff = iTermOff; if( iOff>=n ){ - FTS5_CORRUPT_ITER(p, pIter); + p->rc = FTS5_CORRUPT; return; } @@ -12214,7 +12174,7 @@ static void fts5LeafSeek( iPgidx = (u32)pIter->pLeaf->szLeaf; iPgidx += fts5GetVarint32(&pIter->pLeaf->p[iPgidx], iOff); if( iOff<4 || (i64)iOff>=pIter->pLeaf->szLeaf ){ - FTS5_CORRUPT_ITER(p, pIter); + p->rc = FTS5_CORRUPT; return; }else{ nKeep = 0; @@ -12229,7 +12189,7 @@ static void fts5LeafSeek( search_success: if( (i64)iOff+nNew>n || nNew<1 ){ - FTS5_CORRUPT_ITER(p, pIter); + p->rc = FTS5_CORRUPT; return; } pIter->iLeafOffset = iOff + nNew; @@ -12694,7 +12654,7 @@ static void fts5SegIterGotoPage( assert( iLeafPgno>pIter->iLeafPgno ); if( iLeafPgno>pIter->pSeg->pgnoLast ){ - FTS5_CORRUPT_IDX(p); + p->rc = FTS5_CORRUPT; }else{ fts5DataRelease(pIter->pNextLeaf); pIter->pNextLeaf = 0; @@ -12709,7 +12669,7 @@ static void fts5SegIterGotoPage( u8 *a = pIter->pLeaf->p; int n = pIter->pLeaf->szLeaf; if( iOff<4 || iOff>=n ){ - FTS5_CORRUPT_IDX(p); + p->rc = FTS5_CORRUPT; }else{ iOff += fts5GetVarint(&a[iOff], (u64*)&pIter->iRowid); pIter->iLeafOffset = iOff; @@ -13188,7 +13148,7 @@ static void fts5ChunkIterate( if( nRem<=0 ){ break; }else if( pSeg->pSeg==0 ){ - FTS5_CORRUPT_IDX(p); + p->rc = FTS5_CORRUPT; return; }else{ pgno++; @@ -14291,7 +14251,7 @@ static void fts5TrimSegments(Fts5Index *p, Fts5Iter *pIter){ ** a single page has been assigned to more than one segment. In ** this case a prior iteration of this loop may have corrupted the ** segment currently being trimmed. */ - FTS5_CORRUPT_ROWID(p, iLeafRowid); + p->rc = FTS5_CORRUPT; }else{ fts5BufferZero(&buf); fts5BufferGrow(&p->rc, &buf, pData->nn); @@ -14758,7 +14718,7 @@ static void fts5SecureDeleteOverflow( }else if( bDetailNone ){ break; }else if( iNext>=pLeaf->szLeaf || pLeaf->nn<pLeaf->szLeaf || iNext<4 ){ - FTS5_CORRUPT_ROWID(p, iRowid); + p->rc = FTS5_CORRUPT; break; }else{ int nShift = iNext - 4; @@ -14778,7 +14738,7 @@ static void fts5SecureDeleteOverflow( i1 += fts5GetVarint32(&aPg[i1], iFirst); if( iFirst<iNext ){ - FTS5_CORRUPT_ROWID(p, iRowid); + p->rc = FTS5_CORRUPT; break; } aIdx = sqlite3Fts5MallocZero(&p->rc, (pLeaf->nn-pLeaf->szLeaf)+2); @@ -15001,14 +14961,14 @@ static void fts5DoSecureDelete( nSuffix = (nPrefix2 + nSuffix2) - nPrefix; if( (iKeyOff+nSuffix)>iPgIdx || (iNextOff+nSuffix2)>iPgIdx ){ - FTS5_CORRUPT_IDX(p); + p->rc = FTS5_CORRUPT; }else{ if( iKey!=1 ){ iOff += sqlite3Fts5PutVarint(&aPg[iOff], nPrefix); } iOff += sqlite3Fts5PutVarint(&aPg[iOff], nSuffix); if( nPrefix2>pSeg->term.n ){ - FTS5_CORRUPT_IDX(p); + p->rc = FTS5_CORRUPT; }else if( nPrefix2>nPrefix ){ memcpy(&aPg[iOff], &pSeg->term.p[nPrefix], nPrefix2-nPrefix); iOff += (nPrefix2-nPrefix); @@ -15432,7 +15392,7 @@ static Fts5Structure *fts5IndexOptimizeStruct( } nByte += (((i64)pStruct->nLevel)+1) * sizeof(Fts5StructureLevel); - assert( nByte==(i64)SZ_FTS5STRUCTURE(pStruct->nLevel+2) ); + assert( nByte==SZ_FTS5STRUCTURE(pStruct->nLevel+2) ); pNew = (Fts5Structure*)sqlite3Fts5MallocZero(&p->rc, nByte); if( pNew ){ @@ -15801,7 +15761,7 @@ static void fts5MergePrefixLists( } if( pHead==0 || pHead->pNext==0 ){ - FTS5_CORRUPT_IDX(p); + p->rc = FTS5_CORRUPT; break; } @@ -15838,7 +15798,7 @@ static void fts5MergePrefixLists( assert_nc( tmp.n+nTail<=nTmp ); assert( tmp.n+nTail<=nTmp+nMerge*10 ); if( tmp.n+nTail>nTmp-FTS5_DATA_ZERO_PADDING ){ - if( p->rc==SQLITE_OK ) FTS5_CORRUPT_IDX(p); + if( p->rc==SQLITE_OK ) p->rc = FTS5_CORRUPT; break; } fts5BufferSafeAppendVarint(&out, (tmp.n+nTail) * 2); @@ -16407,14 +16367,11 @@ static int sqlite3Fts5IndexRollback(Fts5Index *p){ */ static int sqlite3Fts5IndexReinit(Fts5Index *p){ Fts5Structure *pTmp; - union { - Fts5Structure sFts; - u8 tmpSpace[SZ_FTS5STRUCTURE(1)]; - } uFts; + u8 tmpSpace[SZ_FTS5STRUCTURE(1)]; fts5StructureInvalidate(p); fts5IndexDiscardData(p); - pTmp = &uFts.sFts; - memset(uFts.tmpSpace, 0, sizeof(uFts.tmpSpace)); + pTmp = (Fts5Structure*)tmpSpace; + memset(pTmp, 0, SZ_FTS5STRUCTURE(1)); if( p->pConfig->bContentlessDelete ){ pTmp->nOriginCntr = 1; } @@ -17874,27 +17831,19 @@ static int fts5TestUtf8(const char *z, int n){ /* ** This function is also purely an internal test. It does not contribute to ** FTS functionality, or even the integrity-check, in any way. -** -** This function sets output variable (*pbFail) to true if the test fails. Or -** leaves it unchanged if the test succeeds. */ static void fts5TestTerm( Fts5Index *p, Fts5Buffer *pPrev, /* Previous term */ const char *z, int n, /* Possibly new term to test */ u64 expected, - u64 *pCksum, - int *pbFail + u64 *pCksum ){ int rc = p->rc; if( pPrev->n==0 ){ fts5BufferSet(&rc, pPrev, n, (const u8*)z); }else - if( *pbFail==0 - && rc==SQLITE_OK - && (pPrev->n!=n || memcmp(pPrev->p, z, n)) - && (p->pHash==0 || p->pHash->nEntry==0) - ){ + if( rc==SQLITE_OK && (pPrev->n!=n || memcmp(pPrev->p, z, n)) ){ u64 cksum3 = *pCksum; const char *zTerm = (const char*)&pPrev->p[1]; /* term sans prefix-byte */ int nTerm = pPrev->n-1; /* Size of zTerm in bytes */ @@ -17944,7 +17893,7 @@ static void fts5TestTerm( fts5BufferSet(&rc, pPrev, n, (const u8*)z); if( rc==SQLITE_OK && cksum3!=expected ){ - *pbFail = 1; + rc = FTS5_CORRUPT; } *pCksum = cksum3; } @@ -17953,7 +17902,7 @@ static void fts5TestTerm( #else # define fts5TestDlidxReverse(x,y,z) -# define fts5TestTerm(t,u,v,w,x,y,z) +# define fts5TestTerm(u,v,w,x,y,z) #endif /* @@ -17978,17 +17927,14 @@ static void fts5IndexIntegrityCheckEmpty( for(i=iFirst; p->rc==SQLITE_OK && i<=iLast; i++){ Fts5Data *pLeaf = fts5DataRead(p, FTS5_SEGMENT_ROWID(pSeg->iSegid, i)); if( pLeaf ){ - if( !fts5LeafIsTermless(pLeaf) - || (i>=iNoRowid && 0!=fts5LeafFirstRowidOff(pLeaf)) - ){ - FTS5_CORRUPT_ROWID(p, FTS5_SEGMENT_ROWID(pSeg->iSegid, i)); - } + if( !fts5LeafIsTermless(pLeaf) ) p->rc = FTS5_CORRUPT; + if( i>=iNoRowid && 0!=fts5LeafFirstRowidOff(pLeaf) ) p->rc = FTS5_CORRUPT; } fts5DataRelease(pLeaf); } } -static void fts5IntegrityCheckPgidx(Fts5Index *p, i64 iRowid, Fts5Data *pLeaf){ +static void fts5IntegrityCheckPgidx(Fts5Index *p, Fts5Data *pLeaf){ i64 iTermOff = 0; int ii; @@ -18006,12 +17952,12 @@ static void fts5IntegrityCheckPgidx(Fts5Index *p, i64 iRowid, Fts5Data *pLeaf){ iOff = iTermOff; if( iOff>=pLeaf->szLeaf ){ - FTS5_CORRUPT_ROWID(p, iRowid); + p->rc = FTS5_CORRUPT; }else if( iTermOff==nIncr ){ int nByte; iOff += fts5GetVarint32(&pLeaf->p[iOff], nByte); if( (iOff+nByte)>pLeaf->szLeaf ){ - FTS5_CORRUPT_ROWID(p, iRowid); + p->rc = FTS5_CORRUPT; }else{ fts5BufferSet(&p->rc, &buf1, nByte, &pLeaf->p[iOff]); } @@ -18020,7 +17966,7 @@ static void fts5IntegrityCheckPgidx(Fts5Index *p, i64 iRowid, Fts5Data *pLeaf){ iOff += fts5GetVarint32(&pLeaf->p[iOff], nKeep); iOff += fts5GetVarint32(&pLeaf->p[iOff], nByte); if( nKeep>buf1.n || (iOff+nByte)>pLeaf->szLeaf ){ - FTS5_CORRUPT_ROWID(p, iRowid); + p->rc = FTS5_CORRUPT; }else{ buf1.n = nKeep; fts5BufferAppendBlob(&p->rc, &buf1, nByte, &pLeaf->p[iOff]); @@ -18028,7 +17974,7 @@ static void fts5IntegrityCheckPgidx(Fts5Index *p, i64 iRowid, Fts5Data *pLeaf){ if( p->rc==SQLITE_OK ){ res = fts5BufferCompare(&buf1, &buf2); - if( res<=0 ) FTS5_CORRUPT_ROWID(p, iRowid); + if( res<=0 ) p->rc = FTS5_CORRUPT; } } fts5BufferSet(&p->rc, &buf2, buf1.n, buf1.p); @@ -18089,7 +18035,7 @@ static void fts5IndexIntegrityCheckSegment( ** entry even if all the terms are removed from it by secure-delete ** operations. */ }else{ - FTS5_CORRUPT_ROWID(p, iRow); + p->rc = FTS5_CORRUPT; } }else{ @@ -18101,15 +18047,15 @@ static void fts5IndexIntegrityCheckSegment( iOff = fts5LeafFirstTermOff(pLeaf); iRowidOff = fts5LeafFirstRowidOff(pLeaf); if( iRowidOff>=iOff || iOff>=pLeaf->szLeaf ){ - FTS5_CORRUPT_ROWID(p, iRow); + p->rc = FTS5_CORRUPT; }else{ iOff += fts5GetVarint32(&pLeaf->p[iOff], nTerm); res = fts5Memcmp(&pLeaf->p[iOff], zIdxTerm, MIN(nTerm, nIdxTerm)); if( res==0 ) res = nTerm - nIdxTerm; - if( res<0 ) FTS5_CORRUPT_ROWID(p, iRow); + if( res<0 ) p->rc = FTS5_CORRUPT; } - fts5IntegrityCheckPgidx(p, iRow, pLeaf); + fts5IntegrityCheckPgidx(p, pLeaf); } fts5DataRelease(pLeaf); if( p->rc ) break; @@ -18139,7 +18085,7 @@ static void fts5IndexIntegrityCheckSegment( iKey = FTS5_SEGMENT_ROWID(iSegid, iPg); pLeaf = fts5DataRead(p, iKey); if( pLeaf ){ - if( fts5LeafFirstRowidOff(pLeaf)!=0 ) FTS5_CORRUPT_ROWID(p, iKey); + if( fts5LeafFirstRowidOff(pLeaf)!=0 ) p->rc = FTS5_CORRUPT; fts5DataRelease(pLeaf); } } @@ -18154,12 +18100,12 @@ static void fts5IndexIntegrityCheckSegment( int iRowidOff = fts5LeafFirstRowidOff(pLeaf); ASSERT_SZLEAF_OK(pLeaf); if( iRowidOff>=pLeaf->szLeaf ){ - FTS5_CORRUPT_ROWID(p, iKey); + p->rc = FTS5_CORRUPT; }else if( bSecureDelete==0 || iRowidOff>0 ){ i64 iDlRowid = fts5DlidxIterRowid(pDlidx); fts5GetVarint(&pLeaf->p[iRowidOff], (u64*)&iRowid); if( iRowid<iDlRowid || (bSecureDelete==0 && iRowid!=iDlRowid) ){ - FTS5_CORRUPT_ROWID(p, iKey); + p->rc = FTS5_CORRUPT; } } fts5DataRelease(pLeaf); @@ -18211,7 +18157,6 @@ static int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum, int bUseCksum /* Used by extra internal tests only run if NDEBUG is not defined */ u64 cksum3 = 0; /* Checksum based on contents of indexes */ Fts5Buffer term = {0,0,0}; /* Buffer used to hold most recent term */ - int bTestFail = 0; #endif const int flags = FTS5INDEX_QUERY_NOOUTPUT; @@ -18254,7 +18199,7 @@ static int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum, int bUseCksum char *z = (char*)fts5MultiIterTerm(pIter, &n); /* If this is a new term, query for it. Update cksum3 with the results. */ - fts5TestTerm(p, &term, z, n, cksum2, &cksum3, &bTestFail); + fts5TestTerm(p, &term, z, n, cksum2, &cksum3); if( p->rc ) break; if( eDetail==FTS5_DETAIL_NONE ){ @@ -18272,26 +18217,15 @@ static int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum, int bUseCksum } } } - fts5TestTerm(p, &term, 0, 0, cksum2, &cksum3, &bTestFail); + fts5TestTerm(p, &term, 0, 0, cksum2, &cksum3); fts5MultiIterFree(pIter); - if( p->rc==SQLITE_OK && bUseCksum && cksum!=cksum2 ){ - p->rc = FTS5_CORRUPT; - sqlite3Fts5ConfigErrmsg(p->pConfig, - "fts5: checksum mismatch for table \"%s\"", p->pConfig->zName - ); - } + if( p->rc==SQLITE_OK && bUseCksum && cksum!=cksum2 ) p->rc = FTS5_CORRUPT; + + fts5StructureRelease(pStruct); #ifdef SQLITE_DEBUG - /* In SQLITE_DEBUG builds, expensive extra checks were run as part of - ** the integrity-check above. If no other errors were detected, but one - ** of these tests failed, set the result to SQLITE_CORRUPT_VTAB here. */ - if( p->rc==SQLITE_OK && bTestFail ){ - p->rc = FTS5_CORRUPT; - } fts5BufferFree(&term); #endif - - fts5StructureRelease(pStruct); fts5BufferFree(&poslist); return fts5IndexReturn(p); } @@ -19636,17 +19570,6 @@ static void fts5SetUniqueFlag(sqlite3_index_info *pIdxInfo){ #endif } -static void fts5SetEstimatedRows(sqlite3_index_info *pIdxInfo, i64 nRow){ -#if SQLITE_VERSION_NUMBER>=3008002 -#ifndef SQLITE_CORE - if( sqlite3_libversion_number()>=3008002 ) -#endif - { - pIdxInfo->estimatedRows = nRow; - } -#endif -} - static int fts5UsePatternMatch( Fts5Config *pConfig, struct sqlite3_index_constraint *p @@ -19782,7 +19705,7 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ nSeenMatch++; idxStr[iIdxStr++] = 'M'; sqlite3_snprintf(6, &idxStr[iIdxStr], "%d", iCol); - iIdxStr += (int)strlen(&idxStr[iIdxStr]); + idxStr += strlen(&idxStr[iIdxStr]); assert( idxStr[iIdxStr]=='\0' ); } pInfo->aConstraintUsage[i].argvIndex = ++iCons; @@ -19801,7 +19724,6 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ idxStr[iIdxStr++] = '='; bSeenEq = 1; pInfo->aConstraintUsage[i].argvIndex = ++iCons; - pInfo->aConstraintUsage[i].omit = 1; } } } @@ -19849,21 +19771,17 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ /* Calculate the estimated cost based on the flags set in idxFlags. */ if( bSeenEq ){ - pInfo->estimatedCost = nSeenMatch ? 1000.0 : 25.0; - fts5SetUniqueFlag(pInfo); - fts5SetEstimatedRows(pInfo, 1); + pInfo->estimatedCost = nSeenMatch ? 1000.0 : 10.0; + if( nSeenMatch==0 ) fts5SetUniqueFlag(pInfo); + }else if( bSeenLt && bSeenGt ){ + pInfo->estimatedCost = nSeenMatch ? 5000.0 : 250000.0; + }else if( bSeenLt || bSeenGt ){ + pInfo->estimatedCost = nSeenMatch ? 7500.0 : 750000.0; }else{ - if( bSeenLt && bSeenGt ){ - pInfo->estimatedCost = nSeenMatch ? 5000.0 : 750000.0; - }else if( bSeenLt || bSeenGt ){ - pInfo->estimatedCost = nSeenMatch ? 7500.0 : 2250000.0; - }else{ - pInfo->estimatedCost = nSeenMatch ? 10000.0 : 3000000.0; - } - for(i=1; i<nSeenMatch; i++){ - pInfo->estimatedCost *= 0.4; - } - fts5SetEstimatedRows(pInfo, (i64)(pInfo->estimatedCost / 4.0)); + pInfo->estimatedCost = nSeenMatch ? 10000.0 : 1000000.0; + } + for(i=1; i<nSeenMatch; i++){ + pInfo->estimatedCost *= 0.4; } pInfo->idxNum = idxFlags; @@ -20062,9 +19980,7 @@ static int fts5CursorReseek(Fts5Cursor *pCsr, int *pbSkip){ int bDesc = pCsr->bDesc; i64 iRowid = sqlite3Fts5ExprRowid(pCsr->pExpr); - rc = sqlite3Fts5ExprFirst( - pCsr->pExpr, pTab->p.pIndex, iRowid, pCsr->iLastRowid, bDesc - ); + rc = sqlite3Fts5ExprFirst(pCsr->pExpr, pTab->p.pIndex, iRowid, bDesc); if( rc==SQLITE_OK && iRowid!=sqlite3Fts5ExprRowid(pCsr->pExpr) ){ *pbSkip = 1; } @@ -20236,9 +20152,7 @@ static int fts5CursorFirstSorted( static int fts5CursorFirst(Fts5FullTable *pTab, Fts5Cursor *pCsr, int bDesc){ int rc; Fts5Expr *pExpr = pCsr->pExpr; - rc = sqlite3Fts5ExprFirst( - pExpr, pTab->p.pIndex, pCsr->iFirstRowid, pCsr->iLastRowid, bDesc - ); + rc = sqlite3Fts5ExprFirst(pExpr, pTab->p.pIndex, pCsr->iFirstRowid, bDesc); if( sqlite3Fts5ExprEof(pExpr) ){ CsrFlagSet(pCsr, FTS5CSR_EOF); } @@ -22723,7 +22637,7 @@ static void fts5SourceIdFunc( ){ assert( nArg==0 ); UNUSED_PARAM2(nArg, apUnused); - sqlite3_result_text(pCtx, "fts5: 2025-11-04 19:38:17 fb2c931ae597f8d00a37574ff67aeed3eced4e5547f9120744ae4bfa8e74527b", -1, SQLITE_TRANSIENT); + sqlite3_result_text(pCtx, "fts5: 2025-07-30 19:33:53 4d8adfb30e03f9cf27f800a2c1ba3c48fb4ca1b08b0f5ed59a4d5ecbf45e20a3", -1, SQLITE_TRANSIENT); } /* @@ -22746,9 +22660,9 @@ static void fts5LocaleFunc( sqlite3_value **apArg /* Function arguments */ ){ const char *zLocale = 0; - i64 nLocale = 0; + int nLocale = 0; const char *zText = 0; - i64 nText = 0; + int nText = 0; assert( nArg==2 ); UNUSED_PARAM(nArg); @@ -22765,10 +22679,10 @@ static void fts5LocaleFunc( Fts5Global *p = (Fts5Global*)sqlite3_user_data(pCtx); u8 *pBlob = 0; u8 *pCsr = 0; - i64 nBlob = 0; + int nBlob = 0; nBlob = FTS5_LOCALE_HDR_SIZE + nLocale + 1 + nText; - pBlob = (u8*)sqlite3_malloc64(nBlob); + pBlob = (u8*)sqlite3_malloc(nBlob); if( pBlob==0 ){ sqlite3_result_error_nomem(pCtx); return; @@ -22846,9 +22760,8 @@ static int fts5IntegrityMethod( " FTS5 table %s.%s: %s", zSchema, zTabname, sqlite3_errstr(rc)); } - }else if( (rc&0xff)==SQLITE_CORRUPT ){ - rc = SQLITE_OK; } + sqlite3Fts5IndexCloseReader(pTab->p.pIndex); pTab->p.pConfig->pzErrmsg = 0; diff --git a/third_party/sqlite3/ext/misc/carray.c b/third_party/sqlite3/ext/misc/carray.c @@ -0,0 +1,561 @@ +/* +** 2016-06-29 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** This file demonstrates how to create a table-valued-function that +** returns the values in a C-language array. +** Examples: +** +** SELECT * FROM carray($ptr,5) +** +** The query above returns 5 integers contained in a C-language array +** at the address $ptr. $ptr is a pointer to the array of integers. +** The pointer value must be assigned to $ptr using the +** sqlite3_bind_pointer() interface with a pointer type of "carray". +** For example: +** +** static int aX[] = { 53, 9, 17, 2231, 4, 99 }; +** int i = sqlite3_bind_parameter_index(pStmt, "$ptr"); +** sqlite3_bind_pointer(pStmt, i, aX, "carray", 0); +** +** There is an optional third parameter to determine the datatype of +** the C-language array. Allowed values of the third parameter are +** 'int32', 'int64', 'double', 'char*', 'struct iovec'. Example: +** +** SELECT * FROM carray($ptr,10,'char*'); +** +** The default value of the third parameter is 'int32'. +** +** HOW IT WORKS +** +** The carray "function" is really a virtual table with the +** following schema: +** +** CREATE TABLE carray( +** value, +** pointer HIDDEN, +** count HIDDEN, +** ctype TEXT HIDDEN +** ); +** +** If the hidden columns "pointer" and "count" are unconstrained, then +** the virtual table has no rows. Otherwise, the virtual table interprets +** the integer value of "pointer" as a pointer to the array and "count" +** as the number of elements in the array. The virtual table steps through +** the array, element by element. +*/ +#include "sqlite3ext.h" +SQLITE_EXTENSION_INIT1 +#include <assert.h> +#include <string.h> +#ifdef _WIN32 + struct iovec { + void *iov_base; + size_t iov_len; + }; +#else +# include <sys/uio.h> +#endif + +/* Allowed values for the mFlags parameter to sqlite3_carray_bind(). +** Must exactly match the definitions in carray.h. +*/ +#ifndef CARRAY_INT32 +# define CARRAY_INT32 0 /* Data is 32-bit signed integers */ +# define CARRAY_INT64 1 /* Data is 64-bit signed integers */ +# define CARRAY_DOUBLE 2 /* Data is doubles */ +# define CARRAY_TEXT 3 /* Data is char* */ +# define CARRAY_BLOB 4 /* Data is struct iovec* */ +#endif + +#ifndef SQLITE_API +# ifdef _WIN32 +# define SQLITE_API __declspec(dllexport) +# else +# define SQLITE_API +# endif +#endif + +#ifndef SQLITE_OMIT_VIRTUALTABLE + +/* +** Names of allowed datatypes +*/ +static const char *azType[] = { "int32", "int64", "double", "char*", + "struct iovec" }; + +/* +** Structure used to hold the sqlite3_carray_bind() information +*/ +typedef struct carray_bind carray_bind; +struct carray_bind { + void *aData; /* The data */ + int nData; /* Number of elements */ + int mFlags; /* Control flags */ + void (*xDel)(void*); /* Destructor for aData */ +}; + + +/* carray_cursor is a subclass of sqlite3_vtab_cursor which will +** serve as the underlying representation of a cursor that scans +** over rows of the result +*/ +typedef struct carray_cursor carray_cursor; +struct carray_cursor { + sqlite3_vtab_cursor base; /* Base class - must be first */ + sqlite3_int64 iRowid; /* The rowid */ + void *pPtr; /* Pointer to the array of values */ + sqlite3_int64 iCnt; /* Number of integers in the array */ + unsigned char eType; /* One of the CARRAY_type values */ +}; + +/* +** The carrayConnect() method is invoked to create a new +** carray_vtab that describes the carray virtual table. +** +** Think of this routine as the constructor for carray_vtab objects. +** +** All this routine needs to do is: +** +** (1) Allocate the carray_vtab object and initialize all fields. +** +** (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the +** result set of queries against carray will look like. +*/ +static int carrayConnect( + sqlite3 *db, + void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVtab, + char **pzErr +){ + sqlite3_vtab *pNew; + int rc; + +/* Column numbers */ +#define CARRAY_COLUMN_VALUE 0 +#define CARRAY_COLUMN_POINTER 1 +#define CARRAY_COLUMN_COUNT 2 +#define CARRAY_COLUMN_CTYPE 3 + + rc = sqlite3_declare_vtab(db, + "CREATE TABLE x(value,pointer hidden,count hidden,ctype hidden)"); + if( rc==SQLITE_OK ){ + pNew = *ppVtab = sqlite3_malloc( sizeof(*pNew) ); + if( pNew==0 ) return SQLITE_NOMEM; + memset(pNew, 0, sizeof(*pNew)); + } + return rc; +} + +/* +** This method is the destructor for carray_cursor objects. +*/ +static int carrayDisconnect(sqlite3_vtab *pVtab){ + sqlite3_free(pVtab); + return SQLITE_OK; +} + +/* +** Constructor for a new carray_cursor object. +*/ +static int carrayOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ + carray_cursor *pCur; + pCur = sqlite3_malloc( sizeof(*pCur) ); + if( pCur==0 ) return SQLITE_NOMEM; + memset(pCur, 0, sizeof(*pCur)); + *ppCursor = &pCur->base; + return SQLITE_OK; +} + +/* +** Destructor for a carray_cursor. +*/ +static int carrayClose(sqlite3_vtab_cursor *cur){ + sqlite3_free(cur); + return SQLITE_OK; +} + + +/* +** Advance a carray_cursor to its next row of output. +*/ +static int carrayNext(sqlite3_vtab_cursor *cur){ + carray_cursor *pCur = (carray_cursor*)cur; + pCur->iRowid++; + return SQLITE_OK; +} + +/* +** Return values of columns for the row at which the carray_cursor +** is currently pointing. +*/ +static int carrayColumn( + sqlite3_vtab_cursor *cur, /* The cursor */ + sqlite3_context *ctx, /* First argument to sqlite3_result_...() */ + int i /* Which column to return */ +){ + carray_cursor *pCur = (carray_cursor*)cur; + sqlite3_int64 x = 0; + switch( i ){ + case CARRAY_COLUMN_POINTER: return SQLITE_OK; + case CARRAY_COLUMN_COUNT: x = pCur->iCnt; break; + case CARRAY_COLUMN_CTYPE: { + sqlite3_result_text(ctx, azType[pCur->eType], -1, SQLITE_STATIC); + return SQLITE_OK; + } + default: { + switch( pCur->eType ){ + case CARRAY_INT32: { + int *p = (int*)pCur->pPtr; + sqlite3_result_int(ctx, p[pCur->iRowid-1]); + return SQLITE_OK; + } + case CARRAY_INT64: { + sqlite3_int64 *p = (sqlite3_int64*)pCur->pPtr; + sqlite3_result_int64(ctx, p[pCur->iRowid-1]); + return SQLITE_OK; + } + case CARRAY_DOUBLE: { + double *p = (double*)pCur->pPtr; + sqlite3_result_double(ctx, p[pCur->iRowid-1]); + return SQLITE_OK; + } + case CARRAY_TEXT: { + const char **p = (const char**)pCur->pPtr; + sqlite3_result_text(ctx, p[pCur->iRowid-1], -1, SQLITE_TRANSIENT); + return SQLITE_OK; + } + case CARRAY_BLOB: { + const struct iovec *p = (struct iovec*)pCur->pPtr; + sqlite3_result_blob(ctx, p[pCur->iRowid-1].iov_base, + (int)p[pCur->iRowid-1].iov_len, SQLITE_TRANSIENT); + return SQLITE_OK; + } + } + } + } + sqlite3_result_int64(ctx, x); + return SQLITE_OK; +} + +/* +** Return the rowid for the current row. In this implementation, the +** rowid is the same as the output value. +*/ +static int carrayRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ + carray_cursor *pCur = (carray_cursor*)cur; + *pRowid = pCur->iRowid; + return SQLITE_OK; +} + +/* +** Return TRUE if the cursor has been moved off of the last +** row of output. +*/ +static int carrayEof(sqlite3_vtab_cursor *cur){ + carray_cursor *pCur = (carray_cursor*)cur; + return pCur->iRowid>pCur->iCnt; +} + +/* +** This method is called to "rewind" the carray_cursor object back +** to the first row of output. +*/ +static int carrayFilter( + sqlite3_vtab_cursor *pVtabCursor, + int idxNum, const char *idxStr, + int argc, sqlite3_value **argv +){ + carray_cursor *pCur = (carray_cursor *)pVtabCursor; + pCur->pPtr = 0; + pCur->iCnt = 0; + switch( idxNum ){ + case 1: { + carray_bind *pBind = sqlite3_value_pointer(argv[0], "carray-bind"); + if( pBind==0 ) break; + pCur->pPtr = pBind->aData; + pCur->iCnt = pBind->nData; + pCur->eType = pBind->mFlags & 0x07; + break; + } + case 2: + case 3: { + pCur->pPtr = sqlite3_value_pointer(argv[0], "carray"); + pCur->iCnt = pCur->pPtr ? sqlite3_value_int64(argv[1]) : 0; + if( idxNum<3 ){ + pCur->eType = CARRAY_INT32; + }else{ + unsigned char i; + const char *zType = (const char*)sqlite3_value_text(argv[2]); + for(i=0; i<sizeof(azType)/sizeof(azType[0]); i++){ + if( sqlite3_stricmp(zType, azType[i])==0 ) break; + } + if( i>=sizeof(azType)/sizeof(azType[0]) ){ + pVtabCursor->pVtab->zErrMsg = sqlite3_mprintf( + "unknown datatype: %Q", zType); + return SQLITE_ERROR; + }else{ + pCur->eType = i; + } + } + break; + } + } + pCur->iRowid = 1; + return SQLITE_OK; +} + +/* +** SQLite will invoke this method one or more times while planning a query +** that uses the carray virtual table. This routine needs to create +** a query plan for each invocation and compute an estimated cost for that +** plan. +** +** In this implementation idxNum is used to represent the +** query plan. idxStr is unused. +** +** idxNum is: +** +** 1 If only the pointer= constraint exists. In this case, the +** parameter must be bound using sqlite3_carray_bind(). +** +** 2 if the pointer= and count= constraints exist. +** +** 3 if the ctype= constraint also exists. +** +** idxNum is 0 otherwise and carray becomes an empty table. +*/ +static int carrayBestIndex( + sqlite3_vtab *tab, + sqlite3_index_info *pIdxInfo +){ + int i; /* Loop over constraints */ + int ptrIdx = -1; /* Index of the pointer= constraint, or -1 if none */ + int cntIdx = -1; /* Index of the count= constraint, or -1 if none */ + int ctypeIdx = -1; /* Index of the ctype= constraint, or -1 if none */ + + const struct sqlite3_index_constraint *pConstraint; + pConstraint = pIdxInfo->aConstraint; + for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){ + if( pConstraint->usable==0 ) continue; + if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue; + switch( pConstraint->iColumn ){ + case CARRAY_COLUMN_POINTER: + ptrIdx = i; + break; + case CARRAY_COLUMN_COUNT: + cntIdx = i; + break; + case CARRAY_COLUMN_CTYPE: + ctypeIdx = i; + break; + } + } + if( ptrIdx>=0 ){ + pIdxInfo->aConstraintUsage[ptrIdx].argvIndex = 1; + pIdxInfo->aConstraintUsage[ptrIdx].omit = 1; + pIdxInfo->estimatedCost = (double)1; + pIdxInfo->estimatedRows = 100; + pIdxInfo->idxNum = 1; + if( cntIdx>=0 ){ + pIdxInfo->aConstraintUsage[cntIdx].argvIndex = 2; + pIdxInfo->aConstraintUsage[cntIdx].omit = 1; + pIdxInfo->idxNum = 2; + if( ctypeIdx>=0 ){ + pIdxInfo->aConstraintUsage[ctypeIdx].argvIndex = 3; + pIdxInfo->aConstraintUsage[ctypeIdx].omit = 1; + pIdxInfo->idxNum = 3; + } + } + }else{ + pIdxInfo->estimatedCost = (double)2147483647; + pIdxInfo->estimatedRows = 2147483647; + pIdxInfo->idxNum = 0; + } + return SQLITE_OK; +} + +/* +** This following structure defines all the methods for the +** carray virtual table. +*/ +static sqlite3_module carrayModule = { + 0, /* iVersion */ + 0, /* xCreate */ + carrayConnect, /* xConnect */ + carrayBestIndex, /* xBestIndex */ + carrayDisconnect, /* xDisconnect */ + 0, /* xDestroy */ + carrayOpen, /* xOpen - open a cursor */ + carrayClose, /* xClose - close a cursor */ + carrayFilter, /* xFilter - configure scan constraints */ + carrayNext, /* xNext - advance a cursor */ + carrayEof, /* xEof - check for end of scan */ + carrayColumn, /* xColumn - read data */ + carrayRowid, /* xRowid - read data */ + 0, /* xUpdate */ + 0, /* xBegin */ + 0, /* xSync */ + 0, /* xCommit */ + 0, /* xRollback */ + 0, /* xFindMethod */ + 0, /* xRename */ + 0, /* xSavepoint */ + 0, /* xRelease */ + 0, /* xRollbackTo */ + 0, /* xShadow */ + 0 /* xIntegrity */ +}; + +/* +** Destructor for the carray_bind object +*/ +static void carrayBindDel(void *pPtr){ + carray_bind *p = (carray_bind*)pPtr; + if( p->xDel!=SQLITE_STATIC ){ + p->xDel(p->aData); + } + sqlite3_free(p); +} + +/* +** Invoke this interface in order to bind to the single-argument +** version of CARRAY(). +*/ +SQLITE_API int sqlite3_carray_bind( + sqlite3_stmt *pStmt, + int idx, + void *aData, + int nData, + int mFlags, + void (*xDestroy)(void*) +){ + carray_bind *pNew; + int i; + pNew = sqlite3_malloc64(sizeof(*pNew)); + if( pNew==0 ){ + if( xDestroy!=SQLITE_STATIC && xDestroy!=SQLITE_TRANSIENT ){ + xDestroy(aData); + } + return SQLITE_NOMEM; + } + pNew->nData = nData; + pNew->mFlags = mFlags; + if( xDestroy==SQLITE_TRANSIENT ){ + sqlite3_int64 sz = nData; + switch( mFlags & 0x07 ){ + case CARRAY_INT32: sz *= 4; break; + case CARRAY_INT64: sz *= 8; break; + case CARRAY_DOUBLE: sz *= 8; break; + case CARRAY_TEXT: sz *= sizeof(char*); break; + case CARRAY_BLOB: sz *= sizeof(struct iovec); break; + } + if( (mFlags & 0x07)==CARRAY_TEXT ){ + for(i=0; i<nData; i++){ + const char *z = ((char**)aData)[i]; + if( z ) sz += strlen(z) + 1; + } + }else if( (mFlags & 0x07)==CARRAY_BLOB ){ + for(i=0; i<nData; i++){ + sz += ((struct iovec*)aData)[i].iov_len; + } + } + pNew->aData = sqlite3_malloc64( sz ); + if( pNew->aData==0 ){ + sqlite3_free(pNew); + return SQLITE_NOMEM; + } + if( (mFlags & 0x07)==CARRAY_TEXT ){ + char **az = (char**)pNew->aData; + char *z = (char*)&az[nData]; + for(i=0; i<nData; i++){ + const char *zData = ((char**)aData)[i]; + sqlite3_int64 n; + if( zData==0 ){ + az[i] = 0; + continue; + } + az[i] = z; + n = strlen(zData); + memcpy(z, zData, n+1); + z += n+1; + } + }else if( (mFlags & 0x07)==CARRAY_BLOB ){ + struct iovec *p = (struct iovec*)pNew->aData; + unsigned char *z = (unsigned char*)&p[nData]; + for(i=0; i<nData; i++){ + size_t n = ((struct iovec*)aData)[i].iov_len; + p[i].iov_len = n; + p[i].iov_base = z; + z += n; + memcpy(p[i].iov_base, ((struct iovec*)aData)[i].iov_base, n); + } + }else{ + memcpy(pNew->aData, aData, sz); + } + pNew->xDel = sqlite3_free; + }else{ + pNew->aData = aData; + pNew->xDel = xDestroy; + } + return sqlite3_bind_pointer(pStmt, idx, pNew, "carray-bind", carrayBindDel); +} + + +/* +** For testing purpose in the TCL test harness, we need a method for +** setting the pointer value. The inttoptr(X) SQL function accomplishes +** this. Tcl script will bind an integer to X and the inttoptr() SQL +** function will use sqlite3_result_pointer() to convert that integer into +** a pointer. +** +** This is for testing on TCL only. +*/ +#ifdef SQLITE_TEST +static void inttoptrFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + void *p; + sqlite3_int64 i64; + i64 = sqlite3_value_int64(argv[0]); + if( sizeof(i64)==sizeof(p) ){ + memcpy(&p, &i64, sizeof(p)); + }else{ + int i32 = i64 & 0xffffffff; + memcpy(&p, &i32, sizeof(p)); + } + sqlite3_result_pointer(context, p, "carray", 0); +} +#endif /* SQLITE_TEST */ + +#endif /* SQLITE_OMIT_VIRTUALTABLE */ + +SQLITE_API int sqlite3_carray_init( + sqlite3 *db, + char **pzErrMsg, + const sqlite3_api_routines *pApi +){ + int rc = SQLITE_OK; + SQLITE_EXTENSION_INIT2(pApi); +#ifndef SQLITE_OMIT_VIRTUALTABLE + rc = sqlite3_create_module(db, "carray", &carrayModule, 0); +#ifdef SQLITE_TEST + if( rc==SQLITE_OK ){ + rc = sqlite3_create_function(db, "inttoptr", 1, SQLITE_UTF8, 0, + inttoptrFunc, 0, 0); + } +#endif /* SQLITE_TEST */ +#endif /* SQLITE_OMIT_VIRTUALTABLE */ + return rc; +} diff --git a/third_party/sqlite3/ext/misc/carray.h b/third_party/sqlite3/ext/misc/carray.h @@ -0,0 +1,50 @@ +/* +** 2020-11-17 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** Interface definitions for the CARRAY table-valued function +** extension. +*/ + +#ifndef _CARRAY_H +#define _CARRAY_H + +#include "sqlite3.h" /* Required for error code definitions */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Use this interface to bind an array to the single-argument version +** of CARRAY(). +*/ +SQLITE_API int sqlite3_carray_bind( + sqlite3_stmt *pStmt, /* Statement to be bound */ + int i, /* Parameter index */ + void *aData, /* Pointer to array data */ + int nData, /* Number of data elements */ + int mFlags, /* CARRAY flags */ + void (*xDel)(void*) /* Destructgor for aData*/ +); + +/* Allowed values for the mFlags parameter to sqlite3_carray_bind(). +*/ +#define CARRAY_INT32 0 /* Data is 32-bit signed integers */ +#define CARRAY_INT64 1 /* Data is 64-bit signed integers */ +#define CARRAY_DOUBLE 2 /* Data is doubles */ +#define CARRAY_TEXT 3 /* Data is char* */ +#define CARRAY_BLOB 4 /* Data is struct iovec */ + +#ifdef __cplusplus +} /* end of the 'extern "C"' block */ +#endif + +#endif /* ifndef _CARRAY_H */ diff --git a/third_party/sqlite3/ext/sqlite3_static_ext.h b/third_party/sqlite3/ext/sqlite3_static_ext.h @@ -0,0 +1,28 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +/** + * This is an exported header containing declarations of methods for statically + * linked SQLite3 extensions. + */ + +#ifndef SQLITE3_STATIC_EXT_H +#define SQLITE3_STATIC_EXT_H +#include "sqlite3.h" +#include "misc/carray.h" + +#ifdef __cplusplus +extern "C" { +#endif + +SQLITE_API int sqlite3_carray_init(sqlite3*, char**, + const sqlite3_api_routines*); + +#ifdef __cplusplus +} /* end of the 'extern "C"' block */ +#endif + +#endif /* SQLITE3_STATIC_EXT_H */ diff --git a/third_party/sqlite3/ext/sqlite3ext.h b/third_party/sqlite3/ext/sqlite3ext.h @@ -368,10 +368,6 @@ struct sqlite3_api_routines { int (*set_clientdata)(sqlite3*, const char*, void*, void(*)(void*)); /* Version 3.50.0 and later */ int (*setlk_timeout)(sqlite3*,int,int); - /* Version 3.51.0 and later */ - int (*set_errmsg)(sqlite3*,int,const char*); - int (*db_status64)(sqlite3*,int,sqlite3_int64*,sqlite3_int64*,int); - }; /* @@ -707,9 +703,6 @@ typedef int (*sqlite3_loadext_entry)( #define sqlite3_set_clientdata sqlite3_api->set_clientdata /* Version 3.50.0 and later */ #define sqlite3_setlk_timeout sqlite3_api->setlk_timeout -/* Version 3.51.0 and later */ -#define sqlite3_set_errmsg sqlite3_api->set_errmsg -#define sqlite3_db_status64 sqlite3_api->db_status64 #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) diff --git a/third_party/sqlite3/moz.yaml b/third_party/sqlite3/moz.yaml @@ -10,8 +10,8 @@ origin: SQLite is a C-language library that implements a small, fast, self-contained, high-reliability, full-featured, SQL database engine. url: https://www.sqlite.org/ - release: version-3.51.0 (2025-11-04T19:38:17Z). - revision: version-3.51.0 + release: version-3.50.4 (2025-07-30T19:33:53Z). + revision: version-3.50.4 license: Public Domain license-file: LICENSE.md notes: > @@ -33,6 +33,8 @@ vendoring: exclude: - "**" include: + - ext/misc/carray.h + - ext/misc/carray.c - LICENSE.md - VERSION keep: @@ -45,6 +47,12 @@ vendoring: - action: move-file from: '{vendor_dir}/VERSION' to: '{vendor_dir}/VERSION.txt' + - action: move-file + from: '{vendor_dir}/ext/misc/carray.h' + to: '{yaml_dir}/ext/misc/carray.h' + - action: move-file + from: '{vendor_dir}/ext/misc/carray.c' + to: '{yaml_dir}/ext/misc/carray.c' - action: run-script script: '{yaml_dir}/vendor.sh' cwd: '{yaml_dir}' diff --git a/third_party/sqlite3/src/LICENSE.md b/third_party/sqlite3/src/LICENSE.md @@ -30,12 +30,14 @@ The public domain source files usually contain a header comment similar to the following to make it clear that the software is public domain. -> The author disclaims copyright to this source code. In place of -> a legal notice, here is a blessing: -> -> * May you do good and not evil. -> * May you find forgiveness for yourself and forgive others. -> * May you share freely, never taking more than you give. +> ~~~ +The author disclaims copyright to this source code. In place of +a legal notice, here is a blessing: + + * May you do good and not evil. + * May you find forgiveness for yourself and forgive others. + * May you share freely, never taking more than you give. +~~~ Almost every file you find in this source repository will be public domain. But there are a small number of exceptions: @@ -47,7 +49,9 @@ This repository contains a (relatively) small amount of non-public-domain code used to help implement the configuration and build logic. In other words, there are some non-public-domain files used to implement: -> ./configure && make +> ~~~ +./configure && make +~~~ In all cases, the non-public-domain files included with this repository have generous BSD-style licenses. So anyone is free to @@ -65,7 +69,7 @@ third-party build scripts in order to compile SQLite. Non-public-domain code included in this respository includes: * The ["autosetup"](http://msteveb.github.io/autosetup/) configuration - system that is contained (mostly) in the autosetup/ directory, but also + system that is contained (mostly) the autosetup/ directory, but also includes the "./configure" script at the top-level of this archive. Autosetup has a separate BSD-style license. See the [autosetup/LICENSE](http://msteveb.github.io/autosetup/license/) @@ -75,11 +79,13 @@ Non-public-domain code included in this respository includes: software found in the legacy autoconf/ directory and its subdirectories. -The following unix shell command can be run from the top-level +The following unix shell command is can be run from the top-level of this source repository in order to remove all non-public-domain code: -> rm -rf configure autosetup autoconf +> ~~~ +rm -rf configure autosetup autoconf +~~~ If you unpack this source repository and then run the command above, what is left will be 100% public domain. diff --git a/third_party/sqlite3/src/VERSION.txt b/third_party/sqlite3/src/VERSION.txt @@ -1 +1 @@ -3.51.0 +3.50.4 diff --git a/third_party/sqlite3/src/moz.build b/third_party/sqlite3/src/moz.build @@ -24,6 +24,7 @@ DIRS += [ ] SOURCES += [ + "../ext/misc/carray.c", "sqlite3.c", ] @@ -137,5 +138,3 @@ DEFINES['SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT'] = 1572864 if CONFIG["MOZ_THUNDERBIRD"] or CONFIG["MOZ_SUITE"]: DEFINES['SQLITE_ENABLE_FTS3'] = 1 -# The carray extension is part of the amalgamation but disabled by default. -DEFINES['SQLITE_ENABLE_CARRAY'] = 1 diff --git a/third_party/sqlite3/src/sqlite.symbols b/third_party/sqlite3/src/sqlite.symbols @@ -24,6 +24,7 @@ sqlite3_busy_handler sqlite3_busy_timeout sqlite3_cancel_auto_extension sqlite3_carray_bind +sqlite3_carray_init sqlite3_changes sqlite3_changes64 sqlite3_clear_bindings diff --git a/third_party/sqlite3/src/sqlite3.c b/third_party/sqlite3/src/sqlite3.c @@ -1,6 +1,6 @@ /****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite -** version 3.51.0. By combining all the individual C code files into this +** version 3.50.4. By combining all the individual C code files into this ** single large file, the entire code can be compiled as a single translation ** unit. This allows many compilers to do optimizations that would not be ** possible if the files were compiled separately. Performance improvements @@ -18,7 +18,7 @@ ** separate file. This file contains only code for the core SQLite library. ** ** The content in this amalgamation comes from Fossil check-in -** fb2c931ae597f8d00a37574ff67aeed3eced with changes in files: +** 4d8adfb30e03f9cf27f800a2c1ba3c48fb4c with changes in files: ** ** */ @@ -170,9 +170,7 @@ #define HAVE_UTIME 1 #else /* This is not VxWorks. */ -#ifndef OS_VXWORKS -# define OS_VXWORKS 0 -#endif +#define OS_VXWORKS 0 #define HAVE_FCHOWN 1 #define HAVE_READLINK 1 #define HAVE_LSTAT 1 @@ -467,12 +465,9 @@ extern "C" { ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.51.0" -#define SQLITE_VERSION_NUMBER 3051000 -#define SQLITE_SOURCE_ID "2025-11-04 19:38:17 fb2c931ae597f8d00a37574ff67aeed3eced4e5547f9120744ae4bfa8e74527b" -#define SQLITE_SCM_BRANCH "trunk" -#define SQLITE_SCM_TAGS "release major-release version-3.51.0" -#define SQLITE_SCM_DATETIME "2025-11-04T19:38:17.314Z" +#define SQLITE_VERSION "3.50.4" +#define SQLITE_VERSION_NUMBER 3050004 +#define SQLITE_SOURCE_ID "2025-07-30 19:33:53 4d8adfb30e03f9cf27f800a2c1ba3c48fb4ca1b08b0f5ed59a4d5ecbf45e20a3" /* ** CAPI3REF: Run-Time Library Version Numbers @@ -492,9 +487,9 @@ extern "C" { ** assert( strcmp(sqlite3_libversion(),SQLITE_VERSION)==0 ); ** </pre></blockquote>)^ ** -** ^The sqlite3_version[] string constant contains the text of the -** [SQLITE_VERSION] macro. ^The sqlite3_libversion() function returns a -** pointer to the sqlite3_version[] string constant. The sqlite3_libversion() +** ^The sqlite3_version[] string constant contains the text of [SQLITE_VERSION] +** macro. ^The sqlite3_libversion() function returns a pointer to the +** to the sqlite3_version[] string constant. The sqlite3_libversion() ** function is provided for use in DLLs since DLL users usually do not have ** direct access to string constants within the DLL. ^The ** sqlite3_libversion_number() function returns an integer equal to @@ -694,7 +689,7 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**); ** without having to use a lot of C code. ** ** ^The sqlite3_exec() interface runs zero or more UTF-8 encoded, -** semicolon-separated SQL statements passed into its 2nd argument, +** semicolon-separate SQL statements passed into its 2nd argument, ** in the context of the [database connection] passed in as its 1st ** argument. ^If the callback function of the 3rd argument to ** sqlite3_exec() is not NULL, then it is invoked for each result row @@ -727,7 +722,7 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**); ** result row is NULL then the corresponding string pointer for the ** sqlite3_exec() callback is a NULL pointer. ^The 4th argument to the ** sqlite3_exec() callback is an array of pointers to strings where each -** entry represents the name of a corresponding result column as obtained +** entry represents the name of corresponding result column as obtained ** from [sqlite3_column_name()]. ** ** ^If the 2nd parameter to sqlite3_exec() is a NULL pointer, a pointer @@ -821,9 +816,6 @@ SQLITE_API int sqlite3_exec( #define SQLITE_ERROR_MISSING_COLLSEQ (SQLITE_ERROR | (1<<8)) #define SQLITE_ERROR_RETRY (SQLITE_ERROR | (2<<8)) #define SQLITE_ERROR_SNAPSHOT (SQLITE_ERROR | (3<<8)) -#define SQLITE_ERROR_RESERVESIZE (SQLITE_ERROR | (4<<8)) -#define SQLITE_ERROR_KEY (SQLITE_ERROR | (5<<8)) -#define SQLITE_ERROR_UNABLE (SQLITE_ERROR | (6<<8)) #define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8)) #define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8)) #define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3<<8)) @@ -858,8 +850,6 @@ SQLITE_API int sqlite3_exec( #define SQLITE_IOERR_DATA (SQLITE_IOERR | (32<<8)) #define SQLITE_IOERR_CORRUPTFS (SQLITE_IOERR | (33<<8)) #define SQLITE_IOERR_IN_PAGE (SQLITE_IOERR | (34<<8)) -#define SQLITE_IOERR_BADKEY (SQLITE_IOERR | (35<<8)) -#define SQLITE_IOERR_CODEC (SQLITE_IOERR | (36<<8)) #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8)) #define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8)) #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) @@ -918,7 +908,7 @@ SQLITE_API int sqlite3_exec( ** Note in particular that passing the SQLITE_OPEN_EXCLUSIVE flag into ** [sqlite3_open_v2()] does *not* cause the underlying database file ** to be opened using O_EXCL. Passing SQLITE_OPEN_EXCLUSIVE into -** [sqlite3_open_v2()] has historically been a no-op and might become an +** [sqlite3_open_v2()] has historically be a no-op and might become an ** error in future versions of SQLite. */ #define SQLITE_OPEN_READONLY 0x00000001 /* Ok for sqlite3_open_v2() */ @@ -1012,7 +1002,7 @@ SQLITE_API int sqlite3_exec( ** SQLite uses one of these integer values as the second ** argument to calls it makes to the xLock() and xUnlock() methods ** of an [sqlite3_io_methods] object. These values are ordered from -** least restrictive to most restrictive. +** lest restrictive to most restrictive. ** ** The argument to xLock() is always SHARED or higher. The argument to ** xUnlock is either SHARED or NONE. @@ -1253,7 +1243,7 @@ struct sqlite3_io_methods { ** connection. See also [SQLITE_FCNTL_FILE_POINTER]. ** ** <li>[[SQLITE_FCNTL_SYNC_OMITTED]] -** The SQLITE_FCNTL_SYNC_OMITTED file-control is no longer used. +** No longer in use. ** ** <li>[[SQLITE_FCNTL_SYNC]] ** The [SQLITE_FCNTL_SYNC] opcode is generated internally by SQLite and @@ -1328,7 +1318,7 @@ struct sqlite3_io_methods { ** ** <li>[[SQLITE_FCNTL_VFSNAME]] ** ^The [SQLITE_FCNTL_VFSNAME] opcode can be used to obtain the names of -** all [VFSes] in the VFS stack. The names of all VFS shims and the +** all [VFSes] in the VFS stack. The names are of all VFS shims and the ** final bottom-level VFS are written into memory obtained from ** [sqlite3_malloc()] and the result is stored in the char* variable ** that the fourth parameter of [sqlite3_file_control()] points to. @@ -1342,7 +1332,7 @@ struct sqlite3_io_methods { ** ^The [SQLITE_FCNTL_VFS_POINTER] opcode finds a pointer to the top-level ** [VFSes] currently in use. ^(The argument X in ** sqlite3_file_control(db,SQLITE_FCNTL_VFS_POINTER,X) must be -** of type "[sqlite3_vfs] **". This opcode will set *X +** of type "[sqlite3_vfs] **". This opcodes will set *X ** to a pointer to the top-level VFS.)^ ** ^When there are multiple VFS shims in the stack, this opcode finds the ** upper-most shim only. @@ -1532,7 +1522,7 @@ struct sqlite3_io_methods { ** <li>[[SQLITE_FCNTL_EXTERNAL_READER]] ** The EXPERIMENTAL [SQLITE_FCNTL_EXTERNAL_READER] opcode is used to detect ** whether or not there is a database client in another process with a wal-mode -** transaction open on the database or not. It is only available on unix. The +** transaction open on the database or not. It is only available on unix.The ** (void*) argument passed with this file-control should be a pointer to a ** value of type (int). The integer value is set to 1 if the database is a wal ** mode database and there exists at least one client in another process that @@ -1550,15 +1540,6 @@ struct sqlite3_io_methods { ** database is not a temp db, then the [SQLITE_FCNTL_RESET_CACHE] file-control ** purges the contents of the in-memory page cache. If there is an open ** transaction, or if the db is a temp-db, this opcode is a no-op, not an error. -** -** <li>[[SQLITE_FCNTL_FILESTAT]] -** The [SQLITE_FCNTL_FILESTAT] opcode returns low-level diagnostic information -** about the [sqlite3_file] objects used access the database and journal files -** for the given schema. The fourth parameter to [sqlite3_file_control()] -** should be an initialized [sqlite3_str] pointer. JSON text describing -** various aspects of the sqlite3_file object is appended to the sqlite3_str. -** The SQLITE_FCNTL_FILESTAT opcode is usually a no-op, unless compile-time -** options are used to enable it. ** </ul> */ #define SQLITE_FCNTL_LOCKSTATE 1 @@ -1604,7 +1585,6 @@ struct sqlite3_io_methods { #define SQLITE_FCNTL_RESET_CACHE 42 #define SQLITE_FCNTL_NULL_IO 43 #define SQLITE_FCNTL_BLOCK_ON_CONNECT 44 -#define SQLITE_FCNTL_FILESTAT 45 /* deprecated names */ #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE @@ -1967,7 +1947,7 @@ struct sqlite3_vfs { ** SQLite interfaces so that an application usually does not need to ** invoke sqlite3_initialize() directly. For example, [sqlite3_open()] ** calls sqlite3_initialize() so the SQLite library will be automatically -** initialized when [sqlite3_open()] is called if it has not been initialized +** initialized when [sqlite3_open()] is called if it has not be initialized ** already. ^However, if SQLite is compiled with the [SQLITE_OMIT_AUTOINIT] ** compile-time option, then the automatic calls to sqlite3_initialize() ** are omitted and the application must call sqlite3_initialize() directly @@ -2224,21 +2204,21 @@ struct sqlite3_mem_methods { ** The [sqlite3_mem_methods] ** structure is filled with the currently defined memory allocation routines.)^ ** This option can be used to overload the default memory allocation -** routines with a wrapper that simulates memory allocation failure or +** routines with a wrapper that simulations memory allocation failure or ** tracks memory usage, for example. </dd> ** ** [[SQLITE_CONFIG_SMALL_MALLOC]] <dt>SQLITE_CONFIG_SMALL_MALLOC</dt> -** <dd> ^The SQLITE_CONFIG_SMALL_MALLOC option takes a single argument of +** <dd> ^The SQLITE_CONFIG_SMALL_MALLOC option takes single argument of ** type int, interpreted as a boolean, which if true provides a hint to ** SQLite that it should avoid large memory allocations if possible. ** SQLite will run faster if it is free to make large memory allocations, -** but some applications might prefer to run slower in exchange for +** but some application might prefer to run slower in exchange for ** guarantees about memory fragmentation that are possible if large ** allocations are avoided. This hint is normally off. ** </dd> ** ** [[SQLITE_CONFIG_MEMSTATUS]] <dt>SQLITE_CONFIG_MEMSTATUS</dt> -** <dd> ^The SQLITE_CONFIG_MEMSTATUS option takes a single argument of type int, +** <dd> ^The SQLITE_CONFIG_MEMSTATUS option takes single argument of type int, ** interpreted as a boolean, which enables or disables the collection of ** memory allocation statistics. ^(When memory allocation statistics are ** disabled, the following SQLite interfaces become non-operational: @@ -2283,7 +2263,7 @@ struct sqlite3_mem_methods { ** ^If pMem is NULL and N is non-zero, then each database connection ** does an initial bulk allocation for page cache memory ** from [sqlite3_malloc()] sufficient for N cache lines if N is positive or -** of -1024*N bytes if N is negative. ^If additional +** of -1024*N bytes if N is negative, . ^If additional ** page cache memory is needed beyond what is provided by the initial ** allocation, then SQLite goes to [sqlite3_malloc()] separately for each ** additional cache line. </dd> @@ -2312,7 +2292,7 @@ struct sqlite3_mem_methods { ** <dd> ^(The SQLITE_CONFIG_MUTEX option takes a single argument which is a ** pointer to an instance of the [sqlite3_mutex_methods] structure. ** The argument specifies alternative low-level mutex routines to be used -** in place of the mutex routines built into SQLite.)^ ^SQLite makes a copy of +** in place the mutex routines built into SQLite.)^ ^SQLite makes a copy of ** the content of the [sqlite3_mutex_methods] structure before the call to ** [sqlite3_config()] returns. ^If SQLite is compiled with ** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then @@ -2354,7 +2334,7 @@ struct sqlite3_mem_methods { ** ** [[SQLITE_CONFIG_GETPCACHE2]] <dt>SQLITE_CONFIG_GETPCACHE2</dt> ** <dd> ^(The SQLITE_CONFIG_GETPCACHE2 option takes a single argument which -** is a pointer to an [sqlite3_pcache_methods2] object. SQLite copies off +** is a pointer to an [sqlite3_pcache_methods2] object. SQLite copies of ** the current page cache implementation into that object.)^ </dd> ** ** [[SQLITE_CONFIG_LOG]] <dt>SQLITE_CONFIG_LOG</dt> @@ -2371,7 +2351,7 @@ struct sqlite3_mem_methods { ** the logger function is a copy of the first parameter to the corresponding ** [sqlite3_log()] call and is intended to be a [result code] or an ** [extended result code]. ^The third parameter passed to the logger is -** a log message after formatting via [sqlite3_snprintf()]. +** log message after formatting via [sqlite3_snprintf()]. ** The SQLite logging interface is not reentrant; the logger function ** supplied by the application must not invoke any SQLite interface. ** In a multi-threaded application, the application-defined logger @@ -2562,7 +2542,7 @@ struct sqlite3_mem_methods { ** These constants are the available integer configuration options that ** can be passed as the second parameter to the [sqlite3_db_config()] interface. ** -** The [sqlite3_db_config()] interface is a var-args function. It takes a +** The [sqlite3_db_config()] interface is a var-args functions. It takes a ** variable number of parameters, though always at least two. The number of ** parameters passed into sqlite3_db_config() depends on which of these ** constants is given as the second parameter. This documentation page @@ -2674,20 +2654,17 @@ struct sqlite3_mem_methods { ** ** [[SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER]] ** <dt>SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER</dt> -** <dd> ^This option is used to enable or disable using the -** [fts3_tokenizer()] function - part of the [FTS3] full-text search engine -** extension - without using bound parameters as the parameters. Doing so -** is disabled by default. There must be two additional arguments. The first -** argument is an integer. If it is passed 0, then using fts3_tokenizer() -** without bound parameters is disabled. If it is passed a positive value, -** then calling fts3_tokenizer without bound parameters is enabled. If it -** is passed a negative value, this setting is not modified - this can be -** used to query for the current setting. The second parameter is a pointer -** to an integer into which is written 0 or 1 to indicate the current value -** of this setting (after it is modified, if applicable). The second -** parameter may be a NULL pointer, in which case the value of the setting -** is not reported back. Refer to [FTS3] documentation for further details. -** </dd> +** <dd> ^This option is used to enable or disable the +** [fts3_tokenizer()] function which is part of the +** [FTS3] full-text search engine extension. +** There must be two additional arguments. +** The first argument is an integer which is 0 to disable fts3_tokenizer() or +** positive to enable fts3_tokenizer() or negative to leave the setting +** unchanged. +** The second parameter is a pointer to an integer into which +** is written 0 or 1 to indicate whether fts3_tokenizer is disabled or enabled +** following this call. The second parameter may be a NULL pointer, in +** which case the new setting is not reported back. </dd> ** ** [[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION]] ** <dt>SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION</dt> @@ -2699,8 +2676,8 @@ struct sqlite3_mem_methods { ** When the first argument to this interface is 1, then only the C-API is ** enabled and the SQL function remains disabled. If the first argument to ** this interface is 0, then both the C-API and the SQL function are disabled. -** If the first argument is -1, then no changes are made to the state of either -** the C-API or the SQL function. +** If the first argument is -1, then no changes are made to state of either the +** C-API or the SQL function. ** The second parameter is a pointer to an integer into which ** is written 0 or 1 to indicate whether [sqlite3_load_extension()] interface ** is disabled or enabled following this call. The second parameter may @@ -2818,7 +2795,7 @@ struct sqlite3_mem_methods { ** [[SQLITE_DBCONFIG_LEGACY_ALTER_TABLE]] ** <dt>SQLITE_DBCONFIG_LEGACY_ALTER_TABLE</dt> ** <dd>The SQLITE_DBCONFIG_LEGACY_ALTER_TABLE option activates or deactivates -** the legacy behavior of the [ALTER TABLE RENAME] command such that it +** the legacy behavior of the [ALTER TABLE RENAME] command such it ** behaves as it did prior to [version 3.24.0] (2018-06-04). See the ** "Compatibility Notice" on the [ALTER TABLE RENAME documentation] for ** additional information. This feature can also be turned on and off @@ -2867,7 +2844,7 @@ struct sqlite3_mem_methods { ** <dt>SQLITE_DBCONFIG_LEGACY_FILE_FORMAT</dt> ** <dd>The SQLITE_DBCONFIG_LEGACY_FILE_FORMAT option activates or deactivates ** the legacy file format flag. When activated, this flag causes all newly -** created database files to have a schema format version number (the 4-byte +** created database file to have a schema format version number (the 4-byte ** integer found at offset 44 into the database header) of 1. This in turn ** means that the resulting database file will be readable and writable by ** any SQLite version back to 3.0.0 ([dateof:3.0.0]). Without this setting, @@ -2894,7 +2871,7 @@ struct sqlite3_mem_methods { ** the database handle both when the SQL statement is prepared and when it ** is stepped. The flag is set (collection of statistics is enabled) ** by default. <p>This option takes two arguments: an integer and a pointer to -** an integer. The first argument is 1, 0, or -1 to enable, disable, or +** an integer.. The first argument is 1, 0, or -1 to enable, disable, or ** leave unchanged the statement scanstatus option. If the second argument ** is not NULL, then the value of the statement scanstatus setting after ** processing the first argument is written into the integer that the second @@ -2937,8 +2914,8 @@ struct sqlite3_mem_methods { ** <dd>The SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE option enables or disables the ** ability of the [ATTACH DATABASE] SQL command to open a database for writing. ** This capability is enabled by default. Applications can disable or -** reenable this capability using the current DBCONFIG option. If -** this capability is disabled, the [ATTACH] command will still work, +** reenable this capability using the current DBCONFIG option. If the +** the this capability is disabled, the [ATTACH] command will still work, ** but the database will be opened read-only. If this option is disabled, ** then the ability to create a new database using [ATTACH] is also disabled, ** regardless of the value of the [SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE] @@ -2972,7 +2949,7 @@ struct sqlite3_mem_methods { ** ** <p>Most of the SQLITE_DBCONFIG options take two arguments, so that the ** overall call to [sqlite3_db_config()] has a total of four parameters. -** The first argument (the third parameter to sqlite3_db_config()) is an integer. +** The first argument (the third parameter to sqlite3_db_config()) is a integer. ** The second argument is a pointer to an integer. If the first argument is 1, ** then the option becomes enabled. If the first integer argument is 0, then the ** option is disabled. If the first argument is -1, then the option setting @@ -3262,7 +3239,7 @@ SQLITE_API int sqlite3_is_interrupted(sqlite3*); ** ^These routines return 0 if the statement is incomplete. ^If a ** memory allocation fails, then SQLITE_NOMEM is returned. ** -** ^These routines do not parse the SQL statements and thus +** ^These routines do not parse the SQL statements thus ** will not detect syntactically incorrect SQL. ** ** ^(If SQLite has not been initialized using [sqlite3_initialize()] prior @@ -3379,7 +3356,7 @@ SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms); ** indefinitely if possible. The results of passing any other negative value ** are undefined. ** -** Internally, each SQLite database handle stores two timeout values - the +** Internally, each SQLite database handle store two timeout values - the ** busy-timeout (used for rollback mode databases, or if the VFS does not ** support blocking locks) and the setlk-timeout (used for blocking locks ** on wal-mode databases). The sqlite3_busy_timeout() method sets both @@ -3409,7 +3386,7 @@ SQLITE_API int sqlite3_setlk_timeout(sqlite3*, int ms, int flags); ** This is a legacy interface that is preserved for backwards compatibility. ** Use of this interface is not recommended. ** -** Definition: A <b>result table</b> is a memory data structure created by the +** Definition: A <b>result table</b> is memory data structure created by the ** [sqlite3_get_table()] interface. A result table records the ** complete query results from one or more queries. ** @@ -3552,7 +3529,7 @@ SQLITE_API char *sqlite3_vsnprintf(int,char*,const char*, va_list); ** ^Calling sqlite3_free() with a pointer previously returned ** by sqlite3_malloc() or sqlite3_realloc() releases that memory so ** that it might be reused. ^The sqlite3_free() routine is -** a no-op if it is called with a NULL pointer. Passing a NULL pointer +** a no-op if is called with a NULL pointer. Passing a NULL pointer ** to sqlite3_free() is harmless. After being freed, memory ** should neither be read nor written. Even reading previously freed ** memory might result in a segmentation fault or other severe error. @@ -3570,13 +3547,13 @@ SQLITE_API char *sqlite3_vsnprintf(int,char*,const char*, va_list); ** sqlite3_free(X). ** ^sqlite3_realloc(X,N) returns a pointer to a memory allocation ** of at least N bytes in size or NULL if insufficient memory is available. -** ^If M is the size of the prior allocation, then min(N,M) bytes of the -** prior allocation are copied into the beginning of the buffer returned +** ^If M is the size of the prior allocation, then min(N,M) bytes +** of the prior allocation are copied into the beginning of buffer returned ** by sqlite3_realloc(X,N) and the prior allocation is freed. ** ^If sqlite3_realloc(X,N) returns NULL and N is positive, then the ** prior allocation is not freed. ** -** ^The sqlite3_realloc64(X,N) interface works the same as +** ^The sqlite3_realloc64(X,N) interfaces works the same as ** sqlite3_realloc(X,N) except that N is a 64-bit unsigned integer instead ** of a 32-bit signed integer. ** @@ -3626,7 +3603,7 @@ SQLITE_API sqlite3_uint64 sqlite3_msize(void*); ** was last reset. ^The values returned by [sqlite3_memory_used()] and ** [sqlite3_memory_highwater()] include any overhead ** added by SQLite in its implementation of [sqlite3_malloc()], -** but not overhead added by any underlying system library +** but not overhead added by the any underlying system library ** routines that [sqlite3_malloc()] may call. ** ** ^The memory high-water mark is reset to the current value of @@ -4078,7 +4055,7 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); ** there is no harm in trying.) ** ** ^(<dt>[SQLITE_OPEN_SHAREDCACHE]</dt> -** <dd>The database is opened with [shared cache] enabled, overriding +** <dd>The database is opened [shared cache] enabled, overriding ** the default shared cache setting provided by ** [sqlite3_enable_shared_cache()].)^ ** The [use of shared cache mode is discouraged] and hence shared cache @@ -4086,7 +4063,7 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); ** this option is a no-op. ** ** ^(<dt>[SQLITE_OPEN_PRIVATECACHE]</dt> -** <dd>The database is opened with [shared cache] disabled, overriding +** <dd>The database is opened [shared cache] disabled, overriding ** the default shared cache setting provided by ** [sqlite3_enable_shared_cache()].)^ ** @@ -4504,7 +4481,7 @@ SQLITE_API void sqlite3_free_filename(sqlite3_filename); ** subsequent calls to other SQLite interface functions.)^ ** ** ^The sqlite3_errstr(E) interface returns the English-language text -** that describes the [result code] E, as UTF-8, or NULL if E is not a +** that describes the [result code] E, as UTF-8, or NULL if E is not an ** result code for which a text error message is available. ** ^(Memory to hold the error message string is managed internally ** and must not be freed by the application)^. @@ -4512,7 +4489,7 @@ SQLITE_API void sqlite3_free_filename(sqlite3_filename); ** ^If the most recent error references a specific token in the input ** SQL, the sqlite3_error_offset() interface returns the byte offset ** of the start of that token. ^The byte offset returned by -** sqlite3_error_offset() assumes that the input SQL is UTF-8. +** sqlite3_error_offset() assumes that the input SQL is UTF8. ** ^If the most recent error does not reference a specific token in the input ** SQL, then the sqlite3_error_offset() function returns -1. ** @@ -4538,34 +4515,6 @@ SQLITE_API const char *sqlite3_errstr(int); SQLITE_API int sqlite3_error_offset(sqlite3 *db); /* -** CAPI3REF: Set Error Codes And Message -** METHOD: sqlite3 -** -** Set the error code of the database handle passed as the first argument -** to errcode, and the error message to a copy of nul-terminated string -** zErrMsg. If zErrMsg is passed NULL, then the error message is set to -** the default message associated with the supplied error code. Subsequent -** calls to [sqlite3_errcode()] and [sqlite3_errmsg()] and similar will -** return the values set by this routine in place of what was previously -** set by SQLite itself. -** -** This function returns SQLITE_OK if the error code and error message are -** successfully set, SQLITE_NOMEM if an OOM occurs, and SQLITE_MISUSE if -** the database handle is NULL or invalid. -** -** The error code and message set by this routine remains in effect until -** they are changed, either by another call to this routine or until they are -** changed to by SQLite itself to reflect the result of some subsquent -** API call. -** -** This function is intended for use by SQLite extensions or wrappers. The -** idea is that an extension or wrapper can use this routine to set error -** messages and error codes and thus behave more like a core SQLite -** feature from the point of view of an application. -*/ -SQLITE_API int sqlite3_set_errmsg(sqlite3 *db, int errcode, const char *zErrMsg); - -/* ** CAPI3REF: Prepared Statement Object ** KEYWORDS: {prepared statement} {prepared statements} ** @@ -4639,8 +4588,8 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); ** ** These constants define various performance limits ** that can be lowered at run-time using [sqlite3_limit()]. -** A concise description of these limits follows, and additional information -** is available at [limits | Limits in SQLite]. +** The synopsis of the meanings of the various limits is shown below. +** Additional information is available at [limits | Limits in SQLite]. ** ** <dl> ** [[SQLITE_LIMIT_LENGTH]] ^(<dt>SQLITE_LIMIT_LENGTH</dt> @@ -4705,7 +4654,7 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); /* ** CAPI3REF: Prepare Flags ** -** These constants define various flags that can be passed into the +** These constants define various flags that can be passed into ** "prepFlags" parameter of the [sqlite3_prepare_v3()] and ** [sqlite3_prepare16_v3()] interfaces. ** @@ -4792,7 +4741,7 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); ** there is a small performance advantage to passing an nByte parameter that ** is the number of bytes in the input string <i>including</i> ** the nul-terminator. -** Note that nByte measures the length of the input in bytes, not +** Note that nByte measure the length of the input in bytes, not ** characters, even for the UTF-16 interfaces. ** ** ^If pzTail is not NULL then *pzTail is made to point to the first byte @@ -4926,7 +4875,7 @@ SQLITE_API int sqlite3_prepare16_v3( ** ** ^The sqlite3_expanded_sql() interface returns NULL if insufficient memory ** is available to hold the result, or if the result would exceed the -** maximum string length determined by the [SQLITE_LIMIT_LENGTH]. +** the maximum string length determined by the [SQLITE_LIMIT_LENGTH]. ** ** ^The [SQLITE_TRACE_SIZE_LIMIT] compile-time option limits the size of ** bound parameter expansions. ^The [SQLITE_OMIT_TRACE] compile-time @@ -5114,7 +5063,7 @@ typedef struct sqlite3_value sqlite3_value; ** ** The context in which an SQL function executes is stored in an ** sqlite3_context object. ^A pointer to an sqlite3_context object -** is always the first parameter to [application-defined SQL functions]. +** is always first parameter to [application-defined SQL functions]. ** The application-defined SQL function implementation will pass this ** pointer through into calls to [sqlite3_result_int | sqlite3_result()], ** [sqlite3_aggregate_context()], [sqlite3_user_data()], @@ -5238,11 +5187,9 @@ typedef struct sqlite3_context sqlite3_context; ** associated with the pointer P of type T. ^D is either a NULL pointer or ** a pointer to a destructor function for P. ^SQLite will invoke the ** destructor D with a single argument of P when it is finished using -** P, even if the call to sqlite3_bind_pointer() fails. Due to a -** historical design quirk, results are undefined if D is -** SQLITE_TRANSIENT. The T parameter should be a static string, -** preferably a string literal. The sqlite3_bind_pointer() routine is -** part of the [pointer passing interface] added for SQLite 3.20.0. +** P. The T parameter should be a static string, preferably a string +** literal. The sqlite3_bind_pointer() routine is part of the +** [pointer passing interface] added for SQLite 3.20.0. ** ** ^If any of the sqlite3_bind_*() routines are called with a NULL pointer ** for the [prepared statement] or with a prepared statement for which @@ -5853,7 +5800,7 @@ SQLITE_API int sqlite3_column_type(sqlite3_stmt*, int iCol); ** ** ^The sqlite3_finalize() function is called to delete a [prepared statement]. ** ^If the most recent evaluation of the statement encountered no errors -** or if the statement has never been evaluated, then sqlite3_finalize() returns +** or if the statement is never been evaluated, then sqlite3_finalize() returns ** SQLITE_OK. ^If the most recent evaluation of statement S failed, then ** sqlite3_finalize(S) returns the appropriate [error code] or ** [extended error code]. @@ -6085,7 +6032,7 @@ SQLITE_API int sqlite3_create_window_function( /* ** CAPI3REF: Text Encodings ** -** These constants define integer codes that represent the various +** These constant define integer codes that represent the various ** text encodings supported by SQLite. */ #define SQLITE_UTF8 1 /* IMP: R-37514-35566 */ @@ -6177,7 +6124,7 @@ SQLITE_API int sqlite3_create_window_function( ** result. ** Every function that invokes [sqlite3_result_subtype()] should have this ** property. If it does not, then the call to [sqlite3_result_subtype()] -** might become a no-op if the function is used as a term in an +** might become a no-op if the function is used as term in an ** [expression index]. On the other hand, SQL functions that never invoke ** [sqlite3_result_subtype()] should avoid setting this property, as the ** purpose of this property is to disable certain optimizations that are @@ -6304,7 +6251,7 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6 ** sqlite3_value_nochange(X) interface returns true if and only if ** the column corresponding to X is unchanged by the UPDATE operation ** that the xUpdate method call was invoked to implement and if -** the prior [xColumn] method call that was invoked to extract +** and the prior [xColumn] method call that was invoked to extracted ** the value for that column returned without setting a result (probably ** because it queried [sqlite3_vtab_nochange()] and found that the column ** was unchanging). ^Within an [xUpdate] method, any value for which @@ -6577,7 +6524,6 @@ SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(voi ** or a NULL pointer if there were no prior calls to ** sqlite3_set_clientdata() with the same values of D and N. ** Names are compared using strcmp() and are thus case sensitive. -** It returns 0 on success and SQLITE_NOMEM on allocation failure. ** ** If P and X are both non-NULL, then the destructor X is invoked with ** argument P on the first of the following occurrences: @@ -9254,18 +9200,9 @@ SQLITE_API int sqlite3_status64( ** ^The sqlite3_db_status() routine returns SQLITE_OK on success and a ** non-zero [error code] on failure. ** -** ^The sqlite3_db_status64(D,O,C,H,R) routine works exactly the same -** way as sqlite3_db_status(D,O,C,H,R) routine except that the C and H -** parameters are pointer to 64-bit integers (type: sqlite3_int64) instead -** of pointers to 32-bit integers, which allows larger status values -** to be returned. If a status value exceeds 2,147,483,647 then -** sqlite3_db_status() will truncate the value whereas sqlite3_db_status64() -** will return the full value. -** ** See also: [sqlite3_status()] and [sqlite3_stmt_status()]. */ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg); -SQLITE_API int sqlite3_db_status64(sqlite3*,int,sqlite3_int64*,sqlite3_int64*,int); /* ** CAPI3REF: Status Parameters for database connections @@ -9362,10 +9299,6 @@ SQLITE_API int sqlite3_db_status64(sqlite3*,int,sqlite3_int64*,sqlite3_int64*,in ** If an IO or other error occurs while writing a page to disk, the effect ** on subsequent SQLITE_DBSTATUS_CACHE_WRITE requests is undefined.)^ ^The ** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0. -** <p> -** ^(There is overlap between the quantities measured by this parameter -** (SQLITE_DBSTATUS_CACHE_WRITE) and SQLITE_DBSTATUS_TEMPBUF_SPILL. -** Resetting one will reduce the other.)^ ** </dd> ** ** [[SQLITE_DBSTATUS_CACHE_SPILL]] ^(<dt>SQLITE_DBSTATUS_CACHE_SPILL</dt> @@ -9381,18 +9314,6 @@ SQLITE_API int sqlite3_db_status64(sqlite3*,int,sqlite3_int64*,sqlite3_int64*,in ** <dd>This parameter returns zero for the current value if and only if ** all foreign key constraints (deferred or immediate) have been ** resolved.)^ ^The highwater mark is always 0. -** -** [[SQLITE_DBSTATUS_TEMPBUF_SPILL] ^(<dt>SQLITE_DBSTATUS_TEMPBUF_SPILL</dt> -** <dd>^(This parameter returns the number of bytes written to temporary -** files on disk that could have been kept in memory had sufficient memory -** been available. This value includes writes to intermediate tables that -** are part of complex queries, external sorts that spill to disk, and -** writes to TEMP tables.)^ -** ^The highwater mark is always 0. -** <p> -** ^(There is overlap between the quantities measured by this parameter -** (SQLITE_DBSTATUS_TEMPBUF_SPILL) and SQLITE_DBSTATUS_CACHE_WRITE. -** Resetting one will reduce the other.)^ ** </dd> ** </dl> */ @@ -9409,8 +9330,7 @@ SQLITE_API int sqlite3_db_status64(sqlite3*,int,sqlite3_int64*,sqlite3_int64*,in #define SQLITE_DBSTATUS_DEFERRED_FKS 10 #define SQLITE_DBSTATUS_CACHE_USED_SHARED 11 #define SQLITE_DBSTATUS_CACHE_SPILL 12 -#define SQLITE_DBSTATUS_TEMPBUF_SPILL 13 -#define SQLITE_DBSTATUS_MAX 13 /* Largest defined DBSTATUS */ +#define SQLITE_DBSTATUS_MAX 12 /* Largest defined DBSTATUS */ /* @@ -10175,7 +10095,7 @@ SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...); ** is the number of pages currently in the write-ahead log file, ** including those that were just committed. ** -** ^The callback function should normally return [SQLITE_OK]. ^If an error +** The callback function should normally return [SQLITE_OK]. ^If an error ** code is returned, that error will propagate back up through the ** SQLite code base to cause the statement that provoked the callback ** to report an error, though the commit will have still occurred. If the @@ -10183,26 +10103,13 @@ SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...); ** that does not correspond to any valid SQLite error code, the results ** are undefined. ** -** ^A single database handle may have at most a single write-ahead log -** callback registered at one time. ^Calling [sqlite3_wal_hook()] -** replaces the default behavior or previously registered write-ahead -** log callback. -** -** ^The return value is a copy of the third parameter from the -** previous call, if any, or 0. -** -** ^The [sqlite3_wal_autocheckpoint()] interface and the -** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and -** will overwrite any prior [sqlite3_wal_hook()] settings. -** -** ^If a write-ahead log callback is set using this function then -** [sqlite3_wal_checkpoint_v2()] or [PRAGMA wal_checkpoint] -** should be invoked periodically to keep the write-ahead log file -** from growing without bound. -** -** ^Passing a NULL pointer for the callback disables automatic -** checkpointing entirely. To re-enable the default behavior, call -** sqlite3_wal_autocheckpoint(db,1000) or use [PRAGMA wal_checkpoint]. +** A single database handle may have at most a single write-ahead log callback +** registered at one time. ^Calling [sqlite3_wal_hook()] replaces any +** previously registered write-ahead log callback. ^The return value is +** a copy of the third parameter from the previous call, if any, or 0. +** ^Note that the [sqlite3_wal_autocheckpoint()] interface and the +** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and will +** overwrite any prior [sqlite3_wal_hook()] settings. */ SQLITE_API void *sqlite3_wal_hook( sqlite3*, @@ -10219,7 +10126,7 @@ SQLITE_API void *sqlite3_wal_hook( ** to automatically [checkpoint] ** after committing a transaction if there are N or ** more frames in the [write-ahead log] file. ^Passing zero or -** a negative value as the N parameter disables automatic +** a negative value as the nFrame parameter disables automatic ** checkpoints entirely. ** ** ^The callback registered by this function replaces any existing callback @@ -10235,10 +10142,9 @@ SQLITE_API void *sqlite3_wal_hook( ** ** ^Every new [database connection] defaults to having the auto-checkpoint ** enabled with a threshold of 1000 or [SQLITE_DEFAULT_WAL_AUTOCHECKPOINT] -** pages. -** -** ^The use of this interface is only necessary if the default setting -** is found to be suboptimal for a particular application. +** pages. The use of this interface +** is only necessary if the default setting is found to be suboptimal +** for a particular application. */ SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N); @@ -10303,11 +10209,6 @@ SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb); ** ^This mode works the same way as SQLITE_CHECKPOINT_RESTART with the ** addition that it also truncates the log file to zero bytes just prior ** to a successful return. -** -** <dt>SQLITE_CHECKPOINT_NOOP<dd> -** ^This mode always checkpoints zero frames. The only reason to invoke -** a NOOP checkpoint is to access the values returned by -** sqlite3_wal_checkpoint_v2() via output parameters *pnLog and *pnCkpt. ** </dl> ** ** ^If pnLog is not NULL, then *pnLog is set to the total number of frames in @@ -10378,7 +10279,6 @@ SQLITE_API int sqlite3_wal_checkpoint_v2( ** See the [sqlite3_wal_checkpoint_v2()] documentation for details on the ** meaning of each of these checkpoint modes. */ -#define SQLITE_CHECKPOINT_NOOP -1 /* Do no work at all */ #define SQLITE_CHECKPOINT_PASSIVE 0 /* Do as much as possible w/o blocking */ #define SQLITE_CHECKPOINT_FULL 1 /* Wait for writers, then checkpoint */ #define SQLITE_CHECKPOINT_RESTART 2 /* Like FULL but wait for readers */ @@ -11206,7 +11106,7 @@ typedef struct sqlite3_snapshot { ** The [sqlite3_snapshot_get()] interface is only available when the ** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used. */ -SQLITE_API int sqlite3_snapshot_get( +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_get( sqlite3 *db, const char *zSchema, sqlite3_snapshot **ppSnapshot @@ -11255,7 +11155,7 @@ SQLITE_API int sqlite3_snapshot_get( ** The [sqlite3_snapshot_open()] interface is only available when the ** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used. */ -SQLITE_API int sqlite3_snapshot_open( +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_open( sqlite3 *db, const char *zSchema, sqlite3_snapshot *pSnapshot @@ -11272,7 +11172,7 @@ SQLITE_API int sqlite3_snapshot_open( ** The [sqlite3_snapshot_free()] interface is only available when the ** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used. */ -SQLITE_API void sqlite3_snapshot_free(sqlite3_snapshot*); +SQLITE_API SQLITE_EXPERIMENTAL void sqlite3_snapshot_free(sqlite3_snapshot*); /* ** CAPI3REF: Compare the ages of two snapshot handles. @@ -11299,7 +11199,7 @@ SQLITE_API void sqlite3_snapshot_free(sqlite3_snapshot*); ** This interface is only available if SQLite is compiled with the ** [SQLITE_ENABLE_SNAPSHOT] option. */ -SQLITE_API int sqlite3_snapshot_cmp( +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp( sqlite3_snapshot *p1, sqlite3_snapshot *p2 ); @@ -11327,7 +11227,7 @@ SQLITE_API int sqlite3_snapshot_cmp( ** This interface is only available if SQLite is compiled with the ** [SQLITE_ENABLE_SNAPSHOT] option. */ -SQLITE_API int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb); +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb); /* ** CAPI3REF: Serialize a database @@ -11401,13 +11301,12 @@ SQLITE_API unsigned char *sqlite3_serialize( ** ** The sqlite3_deserialize(D,S,P,N,M,F) interface causes the ** [database connection] D to disconnect from database S and then -** reopen S as an in-memory database based on the serialization -** contained in P. If S is a NULL pointer, the main database is -** used. The serialized database P is N bytes in size. M is the size -** of the buffer P, which might be larger than N. If M is larger than -** N, and the SQLITE_DESERIALIZE_READONLY bit is not set in F, then -** SQLite is permitted to add content to the in-memory database as -** long as the total size does not exceed M bytes. +** reopen S as an in-memory database based on the serialization contained +** in P. The serialized database P is N bytes in size. M is the size of +** the buffer P, which might be larger than N. If M is larger than N, and +** the SQLITE_DESERIALIZE_READONLY bit is not set in F, then SQLite is +** permitted to add content to the in-memory database as long as the total +** size does not exceed M bytes. ** ** If the SQLITE_DESERIALIZE_FREEONCLOSE bit is set in F, then SQLite will ** invoke sqlite3_free() on the serialization buffer when the database @@ -11475,54 +11374,6 @@ SQLITE_API int sqlite3_deserialize( #define SQLITE_DESERIALIZE_READONLY 4 /* Database is read-only */ /* -** CAPI3REF: Bind array values to the CARRAY table-valued function -** -** The sqlite3_carray_bind(S,I,P,N,F,X) interface binds an array value to -** one of the first argument of the [carray() table-valued function]. The -** S parameter is a pointer to the [prepared statement] that uses the carray() -** functions. I is the parameter index to be bound. P is a pointer to the -** array to be bound, and N is the number of eements in the array. The -** F argument is one of constants [SQLITE_CARRAY_INT32], [SQLITE_CARRAY_INT64], -** [SQLITE_CARRAY_DOUBLE], [SQLITE_CARRAY_TEXT], or [SQLITE_CARRAY_BLOB] to -** indicate the datatype of the array being bound. The X argument is not a -** NULL pointer, then SQLite will invoke the function X on the P parameter -** after it has finished using P, even if the call to -** sqlite3_carray_bind() fails. The special-case finalizer -** SQLITE_TRANSIENT has no effect here. -*/ -SQLITE_API int sqlite3_carray_bind( - sqlite3_stmt *pStmt, /* Statement to be bound */ - int i, /* Parameter index */ - void *aData, /* Pointer to array data */ - int nData, /* Number of data elements */ - int mFlags, /* CARRAY flags */ - void (*xDel)(void*) /* Destructor for aData */ -); - -/* -** CAPI3REF: Datatypes for the CARRAY table-valued function -** -** The fifth argument to the [sqlite3_carray_bind()] interface musts be -** one of the following constants, to specify the datatype of the array -** that is being bound into the [carray table-valued function]. -*/ -#define SQLITE_CARRAY_INT32 0 /* Data is 32-bit signed integers */ -#define SQLITE_CARRAY_INT64 1 /* Data is 64-bit signed integers */ -#define SQLITE_CARRAY_DOUBLE 2 /* Data is doubles */ -#define SQLITE_CARRAY_TEXT 3 /* Data is char* */ -#define SQLITE_CARRAY_BLOB 4 /* Data is struct iovec */ - -/* -** Versions of the above #defines that omit the initial SQLITE_, for -** legacy compatibility. -*/ -#define CARRAY_INT32 0 /* Data is 32-bit signed integers */ -#define CARRAY_INT64 1 /* Data is 64-bit signed integers */ -#define CARRAY_DOUBLE 2 /* Data is doubles */ -#define CARRAY_TEXT 3 /* Data is char* */ -#define CARRAY_BLOB 4 /* Data is struct iovec */ - -/* ** Undo the hack that converts floating point types to integer for ** builds on processors without floating point support. */ @@ -12781,32 +12632,14 @@ SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*); ** update the "main" database attached to handle db with the changes found in ** the changeset passed via the second and third arguments. ** -** All changes made by these functions are enclosed in a savepoint transaction. -** If any other error (aside from a constraint failure when attempting to -** write to the target database) occurs, then the savepoint transaction is -** rolled back, restoring the target database to its original state, and an -** SQLite error code returned. Additionally, starting with version 3.51.0, -** an error code and error message that may be accessed using the -** [sqlite3_errcode()] and [sqlite3_errmsg()] APIs are left in the database -** handle. -** ** The fourth argument (xFilter) passed to these functions is the "filter -** callback". This may be passed NULL, in which case all changes in the -** changeset are applied to the database. For sqlite3changeset_apply() and -** sqlite3_changeset_apply_v2(), if it is not NULL, then it is invoked once -** for each table affected by at least one change in the changeset. In this -** case the table name is passed as the second argument, and a copy of -** the context pointer passed as the sixth argument to apply() or apply_v2() -** as the first. If the "filter callback" returns zero, then no attempt is -** made to apply any changes to the table. Otherwise, if the return value is -** non-zero, all changes related to the table are attempted. -** -** For sqlite3_changeset_apply_v3(), the xFilter callback is invoked once -** per change. The second argument in this case is an sqlite3_changeset_iter -** that may be queried using the usual APIs for the details of the current -** change. If the "filter callback" returns zero in this case, then no attempt -** is made to apply the current change. If it returns non-zero, the change -** is applied. +** callback". If it is not NULL, then for each table affected by at least one +** change in the changeset, the filter callback is invoked with +** the table name as the second argument, and a copy of the context pointer +** passed as the sixth argument as the first. If the "filter callback" +** returns zero, then no attempt is made to apply any changes to the table. +** Otherwise, if the return value is non-zero or the xFilter argument to +** is NULL, all changes related to the table are attempted. ** ** For each table that is not excluded by the filter callback, this function ** tests that the target database contains a compatible table. A table is @@ -12827,11 +12660,11 @@ SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*); ** one such warning is issued for each table in the changeset. ** ** For each change for which there is a compatible table, an attempt is made -** to modify the table contents according to each UPDATE, INSERT or DELETE -** change that is not excluded by a filter callback. If a change cannot be -** applied cleanly, the conflict handler function passed as the fifth argument -** to sqlite3changeset_apply() may be invoked. A description of exactly when -** the conflict handler is invoked for each type of change is below. +** to modify the table contents according to the UPDATE, INSERT or DELETE +** change. If a change cannot be applied cleanly, the conflict handler +** function passed as the fifth argument to sqlite3changeset_apply() may be +** invoked. A description of exactly when the conflict handler is invoked for +** each type of change is below. ** ** Unlike the xFilter argument, xConflict may not be passed NULL. The results ** of passing anything other than a valid function pointer as the xConflict @@ -12927,6 +12760,12 @@ SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*); ** This can be used to further customize the application's conflict ** resolution strategy. ** +** All changes made by these functions are enclosed in a savepoint transaction. +** If any other error (aside from a constraint failure when attempting to +** write to the target database) occurs, then the savepoint transaction is +** rolled back, restoring the target database to its original state, and an +** SQLite error code returned. +** ** If the output parameters (ppRebase) and (pnRebase) are non-NULL and ** the input is a changeset (not a patchset), then sqlite3changeset_apply_v2() ** may set (*ppRebase) to point to a "rebase" that may be used with the @@ -12976,23 +12815,6 @@ SQLITE_API int sqlite3changeset_apply_v2( void **ppRebase, int *pnRebase, /* OUT: Rebase data */ int flags /* SESSION_CHANGESETAPPLY_* flags */ ); -SQLITE_API int sqlite3changeset_apply_v3( - sqlite3 *db, /* Apply change to "main" db of this handle */ - int nChangeset, /* Size of changeset in bytes */ - void *pChangeset, /* Changeset blob */ - int(*xFilter)( - void *pCtx, /* Copy of sixth arg to _apply() */ - sqlite3_changeset_iter *p /* Handle describing change */ - ), - int(*xConflict)( - void *pCtx, /* Copy of sixth arg to _apply() */ - int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ - sqlite3_changeset_iter *p /* Handle describing change and conflict */ - ), - void *pCtx, /* First argument passed to xConflict */ - void **ppRebase, int *pnRebase, /* OUT: Rebase data */ - int flags /* SESSION_CHANGESETAPPLY_* flags */ -); /* ** CAPI3REF: Flags for sqlite3changeset_apply_v2 @@ -13412,23 +13234,6 @@ SQLITE_API int sqlite3changeset_apply_v2_strm( void **ppRebase, int *pnRebase, int flags ); -SQLITE_API int sqlite3changeset_apply_v3_strm( - sqlite3 *db, /* Apply change to "main" db of this handle */ - int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */ - void *pIn, /* First arg for xInput */ - int(*xFilter)( - void *pCtx, /* Copy of sixth arg to _apply() */ - sqlite3_changeset_iter *p - ), - int(*xConflict)( - void *pCtx, /* Copy of sixth arg to _apply() */ - int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ - sqlite3_changeset_iter *p /* Handle describing change and conflict */ - ), - void *pCtx, /* First argument passed to xConflict */ - void **ppRebase, int *pnRebase, - int flags -); SQLITE_API int sqlite3changeset_concat_strm( int (*xInputA)(void *pIn, void *pData, int *pnData), void *pInA, @@ -14505,7 +14310,7 @@ struct fts5_api { ** Maximum number of pages in one database file. ** ** This is really just the default value for the max_page_count pragma. -** This value can be lowered (or raised) at run-time using the +** This value can be lowered (or raised) at run-time using that the ** max_page_count macro. */ #ifndef SQLITE_MAX_PAGE_COUNT @@ -15373,7 +15178,7 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*); ** ourselves. */ #ifndef offsetof -# define offsetof(ST,M) ((size_t)((char*)&((ST*)0)->M - (char*)0)) +#define offsetof(STRUCTURE,FIELD) ((size_t)((char*)&((STRUCTURE*)0)->FIELD)) #endif /* @@ -15761,8 +15566,6 @@ SQLITE_PRIVATE u32 sqlite3TreeTrace; ** 0x00020000 Transform DISTINCT into GROUP BY ** 0x00040000 SELECT tree dump after all code has been generated ** 0x00080000 NOT NULL strength reduction -** 0x00100000 Pointers are all shown as zero -** 0x00200000 EXISTS-to-JOIN optimization */ /* @@ -15807,7 +15610,6 @@ SQLITE_PRIVATE u32 sqlite3WhereTrace; ** 0x00020000 Show WHERE terms returned from whereScanNext() ** 0x00040000 Solver overview messages ** 0x00080000 Star-query heuristic -** 0x00100000 Pointers are all shown as zero */ @@ -15880,7 +15682,7 @@ struct BusyHandler { ** pointer will work here as long as it is distinct from SQLITE_STATIC ** and SQLITE_TRANSIENT. */ -#define SQLITE_DYNAMIC ((sqlite3_destructor_type)sqlite3RowSetClear) +#define SQLITE_DYNAMIC ((sqlite3_destructor_type)sqlite3OomClear) /* ** When SQLITE_OMIT_WSD is defined, it means that the target platform does @@ -16101,8 +15903,8 @@ typedef int VList; ** must provide its own VFS implementation together with sqlite3_os_init() ** and sqlite3_os_end() routines. */ -#if SQLITE_OS_KV+1<=1 && SQLITE_OS_OTHER+1<=1 && \ - SQLITE_OS_WIN+1<=1 && SQLITE_OS_UNIX+1<=1 +#if !defined(SQLITE_OS_KV) && !defined(SQLITE_OS_OTHER) && \ + !defined(SQLITE_OS_UNIX) && !defined(SQLITE_OS_WIN) # if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || \ defined(__MINGW32__) || defined(__BORLANDC__) # define SQLITE_OS_WIN 1 @@ -16948,7 +16750,6 @@ struct BtreePayload { SQLITE_PRIVATE int sqlite3BtreeInsert(BtCursor*, const BtreePayload *pPayload, int flags, int seekResult); SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor*, int *pRes); -SQLITE_PRIVATE int sqlite3BtreeIsEmpty(BtCursor *pCur, int *pRes); SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor*, int *pRes); SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor*, int flags); SQLITE_PRIVATE int sqlite3BtreeEof(BtCursor*); @@ -17282,20 +17083,20 @@ typedef struct VdbeOpList VdbeOpList; #define OP_SorterSort 34 /* jump */ #define OP_Sort 35 /* jump */ #define OP_Rewind 36 /* jump0 */ -#define OP_IfEmpty 37 /* jump, synopsis: if( empty(P1) ) goto P2 */ -#define OP_SorterNext 38 /* jump */ -#define OP_Prev 39 /* jump */ -#define OP_Next 40 /* jump */ -#define OP_IdxLE 41 /* jump, synopsis: key=r[P3@P4] */ -#define OP_IdxGT 42 /* jump, synopsis: key=r[P3@P4] */ +#define OP_SorterNext 37 /* jump */ +#define OP_Prev 38 /* jump */ +#define OP_Next 39 /* jump */ +#define OP_IdxLE 40 /* jump, synopsis: key=r[P3@P4] */ +#define OP_IdxGT 41 /* jump, synopsis: key=r[P3@P4] */ +#define OP_IdxLT 42 /* jump, synopsis: key=r[P3@P4] */ #define OP_Or 43 /* same as TK_OR, synopsis: r[P3]=(r[P1] || r[P2]) */ #define OP_And 44 /* same as TK_AND, synopsis: r[P3]=(r[P1] && r[P2]) */ -#define OP_IdxLT 45 /* jump, synopsis: key=r[P3@P4] */ -#define OP_IdxGE 46 /* jump, synopsis: key=r[P3@P4] */ -#define OP_RowSetRead 47 /* jump, synopsis: r[P3]=rowset(P1) */ -#define OP_RowSetTest 48 /* jump, synopsis: if r[P3] in rowset(P1) goto P2 */ -#define OP_Program 49 /* jump0 */ -#define OP_FkIfZero 50 /* jump, synopsis: if fkctr[P1]==0 goto P2 */ +#define OP_IdxGE 45 /* jump, synopsis: key=r[P3@P4] */ +#define OP_RowSetRead 46 /* jump, synopsis: r[P3]=rowset(P1) */ +#define OP_RowSetTest 47 /* jump, synopsis: if r[P3] in rowset(P1) goto P2 */ +#define OP_Program 48 /* jump0 */ +#define OP_FkIfZero 49 /* jump, synopsis: if fkctr[P1]==0 goto P2 */ +#define OP_IfPos 50 /* jump, synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */ #define OP_IsNull 51 /* jump, same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */ #define OP_NotNull 52 /* jump, same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */ #define OP_Ne 53 /* jump, same as TK_NE, synopsis: IF r[P3]!=r[P1] */ @@ -17305,49 +17106,49 @@ typedef struct VdbeOpList VdbeOpList; #define OP_Lt 57 /* jump, same as TK_LT, synopsis: IF r[P3]<r[P1] */ #define OP_Ge 58 /* jump, same as TK_GE, synopsis: IF r[P3]>=r[P1] */ #define OP_ElseEq 59 /* jump, same as TK_ESCAPE */ -#define OP_IfPos 60 /* jump, synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */ -#define OP_IfNotZero 61 /* jump, synopsis: if r[P1]!=0 then r[P1]--, goto P2 */ -#define OP_DecrJumpZero 62 /* jump, synopsis: if (--r[P1])==0 goto P2 */ -#define OP_IncrVacuum 63 /* jump */ -#define OP_VNext 64 /* jump */ -#define OP_Filter 65 /* jump, synopsis: if key(P3@P4) not in filter(P1) goto P2 */ -#define OP_PureFunc 66 /* synopsis: r[P3]=func(r[P2@NP]) */ -#define OP_Function 67 /* synopsis: r[P3]=func(r[P2@NP]) */ -#define OP_Return 68 -#define OP_EndCoroutine 69 -#define OP_HaltIfNull 70 /* synopsis: if r[P3]=null halt */ -#define OP_Halt 71 -#define OP_Integer 72 /* synopsis: r[P2]=P1 */ -#define OP_Int64 73 /* synopsis: r[P2]=P4 */ -#define OP_String 74 /* synopsis: r[P2]='P4' (len=P1) */ -#define OP_BeginSubrtn 75 /* synopsis: r[P2]=NULL */ -#define OP_Null 76 /* synopsis: r[P2..P3]=NULL */ -#define OP_SoftNull 77 /* synopsis: r[P1]=NULL */ -#define OP_Blob 78 /* synopsis: r[P2]=P4 (len=P1) */ -#define OP_Variable 79 /* synopsis: r[P2]=parameter(P1) */ -#define OP_Move 80 /* synopsis: r[P2@P3]=r[P1@P3] */ -#define OP_Copy 81 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */ -#define OP_SCopy 82 /* synopsis: r[P2]=r[P1] */ -#define OP_IntCopy 83 /* synopsis: r[P2]=r[P1] */ -#define OP_FkCheck 84 -#define OP_ResultRow 85 /* synopsis: output=r[P1@P2] */ -#define OP_CollSeq 86 -#define OP_AddImm 87 /* synopsis: r[P1]=r[P1]+P2 */ -#define OP_RealAffinity 88 -#define OP_Cast 89 /* synopsis: affinity(r[P1]) */ -#define OP_Permutation 90 -#define OP_Compare 91 /* synopsis: r[P1@P3] <-> r[P2@P3] */ -#define OP_IsTrue 92 /* synopsis: r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4 */ -#define OP_ZeroOrNull 93 /* synopsis: r[P2] = 0 OR NULL */ -#define OP_Offset 94 /* synopsis: r[P3] = sqlite_offset(P1) */ -#define OP_Column 95 /* synopsis: r[P3]=PX cursor P1 column P2 */ -#define OP_TypeCheck 96 /* synopsis: typecheck(r[P1@P2]) */ -#define OP_Affinity 97 /* synopsis: affinity(r[P1@P2]) */ -#define OP_MakeRecord 98 /* synopsis: r[P3]=mkrec(r[P1@P2]) */ -#define OP_Count 99 /* synopsis: r[P2]=count() */ -#define OP_ReadCookie 100 -#define OP_SetCookie 101 -#define OP_ReopenIdx 102 /* synopsis: root=P2 iDb=P3 */ +#define OP_IfNotZero 60 /* jump, synopsis: if r[P1]!=0 then r[P1]--, goto P2 */ +#define OP_DecrJumpZero 61 /* jump, synopsis: if (--r[P1])==0 goto P2 */ +#define OP_IncrVacuum 62 /* jump */ +#define OP_VNext 63 /* jump */ +#define OP_Filter 64 /* jump, synopsis: if key(P3@P4) not in filter(P1) goto P2 */ +#define OP_PureFunc 65 /* synopsis: r[P3]=func(r[P2@NP]) */ +#define OP_Function 66 /* synopsis: r[P3]=func(r[P2@NP]) */ +#define OP_Return 67 +#define OP_EndCoroutine 68 +#define OP_HaltIfNull 69 /* synopsis: if r[P3]=null halt */ +#define OP_Halt 70 +#define OP_Integer 71 /* synopsis: r[P2]=P1 */ +#define OP_Int64 72 /* synopsis: r[P2]=P4 */ +#define OP_String 73 /* synopsis: r[P2]='P4' (len=P1) */ +#define OP_BeginSubrtn 74 /* synopsis: r[P2]=NULL */ +#define OP_Null 75 /* synopsis: r[P2..P3]=NULL */ +#define OP_SoftNull 76 /* synopsis: r[P1]=NULL */ +#define OP_Blob 77 /* synopsis: r[P2]=P4 (len=P1) */ +#define OP_Variable 78 /* synopsis: r[P2]=parameter(P1) */ +#define OP_Move 79 /* synopsis: r[P2@P3]=r[P1@P3] */ +#define OP_Copy 80 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */ +#define OP_SCopy 81 /* synopsis: r[P2]=r[P1] */ +#define OP_IntCopy 82 /* synopsis: r[P2]=r[P1] */ +#define OP_FkCheck 83 +#define OP_ResultRow 84 /* synopsis: output=r[P1@P2] */ +#define OP_CollSeq 85 +#define OP_AddImm 86 /* synopsis: r[P1]=r[P1]+P2 */ +#define OP_RealAffinity 87 +#define OP_Cast 88 /* synopsis: affinity(r[P1]) */ +#define OP_Permutation 89 +#define OP_Compare 90 /* synopsis: r[P1@P3] <-> r[P2@P3] */ +#define OP_IsTrue 91 /* synopsis: r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4 */ +#define OP_ZeroOrNull 92 /* synopsis: r[P2] = 0 OR NULL */ +#define OP_Offset 93 /* synopsis: r[P3] = sqlite_offset(P1) */ +#define OP_Column 94 /* synopsis: r[P3]=PX cursor P1 column P2 */ +#define OP_TypeCheck 95 /* synopsis: typecheck(r[P1@P2]) */ +#define OP_Affinity 96 /* synopsis: affinity(r[P1@P2]) */ +#define OP_MakeRecord 97 /* synopsis: r[P3]=mkrec(r[P1@P2]) */ +#define OP_Count 98 /* synopsis: r[P2]=count() */ +#define OP_ReadCookie 99 +#define OP_SetCookie 100 +#define OP_ReopenIdx 101 /* synopsis: root=P2 iDb=P3 */ +#define OP_OpenRead 102 /* synopsis: root=P2 iDb=P3 */ #define OP_BitAnd 103 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */ #define OP_BitOr 104 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */ #define OP_ShiftLeft 105 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<<r[P1] */ @@ -17358,84 +17159,83 @@ typedef struct VdbeOpList VdbeOpList; #define OP_Divide 110 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */ #define OP_Remainder 111 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */ #define OP_Concat 112 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */ -#define OP_OpenRead 113 /* synopsis: root=P2 iDb=P3 */ -#define OP_OpenWrite 114 /* synopsis: root=P2 iDb=P3 */ +#define OP_OpenWrite 113 /* synopsis: root=P2 iDb=P3 */ +#define OP_OpenDup 114 #define OP_BitNot 115 /* same as TK_BITNOT, synopsis: r[P2]= ~r[P1] */ -#define OP_OpenDup 116 -#define OP_OpenAutoindex 117 /* synopsis: nColumn=P2 */ +#define OP_OpenAutoindex 116 /* synopsis: nColumn=P2 */ +#define OP_OpenEphemeral 117 /* synopsis: nColumn=P2 */ #define OP_String8 118 /* same as TK_STRING, synopsis: r[P2]='P4' */ -#define OP_OpenEphemeral 119 /* synopsis: nColumn=P2 */ -#define OP_SorterOpen 120 -#define OP_SequenceTest 121 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */ -#define OP_OpenPseudo 122 /* synopsis: P3 columns in r[P2] */ -#define OP_Close 123 -#define OP_ColumnsUsed 124 -#define OP_SeekScan 125 /* synopsis: Scan-ahead up to P1 rows */ -#define OP_SeekHit 126 /* synopsis: set P2<=seekHit<=P3 */ -#define OP_Sequence 127 /* synopsis: r[P2]=cursor[P1].ctr++ */ -#define OP_NewRowid 128 /* synopsis: r[P2]=rowid */ -#define OP_Insert 129 /* synopsis: intkey=r[P3] data=r[P2] */ -#define OP_RowCell 130 -#define OP_Delete 131 -#define OP_ResetCount 132 -#define OP_SorterCompare 133 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */ -#define OP_SorterData 134 /* synopsis: r[P2]=data */ -#define OP_RowData 135 /* synopsis: r[P2]=data */ -#define OP_Rowid 136 /* synopsis: r[P2]=PX rowid of P1 */ -#define OP_NullRow 137 -#define OP_SeekEnd 138 -#define OP_IdxInsert 139 /* synopsis: key=r[P2] */ -#define OP_SorterInsert 140 /* synopsis: key=r[P2] */ -#define OP_IdxDelete 141 /* synopsis: key=r[P2@P3] */ -#define OP_DeferredSeek 142 /* synopsis: Move P3 to P1.rowid if needed */ -#define OP_IdxRowid 143 /* synopsis: r[P2]=rowid */ -#define OP_FinishSeek 144 -#define OP_Destroy 145 -#define OP_Clear 146 -#define OP_ResetSorter 147 -#define OP_CreateBtree 148 /* synopsis: r[P2]=root iDb=P1 flags=P3 */ -#define OP_SqlExec 149 -#define OP_ParseSchema 150 -#define OP_LoadAnalysis 151 -#define OP_DropTable 152 -#define OP_DropIndex 153 +#define OP_SorterOpen 119 +#define OP_SequenceTest 120 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */ +#define OP_OpenPseudo 121 /* synopsis: P3 columns in r[P2] */ +#define OP_Close 122 +#define OP_ColumnsUsed 123 +#define OP_SeekScan 124 /* synopsis: Scan-ahead up to P1 rows */ +#define OP_SeekHit 125 /* synopsis: set P2<=seekHit<=P3 */ +#define OP_Sequence 126 /* synopsis: r[P2]=cursor[P1].ctr++ */ +#define OP_NewRowid 127 /* synopsis: r[P2]=rowid */ +#define OP_Insert 128 /* synopsis: intkey=r[P3] data=r[P2] */ +#define OP_RowCell 129 +#define OP_Delete 130 +#define OP_ResetCount 131 +#define OP_SorterCompare 132 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */ +#define OP_SorterData 133 /* synopsis: r[P2]=data */ +#define OP_RowData 134 /* synopsis: r[P2]=data */ +#define OP_Rowid 135 /* synopsis: r[P2]=PX rowid of P1 */ +#define OP_NullRow 136 +#define OP_SeekEnd 137 +#define OP_IdxInsert 138 /* synopsis: key=r[P2] */ +#define OP_SorterInsert 139 /* synopsis: key=r[P2] */ +#define OP_IdxDelete 140 /* synopsis: key=r[P2@P3] */ +#define OP_DeferredSeek 141 /* synopsis: Move P3 to P1.rowid if needed */ +#define OP_IdxRowid 142 /* synopsis: r[P2]=rowid */ +#define OP_FinishSeek 143 +#define OP_Destroy 144 +#define OP_Clear 145 +#define OP_ResetSorter 146 +#define OP_CreateBtree 147 /* synopsis: r[P2]=root iDb=P1 flags=P3 */ +#define OP_SqlExec 148 +#define OP_ParseSchema 149 +#define OP_LoadAnalysis 150 +#define OP_DropTable 151 +#define OP_DropIndex 152 +#define OP_DropTrigger 153 #define OP_Real 154 /* same as TK_FLOAT, synopsis: r[P2]=P4 */ -#define OP_DropTrigger 155 -#define OP_IntegrityCk 156 -#define OP_RowSetAdd 157 /* synopsis: rowset(P1)=r[P2] */ -#define OP_Param 158 -#define OP_FkCounter 159 /* synopsis: fkctr[P1]+=P2 */ -#define OP_MemMax 160 /* synopsis: r[P1]=max(r[P1],r[P2]) */ -#define OP_OffsetLimit 161 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */ -#define OP_AggInverse 162 /* synopsis: accum=r[P3] inverse(r[P2@P5]) */ -#define OP_AggStep 163 /* synopsis: accum=r[P3] step(r[P2@P5]) */ -#define OP_AggStep1 164 /* synopsis: accum=r[P3] step(r[P2@P5]) */ -#define OP_AggValue 165 /* synopsis: r[P3]=value N=P2 */ -#define OP_AggFinal 166 /* synopsis: accum=r[P1] N=P2 */ -#define OP_Expire 167 -#define OP_CursorLock 168 -#define OP_CursorUnlock 169 -#define OP_TableLock 170 /* synopsis: iDb=P1 root=P2 write=P3 */ -#define OP_VBegin 171 -#define OP_VCreate 172 -#define OP_VDestroy 173 -#define OP_VOpen 174 -#define OP_VCheck 175 -#define OP_VInitIn 176 /* synopsis: r[P2]=ValueList(P1,P3) */ -#define OP_VColumn 177 /* synopsis: r[P3]=vcolumn(P2) */ -#define OP_VRename 178 -#define OP_Pagecount 179 -#define OP_MaxPgcnt 180 -#define OP_ClrSubtype 181 /* synopsis: r[P1].subtype = 0 */ -#define OP_GetSubtype 182 /* synopsis: r[P2] = r[P1].subtype */ -#define OP_SetSubtype 183 /* synopsis: r[P2].subtype = r[P1] */ -#define OP_FilterAdd 184 /* synopsis: filter(P1) += key(P3@P4) */ -#define OP_Trace 185 -#define OP_CursorHint 186 -#define OP_ReleaseReg 187 /* synopsis: release r[P1@P2] mask P3 */ -#define OP_Noop 188 -#define OP_Explain 189 -#define OP_Abortable 190 +#define OP_IntegrityCk 155 +#define OP_RowSetAdd 156 /* synopsis: rowset(P1)=r[P2] */ +#define OP_Param 157 +#define OP_FkCounter 158 /* synopsis: fkctr[P1]+=P2 */ +#define OP_MemMax 159 /* synopsis: r[P1]=max(r[P1],r[P2]) */ +#define OP_OffsetLimit 160 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */ +#define OP_AggInverse 161 /* synopsis: accum=r[P3] inverse(r[P2@P5]) */ +#define OP_AggStep 162 /* synopsis: accum=r[P3] step(r[P2@P5]) */ +#define OP_AggStep1 163 /* synopsis: accum=r[P3] step(r[P2@P5]) */ +#define OP_AggValue 164 /* synopsis: r[P3]=value N=P2 */ +#define OP_AggFinal 165 /* synopsis: accum=r[P1] N=P2 */ +#define OP_Expire 166 +#define OP_CursorLock 167 +#define OP_CursorUnlock 168 +#define OP_TableLock 169 /* synopsis: iDb=P1 root=P2 write=P3 */ +#define OP_VBegin 170 +#define OP_VCreate 171 +#define OP_VDestroy 172 +#define OP_VOpen 173 +#define OP_VCheck 174 +#define OP_VInitIn 175 /* synopsis: r[P2]=ValueList(P1,P3) */ +#define OP_VColumn 176 /* synopsis: r[P3]=vcolumn(P2) */ +#define OP_VRename 177 +#define OP_Pagecount 178 +#define OP_MaxPgcnt 179 +#define OP_ClrSubtype 180 /* synopsis: r[P1].subtype = 0 */ +#define OP_GetSubtype 181 /* synopsis: r[P2] = r[P1].subtype */ +#define OP_SetSubtype 182 /* synopsis: r[P2].subtype = r[P1] */ +#define OP_FilterAdd 183 /* synopsis: filter(P1) += key(P3@P4) */ +#define OP_Trace 184 +#define OP_CursorHint 185 +#define OP_ReleaseReg 186 /* synopsis: release r[P1@P2] mask P3 */ +#define OP_Noop 187 +#define OP_Explain 188 +#define OP_Abortable 189 /* Properties such as "out2" or "jump" that are specified in ** comments following the "case" for each opcode in the vdbe.c @@ -17454,26 +17254,26 @@ typedef struct VdbeOpList VdbeOpList; /* 8 */ 0x81, 0x01, 0x01, 0x81, 0x83, 0x83, 0x01, 0x01,\ /* 16 */ 0x03, 0x03, 0x01, 0x12, 0x01, 0xc9, 0xc9, 0xc9,\ /* 24 */ 0xc9, 0x01, 0x49, 0x49, 0x49, 0x49, 0xc9, 0x49,\ -/* 32 */ 0xc1, 0x01, 0x41, 0x41, 0xc1, 0x01, 0x01, 0x41,\ -/* 40 */ 0x41, 0x41, 0x41, 0x26, 0x26, 0x41, 0x41, 0x23,\ -/* 48 */ 0x0b, 0x81, 0x01, 0x03, 0x03, 0x0b, 0x0b, 0x0b,\ -/* 56 */ 0x0b, 0x0b, 0x0b, 0x01, 0x03, 0x03, 0x03, 0x01,\ -/* 64 */ 0x41, 0x01, 0x00, 0x00, 0x02, 0x02, 0x08, 0x00,\ -/* 72 */ 0x10, 0x10, 0x10, 0x00, 0x10, 0x00, 0x10, 0x10,\ -/* 80 */ 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x02,\ -/* 88 */ 0x02, 0x02, 0x00, 0x00, 0x12, 0x1e, 0x20, 0x40,\ -/* 96 */ 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x40, 0x26,\ +/* 32 */ 0xc1, 0x01, 0x41, 0x41, 0xc1, 0x01, 0x41, 0x41,\ +/* 40 */ 0x41, 0x41, 0x41, 0x26, 0x26, 0x41, 0x23, 0x0b,\ +/* 48 */ 0x81, 0x01, 0x03, 0x03, 0x03, 0x0b, 0x0b, 0x0b,\ +/* 56 */ 0x0b, 0x0b, 0x0b, 0x01, 0x03, 0x03, 0x01, 0x41,\ +/* 64 */ 0x01, 0x00, 0x00, 0x02, 0x02, 0x08, 0x00, 0x10,\ +/* 72 */ 0x10, 0x10, 0x00, 0x10, 0x00, 0x10, 0x10, 0x00,\ +/* 80 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x02, 0x02,\ +/* 88 */ 0x02, 0x00, 0x00, 0x12, 0x1e, 0x20, 0x40, 0x00,\ +/* 96 */ 0x00, 0x00, 0x10, 0x10, 0x00, 0x40, 0x40, 0x26,\ /* 104 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26,\ -/* 112 */ 0x26, 0x40, 0x00, 0x12, 0x40, 0x40, 0x10, 0x40,\ -/* 120 */ 0x00, 0x00, 0x00, 0x40, 0x00, 0x40, 0x40, 0x10,\ -/* 128 */ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,\ -/* 136 */ 0x50, 0x00, 0x40, 0x04, 0x04, 0x00, 0x40, 0x50,\ -/* 144 */ 0x40, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,\ -/* 152 */ 0x00, 0x00, 0x10, 0x00, 0x00, 0x06, 0x10, 0x00,\ -/* 160 */ 0x04, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ -/* 168 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10,\ -/* 176 */ 0x50, 0x40, 0x00, 0x10, 0x10, 0x02, 0x12, 0x12,\ -/* 184 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,} +/* 112 */ 0x26, 0x00, 0x40, 0x12, 0x40, 0x40, 0x10, 0x00,\ +/* 120 */ 0x00, 0x00, 0x40, 0x00, 0x40, 0x40, 0x10, 0x10,\ +/* 128 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x50,\ +/* 136 */ 0x00, 0x40, 0x04, 0x04, 0x00, 0x40, 0x50, 0x40,\ +/* 144 */ 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,\ +/* 152 */ 0x00, 0x00, 0x10, 0x00, 0x06, 0x10, 0x00, 0x04,\ +/* 160 */ 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ +/* 168 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x50,\ +/* 176 */ 0x40, 0x00, 0x10, 0x10, 0x02, 0x12, 0x12, 0x00,\ +/* 184 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,} /* The resolve3P2Values() routine is able to run faster if it knows ** the value of the largest JUMP opcode. The smaller the maximum @@ -17481,7 +17281,7 @@ typedef struct VdbeOpList VdbeOpList; ** generated this include file strives to group all JUMP opcodes ** together near the beginning of the list. */ -#define SQLITE_MX_JUMP_OPCODE 65 /* Maximum JUMP opcode */ +#define SQLITE_MX_JUMP_OPCODE 64 /* Maximum JUMP opcode */ /************** End of opcodes.h *********************************************/ /************** Continuing where we left off in vdbe.h ***********************/ @@ -17604,11 +17404,8 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql(Vdbe*, const char*); #endif SQLITE_PRIVATE int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*); SQLITE_PRIVATE int sqlite3BlobCompare(const Mem*, const Mem*); -#ifdef SQLITE_ENABLE_PERCENTILE -SQLITE_PRIVATE const char *sqlite3VdbeFuncName(const sqlite3_context*); -#endif -SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(int,const void*,UnpackedRecord*); +SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*); SQLITE_PRIVATE int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*); SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip(int, const void *, UnpackedRecord *, int); SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo*); @@ -17621,9 +17418,7 @@ SQLITE_PRIVATE int sqlite3VdbeHasSubProgram(Vdbe*); SQLITE_PRIVATE void sqlite3MemSetArrayInt64(sqlite3_value *aMem, int iIdx, i64 val); -#ifndef SQLITE_OMIT_DATETIME_FUNCS SQLITE_PRIVATE int sqlite3NotPureFunc(sqlite3_context*); -#endif #ifdef SQLITE_ENABLE_BYTECODE_VTAB SQLITE_PRIVATE int sqlite3VdbeBytecodeVtabInit(sqlite3*); #endif @@ -18279,7 +18074,7 @@ struct sqlite3 { u8 iDb; /* Which db file is being initialized */ u8 busy; /* TRUE if currently initializing */ unsigned orphanTrigger : 1; /* Last statement is orphaned TEMP trigger */ - unsigned imposterTable : 2; /* Building an imposter table */ + unsigned imposterTable : 1; /* Building an imposter table */ unsigned reopenMemdb : 1; /* ATTACH is really a reopen using MemDB */ const char **azInit; /* "type", "name", and "tbl_name" columns */ } init; @@ -18362,7 +18157,6 @@ struct sqlite3 { i64 nDeferredImmCons; /* Net deferred immediate constraints */ int *pnBytesFreed; /* If not NULL, increment this in DbFree() */ DbClientData *pDbData; /* sqlite3_set_clientdata() content */ - u64 nSpill; /* TEMP content spilled to disk */ #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY /* The following variables are all protected by the STATIC_MAIN ** mutex, not by sqlite3.mutex. They are used by code in notify.c. @@ -18506,7 +18300,6 @@ struct sqlite3 { #define SQLITE_OnePass 0x08000000 /* Single-pass DELETE and UPDATE */ #define SQLITE_OrderBySubq 0x10000000 /* ORDER BY in subquery helps outer */ #define SQLITE_StarQuery 0x20000000 /* Heurists for star queries */ -#define SQLITE_ExistsToJoin 0x40000000 /* The EXISTS-to-JOIN optimization */ #define SQLITE_AllOpts 0xffffffff /* All optimizations */ /* @@ -18745,7 +18538,7 @@ struct FuncDestructor { #define STR_FUNCTION(zName, nArg, pArg, bNC, xFunc) \ {nArg, SQLITE_FUNC_BUILTIN|\ SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \ - pArg, 0, xFunc, 0, 0, 0, #zName, {0} } + pArg, 0, xFunc, 0, 0, 0, #zName, } #define LIKEFUNC(zName, nArg, arg, flags) \ {nArg, SQLITE_FUNC_BUILTIN|SQLITE_FUNC_CONSTANT|SQLITE_UTF8|flags, \ (void *)arg, 0, likeFunc, 0, 0, 0, #zName, {0} } @@ -19073,7 +18866,6 @@ struct Table { #define TF_Ephemeral 0x00004000 /* An ephemeral table */ #define TF_Eponymous 0x00008000 /* An eponymous virtual table */ #define TF_Strict 0x00010000 /* STRICT mode */ -#define TF_Imposter 0x00020000 /* An imposter table */ /* ** Allowed values for Table.eTabType @@ -19229,15 +19021,9 @@ struct FKey { ** argument to sqlite3VdbeKeyCompare and is used to control the ** comparison of the two index keys. ** -** The aSortOrder[] and aColl[] arrays have nAllField slots each. There -** are nKeyField slots for the columns of an index then extra slots -** for the rowid or key at the end. The aSortOrder array is located after -** the aColl[] array. -** -** If SQLITE_ENABLE_PREUPDATE_HOOK is defined, then aSortFlags might be NULL -** to indicate that this object is for use by a preupdate hook. When aSortFlags -** is NULL, then nAllField is uninitialized and no space is allocated for -** aColl[], so those fields may not be used. +** Note that aSortOrder[] and aColl[] have nField+1 slots. There +** are nField slots for the columns of an index then one extra slot +** for the rowid at the end. */ struct KeyInfo { u32 nRef; /* Number of references to this KeyInfo object */ @@ -19249,18 +19035,9 @@ struct KeyInfo { CollSeq *aColl[FLEXARRAY]; /* Collating sequence for each term of the key */ }; -/* The size (in bytes) of a KeyInfo object with up to N fields. This includes -** the main body of the KeyInfo object and the aColl[] array of N elements, -** but does not count the memory used to hold aSortFlags[]. */ +/* The size (in bytes) of a KeyInfo object with up to N fields */ #define SZ_KEYINFO(N) (offsetof(KeyInfo,aColl) + (N)*sizeof(CollSeq*)) -/* The size of a bare KeyInfo with no aColl[] entries */ -#if FLEXARRAY+1 > 1 -# define SZ_KEYINFO_0 offsetof(KeyInfo,aColl) -#else -# define SZ_KEYINFO_0 sizeof(KeyInfo) -#endif - /* ** Allowed bit values for entries in the KeyInfo.aSortFlags[] array. */ @@ -19279,8 +19056,9 @@ struct KeyInfo { ** ** An instance of this object serves as a "key" for doing a search on ** an index b+tree. The goal of the search is to find the entry that -** is closest to the key described by this object. This object might hold -** just a prefix of the key. The number of fields is given by nField. +** is closed to the key described by this object. This object might hold +** just a prefix of the key. The number of fields is given by +** pKeyInfo->nField. ** ** The r1 and r2 fields are the values to return if this key is less than ** or greater than a key in the btree, respectively. These are normally @@ -19290,7 +19068,7 @@ struct KeyInfo { ** The key comparison functions actually return default_rc when they find ** an equals comparison. default_rc can be -1, 0, or +1. If there are ** multiple entries in the b-tree with the same key (when only looking -** at the first nField elements) then default_rc can be set to -1 to +** at the first pKeyInfo->nFields,) then default_rc can be set to -1 to ** cause the search to find the last match, or +1 to cause the search to ** find the first match. ** @@ -19302,8 +19080,8 @@ struct KeyInfo { ** b-tree. */ struct UnpackedRecord { - KeyInfo *pKeyInfo; /* Comparison info for the index that is unpacked */ - Mem *aMem; /* Values for columns of the index */ + KeyInfo *pKeyInfo; /* Collation and sort-order information */ + Mem *aMem; /* Values */ union { char *z; /* Cache of aMem[0].z for vdbeRecordCompareString() */ i64 i; /* Cache of aMem[0].u.i for vdbeRecordCompareInt() */ @@ -19952,7 +19730,6 @@ struct SrcItem { unsigned rowidUsed :1; /* The ROWID of this table is referenced */ unsigned fixedSchema :1; /* Uses u4.pSchema, not u4.zDatabase */ unsigned hadSchema :1; /* Had u4.zDatabase before u4.pSchema */ - unsigned fromExists :1; /* Comes from WHERE EXISTS(...) */ } fg; int iCursor; /* The VDBE cursor number used to access this table */ Bitmask colUsed; /* Bit N set if column N used. Details above for N>62 */ @@ -20240,7 +20017,6 @@ struct Select { #define SF_OrderByReqd 0x8000000 /* The ORDER BY clause may not be omitted */ #define SF_UpdateFrom 0x10000000 /* Query originates with UPDATE FROM */ #define SF_Correlated 0x20000000 /* True if references the outer context */ -#define SF_OnToWhere 0x40000000 /* One or more ON clauses moved to WHERE */ /* True if SrcItem X is a subquery that has SF_NestedFrom */ #define IsNestedFrom(X) \ @@ -20484,7 +20260,6 @@ struct Parse { u8 disableLookaside; /* Number of times lookaside has been disabled */ u8 prepFlags; /* SQLITE_PREPARE_* flags */ u8 withinRJSubrtn; /* Nesting level for RIGHT JOIN body subroutines */ - u8 bHasExists; /* Has a correlated "EXISTS (SELECT ....)" expression */ u8 mSubrtnSig; /* mini Bloom filter on available SubrtnSig.selId */ u8 eTriggerOp; /* TK_UPDATE, TK_INSERT or TK_DELETE */ u8 bReturning; /* Coding a RETURNING trigger */ @@ -20994,7 +20769,6 @@ struct Walker { SrcItem *pSrcItem; /* A single FROM clause item */ DbFixer *pFix; /* See sqlite3FixSelect() */ Mem *aMem; /* See sqlite3BtreeCursorHint() */ - struct CheckOnCtx *pCheckOnCtx; /* See selectCheckOnClauses() */ } u; }; @@ -21482,7 +21256,6 @@ SQLITE_PRIVATE void sqlite3ShowTriggerList(const Trigger*); SQLITE_PRIVATE void sqlite3ShowWindow(const Window*); SQLITE_PRIVATE void sqlite3ShowWinFunc(const Window*); #endif -SQLITE_PRIVATE void sqlite3ShowBitvec(Bitvec*); #endif SQLITE_PRIVATE void sqlite3SetString(char **, sqlite3*, const char*); @@ -21799,17 +21572,13 @@ SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void); SQLITE_PRIVATE void sqlite3RegisterJsonFunctions(void); SQLITE_PRIVATE void sqlite3RegisterPerConnectionBuiltinFunctions(sqlite3*); #if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_JSON) -SQLITE_PRIVATE Module *sqlite3JsonVtabRegister(sqlite3*,const char*); +SQLITE_PRIVATE int sqlite3JsonTableFunctions(sqlite3*); #endif SQLITE_PRIVATE int sqlite3SafetyCheckOk(sqlite3*); SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3*); SQLITE_PRIVATE void sqlite3ChangeCookie(Parse*, int); SQLITE_PRIVATE With *sqlite3WithDup(sqlite3 *db, With *p); -#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_CARRAY) -SQLITE_PRIVATE Module *sqlite3CarrayRegister(sqlite3*); -#endif - #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) SQLITE_PRIVATE void sqlite3MaterializeView(Parse*, Table*, Expr*, ExprList*,Expr*,int); #endif @@ -22030,7 +21799,7 @@ SQLITE_PRIVATE void sqlite3Reindex(Parse*, Token*, Token*); SQLITE_PRIVATE void sqlite3AlterFunctions(void); SQLITE_PRIVATE void sqlite3AlterRenameTable(Parse*, SrcList*, Token*); SQLITE_PRIVATE void sqlite3AlterRenameColumn(Parse*, SrcList*, Token*, Token*); -SQLITE_PRIVATE i64 sqlite3GetToken(const unsigned char *, int *); +SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *, int *); SQLITE_PRIVATE void sqlite3NestedParse(Parse*, const char*, ...); SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*, int); SQLITE_PRIVATE void sqlite3CodeRhsOfIN(Parse*, Expr*, int); @@ -22796,9 +22565,6 @@ static const char * const sqlite3azCompileOpt[] = { #ifdef SQLITE_ENABLE_BYTECODE_VTAB "ENABLE_BYTECODE_VTAB", #endif -#ifdef SQLITE_ENABLE_CARRAY - "ENABLE_CARRAY", -#endif #ifdef SQLITE_ENABLE_CEROD "ENABLE_CEROD=" CTIMEOPT_VAL(SQLITE_ENABLE_CEROD), #endif @@ -22889,9 +22655,6 @@ static const char * const sqlite3azCompileOpt[] = { #ifdef SQLITE_ENABLE_OVERSIZE_CELL_CHECK "ENABLE_OVERSIZE_CELL_CHECK", #endif -#ifdef SQLITE_ENABLE_PERCENTILE - "ENABLE_PERCENTILE", -#endif #ifdef SQLITE_ENABLE_PREUPDATE_HOOK "ENABLE_PREUPDATE_HOOK", #endif @@ -24106,7 +23869,7 @@ struct sqlite3_value { ** MEM_Int, MEM_Real, and MEM_IntReal. ** ** * MEM_Blob|MEM_Zero A blob in Mem.z of length Mem.n plus -** Mem.u.nZero extra 0x00 bytes at the end. +** MEM.u.i extra 0x00 bytes at the end. ** ** * MEM_Int Integer stored in Mem.u.i. ** @@ -24375,9 +24138,7 @@ struct PreUpdate { Table *pTab; /* Schema object being updated */ Index *pPk; /* PK index if pTab is WITHOUT ROWID */ sqlite3_value **apDflt; /* Array of default values, if required */ - struct { - u8 keyinfoSpace[SZ_KEYINFO_0]; /* Space to hold pKeyinfo[0] content */ - } uKey; + u8 keyinfoSpace[SZ_KEYINFO(0)]; /* Space to hold pKeyinfo[0] content */ }; /* @@ -24541,11 +24302,9 @@ SQLITE_PRIVATE int sqlite3VdbeCheckMemInvariants(Mem*); #endif #ifndef SQLITE_OMIT_FOREIGN_KEY -SQLITE_PRIVATE int sqlite3VdbeCheckFkImmediate(Vdbe*); -SQLITE_PRIVATE int sqlite3VdbeCheckFkDeferred(Vdbe*); +SQLITE_PRIVATE int sqlite3VdbeCheckFk(Vdbe *, int); #else -# define sqlite3VdbeCheckFkImmediate(p) 0 -# define sqlite3VdbeCheckFkDeferred(p) 0 +# define sqlite3VdbeCheckFk(p,i) 0 #endif #ifdef SQLITE_DEBUG @@ -24754,25 +24513,23 @@ SQLITE_PRIVATE int sqlite3LookasideUsed(sqlite3 *db, int *pHighwater){ /* ** Query status information for a single database connection */ -SQLITE_API int sqlite3_db_status64( - sqlite3 *db, /* The database connection whose status is desired */ - int op, /* Status verb */ - sqlite3_int64 *pCurrent, /* Write current value here */ - sqlite3_int64 *pHighwtr, /* Write high-water mark here */ - int resetFlag /* Reset high-water mark if true */ +SQLITE_API int sqlite3_db_status( + sqlite3 *db, /* The database connection whose status is desired */ + int op, /* Status verb */ + int *pCurrent, /* Write current value here */ + int *pHighwater, /* Write high-water mark here */ + int resetFlag /* Reset high-water mark if true */ ){ int rc = SQLITE_OK; /* Return code */ #ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) || pCurrent==0|| pHighwtr==0 ){ + if( !sqlite3SafetyCheckOk(db) || pCurrent==0|| pHighwater==0 ){ return SQLITE_MISUSE_BKPT; } #endif sqlite3_mutex_enter(db->mutex); switch( op ){ case SQLITE_DBSTATUS_LOOKASIDE_USED: { - int H = 0; - *pCurrent = sqlite3LookasideUsed(db, &H); - *pHighwtr = H; + *pCurrent = sqlite3LookasideUsed(db, pHighwater); if( resetFlag ){ LookasideSlot *p = db->lookaside.pFree; if( p ){ @@ -24803,7 +24560,7 @@ SQLITE_API int sqlite3_db_status64( assert( (op-SQLITE_DBSTATUS_LOOKASIDE_HIT)>=0 ); assert( (op-SQLITE_DBSTATUS_LOOKASIDE_HIT)<3 ); *pCurrent = 0; - *pHighwtr = db->lookaside.anStat[op-SQLITE_DBSTATUS_LOOKASIDE_HIT]; + *pHighwater = (int)db->lookaside.anStat[op-SQLITE_DBSTATUS_LOOKASIDE_HIT]; if( resetFlag ){ db->lookaside.anStat[op - SQLITE_DBSTATUS_LOOKASIDE_HIT] = 0; } @@ -24817,7 +24574,7 @@ SQLITE_API int sqlite3_db_status64( */ case SQLITE_DBSTATUS_CACHE_USED_SHARED: case SQLITE_DBSTATUS_CACHE_USED: { - sqlite3_int64 totalUsed = 0; + int totalUsed = 0; int i; sqlite3BtreeEnterAll(db); for(i=0; i<db->nDb; i++){ @@ -24833,18 +24590,18 @@ SQLITE_API int sqlite3_db_status64( } sqlite3BtreeLeaveAll(db); *pCurrent = totalUsed; - *pHighwtr = 0; + *pHighwater = 0; break; } /* ** *pCurrent gets an accurate estimate of the amount of memory used ** to store the schema for all databases (main, temp, and any ATTACHed - ** databases. *pHighwtr is set to zero. + ** databases. *pHighwater is set to zero. */ case SQLITE_DBSTATUS_SCHEMA_USED: { - int i; /* Used to iterate through schemas */ - int nByte = 0; /* Used to accumulate return value */ + int i; /* Used to iterate through schemas */ + int nByte = 0; /* Used to accumulate return value */ sqlite3BtreeEnterAll(db); db->pnBytesFreed = &nByte; @@ -24878,7 +24635,7 @@ SQLITE_API int sqlite3_db_status64( db->lookaside.pEnd = db->lookaside.pTrueEnd; sqlite3BtreeLeaveAll(db); - *pHighwtr = 0; + *pHighwater = 0; *pCurrent = nByte; break; } @@ -24886,7 +24643,7 @@ SQLITE_API int sqlite3_db_status64( /* ** *pCurrent gets an accurate estimate of the amount of memory used ** to store all prepared statements. - ** *pHighwtr is set to zero. + ** *pHighwater is set to zero. */ case SQLITE_DBSTATUS_STMT_USED: { struct Vdbe *pVdbe; /* Used to iterate through VMs */ @@ -24901,7 +24658,7 @@ SQLITE_API int sqlite3_db_status64( db->lookaside.pEnd = db->lookaside.pTrueEnd; db->pnBytesFreed = 0; - *pHighwtr = 0; /* IMP: R-64479-57858 */ + *pHighwater = 0; /* IMP: R-64479-57858 */ *pCurrent = nByte; break; @@ -24909,7 +24666,7 @@ SQLITE_API int sqlite3_db_status64( /* ** Set *pCurrent to the total cache hits or misses encountered by all - ** pagers the database handle is connected to. *pHighwtr is always set + ** pagers the database handle is connected to. *pHighwater is always set ** to zero. */ case SQLITE_DBSTATUS_CACHE_SPILL: @@ -24929,39 +24686,19 @@ SQLITE_API int sqlite3_db_status64( sqlite3PagerCacheStat(pPager, op, resetFlag, &nRet); } } - *pHighwtr = 0; /* IMP: R-42420-56072 */ + *pHighwater = 0; /* IMP: R-42420-56072 */ /* IMP: R-54100-20147 */ /* IMP: R-29431-39229 */ - *pCurrent = nRet; - break; - } - - /* Set *pCurrent to the number of bytes that the db database connection - ** has spilled to the filesystem in temporary files that could have been - ** stored in memory, had sufficient memory been available. - ** The *pHighwater is always set to zero. - */ - case SQLITE_DBSTATUS_TEMPBUF_SPILL: { - u64 nRet = 0; - if( db->aDb[1].pBt ){ - Pager *pPager = sqlite3BtreePager(db->aDb[1].pBt); - sqlite3PagerCacheStat(pPager, SQLITE_DBSTATUS_CACHE_WRITE, - resetFlag, &nRet); - nRet *= sqlite3BtreeGetPageSize(db->aDb[1].pBt); - } - nRet += db->nSpill; - if( resetFlag ) db->nSpill = 0; - *pHighwtr = 0; - *pCurrent = nRet; + *pCurrent = (int)nRet & 0x7fffffff; break; } /* Set *pCurrent to non-zero if there are unresolved deferred foreign ** key constraints. Set *pCurrent to zero if all foreign key constraints - ** have been satisfied. The *pHighwtr is always set to zero. + ** have been satisfied. The *pHighwater is always set to zero. */ case SQLITE_DBSTATUS_DEFERRED_FKS: { - *pHighwtr = 0; /* IMP: R-11967-56545 */ + *pHighwater = 0; /* IMP: R-11967-56545 */ *pCurrent = db->nDeferredImmCons>0 || db->nDeferredCons>0; break; } @@ -24974,31 +24711,6 @@ SQLITE_API int sqlite3_db_status64( return rc; } -/* -** 32-bit variant of sqlite3_db_status64() -*/ -SQLITE_API int sqlite3_db_status( - sqlite3 *db, /* The database connection whose status is desired */ - int op, /* Status verb */ - int *pCurrent, /* Write current value here */ - int *pHighwtr, /* Write high-water mark here */ - int resetFlag /* Reset high-water mark if true */ -){ - sqlite3_int64 C = 0, H = 0; - int rc; -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) || pCurrent==0|| pHighwtr==0 ){ - return SQLITE_MISUSE_BKPT; - } -#endif - rc = sqlite3_db_status64(db, op, &C, &H, resetFlag); - if( rc==0 ){ - *pCurrent = C & 0x7fffffff; - *pHighwtr = H & 0x7fffffff; - } - return rc; -} - /************** End of status.c **********************************************/ /************** Begin file date.c ********************************************/ /* @@ -25191,10 +24903,6 @@ static int parseTimezone(const char *zDate, DateTime *p){ } zDate += 5; p->tz = sgn*(nMn + nHr*60); - if( p->tz==0 ){ /* Forum post 2025-09-17T10:12:14z */ - p->isLocal = 0; - p->isUtc = 1; - } zulu_time: while( sqlite3Isspace(*zDate) ){ zDate++; } return *zDate!=0; @@ -26390,8 +26098,8 @@ static int daysAfterSunday(DateTime *pDate){ ** %l hour 1-12 (leading zero converted to space) ** %m month 01-12 ** %M minute 00-59 -** %p "AM" or "PM" -** %P "am" or "pm" +** %p "am" or "pm" +** %P "AM" or "PM" ** %R time as HH:MM ** %s seconds since 1970-01-01 ** %S seconds 00-59 @@ -31998,7 +31706,6 @@ typedef struct et_info { /* Information about each format field */ etByte type; /* Conversion paradigm */ etByte charset; /* Offset into aDigits[] of the digits string */ etByte prefix; /* Offset into aPrefix[] of the prefix string */ - char iNxt; /* Next with same hash, or 0 for end of chain */ } et_info; /* @@ -32007,61 +31714,44 @@ typedef struct et_info { /* Information about each format field */ #define FLAG_SIGNED 1 /* True if the value to convert is signed */ #define FLAG_STRING 4 /* Allow infinite precision */ + /* -** The table is searched by hash. In the case of %C where C is the character -** and that character has ASCII value j, then the hash is j%23. -** -** The order of the entries in fmtinfo[] and the hash chain was entered -** manually, but based on the output of the following TCL script: +** The following table is searched linearly, so it is good to put the +** most frequently used conversion types first. */ -#if 0 /***** Beginning of script ******/ -foreach c {d s g z q Q w c o u x X f e E G i n % p T S r} { - scan $c %c x - set n($c) $x -} -set mx [llength [array names n]] -puts "count: $mx" - -set mx 27 -puts "*********** mx=$mx ************" -for {set r 0} {$r<$mx} {incr r} { - puts -nonewline [format %2d: $r] - foreach c [array names n] { - if {($n($c))%$mx==$r} {puts -nonewline " $c"} - } - puts "" -} -#endif /***** End of script ********/ - static const char aDigits[] = "0123456789ABCDEF0123456789abcdef"; static const char aPrefix[] = "-x0\000X0"; -static const et_info fmtinfo[23] = { - /* 0 */ { 's', 0, 4, etSTRING, 0, 0, 1 }, - /* 1 */ { 'E', 0, 1, etEXP, 14, 0, 0 }, /* Hash: 0 */ - /* 2 */ { 'u', 10, 0, etDECIMAL, 0, 0, 3 }, - /* 3 */ { 'G', 0, 1, etGENERIC, 14, 0, 0 }, /* Hash: 2 */ - /* 4 */ { 'w', 0, 4, etESCAPE_w, 0, 0, 0 }, - /* 5 */ { 'x', 16, 0, etRADIX, 16, 1, 0 }, - /* 6 */ { 'c', 0, 0, etCHARX, 0, 0, 0 }, /* Hash: 7 */ - /* 7 */ { 'z', 0, 4, etDYNSTRING, 0, 0, 6 }, - /* 8 */ { 'd', 10, 1, etDECIMAL, 0, 0, 0 }, - /* 9 */ { 'e', 0, 1, etEXP, 30, 0, 0 }, - /* 10 */ { 'f', 0, 1, etFLOAT, 0, 0, 0 }, - /* 11 */ { 'g', 0, 1, etGENERIC, 30, 0, 0 }, - /* 12 */ { 'Q', 0, 4, etESCAPE_Q, 0, 0, 0 }, - /* 13 */ { 'i', 10, 1, etDECIMAL, 0, 0, 0 }, - /* 14 */ { '%', 0, 0, etPERCENT, 0, 0, 16 }, - /* 15 */ { 'T', 0, 0, etTOKEN, 0, 0, 0 }, - /* 16 */ { 'S', 0, 0, etSRCITEM, 0, 0, 0 }, /* Hash: 14 */ - /* 17 */ { 'X', 16, 0, etRADIX, 0, 4, 0 }, /* Hash: 19 */ - /* 18 */ { 'n', 0, 0, etSIZE, 0, 0, 0 }, - /* 19 */ { 'o', 8, 0, etRADIX, 0, 2, 17 }, - /* 20 */ { 'p', 16, 0, etPOINTER, 0, 1, 0 }, - /* 21 */ { 'q', 0, 4, etESCAPE_q, 0, 0, 0 }, - /* 22 */ { 'r', 10, 1, etORDINAL, 0, 0, 0 } +static const et_info fmtinfo[] = { + { 'd', 10, 1, etDECIMAL, 0, 0 }, + { 's', 0, 4, etSTRING, 0, 0 }, + { 'g', 0, 1, etGENERIC, 30, 0 }, + { 'z', 0, 4, etDYNSTRING, 0, 0 }, + { 'q', 0, 4, etESCAPE_q, 0, 0 }, + { 'Q', 0, 4, etESCAPE_Q, 0, 0 }, + { 'w', 0, 4, etESCAPE_w, 0, 0 }, + { 'c', 0, 0, etCHARX, 0, 0 }, + { 'o', 8, 0, etRADIX, 0, 2 }, + { 'u', 10, 0, etDECIMAL, 0, 0 }, + { 'x', 16, 0, etRADIX, 16, 1 }, + { 'X', 16, 0, etRADIX, 0, 4 }, +#ifndef SQLITE_OMIT_FLOATING_POINT + { 'f', 0, 1, etFLOAT, 0, 0 }, + { 'e', 0, 1, etEXP, 30, 0 }, + { 'E', 0, 1, etEXP, 14, 0 }, + { 'G', 0, 1, etGENERIC, 14, 0 }, +#endif + { 'i', 10, 1, etDECIMAL, 0, 0 }, + { 'n', 0, 0, etSIZE, 0, 0 }, + { '%', 0, 0, etPERCENT, 0, 0 }, + { 'p', 16, 0, etPOINTER, 0, 1 }, + + /* All the rest are undocumented and are for internal use only */ + { 'T', 0, 0, etTOKEN, 0, 0 }, + { 'S', 0, 0, etSRCITEM, 0, 0 }, + { 'r', 10, 1, etORDINAL, 0, 0 }, }; -/* Additional Notes: +/* Notes: ** ** %S Takes a pointer to SrcItem. Shows name or database.name ** %!S Like %S but prefer the zName over the zAlias @@ -32188,10 +31878,7 @@ SQLITE_API void sqlite3_str_vappendf( #if HAVE_STRCHRNUL fmt = strchrnul(fmt, '%'); #else - fmt = strchr(fmt, '%'); - if( fmt==0 ){ - fmt = bufpt + strlen(bufpt); - } + do{ fmt++; }while( *fmt && *fmt != '%' ); #endif sqlite3_str_append(pAccum, bufpt, (int)(fmt - bufpt)); if( *fmt==0 ) break; @@ -32305,9 +31992,6 @@ SQLITE_API void sqlite3_str_vappendf( }while( !done && (c=(*++fmt))!=0 ); /* Fetch the info entry for the field */ -#ifdef SQLITE_EBCDIC - /* The hash table only works for ASCII. For EBCDIC, we need to do - ** a linear search of the table */ infop = &fmtinfo[0]; xtype = etINVALID; for(idx=0; idx<ArraySize(fmtinfo); idx++){ @@ -32317,20 +32001,6 @@ SQLITE_API void sqlite3_str_vappendf( break; } } -#else - /* Fast hash-table lookup */ - assert( ArraySize(fmtinfo)==23 ); - idx = ((unsigned)c) % 23; - if( fmtinfo[idx].fmttype==c - || fmtinfo[idx = fmtinfo[idx].iNxt].fmttype==c - ){ - infop = &fmtinfo[idx]; - xtype = infop->type; - }else{ - infop = &fmtinfo[0]; - xtype = etINVALID; - } -#endif /* ** At this point, variables are initialized as follows: @@ -32398,14 +32068,6 @@ SQLITE_API void sqlite3_str_vappendf( } prefix = 0; } - -#if WHERETRACE_ENABLED - if( xtype==etPOINTER && sqlite3WhereTrace & 0x100000 ) longvalue = 0; -#endif -#if TREETRACE_ENABLED - if( xtype==etPOINTER && sqlite3TreeTrace & 0x100000 ) longvalue = 0; -#endif - if( longvalue==0 ) flag_alternateform = 0; if( flag_zeropad && precision<width-(prefix!=0) ){ precision = width-(prefix!=0); @@ -32518,21 +32180,7 @@ SQLITE_API void sqlite3_str_vappendf( } } if( s.sign=='-' ){ - if( flag_alternateform - && !flag_prefix - && xtype==etFLOAT - && s.iDP<=iRound - ){ - /* Suppress the minus sign if all of the following are true: - ** * The value displayed is zero - ** * The '#' flag is used - ** * The '+' flag is not used, and - ** * The format is %f - */ - prefix = 0; - }else{ - prefix = '-'; - } + prefix = '-'; }else{ prefix = flag_prefix; } @@ -33743,13 +33391,9 @@ SQLITE_PRIVATE void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc) n = 0; if( pItem->fg.isSubquery ) n++; if( pItem->fg.isTabFunc ) n++; - if( pItem->fg.isUsing || pItem->u3.pOn!=0 ) n++; + if( pItem->fg.isUsing ) n++; if( pItem->fg.isUsing ){ sqlite3TreeViewIdList(pView, pItem->u3.pUsing, (--n)>0, "USING"); - }else if( pItem->u3.pOn!=0 ){ - sqlite3TreeViewItem(pView, "ON", (--n)>0); - sqlite3TreeViewExpr(pView, pItem->u3.pOn, 0); - sqlite3TreeViewPop(&pView); } if( pItem->fg.isSubquery ){ assert( n==1 ); @@ -38055,20 +37699,20 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ /* 34 */ "SorterSort" OpHelp(""), /* 35 */ "Sort" OpHelp(""), /* 36 */ "Rewind" OpHelp(""), - /* 37 */ "IfEmpty" OpHelp("if( empty(P1) ) goto P2"), - /* 38 */ "SorterNext" OpHelp(""), - /* 39 */ "Prev" OpHelp(""), - /* 40 */ "Next" OpHelp(""), - /* 41 */ "IdxLE" OpHelp("key=r[P3@P4]"), - /* 42 */ "IdxGT" OpHelp("key=r[P3@P4]"), + /* 37 */ "SorterNext" OpHelp(""), + /* 38 */ "Prev" OpHelp(""), + /* 39 */ "Next" OpHelp(""), + /* 40 */ "IdxLE" OpHelp("key=r[P3@P4]"), + /* 41 */ "IdxGT" OpHelp("key=r[P3@P4]"), + /* 42 */ "IdxLT" OpHelp("key=r[P3@P4]"), /* 43 */ "Or" OpHelp("r[P3]=(r[P1] || r[P2])"), /* 44 */ "And" OpHelp("r[P3]=(r[P1] && r[P2])"), - /* 45 */ "IdxLT" OpHelp("key=r[P3@P4]"), - /* 46 */ "IdxGE" OpHelp("key=r[P3@P4]"), - /* 47 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"), - /* 48 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"), - /* 49 */ "Program" OpHelp(""), - /* 50 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"), + /* 45 */ "IdxGE" OpHelp("key=r[P3@P4]"), + /* 46 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"), + /* 47 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"), + /* 48 */ "Program" OpHelp(""), + /* 49 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"), + /* 50 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"), /* 51 */ "IsNull" OpHelp("if r[P1]==NULL goto P2"), /* 52 */ "NotNull" OpHelp("if r[P1]!=NULL goto P2"), /* 53 */ "Ne" OpHelp("IF r[P3]!=r[P1]"), @@ -38078,49 +37722,49 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ /* 57 */ "Lt" OpHelp("IF r[P3]<r[P1]"), /* 58 */ "Ge" OpHelp("IF r[P3]>=r[P1]"), /* 59 */ "ElseEq" OpHelp(""), - /* 60 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"), - /* 61 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]--, goto P2"), - /* 62 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"), - /* 63 */ "IncrVacuum" OpHelp(""), - /* 64 */ "VNext" OpHelp(""), - /* 65 */ "Filter" OpHelp("if key(P3@P4) not in filter(P1) goto P2"), - /* 66 */ "PureFunc" OpHelp("r[P3]=func(r[P2@NP])"), - /* 67 */ "Function" OpHelp("r[P3]=func(r[P2@NP])"), - /* 68 */ "Return" OpHelp(""), - /* 69 */ "EndCoroutine" OpHelp(""), - /* 70 */ "HaltIfNull" OpHelp("if r[P3]=null halt"), - /* 71 */ "Halt" OpHelp(""), - /* 72 */ "Integer" OpHelp("r[P2]=P1"), - /* 73 */ "Int64" OpHelp("r[P2]=P4"), - /* 74 */ "String" OpHelp("r[P2]='P4' (len=P1)"), - /* 75 */ "BeginSubrtn" OpHelp("r[P2]=NULL"), - /* 76 */ "Null" OpHelp("r[P2..P3]=NULL"), - /* 77 */ "SoftNull" OpHelp("r[P1]=NULL"), - /* 78 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"), - /* 79 */ "Variable" OpHelp("r[P2]=parameter(P1)"), - /* 80 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"), - /* 81 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"), - /* 82 */ "SCopy" OpHelp("r[P2]=r[P1]"), - /* 83 */ "IntCopy" OpHelp("r[P2]=r[P1]"), - /* 84 */ "FkCheck" OpHelp(""), - /* 85 */ "ResultRow" OpHelp("output=r[P1@P2]"), - /* 86 */ "CollSeq" OpHelp(""), - /* 87 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"), - /* 88 */ "RealAffinity" OpHelp(""), - /* 89 */ "Cast" OpHelp("affinity(r[P1])"), - /* 90 */ "Permutation" OpHelp(""), - /* 91 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"), - /* 92 */ "IsTrue" OpHelp("r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4"), - /* 93 */ "ZeroOrNull" OpHelp("r[P2] = 0 OR NULL"), - /* 94 */ "Offset" OpHelp("r[P3] = sqlite_offset(P1)"), - /* 95 */ "Column" OpHelp("r[P3]=PX cursor P1 column P2"), - /* 96 */ "TypeCheck" OpHelp("typecheck(r[P1@P2])"), - /* 97 */ "Affinity" OpHelp("affinity(r[P1@P2])"), - /* 98 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"), - /* 99 */ "Count" OpHelp("r[P2]=count()"), - /* 100 */ "ReadCookie" OpHelp(""), - /* 101 */ "SetCookie" OpHelp(""), - /* 102 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"), + /* 60 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]--, goto P2"), + /* 61 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"), + /* 62 */ "IncrVacuum" OpHelp(""), + /* 63 */ "VNext" OpHelp(""), + /* 64 */ "Filter" OpHelp("if key(P3@P4) not in filter(P1) goto P2"), + /* 65 */ "PureFunc" OpHelp("r[P3]=func(r[P2@NP])"), + /* 66 */ "Function" OpHelp("r[P3]=func(r[P2@NP])"), + /* 67 */ "Return" OpHelp(""), + /* 68 */ "EndCoroutine" OpHelp(""), + /* 69 */ "HaltIfNull" OpHelp("if r[P3]=null halt"), + /* 70 */ "Halt" OpHelp(""), + /* 71 */ "Integer" OpHelp("r[P2]=P1"), + /* 72 */ "Int64" OpHelp("r[P2]=P4"), + /* 73 */ "String" OpHelp("r[P2]='P4' (len=P1)"), + /* 74 */ "BeginSubrtn" OpHelp("r[P2]=NULL"), + /* 75 */ "Null" OpHelp("r[P2..P3]=NULL"), + /* 76 */ "SoftNull" OpHelp("r[P1]=NULL"), + /* 77 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"), + /* 78 */ "Variable" OpHelp("r[P2]=parameter(P1)"), + /* 79 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"), + /* 80 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"), + /* 81 */ "SCopy" OpHelp("r[P2]=r[P1]"), + /* 82 */ "IntCopy" OpHelp("r[P2]=r[P1]"), + /* 83 */ "FkCheck" OpHelp(""), + /* 84 */ "ResultRow" OpHelp("output=r[P1@P2]"), + /* 85 */ "CollSeq" OpHelp(""), + /* 86 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"), + /* 87 */ "RealAffinity" OpHelp(""), + /* 88 */ "Cast" OpHelp("affinity(r[P1])"), + /* 89 */ "Permutation" OpHelp(""), + /* 90 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"), + /* 91 */ "IsTrue" OpHelp("r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4"), + /* 92 */ "ZeroOrNull" OpHelp("r[P2] = 0 OR NULL"), + /* 93 */ "Offset" OpHelp("r[P3] = sqlite_offset(P1)"), + /* 94 */ "Column" OpHelp("r[P3]=PX cursor P1 column P2"), + /* 95 */ "TypeCheck" OpHelp("typecheck(r[P1@P2])"), + /* 96 */ "Affinity" OpHelp("affinity(r[P1@P2])"), + /* 97 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"), + /* 98 */ "Count" OpHelp("r[P2]=count()"), + /* 99 */ "ReadCookie" OpHelp(""), + /* 100 */ "SetCookie" OpHelp(""), + /* 101 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"), + /* 102 */ "OpenRead" OpHelp("root=P2 iDb=P3"), /* 103 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"), /* 104 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"), /* 105 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<<r[P1]"), @@ -38131,84 +37775,83 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ /* 110 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"), /* 111 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"), /* 112 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"), - /* 113 */ "OpenRead" OpHelp("root=P2 iDb=P3"), - /* 114 */ "OpenWrite" OpHelp("root=P2 iDb=P3"), + /* 113 */ "OpenWrite" OpHelp("root=P2 iDb=P3"), + /* 114 */ "OpenDup" OpHelp(""), /* 115 */ "BitNot" OpHelp("r[P2]= ~r[P1]"), - /* 116 */ "OpenDup" OpHelp(""), - /* 117 */ "OpenAutoindex" OpHelp("nColumn=P2"), + /* 116 */ "OpenAutoindex" OpHelp("nColumn=P2"), + /* 117 */ "OpenEphemeral" OpHelp("nColumn=P2"), /* 118 */ "String8" OpHelp("r[P2]='P4'"), - /* 119 */ "OpenEphemeral" OpHelp("nColumn=P2"), - /* 120 */ "SorterOpen" OpHelp(""), - /* 121 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"), - /* 122 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"), - /* 123 */ "Close" OpHelp(""), - /* 124 */ "ColumnsUsed" OpHelp(""), - /* 125 */ "SeekScan" OpHelp("Scan-ahead up to P1 rows"), - /* 126 */ "SeekHit" OpHelp("set P2<=seekHit<=P3"), - /* 127 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"), - /* 128 */ "NewRowid" OpHelp("r[P2]=rowid"), - /* 129 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"), - /* 130 */ "RowCell" OpHelp(""), - /* 131 */ "Delete" OpHelp(""), - /* 132 */ "ResetCount" OpHelp(""), - /* 133 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"), - /* 134 */ "SorterData" OpHelp("r[P2]=data"), - /* 135 */ "RowData" OpHelp("r[P2]=data"), - /* 136 */ "Rowid" OpHelp("r[P2]=PX rowid of P1"), - /* 137 */ "NullRow" OpHelp(""), - /* 138 */ "SeekEnd" OpHelp(""), - /* 139 */ "IdxInsert" OpHelp("key=r[P2]"), - /* 140 */ "SorterInsert" OpHelp("key=r[P2]"), - /* 141 */ "IdxDelete" OpHelp("key=r[P2@P3]"), - /* 142 */ "DeferredSeek" OpHelp("Move P3 to P1.rowid if needed"), - /* 143 */ "IdxRowid" OpHelp("r[P2]=rowid"), - /* 144 */ "FinishSeek" OpHelp(""), - /* 145 */ "Destroy" OpHelp(""), - /* 146 */ "Clear" OpHelp(""), - /* 147 */ "ResetSorter" OpHelp(""), - /* 148 */ "CreateBtree" OpHelp("r[P2]=root iDb=P1 flags=P3"), - /* 149 */ "SqlExec" OpHelp(""), - /* 150 */ "ParseSchema" OpHelp(""), - /* 151 */ "LoadAnalysis" OpHelp(""), - /* 152 */ "DropTable" OpHelp(""), - /* 153 */ "DropIndex" OpHelp(""), + /* 119 */ "SorterOpen" OpHelp(""), + /* 120 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"), + /* 121 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"), + /* 122 */ "Close" OpHelp(""), + /* 123 */ "ColumnsUsed" OpHelp(""), + /* 124 */ "SeekScan" OpHelp("Scan-ahead up to P1 rows"), + /* 125 */ "SeekHit" OpHelp("set P2<=seekHit<=P3"), + /* 126 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"), + /* 127 */ "NewRowid" OpHelp("r[P2]=rowid"), + /* 128 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"), + /* 129 */ "RowCell" OpHelp(""), + /* 130 */ "Delete" OpHelp(""), + /* 131 */ "ResetCount" OpHelp(""), + /* 132 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"), + /* 133 */ "SorterData" OpHelp("r[P2]=data"), + /* 134 */ "RowData" OpHelp("r[P2]=data"), + /* 135 */ "Rowid" OpHelp("r[P2]=PX rowid of P1"), + /* 136 */ "NullRow" OpHelp(""), + /* 137 */ "SeekEnd" OpHelp(""), + /* 138 */ "IdxInsert" OpHelp("key=r[P2]"), + /* 139 */ "SorterInsert" OpHelp("key=r[P2]"), + /* 140 */ "IdxDelete" OpHelp("key=r[P2@P3]"), + /* 141 */ "DeferredSeek" OpHelp("Move P3 to P1.rowid if needed"), + /* 142 */ "IdxRowid" OpHelp("r[P2]=rowid"), + /* 143 */ "FinishSeek" OpHelp(""), + /* 144 */ "Destroy" OpHelp(""), + /* 145 */ "Clear" OpHelp(""), + /* 146 */ "ResetSorter" OpHelp(""), + /* 147 */ "CreateBtree" OpHelp("r[P2]=root iDb=P1 flags=P3"), + /* 148 */ "SqlExec" OpHelp(""), + /* 149 */ "ParseSchema" OpHelp(""), + /* 150 */ "LoadAnalysis" OpHelp(""), + /* 151 */ "DropTable" OpHelp(""), + /* 152 */ "DropIndex" OpHelp(""), + /* 153 */ "DropTrigger" OpHelp(""), /* 154 */ "Real" OpHelp("r[P2]=P4"), - /* 155 */ "DropTrigger" OpHelp(""), - /* 156 */ "IntegrityCk" OpHelp(""), - /* 157 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"), - /* 158 */ "Param" OpHelp(""), - /* 159 */ "FkCounter" OpHelp("fkctr[P1]+=P2"), - /* 160 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"), - /* 161 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"), - /* 162 */ "AggInverse" OpHelp("accum=r[P3] inverse(r[P2@P5])"), - /* 163 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"), - /* 164 */ "AggStep1" OpHelp("accum=r[P3] step(r[P2@P5])"), - /* 165 */ "AggValue" OpHelp("r[P3]=value N=P2"), - /* 166 */ "AggFinal" OpHelp("accum=r[P1] N=P2"), - /* 167 */ "Expire" OpHelp(""), - /* 168 */ "CursorLock" OpHelp(""), - /* 169 */ "CursorUnlock" OpHelp(""), - /* 170 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"), - /* 171 */ "VBegin" OpHelp(""), - /* 172 */ "VCreate" OpHelp(""), - /* 173 */ "VDestroy" OpHelp(""), - /* 174 */ "VOpen" OpHelp(""), - /* 175 */ "VCheck" OpHelp(""), - /* 176 */ "VInitIn" OpHelp("r[P2]=ValueList(P1,P3)"), - /* 177 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"), - /* 178 */ "VRename" OpHelp(""), - /* 179 */ "Pagecount" OpHelp(""), - /* 180 */ "MaxPgcnt" OpHelp(""), - /* 181 */ "ClrSubtype" OpHelp("r[P1].subtype = 0"), - /* 182 */ "GetSubtype" OpHelp("r[P2] = r[P1].subtype"), - /* 183 */ "SetSubtype" OpHelp("r[P2].subtype = r[P1]"), - /* 184 */ "FilterAdd" OpHelp("filter(P1) += key(P3@P4)"), - /* 185 */ "Trace" OpHelp(""), - /* 186 */ "CursorHint" OpHelp(""), - /* 187 */ "ReleaseReg" OpHelp("release r[P1@P2] mask P3"), - /* 188 */ "Noop" OpHelp(""), - /* 189 */ "Explain" OpHelp(""), - /* 190 */ "Abortable" OpHelp(""), + /* 155 */ "IntegrityCk" OpHelp(""), + /* 156 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"), + /* 157 */ "Param" OpHelp(""), + /* 158 */ "FkCounter" OpHelp("fkctr[P1]+=P2"), + /* 159 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"), + /* 160 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"), + /* 161 */ "AggInverse" OpHelp("accum=r[P3] inverse(r[P2@P5])"), + /* 162 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"), + /* 163 */ "AggStep1" OpHelp("accum=r[P3] step(r[P2@P5])"), + /* 164 */ "AggValue" OpHelp("r[P3]=value N=P2"), + /* 165 */ "AggFinal" OpHelp("accum=r[P1] N=P2"), + /* 166 */ "Expire" OpHelp(""), + /* 167 */ "CursorLock" OpHelp(""), + /* 168 */ "CursorUnlock" OpHelp(""), + /* 169 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"), + /* 170 */ "VBegin" OpHelp(""), + /* 171 */ "VCreate" OpHelp(""), + /* 172 */ "VDestroy" OpHelp(""), + /* 173 */ "VOpen" OpHelp(""), + /* 174 */ "VCheck" OpHelp(""), + /* 175 */ "VInitIn" OpHelp("r[P2]=ValueList(P1,P3)"), + /* 176 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"), + /* 177 */ "VRename" OpHelp(""), + /* 178 */ "Pagecount" OpHelp(""), + /* 179 */ "MaxPgcnt" OpHelp(""), + /* 180 */ "ClrSubtype" OpHelp("r[P1].subtype = 0"), + /* 181 */ "GetSubtype" OpHelp("r[P2] = r[P1].subtype"), + /* 182 */ "SetSubtype" OpHelp("r[P2].subtype = r[P1]"), + /* 183 */ "FilterAdd" OpHelp("filter(P1) += key(P3@P4)"), + /* 184 */ "Trace" OpHelp(""), + /* 185 */ "CursorHint" OpHelp(""), + /* 186 */ "ReleaseReg" OpHelp("release r[P1@P2] mask P3"), + /* 187 */ "Noop" OpHelp(""), + /* 188 */ "Explain" OpHelp(""), + /* 189 */ "Abortable" OpHelp(""), }; return azName[i]; } @@ -38392,7 +38035,7 @@ static int kvstorageRead(const char*, const char *zKey, char *zBuf, int nBuf); #define KVSTORAGE_KEY_SZ 32 /* Expand the key name with an appropriate prefix and put the result -** in zKeyOut[]. The zKeyOut[] buffer is assumed to hold at least +** zKeyOut[]. The zKeyOut[] buffer is assumed to hold at least ** KVSTORAGE_KEY_SZ bytes. */ static void kvstorageMakeKey( @@ -38451,12 +38094,10 @@ static int kvstorageDelete(const char *zClass, const char *zKey){ ** ** Return the total number of bytes in the data, without truncation, and ** not counting the final zero terminator. Return -1 if the key does -** not exist or its key cannot be read. +** not exist. ** -** If nBuf<=0 then this routine simply returns the size of the data -** without actually reading it. Similarly, if nBuf==1 then it -** zero-terminates zBuf at zBuf[0] and returns the size of the data -** without reading it. +** If nBuf<=0 then this routine simply returns the size of the data without +** actually reading it. */ static int kvstorageRead( const char *zClass, @@ -38505,9 +38146,11 @@ static int kvstorageRead( ** kvvfs i/o methods with JavaScript implementations in WASM builds. ** Maintenance reminder: if this struct changes in any way, the JSON ** rendering of its structure must be updated in -** sqlite3-wasm.c:sqlite3__wasm_enum_json(). There are no binary -** compatibility concerns, so it does not need an iVersion -** member. +** sqlite3_wasm_enum_json(). There are no binary compatibility +** concerns, so it does not need an iVersion member. This file is +** necessarily always compiled together with sqlite3_wasm_enum_json(), +** and JS code dynamically creates the mapping of members based on +** that JSON description. */ typedef struct sqlite3_kvvfs_methods sqlite3_kvvfs_methods; struct sqlite3_kvvfs_methods { @@ -38524,8 +38167,8 @@ struct sqlite3_kvvfs_methods { ** the compiler can hopefully optimize this level of indirection out. ** That said, kvvfs is intended primarily for use in WASM builds. ** -** This is not explicitly flagged as static because the amalgamation -** build will tag it with SQLITE_PRIVATE. +** Note that this is not explicitly flagged as static because the +** amalgamation build will tag it with SQLITE_PRIVATE. */ #ifndef SQLITE_WASM const @@ -39698,11 +39341,10 @@ static struct unix_syscall { #if defined(HAVE_FCHMOD) { "fchmod", (sqlite3_syscall_ptr)fchmod, 0 }, -#define osFchmod ((int(*)(int,mode_t))aSyscall[14].pCurrent) #else { "fchmod", (sqlite3_syscall_ptr)0, 0 }, -#define osFchmod(FID,MODE) 0 #endif +#define osFchmod ((int(*)(int,mode_t))aSyscall[14].pCurrent) #if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE { "fallocate", (sqlite3_syscall_ptr)posix_fallocate, 0 }, @@ -39796,119 +39438,6 @@ static struct unix_syscall { }; /* End of the overrideable system calls */ -#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_FILESTAT) -/* -** Extract Posix Advisory Locking information about file description fd -** from the /proc/PID/fdinfo/FD pseudo-file. Fill the string buffer a[16] -** with characters to indicate which SQLite-relevant locks are held. -** a[16] will be a 15-character zero-terminated string with the following -** schema: -** -** AAA/B.DDD.DDDDD -** -** Each of character A-D will be "w" or "r" or "-" to indicate either a -** write-lock, a read-lock, or no-lock, respectively. The "." and "/" -** characters are delimiters intended to make the string more easily -** readable by humans. Here are the meaning of the specific letters: -** -** AAA -> The main database locks. PENDING_BYTE, RESERVED_BYTE, -** and SHARED_FIRST, respectively. -** -** B -> The deadman switch lock. Offset 128 of the -shm file. -** -** CCC -> WAL locks: WRITE, CKPT, RECOVER -** -** DDDDD -> WAL read-locks 0 through 5 -** -** Note that elements before the "/" apply to the main database file and -** elements after the "/" apply to the -shm file in WAL mode. -** -** Here is another way of thinking about the meaning of the result string: -** -** AAA/B.CCC.DDDDD -** ||| | ||| \___/ -** PENDING--'|| | ||| `----- READ 0-5 -** RESERVED--'| | ||`---- RECOVER -** SHARED ----' | |`----- CKPT -** DMS ------' `------ WRITE -** -** Return SQLITE_OK on success and SQLITE_ERROR_UNABLE if the /proc -** pseudo-filesystem is unavailable. -*/ -static int unixPosixAdvisoryLocks( - int fd, /* The file descriptor to analyze */ - char a[16] /* Write a text description of PALs here */ -){ - int in; - ssize_t n; - char *p, *pNext, *x; - char z[2000]; - - /* 1 */ - /* 012 4 678 01234 */ - memcpy(a, "---/-.---.-----", 16); - sqlite3_snprintf(sizeof(z), z, "/proc/%d/fdinfo/%d", getpid(), fd); - in = osOpen(z, O_RDONLY, 0); - if( in<0 ){ - return SQLITE_ERROR_UNABLE; - } - n = osRead(in, z, sizeof(z)-1); - osClose(in); - if( n<=0 ) return SQLITE_ERROR_UNABLE; - z[n] = 0; - - /* We are looking for lines that begin with "lock:\t". Examples: - ** - ** lock: 1: POSIX ADVISORY READ 494716 08:02:5277597 1073741826 1073742335 - ** lock: 1: POSIX ADVISORY WRITE 494716 08:02:5282282 120 120 - ** lock: 2: POSIX ADVISORY READ 494716 08:02:5282282 123 123 - ** lock: 3: POSIX ADVISORY READ 494716 08:02:5282282 128 128 - */ - pNext = strstr(z, "lock:\t"); - while( pNext ){ - char cType = 0; - sqlite3_int64 iFirst, iLast; - p = pNext+6; - pNext = strstr(p, "lock:\t"); - if( pNext ) pNext[-1] = 0; - if( (x = strstr(p, " READ "))!=0 ){ - cType = 'r'; - x += 6; - }else if( (x = strstr(p, " WRITE "))!=0 ){ - cType = 'w'; - x += 7; - }else{ - continue; - } - x = strrchr(x, ' '); - if( x==0 ) continue; - iLast = strtoll(x+1, 0, 10); - *x = 0; - x = strrchr(p, ' '); - if( x==0 ) continue; - iFirst = strtoll(x+1, 0, 10); - if( iLast>=PENDING_BYTE ){ - if( iFirst<=PENDING_BYTE && iLast>=PENDING_BYTE ) a[0] = cType; - if( iFirst<=PENDING_BYTE+1 && iLast>=PENDING_BYTE+1 ) a[1] = cType; - if( iFirst<=PENDING_BYTE+2 && iLast>=PENDING_BYTE+510 ) a[2] = cType; - }else if( iLast<=128 ){ - if( iFirst<=128 && iLast>=128 ) a[4] = cType; - if( iFirst<=120 && iLast>=120 ) a[6] = cType; - if( iFirst<=121 && iLast>=121 ) a[7] = cType; - if( iFirst<=122 && iLast>=122 ) a[8] = cType; - if( iFirst<=123 && iLast>=123 ) a[10] = cType; - if( iFirst<=124 && iLast>=124 ) a[11] = cType; - if( iFirst<=125 && iLast>=125 ) a[12] = cType; - if( iFirst<=126 && iLast>=126 ) a[13] = cType; - if( iFirst<=127 && iLast>=127 ) a[14] = cType; - } - } - return SQLITE_OK; -} -#else -# define unixPosixAdvisoryLocks(A,B) SQLITE_ERROR_UNABLE -#endif /* SQLITE_DEBUG || SQLITE_ENABLE_FILESTAT */ - /* ** On some systems, calls to fchown() will trigger a message in a security ** log if they come from non-root processes. So avoid calling fchown() if @@ -40073,8 +39602,9 @@ static int robust_open(const char *z, int f, mode_t m){ /* ** Helper functions to obtain and relinquish the global mutex. The -** global mutex is used to protect the unixInodeInfo objects used by -** this file, all of which may be shared by multiple threads. +** global mutex is used to protect the unixInodeInfo and +** vxworksFileId objects used by this file, all of which may be +** shared by multiple threads. ** ** Function unixMutexHeld() is used to assert() that the global mutex ** is held when required. This function is only used as part of assert() @@ -40276,7 +39806,6 @@ struct vxworksFileId { ** variable: */ static struct vxworksFileId *vxworksFileList = 0; -static sqlite3_mutex *vxworksMutex = 0; /* ** Simplify a filename into its canonical form @@ -40342,14 +39871,14 @@ static struct vxworksFileId *vxworksFindFileId(const char *zAbsoluteName){ ** If found, increment the reference count and return a pointer to ** the existing file ID. */ - sqlite3_mutex_enter(vxworksMutex); + unixEnterMutex(); for(pCandidate=vxworksFileList; pCandidate; pCandidate=pCandidate->pNext){ if( pCandidate->nName==n && memcmp(pCandidate->zCanonicalName, pNew->zCanonicalName, n)==0 ){ sqlite3_free(pNew); pCandidate->nRef++; - sqlite3_mutex_leave(vxworksMutex); + unixLeaveMutex(); return pCandidate; } } @@ -40359,7 +39888,7 @@ static struct vxworksFileId *vxworksFindFileId(const char *zAbsoluteName){ pNew->nName = n; pNew->pNext = vxworksFileList; vxworksFileList = pNew; - sqlite3_mutex_leave(vxworksMutex); + unixLeaveMutex(); return pNew; } @@ -40368,7 +39897,7 @@ static struct vxworksFileId *vxworksFindFileId(const char *zAbsoluteName){ ** the object when the reference count reaches zero. */ static void vxworksReleaseFileId(struct vxworksFileId *pId){ - sqlite3_mutex_enter(vxworksMutex); + unixEnterMutex(); assert( pId->nRef>0 ); pId->nRef--; if( pId->nRef==0 ){ @@ -40378,7 +39907,7 @@ static void vxworksReleaseFileId(struct vxworksFileId *pId){ *pp = pId->pNext; sqlite3_free(pId); } - sqlite3_mutex_leave(vxworksMutex); + unixLeaveMutex(); } #endif /* OS_VXWORKS */ /*************** End of Unique File ID Utility Used By VxWorks **************** @@ -40766,10 +40295,6 @@ static int findInodeInfo( storeLastErrno(pFile, errno); return SQLITE_IOERR; } - if( fsync(fd) ){ - storeLastErrno(pFile, errno); - return SQLITE_IOERR_FSYNC; - } rc = osFstat(fd, &statbuf); if( rc!=0 ){ storeLastErrno(pFile, errno); @@ -40939,42 +40464,18 @@ static int osSetPosixAdvisoryLock( struct flock *pLock, /* The description of the lock */ unixFile *pFile /* Structure holding timeout value */ ){ - int rc = 0; - - if( pFile->iBusyTimeout==0 ){ - /* unixFile->iBusyTimeout is set to 0. In this case, attempt a - ** non-blocking lock. */ - rc = osFcntl(h,F_SETLK,pLock); - }else{ - /* unixFile->iBusyTimeout is set to greater than zero. In this case, - ** attempt a blocking-lock with a unixFile->iBusyTimeout ms timeout. - ** - ** On systems that support some kind of blocking file lock operation, - ** this block should be replaced by code to attempt a blocking lock - ** with a timeout of unixFile->iBusyTimeout ms. The code below is - ** placeholder code. If SQLITE_TEST is defined, the placeholder code - ** retries the lock once every 1ms until it succeeds or the timeout - ** is reached. Or, if SQLITE_TEST is not defined, the placeholder - ** code attempts a non-blocking lock and sets unixFile->iBusyTimeout - ** to 0. This causes the caller to return SQLITE_BUSY, instead of - ** SQLITE_BUSY_TIMEOUT to SQLite - as required by a VFS that does not - ** support blocking locks. - */ -#ifdef SQLITE_TEST - int tm = pFile->iBusyTimeout; - while( tm>0 ){ - rc = osFcntl(h,F_SETLK,pLock); - if( rc==0 ) break; - unixSleep(0,1000); - tm--; - } -#else + int tm = pFile->iBusyTimeout; + int rc = osFcntl(h,F_SETLK,pLock); + while( rc<0 && tm>0 ){ + /* On systems that support some kind of blocking file lock with a timeout, + ** make appropriate changes here to invoke that blocking file lock. On + ** generic posix, however, there is no such API. So we simply try the + ** lock once every millisecond until either the timeout expires, or until + ** the lock is obtained. */ + unixSleep(0,1000); rc = osFcntl(h,F_SETLK,pLock); - pFile->iBusyTimeout = 0; -#endif - /* End of code to replace with real blocking-locks code. */ + tm--; } - return rc; } #endif /* SQLITE_ENABLE_SETLK_TIMEOUT */ @@ -41032,13 +40533,6 @@ static int unixFileLock(unixFile *pFile, struct flock *pLock){ return rc; } -#if !defined(SQLITE_WASI) && !defined(SQLITE_OMIT_WAL) -/* Forward reference */ -static int unixIsSharingShmNode(unixFile*); -#else -#define unixIsSharingShmNode(pFile) (0) -#endif - /* ** Lock the file with the lock specified by parameter eFileLock - one ** of the following: @@ -41227,9 +40721,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){ pInode->nLock++; pInode->nShared = 1; } - }else if( (eFileLock==EXCLUSIVE_LOCK && pInode->nShared>1) - || unixIsSharingShmNode(pFile) - ){ + }else if( eFileLock==EXCLUSIVE_LOCK && pInode->nShared>1 ){ /* We are trying for an exclusive lock but another thread in this ** same process is still holding a shared lock. */ rc = SQLITE_BUSY; @@ -43324,10 +42816,6 @@ static int unixGetTempname(int nBuf, char *zBuf); #if !defined(SQLITE_WASI) && !defined(SQLITE_OMIT_WAL) static int unixFcntlExternalReader(unixFile*, int*); #endif -#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_FILESTAT) - static void unixDescribeShm(sqlite3_str*,unixShm*); -#endif - /* ** Information and control of an open file handle. @@ -43470,66 +42958,6 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){ return SQLITE_OK; #endif } - -#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_FILESTAT) - case SQLITE_FCNTL_FILESTAT: { - sqlite3_str *pStr = (sqlite3_str*)pArg; - char aLck[16]; - unixInodeInfo *pInode; - static const char *azLock[] = { "SHARED", "RESERVED", - "PENDING", "EXCLUSIVE" }; - sqlite3_str_appendf(pStr, "{\"h\":%d", pFile->h); - sqlite3_str_appendf(pStr, ",\"vfs\":\"%s\"", pFile->pVfs->zName); - if( pFile->eFileLock ){ - sqlite3_str_appendf(pStr, ",\"eFileLock\":\"%s\"", - azLock[pFile->eFileLock-1]); - if( unixPosixAdvisoryLocks(pFile->h, aLck)==SQLITE_OK ){ - sqlite3_str_appendf(pStr, ",\"pal\":\"%s\"", aLck); - } - } - unixEnterMutex(); - if( pFile->pShm ){ - sqlite3_str_appendall(pStr, ",\"shm\":"); - unixDescribeShm(pStr, pFile->pShm); - } -#if SQLITE_MAX_MMAP_SIZE>0 - if( pFile->mmapSize ){ - sqlite3_str_appendf(pStr, ",\"mmapSize\":%lld", pFile->mmapSize); - sqlite3_str_appendf(pStr, ",\"nFetchOut\":%d", pFile->nFetchOut); - } -#endif - if( (pInode = pFile->pInode)!=0 ){ - sqlite3_str_appendf(pStr, ",\"inode\":{\"nRef\":%d",pInode->nRef); - sqlite3_mutex_enter(pInode->pLockMutex); - sqlite3_str_appendf(pStr, ",\"nShared\":%d", pInode->nShared); - if( pInode->eFileLock ){ - sqlite3_str_appendf(pStr, ",\"eFileLock\":\"%s\"", - azLock[pInode->eFileLock-1]); - } - if( pInode->pUnused ){ - char cSep = '['; - UnixUnusedFd *pUFd = pFile->pInode->pUnused; - sqlite3_str_appendall(pStr, ",\"unusedFd\":"); - while( pUFd ){ - sqlite3_str_appendf(pStr, "%c{\"fd\":%d,\"flags\":%d", - cSep, pUFd->fd, pUFd->flags); - cSep = ','; - if( unixPosixAdvisoryLocks(pUFd->fd, aLck)==SQLITE_OK ){ - sqlite3_str_appendf(pStr, ",\"pal\":\"%s\"", aLck); - } - sqlite3_str_append(pStr, "}", 1); - pUFd = pUFd->pNext; - } - sqlite3_str_append(pStr, "]", 1); - } - sqlite3_mutex_leave(pInode->pLockMutex); - sqlite3_str_append(pStr, "}", 1); - } - unixLeaveMutex(); - sqlite3_str_append(pStr, "}", 1); - return SQLITE_OK; - } -#endif /* SQLITE_DEBUG || SQLITE_ENABLE_FILESTAT */ } return SQLITE_NOTFOUND; } @@ -43796,26 +43224,6 @@ struct unixShm { #define UNIX_SHM_BASE ((22+SQLITE_SHM_NLOCK)*4) /* first lock byte */ #define UNIX_SHM_DMS (UNIX_SHM_BASE+SQLITE_SHM_NLOCK) /* deadman switch */ -#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_FILESTAT) -/* -** Describe the pShm object using JSON. Used for diagnostics only. -*/ -static void unixDescribeShm(sqlite3_str *pStr, unixShm *pShm){ - unixShmNode *pNode = pShm->pShmNode; - char aLck[16]; - sqlite3_str_appendf(pStr, "{\"h\":%d", pNode->hShm); - assert( unixMutexHeld() ); - sqlite3_str_appendf(pStr, ",\"nRef\":%d", pNode->nRef); - sqlite3_str_appendf(pStr, ",\"id\":%d", pShm->id); - sqlite3_str_appendf(pStr, ",\"sharedMask\":%d", pShm->sharedMask); - sqlite3_str_appendf(pStr, ",\"exclMask\":%d", pShm->exclMask); - if( unixPosixAdvisoryLocks(pNode->hShm, aLck)==SQLITE_OK ){ - sqlite3_str_appendf(pStr, ",\"pal\":\"%s\"", aLck); - } - sqlite3_str_append(pStr, "}", 1); -} -#endif /* SQLITE_DEBUG || SQLITE_ENABLE_FILESTAT */ - /* ** Use F_GETLK to check whether or not there are any readers with open ** wal-mode transactions in other processes on database file pFile. If @@ -43849,49 +43257,6 @@ static int unixFcntlExternalReader(unixFile *pFile, int *piOut){ return rc; } -/* -** If pFile has a -shm file open and it is sharing that file with some -** other connection, either in the same process or in a separate process, -** then return true. Return false if either pFile does not have a -shm -** file open or if it is the only connection to that -shm file across the -** entire system. -** -** This routine is not required for correct operation. It can always return -** false and SQLite will continue to operate according to spec. However, -** when this routine does its job, it adds extra robustness in cases -** where database file locks have been erroneously deleted in a WAL-mode -** database by doing close(open(DATABASE_PATHNAME)) or similar. -** -** With false negatives, SQLite still operates to spec, though with less -** robustness. With false positives, the last database connection on a -** WAL-mode database will fail to unlink the -wal and -shm files, which -** is annoying but harmless. False positives will also prevent a database -** connection from running "PRAGMA journal_mode=DELETE" in order to take -** the database out of WAL mode, which is perhaps more serious, but is -** still not a disaster. -*/ -static int unixIsSharingShmNode(unixFile *pFile){ - int rc; - unixShmNode *pShmNode; - if( pFile->pShm==0 ) return 0; - if( pFile->ctrlFlags & UNIXFILE_EXCL ) return 0; - pShmNode = pFile->pShm->pShmNode; - rc = 1; - unixEnterMutex(); - if( ALWAYS(pShmNode->nRef==1) ){ - struct flock lock; - lock.l_whence = SEEK_SET; - lock.l_start = UNIX_SHM_DMS; - lock.l_len = 1; - lock.l_type = F_WRLCK; - osFcntl(pShmNode->hShm, F_GETLK, &lock); - if( lock.l_type==F_UNLCK ){ - rc = 0; - } - } - unixLeaveMutex(); - return rc; -} /* ** Apply posix advisory locks for all bytes from ofst through ofst+n-1. @@ -43937,8 +43302,7 @@ static int unixShmSystemLock( /* Locks are within range */ assert( n>=1 && n<=SQLITE_SHM_NLOCK ); - assert( ofst>=UNIX_SHM_BASE && ofst<=UNIX_SHM_DMS ); - assert( ofst+n-1<=UNIX_SHM_DMS ); + assert( ofst>=UNIX_SHM_BASE && ofst<=(UNIX_SHM_DMS+SQLITE_SHM_NLOCK) ); if( pShmNode->hShm>=0 ){ int res; @@ -44470,7 +43834,7 @@ static int assertLockingArrayOk(unixShmNode *pShmNode){ return (memcmp(pShmNode->aLock, aLock, sizeof(aLock))==0); #endif } -#endif /* !defined(SQLITE_WASI) && !defined(SQLITE_OMIT_WAL) */ +#endif /* ** Change the lock state for a shared-memory segment. @@ -45432,17 +44796,10 @@ static int fillInUnixFile( storeLastErrno(pNew, 0); #if OS_VXWORKS if( rc!=SQLITE_OK ){ - if( h>=0 ){ - robust_close(pNew, h, __LINE__); - h = -1; - } - if( pNew->ctrlFlags & UNIXFILE_DELETE ){ - osUnlink(zFilename); - } - if( pNew->pId ){ - vxworksReleaseFileId(pNew->pId); - pNew->pId = 0; - } + if( h>=0 ) robust_close(pNew, h, __LINE__); + h = -1; + osUnlink(zFilename); + pNew->ctrlFlags |= UNIXFILE_DELETE; } #endif if( rc!=SQLITE_OK ){ @@ -45486,9 +44843,6 @@ static const char *unixTempFileDir(void){ while(1){ if( zDir!=0 -#if OS_VXWORKS - && zDir[0]=='/' -#endif && osStat(zDir, &buf)==0 && S_ISDIR(buf.st_mode) && osAccess(zDir, 03)==0 @@ -45803,12 +45157,6 @@ static int unixOpen( || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL ); -#if OS_VXWORKS - /* The file-ID mechanism used in Vxworks requires that all pathnames - ** provided to unixOpen must be absolute pathnames. */ - if( zPath!=0 && zPath[0]!='/' ){ return SQLITE_CANTOPEN; } -#endif - /* Detect a pid change and reset the PRNG. There is a race condition ** here such that two or more threads all trying to open databases at ** the same instant might all reset the PRNG. But multiple resets @@ -46009,11 +45357,8 @@ static int unixOpen( } #endif - assert( zPath==0 - || zPath[0]=='/' - || eType==SQLITE_OPEN_SUPER_JOURNAL - || eType==SQLITE_OPEN_MAIN_JOURNAL - || eType==SQLITE_OPEN_TEMP_JOURNAL + assert( zPath==0 || zPath[0]=='/' + || eType==SQLITE_OPEN_SUPER_JOURNAL || eType==SQLITE_OPEN_MAIN_JOURNAL ); rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags); @@ -47742,9 +47087,6 @@ SQLITE_API int sqlite3_os_init(void){ sqlite3KvvfsInit(); #endif unixBigLock = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1); -#if OS_VXWORKS - vxworksMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS2); -#endif #ifndef SQLITE_OMIT_WAL /* Validate lock assumptions */ @@ -47779,9 +47121,6 @@ SQLITE_API int sqlite3_os_init(void){ */ SQLITE_API int sqlite3_os_end(void){ unixBigLock = 0; -#if OS_VXWORKS - vxworksMutex = 0; -#endif return SQLITE_OK; } @@ -50454,7 +49793,6 @@ static BOOL winLockFile( #endif } -#ifndef SQLITE_OMIT_WAL /* ** Lock a region of nByte bytes starting at offset offset of file hFile. ** Take an EXCLUSIVE lock if parameter bExclusive is true, or a SHARED lock @@ -50537,7 +49875,6 @@ static int winHandleLockTimeout( } return rc; } -#endif /* #ifndef SQLITE_OMIT_WAL */ /* ** Unlock a file region. @@ -50572,7 +49909,6 @@ static BOOL winUnlockFile( #endif } -#ifndef SQLITE_OMIT_WAL /* ** Remove an nByte lock starting at offset iOff from HANDLE h. */ @@ -50580,7 +49916,6 @@ static int winHandleUnlock(HANDLE h, int iOff, int nByte){ BOOL ret = winUnlockFile(&h, iOff, 0, nByte, 0); return (ret ? SQLITE_OK : SQLITE_IOERR_UNLOCK); } -#endif /***************************************************************************** ** The next group of routines implement the I/O methods specified @@ -50918,7 +50253,6 @@ static int winWrite( return SQLITE_OK; } -#ifndef SQLITE_OMIT_WAL /* ** Truncate the file opened by handle h to nByte bytes in size. */ @@ -50972,7 +50306,6 @@ static void winHandleClose(HANDLE h){ osCloseHandle(h); } } -#endif /* #ifndef SQLITE_OMIT_WAL */ /* ** Truncate an open file to a specified size @@ -51750,28 +51083,6 @@ static int winFileControl(sqlite3_file *id, int op, void *pArg){ } #endif /* SQLITE_ENABLE_SETLK_TIMEOUT */ -#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_FILESTAT) - case SQLITE_FCNTL_FILESTAT: { - sqlite3_str *pStr = (sqlite3_str*)pArg; - sqlite3_str_appendf(pStr, "{\"h\":%llu", (sqlite3_uint64)pFile->h); - sqlite3_str_appendf(pStr, ",\"vfs\":\"%s\"", pFile->pVfs->zName); - if( pFile->locktype ){ - static const char *azLock[] = { "SHARED", "RESERVED", - "PENDING", "EXCLUSIVE" }; - sqlite3_str_appendf(pStr, ",\"locktype\":\"%s\"", - azLock[pFile->locktype-1]); - } -#if SQLITE_MAX_MMAP_SIZE>0 - if( pFile->mmapSize ){ - sqlite3_str_appendf(pStr, ",\"mmapSize\":%lld", pFile->mmapSize); - sqlite3_str_appendf(pStr, ",\"nFetchOut\":%d", pFile->nFetchOut); - } -#endif - sqlite3_str_append(pStr, "}", 1); - return SQLITE_OK; - } -#endif /* SQLITE_DEBUG || SQLITE_ENABLE_FILESTAT */ - } OSTRACE(("FCNTL file=%p, rc=SQLITE_NOTFOUND\n", pFile->h)); return SQLITE_NOTFOUND; @@ -51809,103 +51120,6 @@ static int winDeviceCharacteristics(sqlite3_file *id){ */ static SYSTEM_INFO winSysInfo; -/* -** Convert a UTF-8 filename into whatever form the underlying -** operating system wants filenames in. Space to hold the result -** is obtained from malloc and must be freed by the calling -** function -** -** On Cygwin, 3 possible input forms are accepted: -** - If the filename starts with "<drive>:/" or "<drive>:\", -** it is converted to UTF-16 as-is. -** - If the filename contains '/', it is assumed to be a -** Cygwin absolute path, it is converted to a win32 -** absolute path in UTF-16. -** - Otherwise it must be a filename only, the win32 filename -** is returned in UTF-16. -** Note: If the function cygwin_conv_path() fails, only -** UTF-8 -> UTF-16 conversion will be done. This can only -** happen when the file path >32k, in which case winUtf8ToUnicode() -** will fail too. -*/ -static void *winConvertFromUtf8Filename(const char *zFilename){ - void *zConverted = 0; - if( osIsNT() ){ -#ifdef __CYGWIN__ - int nChar; - LPWSTR zWideFilename; - - if( osCygwin_conv_path && !(winIsDriveLetterAndColon(zFilename) - && winIsDirSep(zFilename[2])) ){ - i64 nByte; - int convertflag = CCP_POSIX_TO_WIN_W; - if( !strchr(zFilename, '/') ) convertflag |= CCP_RELATIVE; - nByte = (i64)osCygwin_conv_path(convertflag, - zFilename, 0, 0); - if( nByte>0 ){ - zConverted = sqlite3MallocZero(12+(u64)nByte); - if ( zConverted==0 ){ - return zConverted; - } - zWideFilename = zConverted; - /* Filenames should be prefixed, except when converted - * full path already starts with "\\?\". */ - if( osCygwin_conv_path(convertflag, zFilename, - zWideFilename+4, nByte)==0 ){ - if( (convertflag&CCP_RELATIVE) ){ - memmove(zWideFilename, zWideFilename+4, nByte); - }else if( memcmp(zWideFilename+4, L"\\\\", 4) ){ - memcpy(zWideFilename, L"\\\\?\\", 8); - }else if( zWideFilename[6]!='?' ){ - memmove(zWideFilename+6, zWideFilename+4, nByte); - memcpy(zWideFilename, L"\\\\?\\UNC", 14); - }else{ - memmove(zWideFilename, zWideFilename+4, nByte); - } - return zConverted; - } - sqlite3_free(zConverted); - } - } - nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0); - if( nChar==0 ){ - return 0; - } - zWideFilename = sqlite3MallocZero( nChar*sizeof(WCHAR)+12 ); - if( zWideFilename==0 ){ - return 0; - } - nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1, - zWideFilename, nChar); - if( nChar==0 ){ - sqlite3_free(zWideFilename); - zWideFilename = 0; - }else if( nChar>MAX_PATH - && winIsDriveLetterAndColon(zFilename) - && winIsDirSep(zFilename[2]) ){ - memmove(zWideFilename+4, zWideFilename, nChar*sizeof(WCHAR)); - zWideFilename[2] = '\\'; - memcpy(zWideFilename, L"\\\\?\\", 8); - }else if( nChar>MAX_PATH - && winIsDirSep(zFilename[0]) && winIsDirSep(zFilename[1]) - && zFilename[2] != '?' ){ - memmove(zWideFilename+6, zWideFilename, nChar*sizeof(WCHAR)); - memcpy(zWideFilename, L"\\\\?\\UNC", 14); - } - zConverted = zWideFilename; -#else - zConverted = winUtf8ToUnicode(zFilename); -#endif /* __CYGWIN__ */ - } -#if defined(SQLITE_WIN32_HAS_ANSI) && defined(_WIN32) - else{ - zConverted = winUtf8ToMbcs(zFilename, osAreFileApisANSI()); - } -#endif - /* caller will handle out of memory */ - return zConverted; -} - #ifndef SQLITE_OMIT_WAL /* @@ -51942,35 +51156,29 @@ static int winShmMutexHeld(void) { ** log-summary is opened only once per process. ** ** winShmMutexHeld() must be true when creating or destroying -** this object, or while editing the global linked list that starts -** at winShmNodeList. +** this object or while reading or writing the following fields: ** -** When reading or writing the linked list starting at winShmNode.pWinShmList, -** pShmNode->mutex must be held. +** nRef +** pNext ** -** The following fields are constant after the object is created: +** The following fields are read-only after the object is created: ** ** zFilename -** hSharedShm -** mutex -** bUseSharedLockHandle ** -** Either winShmNode.mutex must be held or winShmNode.pWinShmList==0 and +** Either winShmNode.mutex must be held or winShmNode.nRef==0 and ** winShmMutexHeld() is true when reading or writing any other field ** in this structure. ** -** File-handle hSharedShm is always used to (a) take the DMS lock, (b) -** truncate the *-shm file if the DMS-locking protocol demands it, and -** (c) map regions of the *-shm file into memory using MapViewOfFile() -** or similar. If bUseSharedLockHandle is true, then other locks are also -** taken on hSharedShm. Or, if bUseSharedLockHandle is false, then other -** locks are taken using each connection's winShm.hShm handles. +** File-handle hSharedShm is used to (a) take the DMS lock, (b) truncate +** the *-shm file if the DMS-locking protocol demands it, and (c) map +** regions of the *-shm file into memory using MapViewOfFile() or +** similar. Other locks are taken by individual clients using the +** winShm.hShm handles. */ struct winShmNode { sqlite3_mutex *mutex; /* Mutex to access this object */ char *zFilename; /* Name of the file */ HANDLE hSharedShm; /* File handle open on zFilename */ - int bUseSharedLockHandle; /* True to use hSharedShm for everything */ int isUnlocked; /* DMS lock has not yet been obtained */ int isReadonly; /* True if read-only */ @@ -51983,8 +51191,7 @@ struct winShmNode { } *aRegion; DWORD lastErrno; /* The Windows errno from the last I/O error */ - winShm *pWinShmList; /* List of winShm objects with ptrs to this */ - + int nRef; /* Number of winShm objects pointing to this */ winShmNode *pNext; /* Next in list of all winShmNode objects */ #if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) u8 nextShmId; /* Next available winShm.id value */ @@ -52012,7 +51219,6 @@ struct winShm { #if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) u8 id; /* Id of this connection with its winShmNode */ #endif - winShm *pWinShmNext; /* Next winShm object on same winShmNode */ }; /* @@ -52026,7 +51232,7 @@ static int winOpen(sqlite3_vfs*,const char*,sqlite3_file*,int,int*); static int winDelete(sqlite3_vfs *,const char*,int); /* -** Purge the winShmNodeList list of all entries with winShmNode.pWinShmList==0. +** Purge the winShmNodeList list of all entries with winShmNode.nRef==0. ** ** This is not a VFS shared-memory method; it is a utility function called ** by VFS shared-memory methods. @@ -52039,7 +51245,7 @@ static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){ osGetCurrentProcessId(), deleteFlag)); pp = &winShmNodeList; while( (p = *pp)!=0 ){ - if( p->pWinShmList==0 ){ + if( p->nRef==0 ){ int i; if( p->mutex ){ sqlite3_mutex_free(p->mutex); } for(i=0; i<p->nRegion; i++){ @@ -52109,6 +51315,103 @@ static int winLockSharedMemory(winShmNode *pShmNode, DWORD nMs){ /* +** Convert a UTF-8 filename into whatever form the underlying +** operating system wants filenames in. Space to hold the result +** is obtained from malloc and must be freed by the calling +** function +** +** On Cygwin, 3 possible input forms are accepted: +** - If the filename starts with "<drive>:/" or "<drive>:\", +** it is converted to UTF-16 as-is. +** - If the filename contains '/', it is assumed to be a +** Cygwin absolute path, it is converted to a win32 +** absolute path in UTF-16. +** - Otherwise it must be a filename only, the win32 filename +** is returned in UTF-16. +** Note: If the function cygwin_conv_path() fails, only +** UTF-8 -> UTF-16 conversion will be done. This can only +** happen when the file path >32k, in which case winUtf8ToUnicode() +** will fail too. +*/ +static void *winConvertFromUtf8Filename(const char *zFilename){ + void *zConverted = 0; + if( osIsNT() ){ +#ifdef __CYGWIN__ + int nChar; + LPWSTR zWideFilename; + + if( osCygwin_conv_path && !(winIsDriveLetterAndColon(zFilename) + && winIsDirSep(zFilename[2])) ){ + i64 nByte; + int convertflag = CCP_POSIX_TO_WIN_W; + if( !strchr(zFilename, '/') ) convertflag |= CCP_RELATIVE; + nByte = (i64)osCygwin_conv_path(convertflag, + zFilename, 0, 0); + if( nByte>0 ){ + zConverted = sqlite3MallocZero(12+(u64)nByte); + if ( zConverted==0 ){ + return zConverted; + } + zWideFilename = zConverted; + /* Filenames should be prefixed, except when converted + * full path already starts with "\\?\". */ + if( osCygwin_conv_path(convertflag, zFilename, + zWideFilename+4, nByte)==0 ){ + if( (convertflag&CCP_RELATIVE) ){ + memmove(zWideFilename, zWideFilename+4, nByte); + }else if( memcmp(zWideFilename+4, L"\\\\", 4) ){ + memcpy(zWideFilename, L"\\\\?\\", 8); + }else if( zWideFilename[6]!='?' ){ + memmove(zWideFilename+6, zWideFilename+4, nByte); + memcpy(zWideFilename, L"\\\\?\\UNC", 14); + }else{ + memmove(zWideFilename, zWideFilename+4, nByte); + } + return zConverted; + } + sqlite3_free(zConverted); + } + } + nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0); + if( nChar==0 ){ + return 0; + } + zWideFilename = sqlite3MallocZero( nChar*sizeof(WCHAR)+12 ); + if( zWideFilename==0 ){ + return 0; + } + nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1, + zWideFilename, nChar); + if( nChar==0 ){ + sqlite3_free(zWideFilename); + zWideFilename = 0; + }else if( nChar>MAX_PATH + && winIsDriveLetterAndColon(zFilename) + && winIsDirSep(zFilename[2]) ){ + memmove(zWideFilename+4, zWideFilename, nChar*sizeof(WCHAR)); + zWideFilename[2] = '\\'; + memcpy(zWideFilename, L"\\\\?\\", 8); + }else if( nChar>MAX_PATH + && winIsDirSep(zFilename[0]) && winIsDirSep(zFilename[1]) + && zFilename[2] != '?' ){ + memmove(zWideFilename+6, zWideFilename, nChar*sizeof(WCHAR)); + memcpy(zWideFilename, L"\\\\?\\UNC", 14); + } + zConverted = zWideFilename; +#else + zConverted = winUtf8ToUnicode(zFilename); +#endif /* __CYGWIN__ */ + } +#if defined(SQLITE_WIN32_HAS_ANSI) && defined(_WIN32) + else{ + zConverted = winUtf8ToMbcs(zFilename, osAreFileApisANSI()); + } +#endif + /* caller will handle out of memory */ + return zConverted; +} + +/* ** This function is used to open a handle on a *-shm file. ** ** If SQLITE_ENABLE_SETLK_TIMEOUT is defined at build time, then the file @@ -52203,60 +51506,6 @@ static int winHandleOpen( return rc; } -/* -** Close pDbFd's connection to shared-memory. Delete the underlying -** *-shm file if deleteFlag is true. -*/ -static int winCloseSharedMemory(winFile *pDbFd, int deleteFlag){ - winShm *p; /* The connection to be closed */ - winShm **pp; /* Iterator for pShmNode->pWinShmList */ - winShmNode *pShmNode; /* The underlying shared-memory file */ - - p = pDbFd->pShm; - if( p==0 ) return SQLITE_OK; - if( p->hShm!=INVALID_HANDLE_VALUE ){ - osCloseHandle(p->hShm); - } - - winShmEnterMutex(); - pShmNode = p->pShmNode; - - /* Remove this connection from the winShmNode.pWinShmList list */ - sqlite3_mutex_enter(pShmNode->mutex); - for(pp=&pShmNode->pWinShmList; *pp!=p; pp=&(*pp)->pWinShmNext){} - *pp = p->pWinShmNext; - sqlite3_mutex_leave(pShmNode->mutex); - - winShmPurge(pDbFd->pVfs, deleteFlag); - winShmLeaveMutex(); - - /* Free the connection p */ - sqlite3_free(p); - pDbFd->pShm = 0; - return SQLITE_OK; -} - -/* -** testfixture builds may set this global variable to true via a -** Tcl interface. This forces the VFS to use the locking normally -** only used for UNC paths for all files. -*/ -#ifdef SQLITE_TEST -SQLITE_API int sqlite3_win_test_unc_locking = 0; -#else -# define sqlite3_win_test_unc_locking 0 -#endif - -/* -** Return true if the string passed as the only argument is likely -** to be a UNC path. In other words, if it starts with "\\". -*/ -static int winIsUNCPath(const char *zFile){ - if( zFile[0]=='\\' && zFile[1]=='\\' ){ - return 1; - } - return sqlite3_win_test_unc_locking; -} /* ** Open the shared-memory area associated with database file pDbFd. @@ -52283,10 +51532,15 @@ static int winOpenSharedMemory(winFile *pDbFd){ pNew->zFilename = (char*)&pNew[1]; pNew->hSharedShm = INVALID_HANDLE_VALUE; pNew->isUnlocked = 1; - pNew->bUseSharedLockHandle = winIsUNCPath(pDbFd->zPath); sqlite3_snprintf(nName+15, pNew->zFilename, "%s-shm", pDbFd->zPath); sqlite3FileSuffix3(pDbFd->zPath, pNew->zFilename); + /* Open a file-handle on the *-shm file for this connection. This file-handle + ** is only used for locking. The mapping of the *-shm file is created using + ** the shared file handle in winShmNode.hSharedShm. */ + p->bReadonly = sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0); + rc = winHandleOpen(pNew->zFilename, &p->bReadonly, &p->hShm); + /* Look to see if there is an existing winShmNode that can be used. ** If no matching winShmNode currently exists, then create a new one. */ winShmEnterMutex(); @@ -52307,7 +51561,7 @@ static int winOpenSharedMemory(winFile *pDbFd){ /* Open a file-handle to use for mappings, and for the DMS lock. */ if( rc==SQLITE_OK ){ HANDLE h = INVALID_HANDLE_VALUE; - pShmNode->isReadonly = sqlite3_uri_boolean(pDbFd->zPath,"readonly_shm",0); + pShmNode->isReadonly = p->bReadonly; rc = winHandleOpen(pNew->zFilename, &pShmNode->isReadonly, &h); pShmNode->hSharedShm = h; } @@ -52329,35 +51583,20 @@ static int winOpenSharedMemory(winFile *pDbFd){ /* If no error has occurred, link the winShm object to the winShmNode and ** the winShm to pDbFd. */ if( rc==SQLITE_OK ){ - sqlite3_mutex_enter(pShmNode->mutex); p->pShmNode = pShmNode; - p->pWinShmNext = pShmNode->pWinShmList; - pShmNode->pWinShmList = p; + pShmNode->nRef++; #if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) p->id = pShmNode->nextShmId++; #endif pDbFd->pShm = p; - sqlite3_mutex_leave(pShmNode->mutex); }else if( p ){ + winHandleClose(p->hShm); sqlite3_free(p); } assert( rc!=SQLITE_OK || pShmNode->isUnlocked==0 || pShmNode->nRegion==0 ); winShmLeaveMutex(); sqlite3_free(pNew); - - /* Open a file-handle on the *-shm file for this connection. This file-handle - ** is only used for locking. The mapping of the *-shm file is created using - ** the shared file handle in winShmNode.hSharedShm. */ - if( rc==SQLITE_OK && pShmNode->bUseSharedLockHandle==0 ){ - p->bReadonly = sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0); - rc = winHandleOpen(pShmNode->zFilename, &p->bReadonly, &p->hShm); - if( rc!=SQLITE_OK ){ - assert( p->hShm==INVALID_HANDLE_VALUE ); - winCloseSharedMemory(pDbFd, 0); - } - } - return rc; } @@ -52369,7 +51608,33 @@ static int winShmUnmap( sqlite3_file *fd, /* Database holding shared memory */ int deleteFlag /* Delete after closing if true */ ){ - return winCloseSharedMemory((winFile*)fd, deleteFlag); + winFile *pDbFd; /* Database holding shared-memory */ + winShm *p; /* The connection to be closed */ + winShmNode *pShmNode; /* The underlying shared-memory file */ + + pDbFd = (winFile*)fd; + p = pDbFd->pShm; + if( p==0 ) return SQLITE_OK; + if( p->hShm!=INVALID_HANDLE_VALUE ){ + osCloseHandle(p->hShm); + } + + pShmNode = p->pShmNode; + winShmEnterMutex(); + + /* If pShmNode->nRef has reached 0, then close the underlying + ** shared-memory file, too. */ + assert( pShmNode->nRef>0 ); + pShmNode->nRef--; + if( pShmNode->nRef==0 ){ + winShmPurge(pDbFd->pVfs, deleteFlag); + } + winShmLeaveMutex(); + + /* Free the connection p */ + sqlite3_free(p); + pDbFd->pShm = 0; + return SQLITE_OK; } /* @@ -52438,7 +51703,6 @@ static int winShmLock( || (flags==(SQLITE_SHM_SHARED|SQLITE_SHM_LOCK) && 0==(p->sharedMask & mask)) || (flags==(SQLITE_SHM_EXCLUSIVE|SQLITE_SHM_LOCK)) ){ - HANDLE h = p->hShm; if( flags & SQLITE_SHM_UNLOCK ){ /* Case (a) - unlock. */ @@ -52447,27 +51711,7 @@ static int winShmLock( assert( !(flags & SQLITE_SHM_EXCLUSIVE) || (p->exclMask & mask)==mask ); assert( !(flags & SQLITE_SHM_SHARED) || (p->sharedMask & mask)==mask ); - assert( !(flags & SQLITE_SHM_SHARED) || n==1 ); - if( pShmNode->bUseSharedLockHandle ){ - h = pShmNode->hSharedShm; - if( flags & SQLITE_SHM_SHARED ){ - winShm *pShm; - sqlite3_mutex_enter(pShmNode->mutex); - for(pShm=pShmNode->pWinShmList; pShm; pShm=pShm->pWinShmNext){ - if( pShm!=p && (pShm->sharedMask & mask) ){ - /* Another connection within this process is also holding this - ** SHARED lock. So do not actually release the OS lock. */ - h = INVALID_HANDLE_VALUE; - break; - } - } - sqlite3_mutex_leave(pShmNode->mutex); - } - } - - if( h!=INVALID_HANDLE_VALUE ){ - rc = winHandleUnlock(h, ofst+WIN_SHM_BASE, n); - } + rc = winHandleUnlock(p->hShm, ofst+WIN_SHM_BASE, n); /* If successful, also clear the bits in sharedMask/exclMask */ if( rc==SQLITE_OK ){ @@ -52477,32 +51721,7 @@ static int winShmLock( }else{ int bExcl = ((flags & SQLITE_SHM_EXCLUSIVE) ? 1 : 0); DWORD nMs = winFileBusyTimeout(pDbFd); - - if( pShmNode->bUseSharedLockHandle ){ - winShm *pShm; - h = pShmNode->hSharedShm; - sqlite3_mutex_enter(pShmNode->mutex); - for(pShm=pShmNode->pWinShmList; pShm; pShm=pShm->pWinShmNext){ - if( bExcl ){ - if( (pShm->sharedMask|pShm->exclMask) & mask ){ - rc = SQLITE_BUSY; - h = INVALID_HANDLE_VALUE; - } - }else{ - if( pShm->sharedMask & mask ){ - h = INVALID_HANDLE_VALUE; - }else if( pShm->exclMask & mask ){ - rc = SQLITE_BUSY; - h = INVALID_HANDLE_VALUE; - } - } - } - sqlite3_mutex_leave(pShmNode->mutex); - } - - if( h!=INVALID_HANDLE_VALUE ){ - rc = winHandleLockTimeout(h, ofst+WIN_SHM_BASE, n, bExcl, nMs); - } + rc = winHandleLockTimeout(p->hShm, ofst+WIN_SHM_BASE, n, bExcl, nMs); if( rc==SQLITE_OK ){ if( bExcl ){ p->exclMask = (p->exclMask | mask); @@ -55641,7 +54860,6 @@ struct Bitvec { } u; }; - /* ** Create a new bitmap object able to handle bits between 0 and iSize, ** inclusive. Return a pointer to the new object. Return NULL if @@ -55830,52 +55048,6 @@ SQLITE_PRIVATE u32 sqlite3BitvecSize(Bitvec *p){ return p->iSize; } -#ifdef SQLITE_DEBUG -/* -** Show the content of a Bitvec option and its children. Indent -** everything by n spaces. Add x to each bitvec value. -** -** From a debugger such as gdb, one can type: -** -** call sqlite3ShowBitvec(p) -** -** For some Bitvec p and see a recursive view of the Bitvec's content. -*/ -static void showBitvec(Bitvec *p, int n, unsigned x){ - int i; - if( p==0 ){ - printf("NULL\n"); - return; - } - printf("Bitvec 0x%p iSize=%u", p, p->iSize); - if( p->iSize<=BITVEC_NBIT ){ - printf(" bitmap\n"); - printf("%*s bits:", n, ""); - for(i=1; i<=BITVEC_NBIT; i++){ - if( sqlite3BitvecTest(p,i) ) printf(" %u", x+(unsigned)i); - } - printf("\n"); - }else if( p->iDivisor==0 ){ - printf(" hash with %u entries\n", p->nSet); - printf("%*s bits:", n, ""); - for(i=0; i<BITVEC_NINT; i++){ - if( p->u.aHash[i] ) printf(" %u", x+(unsigned)p->u.aHash[i]); - } - printf("\n"); - }else{ - printf(" sub-bitvec with iDivisor=%u\n", p->iDivisor); - for(i=0; i<BITVEC_NPTR; i++){ - if( p->u.apSub[i]==0 ) continue; - printf("%*s apSub[%d]=", n, "", i); - showBitvec(p->u.apSub[i], n+4, i*p->iDivisor); - } - } -} -SQLITE_PRIVATE void sqlite3ShowBitvec(Bitvec *p){ - showBitvec(p, 0, 0); -} -#endif - #ifndef SQLITE_UNTESTABLE /* ** Let V[] be an array of unsigned characters sufficient to hold @@ -55887,7 +55059,6 @@ SQLITE_PRIVATE void sqlite3ShowBitvec(Bitvec *p){ #define CLEARBIT(V,I) V[I>>3] &= ~(BITVEC_TELEM)(1<<(I&7)) #define TESTBIT(V,I) (V[I>>3]&(1<<(I&7)))!=0 - /* ** This routine runs an extensive test of the Bitvec code. ** @@ -55896,7 +55067,7 @@ SQLITE_PRIVATE void sqlite3ShowBitvec(Bitvec *p){ ** by 0, 1, or 3 operands, depending on the opcode. Another ** opcode follows immediately after the last operand. ** -** There are opcodes numbered starting with 0. 0 is the +** There are 6 opcodes numbered from 0 through 5. 0 is the ** "halt" opcode and causes the test to end. ** ** 0 Halt and return the number of errors @@ -55905,25 +55076,18 @@ SQLITE_PRIVATE void sqlite3ShowBitvec(Bitvec *p){ ** 3 N Set N randomly chosen bits ** 4 N Clear N randomly chosen bits ** 5 N S X Set N bits from S increment X in array only, not in bitvec -** 6 Invoice sqlite3ShowBitvec() on the Bitvec object so far -** 7 X Show compile-time parameters and the hash of X ** ** The opcodes 1 through 4 perform set and clear operations are performed ** on both a Bitvec object and on a linear array of bits obtained from malloc. ** Opcode 5 works on the linear array only, not on the Bitvec. ** Opcode 5 is used to deliberately induce a fault in order to -** confirm that error detection works. Opcodes 6 and greater are -** state output opcodes. Opcodes 6 and greater are no-ops unless -** SQLite has been compiled with SQLITE_DEBUG. +** confirm that error detection works. ** ** At the conclusion of the test the linear array is compared ** against the Bitvec object. If there are any differences, ** an error is returned. If they are the same, zero is returned. ** ** If a memory allocation error occurs, return -1. -** -** sz is the size of the Bitvec. Or if sz is negative, make the size -** 2*(unsigned)(-sz) and disabled the linear vector check. */ SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int sz, int *aOp){ Bitvec *pBitvec = 0; @@ -55934,15 +55098,10 @@ SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int sz, int *aOp){ /* Allocate the Bitvec to be tested and a linear array of ** bits to act as the reference */ - if( sz<=0 ){ - pBitvec = sqlite3BitvecCreate( 2*(unsigned)(-sz) ); - pV = 0; - }else{ - pBitvec = sqlite3BitvecCreate( sz ); - pV = sqlite3MallocZero( (7+(i64)sz)/8 + 1 ); - } + pBitvec = sqlite3BitvecCreate( sz ); + pV = sqlite3MallocZero( (7+(i64)sz)/8 + 1 ); pTmpSpace = sqlite3_malloc64(BITVEC_SZ); - if( pBitvec==0 || pTmpSpace==0 || (pV==0 && sz>0) ) goto bitvec_end; + if( pBitvec==0 || pV==0 || pTmpSpace==0 ) goto bitvec_end; /* NULL pBitvec tests */ sqlite3BitvecSet(0, 1); @@ -55951,24 +55110,6 @@ SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int sz, int *aOp){ /* Run the program */ pc = i = 0; while( (op = aOp[pc])!=0 ){ - if( op>=6 ){ -#ifdef SQLITE_DEBUG - if( op==6 ){ - sqlite3ShowBitvec(pBitvec); - }else if( op==7 ){ - printf("BITVEC_SZ = %d (%d by sizeof)\n", - BITVEC_SZ, (int)sizeof(Bitvec)); - printf("BITVEC_USIZE = %d\n", (int)BITVEC_USIZE); - printf("BITVEC_NELEM = %d\n", (int)BITVEC_NELEM); - printf("BITVEC_NBIT = %d\n", (int)BITVEC_NBIT); - printf("BITVEC_NINT = %d\n", (int)BITVEC_NINT); - printf("BITVEC_MXHASH = %d\n", (int)BITVEC_MXHASH); - printf("BITVEC_NPTR = %d\n", (int)BITVEC_NPTR); - } -#endif - pc++; - continue; - } switch( op ){ case 1: case 2: @@ -55990,12 +55131,12 @@ SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int sz, int *aOp){ pc += nx; i = (i & 0x7fffffff)%sz; if( (op & 1)!=0 ){ - if( pV ) SETBIT(pV, (i+1)); + SETBIT(pV, (i+1)); if( op!=5 ){ if( sqlite3BitvecSet(pBitvec, i+1) ) goto bitvec_end; } }else{ - if( pV ) CLEARBIT(pV, (i+1)); + CLEARBIT(pV, (i+1)); sqlite3BitvecClear(pBitvec, i+1, pTmpSpace); } } @@ -56005,18 +55146,14 @@ SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int sz, int *aOp){ ** match (rc==0). Change rc to non-zero if a discrepancy ** is found. */ - if( pV ){ - rc = sqlite3BitvecTest(0,0) + sqlite3BitvecTest(pBitvec, sz+1) - + sqlite3BitvecTest(pBitvec, 0) - + (sqlite3BitvecSize(pBitvec) - sz); - for(i=1; i<=sz; i++){ - if( (TESTBIT(pV,i))!=sqlite3BitvecTest(pBitvec,i) ){ - rc = i; - break; - } + rc = sqlite3BitvecTest(0,0) + sqlite3BitvecTest(pBitvec, sz+1) + + sqlite3BitvecTest(pBitvec, 0) + + (sqlite3BitvecSize(pBitvec) - sz); + for(i=1; i<=sz; i++){ + if( (TESTBIT(pV,i))!=sqlite3BitvecTest(pBitvec,i) ){ + rc = i; + break; } - }else{ - rc = 0; } /* Free allocated structure */ @@ -60777,7 +59914,7 @@ static void pager_unlock(Pager *pPager){ ** have sqlite3WalEndReadTransaction() drop the write-lock, as it once ** did, because this would break "BEGIN EXCLUSIVE" handling for ** SQLITE_ENABLE_SETLK_TIMEOUT builds. */ - (void)sqlite3WalEndWriteTransaction(pPager->pWal); + sqlite3WalEndWriteTransaction(pPager->pWal); } sqlite3WalEndReadTransaction(pPager->pWal); pPager->eState = PAGER_OPEN; @@ -62533,27 +61670,14 @@ SQLITE_PRIVATE void sqlite3PagerSetFlags( unsigned pgFlags /* Various flags */ ){ unsigned level = pgFlags & PAGER_SYNCHRONOUS_MASK; - if( pPager->tempFile || level==PAGER_SYNCHRONOUS_OFF ){ + if( pPager->tempFile ){ pPager->noSync = 1; pPager->fullSync = 0; pPager->extraSync = 0; }else{ - pPager->noSync = 0; + pPager->noSync = level==PAGER_SYNCHRONOUS_OFF ?1:0; pPager->fullSync = level>=PAGER_SYNCHRONOUS_FULL ?1:0; - - /* Set Pager.extraSync if "PRAGMA synchronous=EXTRA" is requested, or - ** if the file-system supports F2FS style atomic writes. If this flag - ** is set, SQLite syncs the directory to disk immediately after deleting - ** a journal file in "PRAGMA journal_mode=DELETE" mode. */ - if( level==PAGER_SYNCHRONOUS_EXTRA -#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE - || (sqlite3OsDeviceCharacteristics(pPager->fd) & SQLITE_IOCAP_BATCH_ATOMIC) -#endif - ){ - pPager->extraSync = 1; - }else{ - pPager->extraSync = 0; - } + pPager->extraSync = level==PAGER_SYNCHRONOUS_EXTRA ?1:0; } if( pPager->noSync ){ pPager->syncFlags = 0; @@ -66446,7 +65570,7 @@ SQLITE_PRIVATE int sqlite3PagerCheckpoint( } if( pPager->pWal ){ rc = sqlite3WalCheckpoint(pPager->pWal, db, eMode, - (eMode<=SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler), + (eMode==SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler), pPager->pBusyHandlerArg, pPager->walSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace, pnLog, pnCkpt @@ -67356,7 +66480,7 @@ struct WalIterator { /* Size (in bytes) of a WalIterator object suitable for N or fewer segments */ #define SZ_WALITERATOR(N) \ - (offsetof(WalIterator,aSegment)+(N)*sizeof(struct WalSegment)) + (offsetof(WalIterator,aSegment)*(N)*sizeof(struct WalSegment)) /* ** Define the parameters of the hash tables in the wal-index file. There @@ -70242,7 +69366,7 @@ SQLITE_PRIVATE void sqlite3WalEndReadTransaction(Wal *pWal){ assert( pWal->writeLock==0 || pWal->readLock<0 ); #endif if( pWal->readLock>=0 ){ - (void)sqlite3WalEndWriteTransaction(pWal); + sqlite3WalEndWriteTransaction(pWal); walUnlockShared(pWal, WAL_READ_LOCK(pWal->readLock)); pWal->readLock = -1; } @@ -71051,8 +70175,7 @@ SQLITE_PRIVATE int sqlite3WalCheckpoint( /* EVIDENCE-OF: R-62920-47450 The busy-handler callback is never invoked ** in the SQLITE_CHECKPOINT_PASSIVE mode. */ - assert( SQLITE_CHECKPOINT_NOOP<SQLITE_CHECKPOINT_PASSIVE ); - assert( eMode>SQLITE_CHECKPOINT_PASSIVE || xBusy==0 ); + assert( eMode!=SQLITE_CHECKPOINT_PASSIVE || xBusy==0 ); if( pWal->readOnly ) return SQLITE_READONLY; WALTRACE(("WAL%p: checkpoint begins\n", pWal)); @@ -71069,35 +70192,31 @@ SQLITE_PRIVATE int sqlite3WalCheckpoint( ** EVIDENCE-OF: R-53820-33897 Even if there is a busy-handler configured, ** it will not be invoked in this case. */ - if( eMode!=SQLITE_CHECKPOINT_NOOP ){ - rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1); - testcase( rc==SQLITE_BUSY ); - testcase( rc!=SQLITE_OK && xBusy2!=0 ); - if( rc==SQLITE_OK ){ - pWal->ckptLock = 1; + rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1); + testcase( rc==SQLITE_BUSY ); + testcase( rc!=SQLITE_OK && xBusy2!=0 ); + if( rc==SQLITE_OK ){ + pWal->ckptLock = 1; - /* IMPLEMENTATION-OF: R-59782-36818 The SQLITE_CHECKPOINT_FULL, RESTART - ** and TRUNCATE modes also obtain the exclusive "writer" lock on the - ** database file. - ** - ** EVIDENCE-OF: R-60642-04082 If the writer lock cannot be obtained - ** immediately, and a busy-handler is configured, it is invoked and the - ** writer lock retried until either the busy-handler returns 0 or the - ** lock is successfully obtained. - */ - if( eMode!=SQLITE_CHECKPOINT_PASSIVE ){ - rc = walBusyLock(pWal, xBusy2, pBusyArg, WAL_WRITE_LOCK, 1); - if( rc==SQLITE_OK ){ - pWal->writeLock = 1; - }else if( rc==SQLITE_BUSY ){ - eMode2 = SQLITE_CHECKPOINT_PASSIVE; - xBusy2 = 0; - rc = SQLITE_OK; - } + /* IMPLEMENTATION-OF: R-59782-36818 The SQLITE_CHECKPOINT_FULL, RESTART and + ** TRUNCATE modes also obtain the exclusive "writer" lock on the database + ** file. + ** + ** EVIDENCE-OF: R-60642-04082 If the writer lock cannot be obtained + ** immediately, and a busy-handler is configured, it is invoked and the + ** writer lock retried until either the busy-handler returns 0 or the + ** lock is successfully obtained. + */ + if( eMode!=SQLITE_CHECKPOINT_PASSIVE ){ + rc = walBusyLock(pWal, xBusy2, pBusyArg, WAL_WRITE_LOCK, 1); + if( rc==SQLITE_OK ){ + pWal->writeLock = 1; + }else if( rc==SQLITE_BUSY ){ + eMode2 = SQLITE_CHECKPOINT_PASSIVE; + xBusy2 = 0; + rc = SQLITE_OK; } } - }else{ - rc = SQLITE_OK; } @@ -71111,7 +70230,7 @@ SQLITE_PRIVATE int sqlite3WalCheckpoint( ** immediately and do a partial checkpoint if it cannot obtain it. */ walDisableBlocking(pWal); rc = walIndexReadHdr(pWal, &isChanged); - if( eMode2>SQLITE_CHECKPOINT_PASSIVE ) (void)walEnableBlocking(pWal); + if( eMode2!=SQLITE_CHECKPOINT_PASSIVE ) (void)walEnableBlocking(pWal); if( isChanged && pWal->pDbFd->pMethods->iVersion>=3 ){ sqlite3OsUnfetch(pWal->pDbFd, 0, 0); } @@ -71121,7 +70240,7 @@ SQLITE_PRIVATE int sqlite3WalCheckpoint( if( rc==SQLITE_OK ){ if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){ rc = SQLITE_CORRUPT_BKPT; - }else if( eMode2!=SQLITE_CHECKPOINT_NOOP ){ + }else{ rc = walCheckpoint(pWal, db, eMode2, xBusy2, pBusyArg, sync_flags,zBuf); } @@ -71149,7 +70268,7 @@ SQLITE_PRIVATE int sqlite3WalCheckpoint( sqlite3WalDb(pWal, 0); /* Release the locks. */ - (void)sqlite3WalEndWriteTransaction(pWal); + sqlite3WalEndWriteTransaction(pWal); if( pWal->ckptLock ){ walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1); pWal->ckptLock = 0; @@ -73306,7 +72425,7 @@ static int btreeMoveto( assert( nKey==(i64)(int)nKey ); pIdxKey = sqlite3VdbeAllocUnpackedRecord(pKeyInfo); if( pIdxKey==0 ) return SQLITE_NOMEM_BKPT; - sqlite3VdbeRecordUnpack((int)nKey, pKey, pIdxKey); + sqlite3VdbeRecordUnpack(pKeyInfo, (int)nKey, pKey, pIdxKey); if( pIdxKey->nField==0 || pIdxKey->nField>pKeyInfo->nAllField ){ rc = SQLITE_CORRUPT_BKPT; }else{ @@ -74363,10 +73482,10 @@ static int freeSpace(MemPage *pPage, int iStart, int iSize){ assert( pPage->pBt!=0 ); assert( sqlite3PagerIswriteable(pPage->pDbPage) ); assert( CORRUPT_DB || iStart>=pPage->hdrOffset+6+pPage->childPtrSize ); - assert( CORRUPT_DB || iEnd <= (int)pPage->pBt->usableSize ); + assert( CORRUPT_DB || iEnd <= pPage->pBt->usableSize ); assert( sqlite3_mutex_held(pPage->pBt->mutex) ); assert( iSize>=4 ); /* Minimum cell size is 4 */ - assert( CORRUPT_DB || iStart<=(int)pPage->pBt->usableSize-4 ); + assert( CORRUPT_DB || iStart<=pPage->pBt->usableSize-4 ); /* The list of freeblocks must be in ascending order. Find the ** spot on the list where iStart should be inserted. @@ -75290,7 +74409,6 @@ static int removeFromSharingList(BtShared *pBt){ sqlite3_mutex_leave(pMainMtx); return removed; #else - UNUSED_PARAMETER( pBt ); return 1; #endif } @@ -75508,10 +74626,6 @@ SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int pageSize, int nReserve, sqlite3BtreeEnter(p); pBt->nReserveWanted = (u8)nReserve; x = pBt->pageSize - pBt->usableSize; - if( x==nReserve && (pageSize==0 || (u32)pageSize==pBt->pageSize) ){ - sqlite3BtreeLeave(p); - return SQLITE_OK; - } if( nReserve<x ) nReserve = x; if( pBt->btsFlags & BTS_PAGESIZE_FIXED ){ sqlite3BtreeLeave(p); @@ -78101,30 +77215,6 @@ SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){ return rc; } -/* Set *pRes to 1 (true) if the BTree pointed to by cursor pCur contains zero -** rows of content. Set *pRes to 0 (false) if the table contains content. -** Return SQLITE_OK on success or some error code (ex: SQLITE_NOMEM) if -** something goes wrong. -*/ -SQLITE_PRIVATE int sqlite3BtreeIsEmpty(BtCursor *pCur, int *pRes){ - int rc; - - assert( cursorOwnsBtShared(pCur) ); - assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); - if( pCur->eState==CURSOR_VALID ){ - *pRes = 0; - return SQLITE_OK; - } - rc = moveToRoot(pCur); - if( rc==SQLITE_EMPTY ){ - *pRes = 1; - rc = SQLITE_OK; - }else{ - *pRes = 0; - } - return rc; -} - #ifdef SQLITE_DEBUG /* The cursors is CURSOR_VALID and has BTCF_AtLast set. Verify that ** this flags are true for a consistent database. @@ -78344,8 +77434,8 @@ moveto_table_finish: } /* -** Compare the "idx"-th cell on the page pPage against the key -** pointing to by pIdxKey using xRecordCompare. Return negative or +** Compare the "idx"-th cell on the page the cursor pCur is currently +** pointing to to pIdxKey using xRecordCompare. Return negative or ** zero if the cell is less than or equal pIdxKey. Return positive ** if unknown. ** @@ -78360,11 +77450,12 @@ moveto_table_finish: ** a positive value as that will cause the optimization to be skipped. */ static int indexCellCompare( - MemPage *pPage, + BtCursor *pCur, int idx, UnpackedRecord *pIdxKey, RecordCompare xRecordCompare ){ + MemPage *pPage = pCur->pPage; int c; int nCell; /* Size of the pCell cell in bytes */ u8 *pCell = findCellPastPtr(pPage, idx); @@ -78473,14 +77564,14 @@ SQLITE_PRIVATE int sqlite3BtreeIndexMoveto( ){ int c; if( pCur->ix==pCur->pPage->nCell-1 - && (c = indexCellCompare(pCur->pPage,pCur->ix,pIdxKey,xRecordCompare))<=0 + && (c = indexCellCompare(pCur, pCur->ix, pIdxKey, xRecordCompare))<=0 && pIdxKey->errCode==SQLITE_OK ){ *pRes = c; return SQLITE_OK; /* Cursor already pointing at the correct spot */ } if( pCur->iPage>0 - && indexCellCompare(pCur->pPage, 0, pIdxKey, xRecordCompare)<=0 + && indexCellCompare(pCur, 0, pIdxKey, xRecordCompare)<=0 && pIdxKey->errCode==SQLITE_OK ){ pCur->curFlags &= ~(BTCF_ValidOvfl|BTCF_AtLast); @@ -78697,7 +77788,7 @@ SQLITE_PRIVATE i64 sqlite3BtreeRowCountEst(BtCursor *pCur){ n = pCur->pPage->nCell; for(i=0; i<pCur->iPage; i++){ - n *= pCur->apPage[i]->nCell+1; + n *= pCur->apPage[i]->nCell; } return n; } @@ -81154,12 +80245,7 @@ static int balance_nonroot( ** of the right-most new sibling page is set to the value that was ** originally in the same field of the right-most old sibling page. */ if( (pageFlags & PTF_LEAF)==0 && nOld!=nNew ){ - MemPage *pOld; - if( nNew>nOld ){ - pOld = apNew[nOld-1]; - }else{ - pOld = apOld[nOld-1]; - } + MemPage *pOld = (nNew>nOld ? apNew : apOld)[nOld-1]; memcpy(&apNew[nNew-1]->aData[8], &pOld->aData[8], 4); } @@ -83791,7 +82877,6 @@ SQLITE_PRIVATE void *sqlite3BtreeSchema(Btree *p, int nBytes, void(*xFree)(void */ SQLITE_PRIVATE int sqlite3BtreeSchemaLocked(Btree *p){ int rc; - UNUSED_PARAMETER(p); /* only used in DEBUG builds */ assert( sqlite3_mutex_held(p->db->mutex) ); sqlite3BtreeEnter(p); rc = querySharedCacheTableLock(p, SCHEMA_ROOT, READ_LOCK); @@ -85977,7 +85062,6 @@ SQLITE_PRIVATE int sqlite3VdbeMemSetStr( if( sqlite3VdbeMemClearAndResize(pMem, (int)MAX(nAlloc,32)) ){ return SQLITE_NOMEM_BKPT; } - assert( pMem->z!=0 ); memcpy(pMem->z, z, nAlloc); }else{ sqlite3VdbeMemRelease(pMem); @@ -89805,12 +88889,10 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){ if( 0==sqlite3Strlen30(sqlite3BtreeGetFilename(db->aDb[0].pBt)) || nTrans<=1 ){ - if( needXcommit ){ - for(i=0; rc==SQLITE_OK && i<db->nDb; i++){ - Btree *pBt = db->aDb[i].pBt; - if( sqlite3BtreeTxnState(pBt)>=SQLITE_TXN_WRITE ){ - rc = sqlite3BtreeCommitPhaseOne(pBt, 0); - } + for(i=0; rc==SQLITE_OK && i<db->nDb; i++){ + Btree *pBt = db->aDb[i].pBt; + if( pBt ){ + rc = sqlite3BtreeCommitPhaseOne(pBt, 0); } } @@ -89821,9 +88903,7 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){ */ for(i=0; rc==SQLITE_OK && i<db->nDb; i++){ Btree *pBt = db->aDb[i].pBt; - int txn = sqlite3BtreeTxnState(pBt); - if( txn!=SQLITE_TXN_NONE ){ - assert( needXcommit || txn==SQLITE_TXN_READ ); + if( pBt ){ rc = sqlite3BtreeCommitPhaseTwo(pBt, 0); } } @@ -90078,31 +89158,28 @@ SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){ /* -** These functions are called when a transaction opened by the database +** This function is called when a transaction opened by the database ** handle associated with the VM passed as an argument is about to be -** committed. If there are outstanding foreign key constraint violations -** return an error code. Otherwise, SQLITE_OK. +** committed. If there are outstanding deferred foreign key constraint +** violations, return SQLITE_ERROR. Otherwise, SQLITE_OK. ** ** If there are outstanding FK violations and this function returns -** non-zero, set the result of the VM to SQLITE_CONSTRAINT_FOREIGNKEY -** and write an error message to it. +** SQLITE_ERROR, set the result of the VM to SQLITE_CONSTRAINT_FOREIGNKEY +** and write an error message to it. Then return SQLITE_ERROR. */ #ifndef SQLITE_OMIT_FOREIGN_KEY -static SQLITE_NOINLINE int vdbeFkError(Vdbe *p){ - p->rc = SQLITE_CONSTRAINT_FOREIGNKEY; - p->errorAction = OE_Abort; - sqlite3VdbeError(p, "FOREIGN KEY constraint failed"); - if( (p->prepFlags & SQLITE_PREPARE_SAVESQL)==0 ) return SQLITE_ERROR; - return SQLITE_CONSTRAINT_FOREIGNKEY; -} -SQLITE_PRIVATE int sqlite3VdbeCheckFkImmediate(Vdbe *p){ - if( p->nFkConstraint==0 ) return SQLITE_OK; - return vdbeFkError(p); -} -SQLITE_PRIVATE int sqlite3VdbeCheckFkDeferred(Vdbe *p){ +SQLITE_PRIVATE int sqlite3VdbeCheckFk(Vdbe *p, int deferred){ sqlite3 *db = p->db; - if( (db->nDeferredCons+db->nDeferredImmCons)==0 ) return SQLITE_OK; - return vdbeFkError(p); + if( (deferred && (db->nDeferredCons+db->nDeferredImmCons)>0) + || (!deferred && p->nFkConstraint>0) + ){ + p->rc = SQLITE_CONSTRAINT_FOREIGNKEY; + p->errorAction = OE_Abort; + sqlite3VdbeError(p, "FOREIGN KEY constraint failed"); + if( (p->prepFlags & SQLITE_PREPARE_SAVESQL)==0 ) return SQLITE_ERROR; + return SQLITE_CONSTRAINT_FOREIGNKEY; + } + return SQLITE_OK; } #endif @@ -90196,7 +89273,7 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){ /* Check for immediate foreign key violations. */ if( p->rc==SQLITE_OK || (p->errorAction==OE_Fail && !isSpecialError) ){ - (void)sqlite3VdbeCheckFkImmediate(p); + (void)sqlite3VdbeCheckFk(p, 0); } /* If the auto-commit flag is set and this is the only active writer @@ -90210,7 +89287,7 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){ && db->nVdbeWrite==(p->readOnly==0) ){ if( p->rc==SQLITE_OK || (p->errorAction==OE_Fail && !isSpecialError) ){ - rc = sqlite3VdbeCheckFkDeferred(p); + rc = sqlite3VdbeCheckFk(p, 1); if( rc!=SQLITE_OK ){ if( NEVER(p->readOnly) ){ sqlite3VdbeLeave(p); @@ -91020,22 +90097,30 @@ SQLITE_PRIVATE void sqlite3VdbeSerialGet( return; } /* -** Allocate sufficient space for an UnpackedRecord structure large enough -** to hold a decoded index record for pKeyInfo. +** This routine is used to allocate sufficient space for an UnpackedRecord +** structure large enough to be used with sqlite3VdbeRecordUnpack() if +** the first argument is a pointer to KeyInfo structure pKeyInfo. +** +** The space is either allocated using sqlite3DbMallocRaw() or from within +** the unaligned buffer passed via the second and third arguments (presumably +** stack space). If the former, then *ppFree is set to a pointer that should +** be eventually freed by the caller using sqlite3DbFree(). Or, if the +** allocation comes from the pSpace/szSpace buffer, *ppFree is set to NULL +** before returning. ** -** The space is allocated using sqlite3DbMallocRaw(). If an OOM error -** occurs, NULL is returned. +** If an OOM error occurs, NULL is returned. */ SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord( KeyInfo *pKeyInfo /* Description of the record */ ){ UnpackedRecord *p; /* Unpacked record to return */ - u64 nByte; /* Number of bytes required for *p */ + int nByte; /* Number of bytes required for *p */ assert( sizeof(UnpackedRecord) + sizeof(Mem)*65536 < 0x7fffffff ); nByte = ROUND8P(sizeof(UnpackedRecord)) + sizeof(Mem)*(pKeyInfo->nKeyField+1); p = (UnpackedRecord *)sqlite3DbMallocRaw(pKeyInfo->db, nByte); if( !p ) return 0; p->aMem = (Mem*)&((char*)p)[ROUND8P(sizeof(UnpackedRecord))]; + assert( pKeyInfo->aSortFlags!=0 ); p->pKeyInfo = pKeyInfo; p->nField = pKeyInfo->nKeyField + 1; return p; @@ -91047,6 +90132,7 @@ SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord( ** contents of the decoded record. */ SQLITE_PRIVATE void sqlite3VdbeRecordUnpack( + KeyInfo *pKeyInfo, /* Information about the record format */ int nKey, /* Size of the binary record */ const void *pKey, /* The binary record */ UnpackedRecord *p /* Populate this structure before returning. */ @@ -91057,7 +90143,6 @@ SQLITE_PRIVATE void sqlite3VdbeRecordUnpack( u16 u; /* Unsigned loop counter */ u32 szHdr; Mem *pMem = p->aMem; - KeyInfo *pKeyInfo = p->pKeyInfo; p->default_rc = 0; assert( EIGHT_BYTE_ALIGNMENT(pMem) ); @@ -91075,18 +90160,16 @@ SQLITE_PRIVATE void sqlite3VdbeRecordUnpack( pMem->z = 0; sqlite3VdbeSerialGet(&aKey[d], serial_type, pMem); d += sqlite3VdbeSerialTypeLen(serial_type); - if( (++u)>=p->nField ) break; pMem++; + if( (++u)>=p->nField ) break; } if( d>(u32)nKey && u ){ assert( CORRUPT_DB ); /* In a corrupt record entry, the last pMem might have been set up using ** uninitialized memory. Overwrite its value with NULL, to prevent ** warnings from MSAN. */ - sqlite3VdbeMemSetNull(pMem-(u<p->nField)); + sqlite3VdbeMemSetNull(pMem-1); } - testcase( u == pKeyInfo->nKeyField + 1 ); - testcase( u < pKeyInfo->nKeyField + 1 ); assert( u<=pKeyInfo->nKeyField + 1 ); p->nField = u; } @@ -91254,32 +90337,6 @@ static void vdbeAssertFieldCountWithinLimits( ** or positive value if *pMem1 is less than, equal to or greater than ** *pMem2, respectively. Similar in spirit to "rc = (*pMem1) - (*pMem2);". */ -static SQLITE_NOINLINE int vdbeCompareMemStringWithEncodingChange( - const Mem *pMem1, - const Mem *pMem2, - const CollSeq *pColl, - u8 *prcErr /* If an OOM occurs, set to SQLITE_NOMEM */ -){ - int rc; - const void *v1, *v2; - Mem c1; - Mem c2; - sqlite3VdbeMemInit(&c1, pMem1->db, MEM_Null); - sqlite3VdbeMemInit(&c2, pMem1->db, MEM_Null); - sqlite3VdbeMemShallowCopy(&c1, pMem1, MEM_Ephem); - sqlite3VdbeMemShallowCopy(&c2, pMem2, MEM_Ephem); - v1 = sqlite3ValueText((sqlite3_value*)&c1, pColl->enc); - v2 = sqlite3ValueText((sqlite3_value*)&c2, pColl->enc); - if( (v1==0 || v2==0) ){ - if( prcErr ) *prcErr = SQLITE_NOMEM_BKPT; - rc = 0; - }else{ - rc = pColl->xCmp(pColl->pUser, c1.n, v1, c2.n, v2); - } - sqlite3VdbeMemReleaseMalloc(&c1); - sqlite3VdbeMemReleaseMalloc(&c2); - return rc; -} static int vdbeCompareMemString( const Mem *pMem1, const Mem *pMem2, @@ -91291,7 +90348,25 @@ static int vdbeCompareMemString( ** comparison function directly */ return pColl->xCmp(pColl->pUser,pMem1->n,pMem1->z,pMem2->n,pMem2->z); }else{ - return vdbeCompareMemStringWithEncodingChange(pMem1,pMem2,pColl,prcErr); + int rc; + const void *v1, *v2; + Mem c1; + Mem c2; + sqlite3VdbeMemInit(&c1, pMem1->db, MEM_Null); + sqlite3VdbeMemInit(&c2, pMem1->db, MEM_Null); + sqlite3VdbeMemShallowCopy(&c1, pMem1, MEM_Ephem); + sqlite3VdbeMemShallowCopy(&c2, pMem2, MEM_Ephem); + v1 = sqlite3ValueText((sqlite3_value*)&c1, pColl->enc); + v2 = sqlite3ValueText((sqlite3_value*)&c2, pColl->enc); + if( (v1==0 || v2==0) ){ + if( prcErr ) *prcErr = SQLITE_NOMEM_BKPT; + rc = 0; + }else{ + rc = pColl->xCmp(pColl->pUser, c1.n, v1, c2.n, v2); + } + sqlite3VdbeMemReleaseMalloc(&c1); + sqlite3VdbeMemReleaseMalloc(&c2); + return rc; } } @@ -91954,7 +91029,6 @@ SQLITE_PRIVATE RecordCompare sqlite3VdbeFindCompare(UnpackedRecord *p){ ** The easiest way to enforce this limit is to consider only records with ** 13 fields or less. If the first field is an integer, the maximum legal ** header size is (12*5 + 1 + 1) bytes. */ - assert( p->pKeyInfo->aSortFlags!=0 ); if( p->pKeyInfo->nAllField<=13 ){ int flags = p->aMem[0].flags; if( p->pKeyInfo->aSortFlags[0] ){ @@ -92204,7 +91278,6 @@ SQLITE_PRIVATE void sqlite3VdbeSetVarmask(Vdbe *v, int iVar){ } } -#ifndef SQLITE_OMIT_DATETIME_FUNCS /* ** Cause a function to throw an error if it was call from OP_PureFunc ** rather than OP_Function. @@ -92238,7 +91311,6 @@ SQLITE_PRIVATE int sqlite3NotPureFunc(sqlite3_context *pCtx){ } return 1; } -#endif /* SQLITE_OMIT_DATETIME_FUNCS */ #if defined(SQLITE_ENABLE_CURSOR_HINTS) && defined(SQLITE_DEBUG) /* @@ -92315,6 +91387,7 @@ SQLITE_PRIVATE void sqlite3VdbePreUpdateHook( i64 iKey2; PreUpdate preupdate; const char *zTbl = pTab->zName; + static const u8 fakeSortOrder = 0; #ifdef SQLITE_DEBUG int nRealCol; if( pTab->tabFlags & TF_WithoutRowid ){ @@ -92349,11 +91422,11 @@ SQLITE_PRIVATE void sqlite3VdbePreUpdateHook( preupdate.pCsr = pCsr; preupdate.op = op; preupdate.iNewReg = iReg; - preupdate.pKeyinfo = (KeyInfo*)&preupdate.uKey; + preupdate.pKeyinfo = (KeyInfo*)&preupdate.keyinfoSpace; preupdate.pKeyinfo->db = db; preupdate.pKeyinfo->enc = ENC(db); preupdate.pKeyinfo->nKeyField = pTab->nCol; - preupdate.pKeyinfo->aSortFlags = 0; /* Indicate .aColl, .nAllField uninit */ + preupdate.pKeyinfo->aSortFlags = (u8*)&fakeSortOrder; preupdate.iKey1 = iKey1; preupdate.iKey2 = iKey2; preupdate.pTab = pTab; @@ -92383,17 +91456,6 @@ SQLITE_PRIVATE void sqlite3VdbePreUpdateHook( } #endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ -#ifdef SQLITE_ENABLE_PERCENTILE -/* -** Return the name of an SQL function associated with the sqlite3_context. -*/ -SQLITE_PRIVATE const char *sqlite3VdbeFuncName(const sqlite3_context *pCtx){ - assert( pCtx!=0 ); - assert( pCtx->pFunc!=0 ); - return pCtx->pFunc->zName; -} -#endif /* SQLITE_ENABLE_PERCENTILE */ - /************** End of vdbeaux.c *********************************************/ /************** Begin file vdbeapi.c *****************************************/ /* @@ -94091,12 +93153,8 @@ static int bindText( if( zData!=0 ){ pVar = &p->aVar[i-1]; rc = sqlite3VdbeMemSetStr(pVar, zData, nData, encoding, xDel); - if( rc==SQLITE_OK ){ - if( encoding==0 ){ - pVar->enc = ENC(p->db); - }else{ - rc = sqlite3VdbeChangeEncoding(pVar, ENC(p->db)); - } + if( rc==SQLITE_OK && encoding!=0 ){ + rc = sqlite3VdbeChangeEncoding(pVar, ENC(p->db)); } if( rc ){ sqlite3Error(p->db, rc); @@ -94565,7 +93623,7 @@ static UnpackedRecord *vdbeUnpackRecord( pRet = sqlite3VdbeAllocUnpackedRecord(pKeyInfo); if( pRet ){ memset(pRet->aMem, 0, sizeof(Mem)*(pKeyInfo->nKeyField+1)); - sqlite3VdbeRecordUnpack(nKey, pKey, pRet); + sqlite3VdbeRecordUnpack(pKeyInfo, nKey, pKey, pRet); } return pRet; } @@ -94594,9 +93652,6 @@ SQLITE_API int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppVa } if( p->pPk ){ iStore = sqlite3TableColumnToIndex(p->pPk, iIdx); - }else if( iIdx >= p->pTab->nCol ){ - rc = SQLITE_MISUSE_BKPT; - goto preupdate_old_out; }else{ iStore = sqlite3TableColumnToStorage(p->pTab, iIdx); } @@ -94752,8 +93807,6 @@ SQLITE_API int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppVa } if( p->pPk && p->op!=SQLITE_UPDATE ){ iStore = sqlite3TableColumnToIndex(p->pPk, iIdx); - }else if( iIdx >= p->pTab->nCol ){ - return SQLITE_MISUSE_BKPT; }else{ iStore = sqlite3TableColumnToStorage(p->pTab, iIdx); } @@ -95029,10 +94082,10 @@ SQLITE_API void sqlite3_stmt_scanstatus_reset(sqlite3_stmt *pStmt){ ** a host parameter. If the text contains no host parameters, return ** the total number of bytes in the text. */ -static i64 findNextHostParameter(const char *zSql, i64 *pnToken){ +static int findNextHostParameter(const char *zSql, int *pnToken){ int tokenType; - i64 nTotal = 0; - i64 n; + int nTotal = 0; + int n; *pnToken = 0; while( zSql[0] ){ @@ -95079,8 +94132,8 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql( sqlite3 *db; /* The database connection */ int idx = 0; /* Index of a host parameter */ int nextIndex = 1; /* Index of next ? host parameter */ - i64 n; /* Length of a token prefix */ - i64 nToken; /* Length of the parameter token */ + int n; /* Length of a token prefix */ + int nToken; /* Length of the parameter token */ int i; /* Loop counter */ Mem *pVar; /* Value of a host parameter */ StrAccum out; /* Accumulate the output here */ @@ -96004,7 +95057,7 @@ static u64 filterHash(const Mem *aMem, const Op *pOp){ static SQLITE_NOINLINE int vdbeColumnFromOverflow( VdbeCursor *pC, /* The BTree cursor from which we are reading */ int iCol, /* The column to read */ - u32 t, /* The serial-type code for the column value */ + int t, /* The serial-type code for the column value */ i64 iOffset, /* Offset to the start of the content value */ u32 cacheStatus, /* Current Vdbe.cacheCtr value */ u32 colCacheCtr, /* Current value of the column cache counter */ @@ -96079,36 +95132,6 @@ static SQLITE_NOINLINE int vdbeColumnFromOverflow( return rc; } -/* -** Send a "statement aborts" message to the error log. -*/ -static SQLITE_NOINLINE void sqlite3VdbeLogAbort( - Vdbe *p, /* The statement that is running at the time of failure */ - int rc, /* Error code */ - Op *pOp, /* Opcode that filed */ - Op *aOp /* All opcodes */ -){ - const char *zSql = p->zSql; /* Original SQL text */ - const char *zPrefix = ""; /* Prefix added to SQL text */ - int pc; /* Opcode address */ - char zXtra[100]; /* Buffer space to store zPrefix */ - - if( p->pFrame ){ - assert( aOp[0].opcode==OP_Init ); - if( aOp[0].p4.z!=0 ){ - assert( aOp[0].p4.z[0]=='-' - && aOp[0].p4.z[1]=='-' - && aOp[0].p4.z[2]==' ' ); - sqlite3_snprintf(sizeof(zXtra), zXtra,"/* %s */ ",aOp[0].p4.z+3); - zPrefix = zXtra; - }else{ - zPrefix = "/* unknown trigger */ "; - } - } - pc = (int)(pOp - aOp); - sqlite3_log(rc, "statement aborts at %d: %s; [%s%s]", - pc, p->zErrMsg, zPrefix, zSql); -} /* ** Return the symbolic name for the data type of a pMem @@ -96634,7 +95657,8 @@ case OP_Halt: { }else{ sqlite3VdbeError(p, "%s", pOp->p4.z); } - sqlite3VdbeLogAbort(p, pOp->p1, pOp, aOp); + pcx = (int)(pOp - aOp); + sqlite3_log(pOp->p1, "abort at %d: %s; [%s]", pcx, p->zErrMsg, p->zSql); } rc = sqlite3VdbeHalt(p); assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR ); @@ -97013,7 +96037,7 @@ case OP_IntCopy: { /* out2 */ ** RETURNING clause. */ case OP_FkCheck: { - if( (rc = sqlite3VdbeCheckFkImmediate(p))!=SQLITE_OK ){ + if( (rc = sqlite3VdbeCheckFk(p,0))!=SQLITE_OK ){ goto abort_due_to_error; } break; @@ -97105,14 +96129,10 @@ case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */ if( sqlite3VdbeMemExpandBlob(pIn2) ) goto no_mem; flags2 = pIn2->flags & ~MEM_Str; } - nByte = pIn1->n; - nByte += pIn2->n; + nByte = pIn1->n + pIn2->n; if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){ goto too_big; } -#if SQLITE_MAX_LENGTH>2147483645 - if( nByte>2147483645 ){ goto too_big; } -#endif if( sqlite3VdbeMemGrow(pOut, (int)nByte+2, pOut==pIn2) ){ goto no_mem; } @@ -97796,7 +96816,6 @@ case OP_Compare: { pKeyInfo = pOp->p4.pKeyInfo; assert( n>0 ); assert( pKeyInfo!=0 ); - assert( pKeyInfo->aSortFlags!=0 ); p1 = pOp->p1; p2 = pOp->p2; #ifdef SQLITE_DEBUG @@ -98559,15 +97578,6 @@ op_column_corrupt: ** Take the affinities from the Table object in P4. If any value ** cannot be coerced into the correct type, then raise an error. ** -** If P3==0, then omit checking of VIRTUAL columns. -** -** If P3==1, then omit checking of all generated column, both VIRTUAL -** and STORED. -** -** If P3>=2, then only check column number P3-2 in the table (which will -** be a VIRTUAL column) against the value in reg[P1]. In this case, -** P2 will be 1. -** ** This opcode is similar to OP_Affinity except that this opcode ** forces the register type to the Table column type. This is used ** to implement "strict affinity". @@ -98581,8 +97591,8 @@ op_column_corrupt: ** ** <ul> ** <li> P2 should be the number of non-virtual columns in the -** table of P4 unless P3>1, in which case P2 will be 1. -** <li> Table P4 is a STRICT table. +** table of P4. +** <li> Table P4 should be a STRICT table. ** </ul> ** ** If any precondition is false, an assertion fault occurs. @@ -98591,28 +97601,16 @@ case OP_TypeCheck: { Table *pTab; Column *aCol; int i; - int nCol; assert( pOp->p4type==P4_TABLE ); pTab = pOp->p4.pTab; assert( pTab->tabFlags & TF_Strict ); - assert( pOp->p3>=0 && pOp->p3<pTab->nCol+2 ); + assert( pTab->nNVCol==pOp->p2 ); aCol = pTab->aCol; pIn1 = &aMem[pOp->p1]; - if( pOp->p3<2 ){ - assert( pTab->nNVCol==pOp->p2 ); - i = 0; - nCol = pTab->nCol; - }else{ - i = pOp->p3-2; - nCol = i+1; - assert( i<pTab->nCol ); - assert( aCol[i].colFlags & COLFLAG_VIRTUAL ); - assert( pOp->p2==1 ); - } - for(; i<nCol; i++){ - if( (aCol[i].colFlags & COLFLAG_GENERATED)!=0 && pOp->p3<2 ){ - if( (aCol[i].colFlags & COLFLAG_VIRTUAL)!=0 ) continue; + for(i=0; i<pTab->nCol; i++){ + if( aCol[i].colFlags & COLFLAG_GENERATED ){ + if( aCol[i].colFlags & COLFLAG_VIRTUAL ) continue; if( pOp->p3 ){ pIn1++; continue; } } assert( pIn1 < &aMem[pOp->p1+pOp->p2] ); @@ -98934,7 +97932,7 @@ case OP_MakeRecord: { len = (u32)pRec->n; serial_type = (len*2) + 12 + ((pRec->flags & MEM_Str)!=0); if( pRec->flags & MEM_Zero ){ - serial_type += (u32)pRec->u.nZero*2; + serial_type += pRec->u.nZero*2; if( nData ){ if( sqlite3VdbeMemExpandBlob(pRec) ) goto no_mem; len += pRec->u.nZero; @@ -99201,7 +98199,7 @@ case OP_Savepoint: { */ int isTransaction = pSavepoint->pNext==0 && db->isTransactionSavepoint; if( isTransaction && p1==SAVEPOINT_RELEASE ){ - if( (rc = sqlite3VdbeCheckFkDeferred(p))!=SQLITE_OK ){ + if( (rc = sqlite3VdbeCheckFk(p, 1))!=SQLITE_OK ){ goto vdbe_return; } db->autoCommit = 1; @@ -99319,7 +98317,7 @@ case OP_AutoCommit: { "SQL statements in progress"); rc = SQLITE_BUSY; goto abort_due_to_error; - }else if( (rc = sqlite3VdbeCheckFkDeferred(p))!=SQLITE_OK ){ + }else if( (rc = sqlite3VdbeCheckFk(p, 1))!=SQLITE_OK ){ goto vdbe_return; }else{ db->autoCommit = (u8)desiredAutoCommit; @@ -100691,7 +99689,7 @@ case OP_Found: { /* jump, in3, ncycle */ if( rc ) goto no_mem; pIdxKey = sqlite3VdbeAllocUnpackedRecord(pC->pKeyInfo); if( pIdxKey==0 ) goto no_mem; - sqlite3VdbeRecordUnpack(r.aMem->n, r.aMem->z, pIdxKey); + sqlite3VdbeRecordUnpack(pC->pKeyInfo, r.aMem->n, r.aMem->z, pIdxKey); pIdxKey->default_rc = 0; rc = sqlite3BtreeIndexMoveto(pC->uc.pCursor, pIdxKey, &pC->seekResult); sqlite3DbFreeNN(db, pIdxKey); @@ -101689,32 +100687,6 @@ case OP_Rewind: { /* jump0, ncycle */ break; } -/* Opcode: IfEmpty P1 P2 * * * -** Synopsis: if( empty(P1) ) goto P2 -** -** Check to see if the b-tree table that cursor P1 references is empty -** and jump to P2 if it is. -*/ -case OP_IfEmpty: { /* jump */ - VdbeCursor *pC; - BtCursor *pCrsr; - int res; - - assert( pOp->p1>=0 && pOp->p1<p->nCursor ); - assert( pOp->p2>=0 && pOp->p2<p->nOp ); - - pC = p->apCsr[pOp->p1]; - assert( pC!=0 ); - assert( pC->eCurType==CURTYPE_BTREE ); - pCrsr = pC->uc.pCursor; - assert( pCrsr ); - rc = sqlite3BtreeIsEmpty(pCrsr, &res); - if( rc ) goto abort_due_to_error; - VdbeBranchTaken(res!=0,2); - if( res ) goto jump_to_p2; - break; -} - /* Opcode: Next P1 P2 P3 * P5 ** ** Advance cursor P1 so that it points to the next key/data pair in its @@ -103251,7 +102223,6 @@ case OP_Checkpoint: { || pOp->p2==SQLITE_CHECKPOINT_FULL || pOp->p2==SQLITE_CHECKPOINT_RESTART || pOp->p2==SQLITE_CHECKPOINT_TRUNCATE - || pOp->p2==SQLITE_CHECKPOINT_NOOP ); rc = sqlite3Checkpoint(db, pOp->p1, pOp->p2, &aRes[1], &aRes[2]); if( rc ){ @@ -103587,14 +102558,7 @@ case OP_VOpen: { /* ncycle */ const sqlite3_module *pModule; assert( p->bIsReader ); - pCur = p->apCsr[pOp->p1]; - if( pCur!=0 - && ALWAYS( pCur->eCurType==CURTYPE_VTAB ) - && ALWAYS( pCur->uc.pVCur->pVtab==pOp->p4.pVtab->pVtab ) - ){ - /* This opcode is a no-op if the cursor is already open */ - break; - } + pCur = 0; pVCur = 0; pVtab = pOp->p4.pVtab->pVtab; if( pVtab==0 || NEVER(pVtab->pModule==0) ){ @@ -104536,7 +103500,8 @@ abort_due_to_error: p->rc = rc; sqlite3SystemError(db, rc); testcase( sqlite3GlobalConfig.xLog!=0 ); - sqlite3VdbeLogAbort(p, rc, pOp, aOp); + sqlite3_log(rc, "statement aborts at %d: %s; [%s]", + (int)(pOp - aOp), p->zErrMsg, p->zSql); if( p->eVdbeState==VDBE_RUN_STATE ) sqlite3VdbeHalt(p); if( rc==SQLITE_IOERR_NOMEM ) sqlite3OomFault(db); if( rc==SQLITE_CORRUPT && db->autoCommit==0 ){ @@ -104997,7 +103962,7 @@ static int blobReadWrite( int iOffset, int (*xCall)(BtCursor*, u32, u32, void*) ){ - int rc = SQLITE_OK; + int rc; Incrblob *p = (Incrblob *)pBlob; Vdbe *v; sqlite3 *db; @@ -105037,32 +104002,17 @@ static int blobReadWrite( ** using the incremental-blob API, this works. For the sessions module ** anyhow. */ - if( sqlite3BtreeCursorIsValidNN(p->pCsr)==0 ){ - /* If the cursor is not currently valid, try to reseek it. This - ** always either fails or finds the correct row - the cursor will - ** have been marked permanently CURSOR_INVALID if the open row has - ** been deleted. */ - int bDiff = 0; - rc = sqlite3BtreeCursorRestore(p->pCsr, &bDiff); - assert( bDiff==0 || sqlite3BtreeCursorIsValidNN(p->pCsr)==0 ); - } - if( sqlite3BtreeCursorIsValidNN(p->pCsr) ){ - sqlite3_int64 iKey; - iKey = sqlite3BtreeIntegerKey(p->pCsr); - assert( v->apCsr[0]!=0 ); - assert( v->apCsr[0]->eCurType==CURTYPE_BTREE ); - sqlite3VdbePreUpdateHook( - v, v->apCsr[0], SQLITE_DELETE, p->zDb, p->pTab, iKey, -1, p->iCol - ); - } - } - if( rc==SQLITE_OK ){ - rc = xCall(p->pCsr, iOffset+p->iOffset, n, z); + sqlite3_int64 iKey; + iKey = sqlite3BtreeIntegerKey(p->pCsr); + assert( v->apCsr[0]!=0 ); + assert( v->apCsr[0]->eCurType==CURTYPE_BTREE ); + sqlite3VdbePreUpdateHook( + v, v->apCsr[0], SQLITE_DELETE, p->zDb, p->pTab, iKey, -1, p->iCol + ); } -#else - rc = xCall(p->pCsr, iOffset+p->iOffset, n, z); #endif + rc = xCall(p->pCsr, iOffset+p->iOffset, n, z); sqlite3BtreeLeaveCursor(p->pCsr); if( rc==SQLITE_ABORT ){ sqlite3VdbeFinalize(v); @@ -105451,7 +104401,6 @@ struct SortSubtask { SorterCompare xCompare; /* Compare function to use */ SorterFile file; /* Temp file for level-0 PMAs */ SorterFile file2; /* Space for other PMAs */ - u64 nSpill; /* Total bytes written by this task */ }; @@ -105572,7 +104521,6 @@ struct PmaWriter { int iBufEnd; /* Last byte of buffer to write */ i64 iWriteOff; /* Offset of start of buffer in file */ sqlite3_file *pFd; /* File handle to write to */ - u64 nPmaSpill; /* Total number of bytes written */ }; /* @@ -105917,7 +104865,7 @@ static int vdbeSorterCompareTail( ){ UnpackedRecord *r2 = pTask->pUnpacked; if( *pbKey2Cached==0 ){ - sqlite3VdbeRecordUnpack(nKey2, pKey2, r2); + sqlite3VdbeRecordUnpack(pTask->pSorter->pKeyInfo, nKey2, pKey2, r2); *pbKey2Cached = 1; } return sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, r2, 1); @@ -105944,7 +104892,7 @@ static int vdbeSorterCompare( ){ UnpackedRecord *r2 = pTask->pUnpacked; if( !*pbKey2Cached ){ - sqlite3VdbeRecordUnpack(nKey2, pKey2, r2); + sqlite3VdbeRecordUnpack(pTask->pSorter->pKeyInfo, nKey2, pKey2, r2); *pbKey2Cached = 1; } return sqlite3VdbeRecordCompare(nKey1, pKey1, r2); @@ -105984,7 +104932,6 @@ static int vdbeSorterCompareText( ); } }else{ - assert( pTask->pSorter->pKeyInfo->aSortFlags!=0 ); assert( !(pTask->pSorter->pKeyInfo->aSortFlags[0]&KEYINFO_ORDER_BIGNULL) ); if( pTask->pSorter->pKeyInfo->aSortFlags[0] ){ res = res * -1; @@ -106048,7 +104995,6 @@ static int vdbeSorterCompareInt( } } - assert( pTask->pSorter->pKeyInfo->aSortFlags!=0 ); if( res==0 ){ if( pTask->pSorter->pKeyInfo->nKeyField>1 ){ res = vdbeSorterCompareTail( @@ -106122,8 +105068,7 @@ SQLITE_PRIVATE int sqlite3VdbeSorterInit( assert( pCsr->eCurType==CURTYPE_SORTER ); assert( sizeof(KeyInfo) + UMXV(pCsr->pKeyInfo->nKeyField)*sizeof(CollSeq*) < 0x7fffffff ); - assert( pCsr->pKeyInfo->nKeyField<=pCsr->pKeyInfo->nAllField ); - szKeyInfo = SZ_KEYINFO(pCsr->pKeyInfo->nAllField); + szKeyInfo = SZ_KEYINFO(pCsr->pKeyInfo->nKeyField); sz = SZ_VDBESORTER(nWorker+1); pSorter = (VdbeSorter*)sqlite3DbMallocZero(db, sz + szKeyInfo); @@ -106137,12 +105082,7 @@ SQLITE_PRIVATE int sqlite3VdbeSorterInit( pKeyInfo->db = 0; if( nField && nWorker==0 ){ pKeyInfo->nKeyField = nField; - assert( nField<=pCsr->pKeyInfo->nAllField ); } - /* It is OK that pKeyInfo reuses the aSortFlags field from pCsr->pKeyInfo, - ** since the pCsr->pKeyInfo->aSortFlags[] array is invariant and lives - ** longer that pSorter. */ - assert( pKeyInfo->aSortFlags==pCsr->pKeyInfo->aSortFlags ); sqlite3BtreeEnter(pBt); pSorter->pgsz = pgsz = sqlite3BtreeGetPageSize(pBt); sqlite3BtreeLeave(pBt); @@ -106431,12 +105371,6 @@ SQLITE_PRIVATE void sqlite3VdbeSorterClose(sqlite3 *db, VdbeCursor *pCsr){ assert( pCsr->eCurType==CURTYPE_SORTER ); pSorter = pCsr->uc.pSorter; if( pSorter ){ - /* Increment db->nSpill by the total number of bytes of data written - ** to temp files by this sort operation. */ - int ii; - for(ii=0; ii<pSorter->nTask; ii++){ - db->nSpill += pSorter->aTask[ii].nSpill; - } sqlite3VdbeSorterReset(db, pSorter); sqlite3_free(pSorter->list.aMemory); sqlite3DbFree(db, pSorter); @@ -106662,7 +105596,6 @@ static void vdbePmaWriteBlob(PmaWriter *p, u8 *pData, int nData){ &p->aBuffer[p->iBufStart], p->iBufEnd - p->iBufStart, p->iWriteOff + p->iBufStart ); - p->nPmaSpill += (p->iBufEnd - p->iBufStart); p->iBufStart = p->iBufEnd = 0; p->iWriteOff += p->nBuffer; } @@ -106679,20 +105612,17 @@ static void vdbePmaWriteBlob(PmaWriter *p, u8 *pData, int nData){ ** required. Otherwise, return an SQLite error code. ** ** Before returning, set *piEof to the offset immediately following the -** last byte written to the file. Also, increment (*pnSpill) by the total -** number of bytes written to the file. +** last byte written to the file. */ -static int vdbePmaWriterFinish(PmaWriter *p, i64 *piEof, u64 *pnSpill){ +static int vdbePmaWriterFinish(PmaWriter *p, i64 *piEof){ int rc; if( p->eFWErr==0 && ALWAYS(p->aBuffer) && p->iBufEnd>p->iBufStart ){ p->eFWErr = sqlite3OsWrite(p->pFd, &p->aBuffer[p->iBufStart], p->iBufEnd - p->iBufStart, p->iWriteOff + p->iBufStart ); - p->nPmaSpill += (p->iBufEnd - p->iBufStart); } *piEof = (p->iWriteOff + p->iBufEnd); - *pnSpill += p->nPmaSpill; sqlite3_free(p->aBuffer); rc = p->eFWErr; memset(p, 0, sizeof(PmaWriter)); @@ -106772,7 +105702,7 @@ static int vdbeSorterListToPMA(SortSubtask *pTask, SorterList *pList){ if( pList->aMemory==0 ) sqlite3_free(p); } pList->pList = p; - rc = vdbePmaWriterFinish(&writer, &pTask->file.iEof, &pTask->nSpill); + rc = vdbePmaWriterFinish(&writer, &pTask->file.iEof); } vdbeSorterWorkDebug(pTask, "exit"); @@ -107086,7 +106016,7 @@ static int vdbeIncrPopulate(IncrMerger *pIncr){ rc = vdbeMergeEngineStep(pIncr->pMerger, &dummy); } - rc2 = vdbePmaWriterFinish(&writer, &pOut->iEof, &pTask->nSpill); + rc2 = vdbePmaWriterFinish(&writer, &pOut->iEof); if( rc==SQLITE_OK ) rc = rc2; vdbeSorterPopulateDebug(pTask, "exit"); return rc; @@ -107932,7 +106862,7 @@ SQLITE_PRIVATE int sqlite3VdbeSorterCompare( assert( r2->nField==nKeyCol ); pKey = vdbeSorterRowkey(pSorter, &nKey); - sqlite3VdbeRecordUnpack(nKey, pKey, r2); + sqlite3VdbeRecordUnpack(pKeyInfo, nKey, pKey, r2); for(i=0; i<nKeyCol; i++){ if( r2->aMem[i].flags & MEM_Null ){ *pRes = -1; @@ -109477,13 +108407,10 @@ static int lookupName( if( cnt>0 ){ if( pItem->fg.isUsing==0 || sqlite3IdListIndex(pItem->u3.pUsing, zCol)<0 - || pMatch==pItem ){ /* Two or more tables have the same column name which is - ** not joined by USING. Or, a single table has two columns - ** that match a USING term (if pMatch==pItem). These are both - ** "ambiguous column name" errors. Signal as much by clearing - ** pFJMatch and letting cnt go above 1. */ + ** not joined by USING. This is an error. Signal as much + ** by clearing pFJMatch and letting cnt go above 1. */ sqlite3ExprListDelete(db, pFJMatch); pFJMatch = 0; }else @@ -110033,8 +108960,8 @@ static void notValidImpl( /* ** Expression p should encode a floating point value between 1.0 and 0.0. -** Return 134,217,728 (2^27) times this value. Or return -1 if p is not -** a floating point value between 1.0 and 0.0. +** Return 1024 times this value. Or return -1 if p is not a floating point +** value between 1.0 and 0.0. */ static int exprProbability(Expr *p){ double r = -1.0; @@ -110465,13 +109392,11 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ return WRC_Prune; } #ifndef SQLITE_OMIT_SUBQUERY - case TK_EXISTS: case TK_SELECT: + case TK_EXISTS: testcase( pExpr->op==TK_EXISTS ); #endif case TK_IN: { testcase( pExpr->op==TK_IN ); - testcase( pExpr->op==TK_EXISTS ); - testcase( pExpr->op==TK_SELECT ); if( ExprUseXSelect(pExpr) ){ int nRef = pNC->nRef; testcase( pNC->ncFlags & NC_IsCheck ); @@ -110479,7 +109404,6 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ testcase( pNC->ncFlags & NC_IdxExpr ); testcase( pNC->ncFlags & NC_GenCol ); assert( pExpr->x.pSelect ); - if( pExpr->op==TK_EXISTS ) pParse->bHasExists = 1; if( pNC->ncFlags & NC_SelfRef ){ notValidImpl(pParse, pNC, "subqueries", pExpr, pExpr); }else{ @@ -111390,17 +110314,14 @@ SQLITE_PRIVATE int sqlite3ResolveSelfReference( SrcList *pSrc; /* Fake SrcList for pParse->pNewTable */ NameContext sNC; /* Name context for pParse->pNewTable */ int rc; - union { - SrcList sSrc; - u8 srcSpace[SZ_SRCLIST_1]; /* Memory space for the fake SrcList */ - } uSrc; + u8 srcSpace[SZ_SRCLIST_1]; /* Memory space for the fake SrcList */ assert( type==0 || pTab!=0 ); assert( type==NC_IsCheck || type==NC_PartIdx || type==NC_IdxExpr || type==NC_GenCol || pTab==0 ); memset(&sNC, 0, sizeof(sNC)); - memset(&uSrc, 0, sizeof(uSrc)); - pSrc = &uSrc.sSrc; + pSrc = (SrcList*)srcSpace; + memset(pSrc, 0, SZ_SRCLIST_1); if( pTab ){ pSrc->nSrc = 1; pSrc->a[0].zName = pTab->zName; @@ -112663,11 +111584,6 @@ SQLITE_PRIVATE void sqlite3ExprAddFunctionOrderBy( sqlite3ExprListDelete(db, pOrderBy); return; } - if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){ - sqlite3ErrorMsg(pParse, "too many terms in ORDER BY clause"); - sqlite3ExprListDelete(db, pOrderBy); - return; - } pOB = sqlite3ExprAlloc(db, TK_ORDER, 0, 0); if( pOB==0 ){ @@ -113803,85 +112719,6 @@ SQLITE_PRIVATE Expr *sqlite3ExprSimplifiedAndOr(Expr *pExpr){ } /* -** Return true if it might be advantageous to compute the right operand -** of expression pExpr first, before the left operand. -** -** Normally the left operand is computed before the right operand. But if -** the left operand contains a subquery and the right does not, then it -** might be more efficient to compute the right operand first. -*/ -static int exprEvalRhsFirst(Expr *pExpr){ - if( ExprHasProperty(pExpr->pLeft, EP_Subquery) - && !ExprHasProperty(pExpr->pRight, EP_Subquery) - ){ - return 1; - }else{ - return 0; - } -} - -/* -** Compute the two operands of a binary operator. -** -** If either operand contains a subquery, then the code strives to -** compute the operand containing the subquery second. If the other -** operand evalutes to NULL, then a jump is made. The address of the -** IsNull operand that does this jump is returned. The caller can use -** this to optimize the computation so as to avoid doing the potentially -** expensive subquery. -** -** If no optimization opportunities exist, return 0. -*/ -static int exprComputeOperands( - Parse *pParse, /* Parsing context */ - Expr *pExpr, /* The comparison expression */ - int *pR1, /* OUT: Register holding the left operand */ - int *pR2, /* OUT: Register holding the right operand */ - int *pFree1, /* OUT: Temp register to free if not zero */ - int *pFree2 /* OUT: Another temp register to free if not zero */ -){ - int addrIsNull; - int r1, r2; - Vdbe *v = pParse->pVdbe; - - assert( v!=0 ); - /* - ** If the left operand contains a (possibly expensive) subquery and the - ** right operand does not and the right operation might be NULL, - ** then compute the right operand first and do an IsNull jump if the - ** right operand evalutes to NULL. - */ - if( exprEvalRhsFirst(pExpr) && sqlite3ExprCanBeNull(pExpr->pRight) ){ - r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, pFree2); - addrIsNull = sqlite3VdbeAddOp1(v, OP_IsNull, r2); - VdbeComment((v, "skip left operand")); - VdbeCoverage(v); - }else{ - r2 = 0; /* Silence a false-positive uninit-var warning in MSVC */ - addrIsNull = 0; - } - r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, pFree1); - if( addrIsNull==0 ){ - /* - ** If the right operand contains a subquery and the left operand does not - ** and the left operand might be NULL, then do an IsNull check - ** check on the left operand before computing the right operand. - */ - if( ExprHasProperty(pExpr->pRight, EP_Subquery) - && sqlite3ExprCanBeNull(pExpr->pLeft) - ){ - addrIsNull = sqlite3VdbeAddOp1(v, OP_IsNull, r1); - VdbeComment((v, "skip right operand")); - VdbeCoverage(v); - } - r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, pFree2); - } - *pR1 = r1; - *pR2 = r2; - return addrIsNull; -} - -/* ** pExpr is a TK_FUNCTION node. Try to determine whether or not the ** function is a constant function. A function is constant if all of ** the following are true: @@ -115325,23 +114162,17 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){ VdbeComment((v, "Init EXISTS result")); } if( pSel->pLimit ){ - /* The subquery already has a limit. If the pre-existing limit X is - ** not already integer value 1 or 0, then make the new limit X<>0 so that - ** the new limit is either 1 or 0 */ - Expr *pLeft = pSel->pLimit->pLeft; - if( ExprHasProperty(pLeft, EP_IntValue)==0 - || (pLeft->u.iValue!=1 && pLeft->u.iValue!=0) - ){ - sqlite3 *db = pParse->db; - pLimit = sqlite3Expr(db, TK_INTEGER, "0"); - if( pLimit ){ - pLimit->affExpr = SQLITE_AFF_NUMERIC; - pLimit = sqlite3PExpr(pParse, TK_NE, - sqlite3ExprDup(db, pLeft, 0), pLimit); - } - sqlite3ExprDeferredDelete(pParse, pLeft); - pSel->pLimit->pLeft = pLimit; + /* The subquery already has a limit. If the pre-existing limit is X + ** then make the new limit X<>0 so that the new limit is either 1 or 0 */ + sqlite3 *db = pParse->db; + pLimit = sqlite3Expr(db, TK_INTEGER, "0"); + if( pLimit ){ + pLimit->affExpr = SQLITE_AFF_NUMERIC; + pLimit = sqlite3PExpr(pParse, TK_NE, + sqlite3ExprDup(db, pSel->pLimit->pLeft, 0), pLimit); } + sqlite3ExprDeferredDelete(pParse, pSel->pLimit->pLeft); + pSel->pLimit->pLeft = pLimit; }else{ /* If there is no pre-existing limit add a limit of 1 */ pLimit = sqlite3Expr(pParse->db, TK_INTEGER, "1"); @@ -115429,6 +114260,7 @@ static void sqlite3ExprCodeIN( int rRhsHasNull = 0; /* Register that is true if RHS contains NULL values */ int eType; /* Type of the RHS */ int rLhs; /* Register(s) holding the LHS values */ + int rLhsOrig; /* LHS values prior to reordering by aiMap[] */ Vdbe *v; /* Statement under construction */ int *aiMap = 0; /* Map from vector field to index column */ char *zAff = 0; /* Affinity string for comparisons */ @@ -115491,8 +114323,19 @@ static void sqlite3ExprCodeIN( ** by code generated below. */ assert( pParse->okConstFactor==okConstFactor ); pParse->okConstFactor = 0; - rLhs = exprCodeVector(pParse, pLeft, &iDummy); + rLhsOrig = exprCodeVector(pParse, pLeft, &iDummy); pParse->okConstFactor = okConstFactor; + for(i=0; i<nVector && aiMap[i]==i; i++){} /* Are LHS fields reordered? */ + if( i==nVector ){ + /* LHS fields are not reordered */ + rLhs = rLhsOrig; + }else{ + /* Need to reorder the LHS fields according to aiMap */ + rLhs = sqlite3GetTempRange(pParse, nVector); + for(i=0; i<nVector; i++){ + sqlite3VdbeAddOp3(v, OP_Copy, rLhsOrig+i, rLhs+aiMap[i], 0); + } + } /* If sqlite3FindInIndex() did not find or create an index that is ** suitable for evaluating the IN operator, then evaluate using a @@ -115507,7 +114350,6 @@ static void sqlite3ExprCodeIN( int r2, regToFree; int regCkNull = 0; int ii; - assert( nVector==1 ); assert( ExprUseXList(pExpr) ); pList = pExpr->x.pList; pColl = sqlite3ExprCollSeq(pParse, pExpr->pLeft); @@ -115549,26 +114391,6 @@ static void sqlite3ExprCodeIN( goto sqlite3ExprCodeIN_finished; } - if( eType!=IN_INDEX_ROWID ){ - /* If this IN operator will use an index, then the order of columns in the - ** vector might be different from the order in the index. In that case, - ** we need to reorder the LHS values to be in index order. Run Affinity - ** before reordering the columns, so that the affinity is correct. - */ - sqlite3VdbeAddOp4(v, OP_Affinity, rLhs, nVector, 0, zAff, nVector); - for(i=0; i<nVector && aiMap[i]==i; i++){} /* Are LHS fields reordered? */ - if( i!=nVector ){ - /* Need to reorder the LHS fields according to aiMap */ - int rLhsOrig = rLhs; - rLhs = sqlite3GetTempRange(pParse, nVector); - for(i=0; i<nVector; i++){ - sqlite3VdbeAddOp3(v, OP_Copy, rLhsOrig+i, rLhs+aiMap[i], 0); - } - sqlite3ReleaseTempReg(pParse, rLhsOrig); - } - } - - /* Step 2: Check to see if the LHS contains any NULL columns. If the ** LHS does contain NULLs then the result must be either FALSE or NULL. ** We will then skip the binary search of the RHS. @@ -115595,11 +114417,11 @@ static void sqlite3ExprCodeIN( /* In this case, the RHS is the ROWID of table b-tree and so we also ** know that the RHS is non-NULL. Hence, we combine steps 3 and 4 ** into a single opcode. */ - assert( nVector==1 ); sqlite3VdbeAddOp3(v, OP_SeekRowid, iTab, destIfFalse, rLhs); VdbeCoverage(v); addrTruthOp = sqlite3VdbeAddOp0(v, OP_Goto); /* Return True */ }else{ + sqlite3VdbeAddOp4(v, OP_Affinity, rLhs, nVector, 0, zAff, nVector); if( destIfFalse==destIfNull ){ /* Combine Step 3 and Step 5 into a single opcode */ if( ExprHasProperty(pExpr, EP_Subrtn) ){ @@ -115677,6 +114499,7 @@ static void sqlite3ExprCodeIN( sqlite3VdbeJumpHere(v, addrTruthOp); sqlite3ExprCodeIN_finished: + if( rLhs!=rLhsOrig ) sqlite3ReleaseTempReg(pParse, rLhs); VdbeComment((v, "end IN expr")); sqlite3ExprCodeIN_oom_error: sqlite3DbFree(pParse->db, aiMap); @@ -115791,12 +114614,7 @@ SQLITE_PRIVATE void sqlite3ExprCodeGeneratedColumn( iAddr = 0; } sqlite3ExprCodeCopy(pParse, sqlite3ColumnExpr(pTab,pCol), regOut); - if( (pCol->colFlags & COLFLAG_VIRTUAL)!=0 - && (pTab->tabFlags & TF_Strict)!=0 - ){ - int p3 = 2+(int)(pCol - pTab->aCol); - sqlite3VdbeAddOp4(v, OP_TypeCheck, regOut, 1, p3, (char*)pTab, P4_TABLE); - }else if( pCol->affinity>=SQLITE_AFF_TEXT ){ + if( pCol->affinity>=SQLITE_AFF_TEXT ){ sqlite3VdbeAddOp4(v, OP_Affinity, regOut, 1, 0, &pCol->affinity, 1); } if( iAddr ) sqlite3VdbeJumpHere(v, iAddr); @@ -116234,80 +115052,6 @@ static int exprPartidxExprLookup(Parse *pParse, Expr *pExpr, int iTarget){ return 0; } -/* -** Generate code that evaluates an AND or OR operator leaving a -** boolean result in a register. pExpr is the AND/OR expression. -** Store the result in the "target" register. Use short-circuit -** evaluation to avoid computing both operands, if possible. -** -** The code generated might require the use of a temporary register. -** If it does, then write the number of that temporary register -** into *pTmpReg. If not, leave *pTmpReg unchanged. -*/ -static SQLITE_NOINLINE int exprCodeTargetAndOr( - Parse *pParse, /* Parsing context */ - Expr *pExpr, /* AND or OR expression to be coded */ - int target, /* Put result in this register, guaranteed */ - int *pTmpReg /* Write a temporary register here */ -){ - int op; /* The opcode. TK_AND or TK_OR */ - int skipOp; /* Opcode for the branch that skips one operand */ - int addrSkip; /* Branch instruction that skips one of the operands */ - int regSS = 0; /* Register holding computed operand when other omitted */ - int r1, r2; /* Registers for left and right operands, respectively */ - Expr *pAlt; /* Alternative, simplified expression */ - Vdbe *v; /* statement being coded */ - - assert( pExpr!=0 ); - op = pExpr->op; - assert( op==TK_AND || op==TK_OR ); - assert( TK_AND==OP_And ); testcase( op==TK_AND ); - assert( TK_OR==OP_Or ); testcase( op==TK_OR ); - assert( pParse->pVdbe!=0 ); - v = pParse->pVdbe; - pAlt = sqlite3ExprSimplifiedAndOr(pExpr); - if( pAlt!=pExpr ){ - r1 = sqlite3ExprCodeTarget(pParse, pAlt, target); - sqlite3VdbeAddOp3(v, OP_And, r1, r1, target); - return target; - } - skipOp = op==TK_AND ? OP_IfNot : OP_If; - if( exprEvalRhsFirst(pExpr) ){ - /* Compute the right operand first. Skip the computation of the left - ** operand if the right operand fully determines the result */ - r2 = regSS = sqlite3ExprCodeTarget(pParse, pExpr->pRight, target); - addrSkip = sqlite3VdbeAddOp1(v, skipOp, r2); - VdbeComment((v, "skip left operand")); - VdbeCoverage(v); - r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, pTmpReg); - }else{ - /* Compute the left operand first */ - r1 = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); - if( ExprHasProperty(pExpr->pRight, EP_Subquery) ){ - /* Skip over the computation of the right operand if the right - ** operand is a subquery and the left operand completely determines - ** the result */ - regSS = r1; - addrSkip = sqlite3VdbeAddOp1(v, skipOp, r1); - VdbeComment((v, "skip right operand")); - VdbeCoverage(v); - }else{ - addrSkip = regSS = 0; - } - r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, pTmpReg); - } - sqlite3VdbeAddOp3(v, op, r2, r1, target); - testcase( (*pTmpReg)==0 ); - if( addrSkip ){ - sqlite3VdbeAddOp2(v, OP_Goto, 0, sqlite3VdbeCurrentAddr(v)+2); - sqlite3VdbeJumpHere(v, addrSkip); - sqlite3VdbeAddOp3(v, OP_Or, regSS, regSS, target); - VdbeComment((v, "short-circut value")); - } - return target; -} - - /* ** Generate code into the current Vdbe to evaluate the given @@ -116563,17 +115307,11 @@ expr_code_doover: case TK_NE: case TK_EQ: { Expr *pLeft = pExpr->pLeft; - int addrIsNull = 0; if( sqlite3ExprIsVector(pLeft) ){ codeVectorCompare(pParse, pExpr, target, op, p5); }else{ - if( ExprHasProperty(pExpr, EP_Subquery) && p5!=SQLITE_NULLEQ ){ - addrIsNull = exprComputeOperands(pParse, pExpr, - &r1, &r2, ®Free1, ®Free2); - }else{ - r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); - r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); - } + r1 = sqlite3ExprCodeTemp(pParse, pLeft, ®Free1); + r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); sqlite3VdbeAddOp2(v, OP_Integer, 1, inReg); codeCompare(pParse, pLeft, pExpr->pRight, op, r1, r2, sqlite3VdbeCurrentAddr(v)+2, p5, @@ -116588,11 +115326,6 @@ expr_code_doover: sqlite3VdbeAddOp2(v, OP_Integer, 0, inReg); }else{ sqlite3VdbeAddOp3(v, OP_ZeroOrNull, r1, inReg, r2); - if( addrIsNull ){ - sqlite3VdbeAddOp2(v, OP_Goto, 0, sqlite3VdbeCurrentAddr(v)+2); - sqlite3VdbeJumpHere(v, addrIsNull); - sqlite3VdbeAddOp2(v, OP_Null, 0, inReg); - } } testcase( regFree1==0 ); testcase( regFree2==0 ); @@ -116600,10 +115333,7 @@ expr_code_doover: break; } case TK_AND: - case TK_OR: { - inReg = exprCodeTargetAndOr(pParse, pExpr, target, ®Free1); - break; - } + case TK_OR: case TK_PLUS: case TK_STAR: case TK_MINUS: @@ -116614,7 +115344,8 @@ expr_code_doover: case TK_LSHIFT: case TK_RSHIFT: case TK_CONCAT: { - int addrIsNull; + assert( TK_AND==OP_And ); testcase( op==TK_AND ); + assert( TK_OR==OP_Or ); testcase( op==TK_OR ); assert( TK_PLUS==OP_Add ); testcase( op==TK_PLUS ); assert( TK_MINUS==OP_Subtract ); testcase( op==TK_MINUS ); assert( TK_REM==OP_Remainder ); testcase( op==TK_REM ); @@ -116624,23 +115355,11 @@ expr_code_doover: assert( TK_LSHIFT==OP_ShiftLeft ); testcase( op==TK_LSHIFT ); assert( TK_RSHIFT==OP_ShiftRight ); testcase( op==TK_RSHIFT ); assert( TK_CONCAT==OP_Concat ); testcase( op==TK_CONCAT ); - if( ExprHasProperty(pExpr, EP_Subquery) ){ - addrIsNull = exprComputeOperands(pParse, pExpr, - &r1, &r2, ®Free1, ®Free2); - }else{ - r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); - r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); - addrIsNull = 0; - } + r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); + r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); sqlite3VdbeAddOp3(v, op, r2, r1, target); testcase( regFree1==0 ); testcase( regFree2==0 ); - if( addrIsNull ){ - sqlite3VdbeAddOp2(v, OP_Goto, 0, sqlite3VdbeCurrentAddr(v)+2); - sqlite3VdbeJumpHere(v, addrIsNull); - sqlite3VdbeAddOp2(v, OP_Null, 0, target); - VdbeComment((v, "short-circut value")); - } break; } case TK_UMINUS: { @@ -117508,27 +116227,17 @@ SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int Expr *pAlt = sqlite3ExprSimplifiedAndOr(pExpr); if( pAlt!=pExpr ){ sqlite3ExprIfTrue(pParse, pAlt, dest, jumpIfNull); + }else if( op==TK_AND ){ + int d2 = sqlite3VdbeMakeLabel(pParse); + testcase( jumpIfNull==0 ); + sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2, + jumpIfNull^SQLITE_JUMPIFNULL); + sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); + sqlite3VdbeResolveLabel(v, d2); }else{ - Expr *pFirst, *pSecond; - if( exprEvalRhsFirst(pExpr) ){ - pFirst = pExpr->pRight; - pSecond = pExpr->pLeft; - }else{ - pFirst = pExpr->pLeft; - pSecond = pExpr->pRight; - } - if( op==TK_AND ){ - int d2 = sqlite3VdbeMakeLabel(pParse); - testcase( jumpIfNull==0 ); - sqlite3ExprIfFalse(pParse, pFirst, d2, - jumpIfNull^SQLITE_JUMPIFNULL); - sqlite3ExprIfTrue(pParse, pSecond, dest, jumpIfNull); - sqlite3VdbeResolveLabel(v, d2); - }else{ - testcase( jumpIfNull==0 ); - sqlite3ExprIfTrue(pParse, pFirst, dest, jumpIfNull); - sqlite3ExprIfTrue(pParse, pSecond, dest, jumpIfNull); - } + testcase( jumpIfNull==0 ); + sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull); + sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); } break; } @@ -117567,16 +116276,10 @@ SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int case TK_GE: case TK_NE: case TK_EQ: { - int addrIsNull; if( sqlite3ExprIsVector(pExpr->pLeft) ) goto default_expr; - if( ExprHasProperty(pExpr, EP_Subquery) && jumpIfNull!=SQLITE_NULLEQ ){ - addrIsNull = exprComputeOperands(pParse, pExpr, - &r1, &r2, ®Free1, ®Free2); - }else{ - r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); - r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); - addrIsNull = 0; - } + testcase( jumpIfNull==0 ); + r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); + r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, r1, r2, dest, jumpIfNull, ExprHasProperty(pExpr,EP_Commuted)); assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt); @@ -117591,13 +116294,6 @@ SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int VdbeCoverageIf(v, op==OP_Ne && jumpIfNull!=SQLITE_NULLEQ); testcase( regFree1==0 ); testcase( regFree2==0 ); - if( addrIsNull ){ - if( jumpIfNull ){ - sqlite3VdbeChangeP2(v, addrIsNull, dest); - }else{ - sqlite3VdbeJumpHere(v, addrIsNull); - } - } break; } case TK_ISNULL: @@ -117705,27 +116401,17 @@ SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int Expr *pAlt = sqlite3ExprSimplifiedAndOr(pExpr); if( pAlt!=pExpr ){ sqlite3ExprIfFalse(pParse, pAlt, dest, jumpIfNull); + }else if( pExpr->op==TK_AND ){ + testcase( jumpIfNull==0 ); + sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); + sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); }else{ - Expr *pFirst, *pSecond; - if( exprEvalRhsFirst(pExpr) ){ - pFirst = pExpr->pRight; - pSecond = pExpr->pLeft; - }else{ - pFirst = pExpr->pLeft; - pSecond = pExpr->pRight; - } - if( pExpr->op==TK_AND ){ - testcase( jumpIfNull==0 ); - sqlite3ExprIfFalse(pParse, pFirst, dest, jumpIfNull); - sqlite3ExprIfFalse(pParse, pSecond, dest, jumpIfNull); - }else{ - int d2 = sqlite3VdbeMakeLabel(pParse); - testcase( jumpIfNull==0 ); - sqlite3ExprIfTrue(pParse, pFirst, d2, - jumpIfNull^SQLITE_JUMPIFNULL); - sqlite3ExprIfFalse(pParse, pSecond, dest, jumpIfNull); - sqlite3VdbeResolveLabel(v, d2); - } + int d2 = sqlite3VdbeMakeLabel(pParse); + testcase( jumpIfNull==0 ); + sqlite3ExprIfTrue(pParse, pExpr->pLeft, d2, + jumpIfNull^SQLITE_JUMPIFNULL); + sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); + sqlite3VdbeResolveLabel(v, d2); } break; } @@ -117767,16 +116453,10 @@ SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int case TK_GE: case TK_NE: case TK_EQ: { - int addrIsNull; if( sqlite3ExprIsVector(pExpr->pLeft) ) goto default_expr; - if( ExprHasProperty(pExpr, EP_Subquery) && jumpIfNull!=SQLITE_NULLEQ ){ - addrIsNull = exprComputeOperands(pParse, pExpr, - &r1, &r2, ®Free1, ®Free2); - }else{ - r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); - r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); - addrIsNull = 0; - } + testcase( jumpIfNull==0 ); + r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); + r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, r1, r2, dest, jumpIfNull,ExprHasProperty(pExpr,EP_Commuted)); assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt); @@ -117791,13 +116471,6 @@ SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int VdbeCoverageIf(v, op==OP_Ne && jumpIfNull==SQLITE_NULLEQ); testcase( regFree1==0 ); testcase( regFree2==0 ); - if( addrIsNull ){ - if( jumpIfNull ){ - sqlite3VdbeChangeP2(v, addrIsNull, dest); - }else{ - sqlite3VdbeJumpHere(v, addrIsNull); - } - } break; } case TK_ISNULL: @@ -124763,16 +123436,6 @@ SQLITE_PRIVATE Table *sqlite3LocateTable( if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){ pMod = sqlite3PragmaVtabRegister(db, zName); } -#ifndef SQLITE_OMIT_JSON - if( pMod==0 && sqlite3_strnicmp(zName, "json", 4)==0 ){ - pMod = sqlite3JsonVtabRegister(db, zName); - } -#endif -#ifdef SQLITE_ENABLE_CARRAY - if( pMod==0 && sqlite3_stricmp(zName, "carray")==0 ){ - pMod = sqlite3CarrayRegister(db); - } -#endif if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){ testcase( pMod->pEpoTab==0 ); return pMod->pEpoTab; @@ -125411,7 +124074,7 @@ SQLITE_PRIVATE int sqlite3TableColumnToIndex(Index *pIdx, int iCol){ int i; i16 iCol16; assert( iCol>=(-1) && iCol<=SQLITE_MAX_COLUMN ); - assert( pIdx->nColumn<=SQLITE_MAX_COLUMN*2 ); + assert( pIdx->nColumn<=SQLITE_MAX_COLUMN+1 ); iCol16 = iCol; for(i=0; i<pIdx->nColumn; i++){ if( iCol16==pIdx->aiColumn[i] ){ @@ -125708,9 +124371,6 @@ SQLITE_PRIVATE void sqlite3StartTable( sqlite3VdbeAddOp3(v, OP_Insert, 0, reg3, reg1); sqlite3VdbeChangeP5(v, OPFLAG_APPEND); sqlite3VdbeAddOp0(v, OP_Close); - }else if( db->init.imposterTable ){ - pTable->tabFlags |= TF_Imposter; - if( db->init.imposterTable>=2 ) pTable->tabFlags |= TF_Readonly; } /* Normal (non-error) return. */ @@ -129480,22 +128140,16 @@ SQLITE_PRIVATE void sqlite3SrcListIndexedBy(Parse *pParse, SrcList *p, Token *pI ** are deleted by this function. */ SQLITE_PRIVATE SrcList *sqlite3SrcListAppendList(Parse *pParse, SrcList *p1, SrcList *p2){ - assert( p1 ); - assert( p2 || pParse->nErr ); - assert( p2==0 || p2->nSrc>=1 ); - testcase( p1->nSrc==0 ); + assert( p1 && p1->nSrc==1 ); if( p2 ){ - int nOld = p1->nSrc; - SrcList *pNew = sqlite3SrcListEnlarge(pParse, p1, p2->nSrc, nOld); + SrcList *pNew = sqlite3SrcListEnlarge(pParse, p1, p2->nSrc, 1); if( pNew==0 ){ sqlite3SrcListDelete(pParse->db, p2); }else{ p1 = pNew; - memcpy(&p1->a[nOld], p2->a, p2->nSrc*sizeof(SrcItem)); - assert( nOld==1 || (p2->a[0].fg.jointype & JT_LTORJ)==0 ); - assert( p1->nSrc>=1 ); - p1->a[0].fg.jointype |= (JT_LTORJ & p2->a[0].fg.jointype); + memcpy(&p1->a[1], p2->a, p2->nSrc*sizeof(SrcItem)); sqlite3DbFree(pParse->db, p2); + p1->a[0].fg.jointype |= (JT_LTORJ & p1->a[1].fg.jointype); } } return p1; @@ -130006,19 +128660,14 @@ SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoOfIndex(Parse *pParse, Index *pIdx){ } if( pParse->nErr ){ assert( pParse->rc==SQLITE_ERROR_MISSING_COLLSEQ ); - if( pIdx->bNoQuery==0 - && sqlite3HashFind(&pIdx->pSchema->idxHash, pIdx->zName) - ){ + if( pIdx->bNoQuery==0 ){ /* Deactivate the index because it contains an unknown collating ** sequence. The only way to reactive the index is to reload the ** schema. Adding the missing collating sequence later does not ** reactive the index. The application had the chance to register ** the missing index using the collation-needed callback. For ** simplicity, SQLite will not give the application a second chance. - ** - ** Except, do not do this if the index is not in the schema hash - ** table. In this case the index is currently being constructed - ** by a CREATE INDEX statement, and retrying will not help. */ + */ pIdx->bNoQuery = 1; pParse->rc = SQLITE_ERROR_RETRY; } @@ -132215,7 +130864,7 @@ static void *contextMalloc(sqlite3_context *context, i64 nByte){ sqlite3 *db = sqlite3_context_db_handle(context); assert( nByte>0 ); testcase( nByte==db->aLimit[SQLITE_LIMIT_LENGTH] ); - testcase( nByte==(i64)db->aLimit[SQLITE_LIMIT_LENGTH]+1 ); + testcase( nByte==db->aLimit[SQLITE_LIMIT_LENGTH]+1 ); if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){ sqlite3_result_error_toobig(context); z = 0; @@ -132886,7 +131535,7 @@ SQLITE_PRIVATE void sqlite3QuoteValue(StrAccum *pStr, sqlite3_value *pValue, int */ static int isNHex(const char *z, int N, u32 *pVal){ int i; - u32 v = 0; + int v = 0; for(i=0; i<N; i++){ if( !sqlite3Isxdigit(z[i]) ) return 0; v = (v<<4) + sqlite3HexToInt(z[i]); @@ -133399,7 +132048,6 @@ static void concatFuncCore( ){ i64 j, n = 0; int i; - int bNotNull = 0; /* True after at least NOT NULL argument seen */ char *z; for(i=0; i<argc; i++){ n += sqlite3_value_bytes(argv[i]); @@ -133416,13 +132064,12 @@ static void concatFuncCore( int k = sqlite3_value_bytes(argv[i]); const char *v = (const char*)sqlite3_value_text(argv[i]); if( v!=0 ){ - if( bNotNull && nSep>0 ){ + if( j>0 && nSep>0 ){ memcpy(&z[j], zSep, nSep); j += nSep; } memcpy(&z[j], v, k); j += k; - bNotNull = 1; } } } @@ -134368,502 +133015,6 @@ static void signFunc( sqlite3_result_int(context, x<0.0 ? -1 : x>0.0 ? +1 : 0); } -#if defined(SQLITE_ENABLE_PERCENTILE) -/*********************************************************************** -** This section implements the percentile(Y,P) SQL function and similar. -** Requirements: -** -** (1) The percentile(Y,P) function is an aggregate function taking -** exactly two arguments. -** -** (2) If the P argument to percentile(Y,P) is not the same for every -** row in the aggregate then an error is thrown. The word "same" -** in the previous sentence means that the value differ by less -** than 0.001. -** -** (3) If the P argument to percentile(Y,P) evaluates to anything other -** than a number in the range of 0.0 to 100.0 inclusive then an -** error is thrown. -** -** (4) If any Y argument to percentile(Y,P) evaluates to a value that -** is not NULL and is not numeric then an error is thrown. -** -** (5) If any Y argument to percentile(Y,P) evaluates to plus or minus -** infinity then an error is thrown. (SQLite always interprets NaN -** values as NULL.) -** -** (6) Both Y and P in percentile(Y,P) can be arbitrary expressions, -** including CASE WHEN expressions. -** -** (7) The percentile(Y,P) aggregate is able to handle inputs of at least -** one million (1,000,000) rows. -** -** (8) If there are no non-NULL values for Y, then percentile(Y,P) -** returns NULL. -** -** (9) If there is exactly one non-NULL value for Y, the percentile(Y,P) -** returns the one Y value. -** -** (10) If there N non-NULL values of Y where N is two or more and -** the Y values are ordered from least to greatest and a graph is -** drawn from 0 to N-1 such that the height of the graph at J is -** the J-th Y value and such that straight lines are drawn between -** adjacent Y values, then the percentile(Y,P) function returns -** the height of the graph at P*(N-1)/100. -** -** (11) The percentile(Y,P) function always returns either a floating -** point number or NULL. -** -** (12) The percentile(Y,P) is implemented as a single C99 source-code -** file that compiles into a shared-library or DLL that can be loaded -** into SQLite using the sqlite3_load_extension() interface. -** -** (13) A separate median(Y) function is the equivalent percentile(Y,50). -** -** (14) A separate percentile_cont(Y,P) function is equivalent to -** percentile(Y,P/100.0). In other words, the fraction value in -** the second argument is in the range of 0 to 1 instead of 0 to 100. -** -** (15) A separate percentile_disc(Y,P) function is like -** percentile_cont(Y,P) except that instead of returning the weighted -** average of the nearest two input values, it returns the next lower -** value. So the percentile_disc(Y,P) will always return a value -** that was one of the inputs. -** -** (16) All of median(), percentile(Y,P), percentile_cont(Y,P) and -** percentile_disc(Y,P) can be used as window functions. -** -** Differences from standard SQL: -** -** * The percentile_cont(X,P) function is equivalent to the following in -** standard SQL: -** -** (percentile_cont(P) WITHIN GROUP (ORDER BY X)) -** -** The SQLite syntax is much more compact. The standard SQL syntax -** is also supported if SQLite is compiled with the -** -DSQLITE_ENABLE_ORDERED_SET_AGGREGATES option. -** -** * No median(X) function exists in the SQL standard. App developers -** are expected to write "percentile_cont(0.5)WITHIN GROUP(ORDER BY X)". -** -** * No percentile(Y,P) function exists in the SQL standard. Instead of -** percential(Y,P), developers must write this: -** "percentile_cont(P/100.0) WITHIN GROUP (ORDER BY Y)". Note that -** the fraction parameter to percentile() goes from 0 to 100 whereas -** the fraction parameter in SQL standard percentile_cont() goes from -** 0 to 1. -** -** Implementation notes as of 2024-08-31: -** -** * The regular aggregate-function versions of these routines work -** by accumulating all values in an array of doubles, then sorting -** that array using quicksort before computing the answer. Thus -** the runtime is O(NlogN) where N is the number of rows of input. -** -** * For the window-function versions of these routines, the array of -** inputs is sorted as soon as the first value is computed. Thereafter, -** the array is kept in sorted order using an insert-sort. This -** results in O(N*K) performance where K is the size of the window. -** One can imagine alternative implementations that give O(N*logN*logK) -** performance, but they require more complex logic and data structures. -** The developers have elected to keep the asymptotically slower -** algorithm for now, for simplicity, under the theory that window -** functions are seldom used and when they are, the window size K is -** often small. The developers might revisit that decision later, -** should the need arise. -*/ - -/* The following object is the group context for a single percentile() -** aggregate. Remember all input Y values until the very end. -** Those values are accumulated in the Percentile.a[] array. -*/ -typedef struct Percentile Percentile; -struct Percentile { - u64 nAlloc; /* Number of slots allocated for a[] */ - u64 nUsed; /* Number of slots actually used in a[] */ - char bSorted; /* True if a[] is already in sorted order */ - char bKeepSorted; /* True if advantageous to keep a[] sorted */ - char bPctValid; /* True if rPct is valid */ - double rPct; /* Fraction. 0.0 to 1.0 */ - double *a; /* Array of Y values */ -}; - -/* -** Return TRUE if the input floating-point number is an infinity. -*/ -static int percentIsInfinity(double r){ - sqlite3_uint64 u; - assert( sizeof(u)==sizeof(r) ); - memcpy(&u, &r, sizeof(u)); - return ((u>>52)&0x7ff)==0x7ff; -} - -/* -** Return TRUE if two doubles differ by 0.001 or less. -*/ -static int percentSameValue(double a, double b){ - a -= b; - return a>=-0.001 && a<=0.001; -} - -/* -** Search p (which must have p->bSorted) looking for an entry with -** value y. Return the index of that entry. -** -** If bExact is true, return -1 if the entry is not found. -** -** If bExact is false, return the index at which a new entry with -** value y should be insert in order to keep the values in sorted -** order. The smallest return value in this case will be 0, and -** the largest return value will be p->nUsed. -*/ -static i64 percentBinarySearch(Percentile *p, double y, int bExact){ - i64 iFirst = 0; /* First element of search range */ - i64 iLast = (i64)p->nUsed - 1; /* Last element of search range */ - while( iLast>=iFirst ){ - i64 iMid = (iFirst+iLast)/2; - double x = p->a[iMid]; - if( x<y ){ - iFirst = iMid + 1; - }else if( x>y ){ - iLast = iMid - 1; - }else{ - return iMid; - } - } - if( bExact ) return -1; - return iFirst; -} - -/* -** Generate an error for a percentile function. -** -** The error format string must have exactly one occurrence of "%%s()" -** (with two '%' characters). That substring will be replaced by the name -** of the function. -*/ -static void percentError(sqlite3_context *pCtx, const char *zFormat, ...){ - char *zMsg1; - char *zMsg2; - va_list ap; - - va_start(ap, zFormat); - zMsg1 = sqlite3_vmprintf(zFormat, ap); - va_end(ap); - zMsg2 = zMsg1 ? sqlite3_mprintf(zMsg1, sqlite3VdbeFuncName(pCtx)) : 0; - sqlite3_result_error(pCtx, zMsg2, -1); - sqlite3_free(zMsg1); - sqlite3_free(zMsg2); -} - -/* -** The "step" function for percentile(Y,P) is called once for each -** input row. -*/ -static void percentStep(sqlite3_context *pCtx, int argc, sqlite3_value **argv){ - Percentile *p; - double rPct; - int eType; - double y; - assert( argc==2 || argc==1 ); - - if( argc==1 ){ - /* Requirement 13: median(Y) is the same as percentile(Y,50). */ - rPct = 0.5; - }else{ - /* P must be a number between 0 and 100 for percentile() or between - ** 0.0 and 1.0 for percentile_cont() and percentile_disc(). - ** - ** The user-data is an integer which is 10 times the upper bound. - */ - double mxFrac = (SQLITE_PTR_TO_INT(sqlite3_user_data(pCtx))&2)? 100.0 : 1.0; - eType = sqlite3_value_numeric_type(argv[1]); - rPct = sqlite3_value_double(argv[1])/mxFrac; - if( (eType!=SQLITE_INTEGER && eType!=SQLITE_FLOAT) - || rPct<0.0 || rPct>1.0 - ){ - percentError(pCtx, "the fraction argument to %%s()" - " is not between 0.0 and %.1f", - (double)mxFrac); - return; - } - } - - /* Allocate the session context. */ - p = (Percentile*)sqlite3_aggregate_context(pCtx, sizeof(*p)); - if( p==0 ) return; - - /* Remember the P value. Throw an error if the P value is different - ** from any prior row, per Requirement (2). */ - if( !p->bPctValid ){ - p->rPct = rPct; - p->bPctValid = 1; - }else if( !percentSameValue(p->rPct,rPct) ){ - percentError(pCtx, "the fraction argument to %%s()" - " is not the same for all input rows"); - return; - } - - /* Ignore rows for which Y is NULL */ - eType = sqlite3_value_type(argv[0]); - if( eType==SQLITE_NULL ) return; - - /* If not NULL, then Y must be numeric. Otherwise throw an error. - ** Requirement 4 */ - if( eType!=SQLITE_INTEGER && eType!=SQLITE_FLOAT ){ - percentError(pCtx, "input to %%s() is not numeric"); - return; - } - - /* Throw an error if the Y value is infinity or NaN */ - y = sqlite3_value_double(argv[0]); - if( percentIsInfinity(y) ){ - percentError(pCtx, "Inf input to %%s()"); - return; - } - - /* Allocate and store the Y */ - if( p->nUsed>=p->nAlloc ){ - u64 n = p->nAlloc*2 + 250; - double *a = sqlite3_realloc64(p->a, sizeof(double)*n); - if( a==0 ){ - sqlite3_free(p->a); - memset(p, 0, sizeof(*p)); - sqlite3_result_error_nomem(pCtx); - return; - } - p->nAlloc = n; - p->a = a; - } - if( p->nUsed==0 ){ - p->a[p->nUsed++] = y; - p->bSorted = 1; - }else if( !p->bSorted || y>=p->a[p->nUsed-1] ){ - p->a[p->nUsed++] = y; - }else if( p->bKeepSorted ){ - i64 i; - i = percentBinarySearch(p, y, 0); - if( i<(int)p->nUsed ){ - memmove(&p->a[i+1], &p->a[i], (p->nUsed-i)*sizeof(p->a[0])); - } - p->a[i] = y; - p->nUsed++; - }else{ - p->a[p->nUsed++] = y; - p->bSorted = 0; - } -} - -/* -** Interchange two doubles. -*/ -#define SWAP_DOUBLE(X,Y) {double ttt=(X);(X)=(Y);(Y)=ttt;} - -/* -** Sort an array of doubles. -** -** Algorithm: quicksort -** -** This is implemented separately rather than using the qsort() routine -** from the standard library because: -** -** (1) To avoid a dependency on qsort() -** (2) To avoid the function call to the comparison routine for each -** comparison. -*/ -static void percentSort(double *a, unsigned int n){ - int iLt; /* Entries before a[iLt] are less than rPivot */ - int iGt; /* Entries at or after a[iGt] are greater than rPivot */ - int i; /* Loop counter */ - double rPivot; /* The pivot value */ - - assert( n>=2 ); - if( a[0]>a[n-1] ){ - SWAP_DOUBLE(a[0],a[n-1]) - } - if( n==2 ) return; - iGt = n-1; - i = n/2; - if( a[0]>a[i] ){ - SWAP_DOUBLE(a[0],a[i]) - }else if( a[i]>a[iGt] ){ - SWAP_DOUBLE(a[i],a[iGt]) - } - if( n==3 ) return; - rPivot = a[i]; - iLt = i = 1; - do{ - if( a[i]<rPivot ){ - if( i>iLt ) SWAP_DOUBLE(a[i],a[iLt]) - iLt++; - i++; - }else if( a[i]>rPivot ){ - do{ - iGt--; - }while( iGt>i && a[iGt]>rPivot ); - SWAP_DOUBLE(a[i],a[iGt]) - }else{ - i++; - } - }while( i<iGt ); - if( iLt>=2 ) percentSort(a, iLt); - if( n-iGt>=2 ) percentSort(a+iGt, n-iGt); - -/* Uncomment for testing */ -#if 0 - for(i=0; i<n-1; i++){ - assert( a[i]<=a[i+1] ); - } -#endif -} - - -/* -** The "inverse" function for percentile(Y,P) is called to remove a -** row that was previously inserted by "step". -*/ -static void percentInverse(sqlite3_context *pCtx,int argc,sqlite3_value **argv){ - Percentile *p; - int eType; - double y; - i64 i; - assert( argc==2 || argc==1 ); - - /* Allocate the session context. */ - p = (Percentile*)sqlite3_aggregate_context(pCtx, sizeof(*p)); - assert( p!=0 ); - - /* Ignore rows for which Y is NULL */ - eType = sqlite3_value_type(argv[0]); - if( eType==SQLITE_NULL ) return; - - /* If not NULL, then Y must be numeric. Otherwise throw an error. - ** Requirement 4 */ - if( eType!=SQLITE_INTEGER && eType!=SQLITE_FLOAT ){ - return; - } - - /* Ignore the Y value if it is infinity or NaN */ - y = sqlite3_value_double(argv[0]); - if( percentIsInfinity(y) ){ - return; - } - if( p->bSorted==0 ){ - assert( p->nUsed>1 ); - percentSort(p->a, p->nUsed); - p->bSorted = 1; - } - p->bKeepSorted = 1; - - /* Find and remove the row */ - i = percentBinarySearch(p, y, 1); - if( i>=0 ){ - p->nUsed--; - if( i<(int)p->nUsed ){ - memmove(&p->a[i], &p->a[i+1], (p->nUsed - i)*sizeof(p->a[0])); - } - } -} - -/* -** Compute the final output of percentile(). Clean up all allocated -** memory if and only if bIsFinal is true. -*/ -static void percentCompute(sqlite3_context *pCtx, int bIsFinal){ - Percentile *p; - int settings = SQLITE_PTR_TO_INT(sqlite3_user_data(pCtx))&1; /* Discrete? */ - unsigned i1, i2; - double v1, v2; - double ix, vx; - p = (Percentile*)sqlite3_aggregate_context(pCtx, 0); - if( p==0 ) return; - if( p->a==0 ) return; - if( p->nUsed ){ - if( p->bSorted==0 ){ - assert( p->nUsed>1 ); - percentSort(p->a, p->nUsed); - p->bSorted = 1; - } - ix = p->rPct*(p->nUsed-1); - i1 = (unsigned)ix; - if( settings & 1 ){ - vx = p->a[i1]; - }else{ - i2 = ix==(double)i1 || i1==p->nUsed-1 ? i1 : i1+1; - v1 = p->a[i1]; - v2 = p->a[i2]; - vx = v1 + (v2-v1)*(ix-i1); - } - sqlite3_result_double(pCtx, vx); - } - if( bIsFinal ){ - sqlite3_free(p->a); - memset(p, 0, sizeof(*p)); - }else{ - p->bKeepSorted = 1; - } -} -static void percentFinal(sqlite3_context *pCtx){ - percentCompute(pCtx, 1); -} -static void percentValue(sqlite3_context *pCtx){ - percentCompute(pCtx, 0); -} -/****** End of percentile family of functions ******/ -#endif /* SQLITE_ENABLE_PERCENTILE */ - -#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_FILESTAT) -/* -** Implementation of sqlite_filestat(SCHEMA). -** -** Return JSON text that describes low-level debug/diagnostic information -** about the sqlite3_file object associated with SCHEMA. -*/ -static void filestatFunc( - sqlite3_context *context, - int argc, - sqlite3_value **argv -){ - sqlite3 *db = sqlite3_context_db_handle(context); - const char *zDbName; - sqlite3_str *pStr; - Btree *pBtree; - - zDbName = (const char*)sqlite3_value_text(argv[0]); - pBtree = sqlite3DbNameToBtree(db, zDbName); - if( pBtree ){ - Pager *pPager; - sqlite3_file *fd; - int rc; - sqlite3BtreeEnter(pBtree); - pPager = sqlite3BtreePager(pBtree); - assert( pPager!=0 ); - fd = sqlite3PagerFile(pPager); - pStr = sqlite3_str_new(db); - if( pStr==0 ){ - sqlite3_result_error_nomem(context); - }else{ - sqlite3_str_append(pStr, "{\"db\":", 6); - rc = sqlite3OsFileControl(fd, SQLITE_FCNTL_FILESTAT, pStr); - if( rc ) sqlite3_str_append(pStr, "null", 4); - fd = sqlite3PagerJrnlFile(pPager); - if( fd && fd->pMethods!=0 ){ - sqlite3_str_appendall(pStr, ",\"journal\":"); - rc = sqlite3OsFileControl(fd, SQLITE_FCNTL_FILESTAT, pStr); - if( rc ) sqlite3_str_append(pStr, "null", 4); - } - sqlite3_str_append(pStr, "}", 1); - sqlite3_result_text(context, sqlite3_str_finish(pStr), -1, - sqlite3_free); - } - sqlite3BtreeLeave(pBtree); - }else{ - sqlite3_result_text(context, "{}", 2, SQLITE_STATIC); - } -} -#endif /* SQLITE_DEBUG || SQLITE_ENABLE_FILESTAT */ - #ifdef SQLITE_DEBUG /* ** Implementation of fpdecode(x,y,z) function. @@ -135022,9 +133173,6 @@ SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void){ #ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC INLINE_FUNC(sqlite_offset, 1, INLINEFUNC_sqlite_offset, 0 ), #endif -#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_FILESTAT) - FUNCTION(sqlite_filestat, 1, 0, 0, filestatFunc ), -#endif FUNCTION(ltrim, 1, 1, 0, trimFunc ), FUNCTION(ltrim, 2, 1, 0, trimFunc ), FUNCTION(rtrim, 1, 2, 0, trimFunc ), @@ -135097,21 +133245,6 @@ SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void){ WAGGREGATE(string_agg, 2, 0, 0, groupConcatStep, groupConcatFinalize, groupConcatValue, groupConcatInverse, 0), -#ifdef SQLITE_ENABLE_PERCENTILE - WAGGREGATE(median, 1, 0,0, percentStep, - percentFinal, percentValue, percentInverse, - SQLITE_INNOCUOUS|SQLITE_SELFORDER1), - WAGGREGATE(percentile, 2, 0x2,0, percentStep, - percentFinal, percentValue, percentInverse, - SQLITE_INNOCUOUS|SQLITE_SELFORDER1), - WAGGREGATE(percentile_cont, 2, 0,0, percentStep, - percentFinal, percentValue, percentInverse, - SQLITE_INNOCUOUS|SQLITE_SELFORDER1), - WAGGREGATE(percentile_disc, 2, 0x1,0, percentStep, - percentFinal, percentValue, percentInverse, - SQLITE_INNOCUOUS|SQLITE_SELFORDER1), -#endif /* SQLITE_ENABLE_PERCENTILE */ - LIKEFUNC(glob, 2, &globInfo, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE), #ifdef SQLITE_CASE_SENSITIVE_LIKE LIKEFUNC(like, 2, &likeInfoAlt, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE), @@ -136866,15 +134999,12 @@ SQLITE_PRIVATE void sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){ ** by one slot and insert a new OP_TypeCheck where the current ** OP_MakeRecord is found */ VdbeOp *pPrev; - int p3; sqlite3VdbeAppendP4(v, pTab, P4_TABLE); pPrev = sqlite3VdbeGetLastOp(v); assert( pPrev!=0 ); assert( pPrev->opcode==OP_MakeRecord || sqlite3VdbeDb(v)->mallocFailed ); pPrev->opcode = OP_TypeCheck; - p3 = pPrev->p3; - pPrev->p3 = 0; - sqlite3VdbeAddOp3(v, OP_MakeRecord, pPrev->p1, pPrev->p2, p3); + sqlite3VdbeAddOp3(v, OP_MakeRecord, pPrev->p1, pPrev->p2, pPrev->p3); }else{ /* Insert an isolated OP_Typecheck */ sqlite3VdbeAddOp2(v, OP_TypeCheck, iReg, pTab->nNVCol); @@ -140609,10 +138739,6 @@ struct sqlite3_api_routines { int (*set_clientdata)(sqlite3*, const char*, void*, void(*)(void*)); /* Version 3.50.0 and later */ int (*setlk_timeout)(sqlite3*,int,int); - /* Version 3.51.0 and later */ - int (*set_errmsg)(sqlite3*,int,const char*); - int (*db_status64)(sqlite3*,int,sqlite3_int64*,sqlite3_int64*,int); - }; /* @@ -140948,9 +139074,6 @@ typedef int (*sqlite3_loadext_entry)( #define sqlite3_set_clientdata sqlite3_api->set_clientdata /* Version 3.50.0 and later */ #define sqlite3_setlk_timeout sqlite3_api->setlk_timeout -/* Version 3.51.0 and later */ -#define sqlite3_set_errmsg sqlite3_api->set_errmsg -#define sqlite3_db_status64 sqlite3_api->db_status64 #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) @@ -141474,10 +139597,7 @@ static const sqlite3_api_routines sqlite3Apis = { sqlite3_get_clientdata, sqlite3_set_clientdata, /* Version 3.50.0 and later */ - sqlite3_setlk_timeout, - /* Version 3.51.0 and later */ - sqlite3_set_errmsg, - sqlite3_db_status64 + sqlite3_setlk_timeout }; /* True if x is the directory separator character @@ -142940,22 +141060,6 @@ static int integrityCheckResultRow(Vdbe *v){ } /* -** Should table pTab be skipped when doing an integrity_check? -** Return true or false. -** -** If pObjTab is not null, the return true if pTab matches pObjTab. -** -** If pObjTab is null, then return true only if pTab is an imposter table. -*/ -static int tableSkipIntegrityCheck(const Table *pTab, const Table *pObjTab){ - if( pObjTab ){ - return pTab!=pObjTab; - }else{ - return (pTab->tabFlags & TF_Imposter)!=0; - } -} - -/* ** Process a pragma statement. ** ** Pragmas are of this form: @@ -144300,7 +142404,7 @@ SQLITE_PRIVATE void sqlite3Pragma( Table *pTab = sqliteHashData(x); /* Current table */ Index *pIdx; /* An index on pTab */ int nIdx; /* Number of indexes on pTab */ - if( tableSkipIntegrityCheck(pTab,pObjTab) ) continue; + if( pObjTab && pObjTab!=pTab ) continue; if( HasRowid(pTab) ) cnt++; for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){ cnt++; } } @@ -144313,7 +142417,7 @@ SQLITE_PRIVATE void sqlite3Pragma( for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){ Table *pTab = sqliteHashData(x); Index *pIdx; - if( tableSkipIntegrityCheck(pTab,pObjTab) ) continue; + if( pObjTab && pObjTab!=pTab ) continue; if( HasRowid(pTab) ) aRoot[++cnt] = pTab->tnum; for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ aRoot[++cnt] = pIdx->tnum; @@ -144344,7 +142448,7 @@ SQLITE_PRIVATE void sqlite3Pragma( int iTab = 0; Table *pTab = sqliteHashData(x); Index *pIdx; - if( tableSkipIntegrityCheck(pTab,pObjTab) ) continue; + if( pObjTab && pObjTab!=pTab ) continue; if( HasRowid(pTab) ){ iTab = cnt++; }else{ @@ -144380,7 +142484,7 @@ SQLITE_PRIVATE void sqlite3Pragma( int r2; /* Previous key for WITHOUT ROWID tables */ int mxCol; /* Maximum non-virtual column number */ - if( tableSkipIntegrityCheck(pTab,pObjTab) ) continue; + if( pObjTab && pObjTab!=pTab ) continue; if( !IsOrdinaryTable(pTab) ) continue; if( isQuick || HasRowid(pTab) ){ pPk = 0; @@ -144704,7 +142808,7 @@ SQLITE_PRIVATE void sqlite3Pragma( Table *pTab = sqliteHashData(x); sqlite3_vtab *pVTab; int a1; - if( tableSkipIntegrityCheck(pTab,pObjTab) ) continue; + if( pObjTab && pObjTab!=pTab ) continue; if( IsOrdinaryTable(pTab) ) continue; if( !IsVirtual(pTab) ) continue; if( pTab->nCol<=0 ){ @@ -144936,8 +143040,6 @@ SQLITE_PRIVATE void sqlite3Pragma( eMode = SQLITE_CHECKPOINT_RESTART; }else if( sqlite3StrICmp(zRight, "truncate")==0 ){ eMode = SQLITE_CHECKPOINT_TRUNCATE; - }else if( sqlite3StrICmp(zRight, "noop")==0 ){ - eMode = SQLITE_CHECKPOINT_NOOP; } } pParse->nMem = 3; @@ -146504,11 +144606,9 @@ static int sqlite3LockAndPrepare( rc = sqlite3Prepare(db, zSql, nBytes, prepFlags, pOld, ppStmt, pzTail); assert( rc==SQLITE_OK || *ppStmt==0 ); if( rc==SQLITE_OK || db->mallocFailed ) break; - cnt++; - }while( (rc==SQLITE_ERROR_RETRY && ALWAYS(cnt<=SQLITE_MAX_PREPARE_RETRY)) - || (rc==SQLITE_SCHEMA && (sqlite3ResetOneSchema(db,-1), cnt)==1) ); + }while( (rc==SQLITE_ERROR_RETRY && (cnt++)<SQLITE_MAX_PREPARE_RETRY) + || (rc==SQLITE_SCHEMA && (sqlite3ResetOneSchema(db,-1), cnt++)==0) ); sqlite3BtreeLeaveAll(db); - assert( rc!=SQLITE_ERROR_RETRY ); rc = sqlite3ApiExit(db, rc); assert( (rc&db->errMask)==rc ); db->busyHandler.nBusy = 0; @@ -147123,7 +145223,7 @@ static int tableAndColumnIndex( int iEnd, /* Last member of pSrc->a[] to check */ const char *zCol, /* Name of the column we are looking for */ int *piTab, /* Write index of pSrc->a[] here */ - int *piCol, /* Write index of pSrc->a[*piTab].pSTab->aCol[] here */ + int *piCol, /* Write index of pSrc->a[*piTab].pTab->aCol[] here */ int bIgnoreHidden /* Ignore hidden columns */ ){ int i; /* For looping over tables in pSrc */ @@ -147182,7 +145282,8 @@ SQLITE_PRIVATE void sqlite3SetJoinExpr(Expr *p, int iTable, u32 joinFlag){ assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) ); ExprSetVVAProperty(p, EP_NoReduce); p->w.iJoin = iTable; - if( ExprUseXList(p) ){ + if( p->op==TK_FUNCTION ){ + assert( ExprUseXList(p) ); if( p->x.pList ){ int i; for(i=0; i<p->x.pList->nExpr; i++){ @@ -147398,7 +145499,6 @@ static int sqlite3ProcessJoin(Parse *pParse, Select *p){ p->pWhere = sqlite3ExprAnd(pParse, p->pWhere, pRight->u3.pOn); pRight->u3.pOn = 0; pRight->fg.isOn = 1; - p->selFlags |= SF_OnToWhere; } } return 0; @@ -148285,10 +146385,7 @@ static void selectInnerLoop( */ SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N, int X){ int nExtra = (N+X)*(sizeof(CollSeq*)+1); - KeyInfo *p; - assert( X>=0 ); - if( NEVER(N+X>0xffff) ) return (KeyInfo*)sqlite3OomFault(db); - p = sqlite3DbMallocRawNN(db, SZ_KEYINFO(0) + nExtra); + KeyInfo *p = sqlite3DbMallocRawNN(db, SZ_KEYINFO(0) + nExtra); if( p ){ p->aSortFlags = (u8*)&p->aColl[N+X]; p->nKeyField = (u16)N; @@ -148855,10 +146952,6 @@ static void generateColumnTypes( #endif sqlite3VdbeSetColName(v, i, COLNAME_DECLTYPE, zType, SQLITE_TRANSIENT); } -#else - UNUSED_PARAMETER(pParse); - UNUSED_PARAMETER(pTabList); - UNUSED_PARAMETER(pEList); #endif /* !defined(SQLITE_OMIT_DECLTYPE) */ } @@ -149778,10 +147871,8 @@ static int multiSelect( int priorOp; /* The SRT_ operation to apply to prior selects */ Expr *pLimit; /* Saved values of p->nLimit */ int addr; - int emptyBypass = 0; /* IfEmpty opcode to bypass RHS */ SelectDest uniondest; - testcase( p->op==TK_EXCEPT ); testcase( p->op==TK_UNION ); priorOp = SRT_Union; @@ -149819,8 +147910,6 @@ static int multiSelect( */ if( p->op==TK_EXCEPT ){ op = SRT_Except; - emptyBypass = sqlite3VdbeAddOp1(v, OP_IfEmpty, unionTab); - VdbeCoverage(v); }else{ assert( p->op==TK_UNION ); op = SRT_Union; @@ -149841,7 +147930,6 @@ static int multiSelect( if( p->op==TK_UNION ){ p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow); } - if( emptyBypass ) sqlite3VdbeJumpHere(v, emptyBypass); sqlite3ExprDelete(db, p->pLimit); p->pLimit = pLimit; p->iLimit = 0; @@ -149872,10 +147960,9 @@ static int multiSelect( int tab1, tab2; int iCont, iBreak, iStart; Expr *pLimit; - int addr, iLimit, iOffset; + int addr; SelectDest intersectdest; int r1; - int emptyBypass; /* INTERSECT is different from the others since it requires ** two temporary tables. Hence it has its own case. Begin @@ -149900,28 +147987,14 @@ static int multiSelect( goto multi_select_end; } - /* Initialize LIMIT counters before checking to see if the LHS - ** is empty, in case the jump is taken */ - iBreak = sqlite3VdbeMakeLabel(pParse); - computeLimitRegisters(pParse, p, iBreak); - emptyBypass = sqlite3VdbeAddOp1(v, OP_IfEmpty, tab1); VdbeCoverage(v); - /* Code the current SELECT into temporary table "tab2" */ addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab2, 0); assert( p->addrOpenEphm[1] == -1 ); p->addrOpenEphm[1] = addr; - - /* Disable prior SELECTs and the LIMIT counters during the computation - ** of the RHS select */ - pLimit = p->pLimit; - iLimit = p->iLimit; - iOffset = p->iOffset; p->pPrior = 0; + pLimit = p->pLimit; p->pLimit = 0; - p->iLimit = 0; - p->iOffset = 0; - intersectdest.iSDParm = tab2; ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE", sqlite3SelectOpName(p->op))); @@ -149934,21 +148007,19 @@ static int multiSelect( p->nSelectRow = pPrior->nSelectRow; } sqlite3ExprDelete(db, p->pLimit); - - /* Reinstate the LIMIT counters prior to running the final intersect */ p->pLimit = pLimit; - p->iLimit = iLimit; - p->iOffset = iOffset; /* Generate code to take the intersection of the two temporary ** tables. */ if( rc ) break; assert( p->pEList ); - sqlite3VdbeAddOp1(v, OP_Rewind, tab1); + iBreak = sqlite3VdbeMakeLabel(pParse); + iCont = sqlite3VdbeMakeLabel(pParse); + computeLimitRegisters(pParse, p, iBreak); + sqlite3VdbeAddOp2(v, OP_Rewind, tab1, iBreak); VdbeCoverage(v); r1 = sqlite3GetTempReg(pParse); iStart = sqlite3VdbeAddOp2(v, OP_RowData, tab1, r1); - iCont = sqlite3VdbeMakeLabel(pParse); sqlite3VdbeAddOp4Int(v, OP_NotFound, tab2, iCont, r1, 0); VdbeCoverage(v); sqlite3ReleaseTempReg(pParse, r1); @@ -149958,7 +148029,6 @@ static int multiSelect( sqlite3VdbeAddOp2(v, OP_Next, tab1, iStart); VdbeCoverage(v); sqlite3VdbeResolveLabel(v, iBreak); sqlite3VdbeAddOp2(v, OP_Close, tab2, 0); - sqlite3VdbeJumpHere(v, emptyBypass); sqlite3VdbeAddOp2(v, OP_Close, tab1, 0); break; } @@ -150607,7 +148677,7 @@ static int multiSelectOrderBy( ** ## About "isOuterJoin": ** ** The isOuterJoin column indicates that the replacement will occur into a -** position in the parent that is NULL-able due to an OUTER JOIN. Either the +** position in the parent that NULL-able due to an OUTER JOIN. Either the ** target slot in the parent is the right operand of a LEFT JOIN, or one of ** the left operands of a RIGHT JOIN. In either case, we need to potentially ** bypass the substituted expression with OP_IfNullRow. @@ -150637,7 +148707,6 @@ typedef struct SubstContext { int iTable; /* Replace references to this table */ int iNewTable; /* New table number */ int isOuterJoin; /* Add TK_IF_NULL_ROW opcodes on each replacement */ - int nSelDepth; /* Depth of sub-query recursion. Top==1 */ ExprList *pEList; /* Replacement expressions */ ExprList *pCList; /* Collation sequences for replacement expr */ } SubstContext; @@ -150745,9 +148814,6 @@ static Expr *substExpr( if( pExpr->op==TK_IF_NULL_ROW && pExpr->iTable==pSubst->iTable ){ pExpr->iTable = pSubst->iNewTable; } - if( pExpr->op==TK_AGG_FUNCTION && pExpr->op2>=pSubst->nSelDepth ){ - pExpr->op2--; - } pExpr->pLeft = substExpr(pSubst, pExpr->pLeft); pExpr->pRight = substExpr(pSubst, pExpr->pRight); if( ExprUseXSelect(pExpr) ){ @@ -150785,7 +148851,6 @@ static void substSelect( SrcItem *pItem; int i; if( !p ) return; - pSubst->nSelDepth++; do{ substExprList(pSubst, p->pEList); substExprList(pSubst, p->pGroupBy); @@ -150803,7 +148868,6 @@ static void substSelect( } } }while( doPrior && (p = p->pPrior)!=0 ); - pSubst->nSelDepth--; } #endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */ @@ -151415,7 +149479,7 @@ static int flattenSubquery( ** complete, since there may still exist Expr.pTab entries that ** refer to the subquery even after flattening. Ticket #3346. ** - ** pSubitem->pSTab is always non-NULL by test restrictions and tests above. + ** pSubitem->pTab is always non-NULL by test restrictions and tests above. */ if( ALWAYS(pSubitem->pSTab!=0) ){ Table *pTabToDel = pSubitem->pSTab; @@ -151445,12 +149509,17 @@ static int flattenSubquery( pSub = pSub1; for(pParent=p; pParent; pParent=pParent->pPrior, pSub=pSub->pPrior){ int nSubSrc; - u8 jointype = pSubitem->fg.jointype; + u8 jointype = 0; + u8 ltorj = pSrc->a[iFrom].fg.jointype & JT_LTORJ; assert( pSub!=0 ); pSubSrc = pSub->pSrc; /* FROM clause of subquery */ nSubSrc = pSubSrc->nSrc; /* Number of terms in subquery FROM clause */ pSrc = pParent->pSrc; /* FROM clause of the outer query */ + if( pParent==p ){ + jointype = pSubitem->fg.jointype; /* First time through the loop */ + } + /* The subquery uses a single slot of the FROM clause of the outer ** query. If the subquery has more than one element in its FROM clause, ** then expand the outer query to make space for it to hold all elements @@ -151470,7 +149539,6 @@ static int flattenSubquery( pSrc = sqlite3SrcListEnlarge(pParse, pSrc, nSubSrc-1,iFrom+1); if( pSrc==0 ) break; pParent->pSrc = pSrc; - pSubitem = &pSrc->a[iFrom]; } /* Transfer the FROM clause terms from the subquery into the @@ -151485,10 +149553,11 @@ static int flattenSubquery( || pItem->u4.zDatabase==0 ); if( pItem->fg.isUsing ) sqlite3IdListDelete(db, pItem->u3.pUsing); *pItem = pSubSrc->a[i]; - pItem->fg.jointype |= (jointype & JT_LTORJ); + pItem->fg.jointype |= ltorj; memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i])); } - pSubitem->fg.jointype |= jointype; + pSrc->a[iFrom].fg.jointype &= JT_LTORJ; + pSrc->a[iFrom].fg.jointype |= jointype | ltorj; /* Now begin substituting subquery result set expressions for ** references to the iParent in the outer query. @@ -151540,7 +149609,6 @@ static int flattenSubquery( x.iTable = iParent; x.iNewTable = iNewParent; x.isOuterJoin = isOuterJoin; - x.nSelDepth = 0; x.pEList = pSub->pEList; x.pCList = findLeftmostExprlist(pSub); substSelect(&x, pParent, 0); @@ -152126,7 +150194,6 @@ static int pushDownWhereTerms( x.iTable = pSrc->iCursor; x.iNewTable = pSrc->iCursor; x.isOuterJoin = 0; - x.nSelDepth = 0; x.pEList = pSubq->pEList; x.pCList = findLeftmostExprlist(pSubq); pNew = substExpr(&x, pNew); @@ -152524,7 +150591,7 @@ SQLITE_PRIVATE With *sqlite3WithPush(Parse *pParse, With *pWith, u8 bFree){ ** CTE expression, through routine checks to see if the reference is ** a recursive reference to the CTE. ** -** If pFrom matches a CTE according to either of these two above, pFrom->pSTab +** If pFrom matches a CTE according to either of these two above, pFrom->pTab ** and other fields are populated accordingly. ** ** Return 0 if no match is found. @@ -153562,7 +151629,6 @@ static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){ if( pFunc->bOBPayload ){ /* extra columns for the function arguments */ assert( ExprUseXList(pFunc->pFExpr) ); - assert( pFunc->pFExpr->x.pList!=0 ); nExtra += pFunc->pFExpr->x.pList->nExpr; } if( pFunc->bUseSubtype ){ @@ -154153,193 +152219,6 @@ static int fromClauseTermCanBeCoroutine( } /* -** Argument pWhere is the WHERE clause belonging to SELECT statement p. This -** function attempts to transform expressions of the form: -** -** EXISTS (SELECT ...) -** -** into joins. For example, given -** -** CREATE TABLE sailors(sid INTEGER PRIMARY KEY, name TEXT); -** CREATE TABLE reserves(sid INT, day DATE, PRIMARY KEY(sid, day)); -** -** SELECT name FROM sailors AS S WHERE EXISTS ( -** SELECT * FROM reserves AS R WHERE S.sid = R.sid AND R.day = '2022-10-25' -** ); -** -** the SELECT statement may be transformed as follows: -** -** SELECT name FROM sailors AS S, reserves AS R -** WHERE S.sid = R.sid AND R.day = '2022-10-25'; -** -** **Approximately**. Really, we have to ensure that the FROM-clause term -** that was formerly inside the EXISTS is only executed once. This is handled -** by setting the SrcItem.fg.fromExists flag, which then causes code in -** the where.c file to exit the corresponding loop after the first successful -** match (if any). -*/ -static SQLITE_NOINLINE void existsToJoin( - Parse *pParse, /* Parsing context */ - Select *p, /* The SELECT statement being optimized */ - Expr *pWhere /* part of the WHERE clause currently being examined */ -){ - if( pParse->nErr==0 - && pWhere!=0 - && !ExprHasProperty(pWhere, EP_OuterON|EP_InnerON) - && ALWAYS(p->pSrc!=0) - && p->pSrc->nSrc<BMS - ){ - if( pWhere->op==TK_AND ){ - Expr *pRight = pWhere->pRight; - existsToJoin(pParse, p, pWhere->pLeft); - existsToJoin(pParse, p, pRight); - } - else if( pWhere->op==TK_EXISTS ){ - Select *pSub = pWhere->x.pSelect; - Expr *pSubWhere = pSub->pWhere; - if( pSub->pSrc->nSrc==1 - && (pSub->selFlags & SF_Aggregate)==0 - && !pSub->pSrc->a[0].fg.isSubquery - && pSub->pLimit==0 - ){ - memset(pWhere, 0, sizeof(*pWhere)); - pWhere->op = TK_INTEGER; - pWhere->u.iValue = 1; - ExprSetProperty(pWhere, EP_IntValue); - - assert( p->pWhere!=0 ); - pSub->pSrc->a[0].fg.fromExists = 1; - pSub->pSrc->a[0].fg.jointype |= JT_CROSS; - p->pSrc = sqlite3SrcListAppendList(pParse, p->pSrc, pSub->pSrc); - if( pSubWhere ){ - p->pWhere = sqlite3PExpr(pParse, TK_AND, p->pWhere, pSubWhere); - pSub->pWhere = 0; - } - pSub->pSrc = 0; - sqlite3ParserAddCleanup(pParse, sqlite3SelectDeleteGeneric, pSub); -#if TREETRACE_ENABLED - if( sqlite3TreeTrace & 0x100000 ){ - TREETRACE(0x100000,pParse,p, - ("After EXISTS-to-JOIN optimization:\n")); - sqlite3TreeViewSelect(0, p, 0); - } -#endif - existsToJoin(pParse, p, pSubWhere); - } - } - } -} - -/* -** Type used for Walker callbacks by selectCheckOnClauses(). -*/ -typedef struct CheckOnCtx CheckOnCtx; -struct CheckOnCtx { - SrcList *pSrc; /* SrcList for this context */ - int iJoin; /* Cursor numbers must be =< than this */ - CheckOnCtx *pParent; /* Parent context */ -}; - -/* -** True if the SrcList passed as the only argument contains at least -** one RIGHT or FULL JOIN. False otherwise. -*/ -#define hasRightJoin(pSrc) (((pSrc)->a[0].fg.jointype & JT_LTORJ)!=0) - -/* -** The xExpr callback for the search of invalid ON clause terms. -*/ -static int selectCheckOnClausesExpr(Walker *pWalker, Expr *pExpr){ - CheckOnCtx *pCtx = pWalker->u.pCheckOnCtx; - - /* Check if pExpr is root or near-root of an ON clause constraint that needs - ** to be checked to ensure that it does not refer to tables in its FROM - ** clause to the right of itself. i.e. it is either: - ** - ** + an ON clause on an OUTER join, or - ** + an ON clause on an INNER join within a FROM that features at - ** least one RIGHT or FULL join. - */ - if( (ExprHasProperty(pExpr, EP_OuterON)) - || (ExprHasProperty(pExpr, EP_InnerON) && hasRightJoin(pCtx->pSrc)) - ){ - /* If CheckOnCtx.iJoin is already set, then fall through and process - ** this expression node as normal. Or, if CheckOnCtx.iJoin is still 0, - ** set it to the cursor number of the RHS of the join to which this - ** ON expression was attached and then iterate through the entire - ** expression. */ - assert( pCtx->iJoin==0 || pCtx->iJoin==pExpr->w.iJoin ); - if( pCtx->iJoin==0 ){ - pCtx->iJoin = pExpr->w.iJoin; - sqlite3WalkExprNN(pWalker, pExpr); - pCtx->iJoin = 0; - return WRC_Prune; - } - } - - if( pExpr->op==TK_COLUMN ){ - /* A column expression. Find the SrcList (if any) to which it refers. - ** Then, if CheckOnCtx.iJoin indicates that this expression is part of an - ** ON clause from that SrcList (i.e. if iJoin is non-zero), check that it - ** does not refer to a table to the right of CheckOnCtx.iJoin. */ - do { - SrcList *pSrc = pCtx->pSrc; - int iTab = pExpr->iTable; - if( iTab>=pSrc->a[0].iCursor && iTab<=pSrc->a[pSrc->nSrc-1].iCursor ){ - if( pCtx->iJoin && iTab>pCtx->iJoin ){ - sqlite3ErrorMsg(pWalker->pParse, - "ON clause references tables to its right"); - return WRC_Abort; - } - break; - } - pCtx = pCtx->pParent; - }while( pCtx ); - } - return WRC_Continue; -} - -/* -** The xSelect callback for the search of invalid ON clause terms. -*/ -static int selectCheckOnClausesSelect(Walker *pWalker, Select *pSelect){ - CheckOnCtx *pCtx = pWalker->u.pCheckOnCtx; - if( pSelect->pSrc==pCtx->pSrc || pSelect->pSrc->nSrc==0 ){ - return WRC_Continue; - }else{ - CheckOnCtx sCtx; - memset(&sCtx, 0, sizeof(sCtx)); - sCtx.pSrc = pSelect->pSrc; - sCtx.pParent = pCtx; - pWalker->u.pCheckOnCtx = &sCtx; - sqlite3WalkSelect(pWalker, pSelect); - pWalker->u.pCheckOnCtx = pCtx; - pSelect->selFlags &= ~SF_OnToWhere; - return WRC_Prune; - } -} - -/* -** Check all ON clauses in pSelect to verify that they do not reference -** columns to the right. -*/ -static void selectCheckOnClauses(Parse *pParse, Select *pSelect){ - Walker w; - CheckOnCtx sCtx; - assert( pSelect->selFlags & SF_OnToWhere ); - assert( pSelect->pSrc!=0 && pSelect->pSrc->nSrc>=2 ); - memset(&w, 0, sizeof(w)); - w.pParse = pParse; - w.xExprCallback = selectCheckOnClausesExpr; - w.xSelectCallback = selectCheckOnClausesSelect; - w.u.pCheckOnCtx = &sCtx; - memset(&sCtx, 0, sizeof(sCtx)); - sCtx.pSrc = pSelect->pSrc; - sqlite3WalkExprNN(&w, pSelect->pWhere); - pSelect->selFlags &= ~SF_OnToWhere; -} - -/* ** Generate byte-code for the SELECT statement given in the p argument. ** ** The results are returned according to the SelectDest structure. @@ -154466,18 +152345,6 @@ SQLITE_PRIVATE int sqlite3Select( } #endif - /* If the SELECT statement contains ON clauses that were moved into - ** the WHERE clause, go through and verify that none of the terms - ** in the ON clauses reference tables to the right of the ON clause. - ** Do this now, after name resolution, but before query flattening - */ - if( p->selFlags & SF_OnToWhere ){ - selectCheckOnClauses(pParse, p); - if( pParse->nErr ){ - goto select_end; - } - } - /* If the SF_UFSrcCheck flag is set, then this function is being called ** as part of populating the temp table for an UPDATE...FROM statement. ** In this case, it is an error if the target object (pSrc->a[0]) name @@ -154719,13 +152586,6 @@ SQLITE_PRIVATE int sqlite3Select( } #endif - /* If there may be an "EXISTS (SELECT ...)" in the WHERE clause, attempt - ** to change it into a join. */ - if( pParse->bHasExists && OptimizationEnabled(db,SQLITE_ExistsToJoin) ){ - existsToJoin(pParse, p, p->pWhere); - pTabList = p->pSrc; - } - /* Do the WHERE-clause constant propagation optimization if this is ** a join. No need to spend time on this operation for non-join queries ** as the equivalent optimization will be handled by query planner in @@ -155513,12 +153373,12 @@ SQLITE_PRIVATE int sqlite3Select( ** for the next GROUP BY batch. */ sqlite3VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow); - VdbeComment((v, "output one row of %d", p->selId)); + VdbeComment((v, "output one row")); sqlite3ExprCodeMove(pParse, iBMem, iAMem, pGroupBy->nExpr); sqlite3VdbeAddOp2(v, OP_IfPos, iAbortFlag, addrEnd); VdbeCoverage(v); VdbeComment((v, "check abort flag")); sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset); - VdbeComment((v, "reset accumulator %d", p->selId)); + VdbeComment((v, "reset accumulator")); /* Update the aggregate accumulators based on the content of ** the current row @@ -155526,7 +153386,7 @@ SQLITE_PRIVATE int sqlite3Select( sqlite3VdbeJumpHere(v, addr1); updateAccumulator(pParse, iUseFlag, pAggInfo, eDist); sqlite3VdbeAddOp2(v, OP_Integer, 1, iUseFlag); - VdbeComment((v, "indicate data in accumulator %d", p->selId)); + VdbeComment((v, "indicate data in accumulator")); /* End of the loop */ @@ -155543,7 +153403,7 @@ SQLITE_PRIVATE int sqlite3Select( /* Output the final row of result */ sqlite3VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow); - VdbeComment((v, "output final row of %d", p->selId)); + VdbeComment((v, "output final row")); /* Jump over the subroutines */ @@ -155564,7 +153424,7 @@ SQLITE_PRIVATE int sqlite3Select( addrOutputRow = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp2(v, OP_IfPos, iUseFlag, addrOutputRow+2); VdbeCoverage(v); - VdbeComment((v, "Groupby result generator entry point %d", p->selId)); + VdbeComment((v, "Groupby result generator entry point")); sqlite3VdbeAddOp1(v, OP_Return, regOutputRow); finalizeAggFunctions(pParse, pAggInfo); sqlite3ExprIfFalse(pParse, pHaving, addrOutputRow+1, SQLITE_JUMPIFNULL); @@ -155572,14 +153432,14 @@ SQLITE_PRIVATE int sqlite3Select( &sDistinct, pDest, addrOutputRow+1, addrSetAbort); sqlite3VdbeAddOp1(v, OP_Return, regOutputRow); - VdbeComment((v, "end groupby result generator %d", p->selId)); + VdbeComment((v, "end groupby result generator")); /* Generate a subroutine that will reset the group-by accumulator */ sqlite3VdbeResolveLabel(v, addrReset); resetAccumulator(pParse, pAggInfo); sqlite3VdbeAddOp2(v, OP_Integer, 0, iUseFlag); - VdbeComment((v, "indicate accumulator %d empty", p->selId)); + VdbeComment((v, "indicate accumulator empty")); sqlite3VdbeAddOp1(v, OP_Return, regReset); if( distFlag!=0 && eDist!=WHERE_DISTINCT_NOOP ){ @@ -157043,10 +154903,7 @@ static void codeReturningTrigger( Returning *pReturning; Select sSelect; SrcList *pFrom; - union { - SrcList sSrc; - u8 fromSpace[SZ_SRCLIST_1]; - } uSrc; + u8 fromSpace[SZ_SRCLIST_1]; assert( v!=0 ); if( !pParse->bReturning ){ @@ -157062,8 +154919,8 @@ static void codeReturningTrigger( return; } memset(&sSelect, 0, sizeof(sSelect)); - memset(&uSrc, 0, sizeof(uSrc)); - pFrom = &uSrc.sSrc; + pFrom = (SrcList*)fromSpace; + memset(pFrom, 0, SZ_SRCLIST_1); sSelect.pEList = sqlite3ExprListDup(db, pReturning->pReturnEL, 0); sSelect.pSrc = pFrom; pFrom->nSrc = 1; @@ -159470,8 +157327,7 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3RunVacuum( saved_nChange = db->nChange; saved_nTotalChange = db->nTotalChange; saved_mTrace = db->mTrace; - db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks | SQLITE_Comments - | SQLITE_AttachCreate | SQLITE_AttachWrite; + db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks | SQLITE_Comments; db->mDbFlags |= DBFLAG_PreferBuiltin | DBFLAG_Vacuum; db->flags &= ~(u64)(SQLITE_ForeignKeys | SQLITE_ReverseOrder | SQLITE_Defensive | SQLITE_CountRows); @@ -161174,7 +159030,6 @@ struct WhereLevel { int iTabCur; /* The VDBE cursor used to access the table */ int iIdxCur; /* The VDBE cursor used to access pIdx */ int addrBrk; /* Jump here to break out of the loop */ - int addrHalt; /* Abort the query due to empty table or similar */ int addrNxt; /* Jump here to start the next IN combination */ int addrSkip; /* Jump here for next iteration of skip-scan */ int addrCont; /* Jump here to continue with the next loop cycle */ @@ -161380,9 +159235,6 @@ struct WhereTerm { u8 eMatchOp; /* Op for vtab MATCH/LIKE/GLOB/REGEXP terms */ int iParent; /* Disable pWC->a[iParent] when this term disabled */ int leftCursor; /* Cursor number of X in "X <op> <expr>" */ -#ifdef SQLITE_DEBUG - int iTerm; /* Which WhereTerm is this, for debug purposes */ -#endif union { struct { int leftColumn; /* Column number of X in "X <op> <expr>" */ @@ -161875,6 +159727,7 @@ SQLITE_PRIVATE void sqlite3WhereAddExplainText( #endif { VdbeOp *pOp = sqlite3VdbeGetOp(pParse->pVdbe, addr); + SrcItem *pItem = &pTabList->a[pLevel->iFrom]; sqlite3 *db = pParse->db; /* Database handle */ int isSearch; /* True for a SEARCH. False for SCAN. */ @@ -161897,10 +159750,7 @@ SQLITE_PRIVATE void sqlite3WhereAddExplainText( sqlite3StrAccumInit(&str, db, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH); str.printfFlags = SQLITE_PRINTF_INTERNAL; - sqlite3_str_appendf(&str, "%s %S%s", - isSearch ? "SEARCH" : "SCAN", - pItem, - pItem->fg.fromExists ? " EXISTS" : ""); + sqlite3_str_appendf(&str, "%s %S", isSearch ? "SEARCH" : "SCAN", pItem); if( (flags & (WHERE_IPK|WHERE_VIRTUALTABLE))==0 ){ const char *zFmt = 0; Index *pIdx; @@ -163144,7 +160994,6 @@ static SQLITE_NOINLINE void filterPullDown( int addrNxt, /* Jump here to bypass inner loops */ Bitmask notReady /* Loops that are not ready */ ){ - int saved_addrBrk; while( ++iLevel < pWInfo->nLevel ){ WhereLevel *pLevel = &pWInfo->a[iLevel]; WhereLoop *pLoop = pLevel->pWLoop; @@ -163153,7 +161002,7 @@ static SQLITE_NOINLINE void filterPullDown( /* ,--- Because sqlite3ConstructBloomFilter() has will not have set ** vvvvv--' pLevel->regFilter if this were true. */ if( NEVER(pLoop->prereq & notReady) ) continue; - saved_addrBrk = pLevel->addrBrk; + assert( pLevel->addrBrk==0 ); pLevel->addrBrk = addrNxt; if( pLoop->wsFlags & WHERE_IPK ){ WhereTerm *pTerm = pLoop->aLTerm[0]; @@ -163183,7 +161032,7 @@ static SQLITE_NOINLINE void filterPullDown( VdbeCoverage(pParse->pVdbe); } pLevel->regFilter = 0; - pLevel->addrBrk = saved_addrBrk; + pLevel->addrBrk = 0; } } @@ -163230,6 +161079,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( sqlite3 *db; /* Database connection */ SrcItem *pTabItem; /* FROM clause term being coded */ int addrBrk; /* Jump here to break out of the loop */ + int addrHalt; /* addrBrk for the outermost loop */ int addrCont; /* Jump here to continue with next cycle */ int iRowidReg = 0; /* Rowid is stored in this register, if not zero */ int iReleaseReg = 0; /* Temp register to free before returning */ @@ -163273,7 +161123,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( ** there are no IN operators in the constraints, the "addrNxt" label ** is the same as "addrBrk". */ - addrBrk = pLevel->addrNxt = pLevel->addrBrk; + addrBrk = pLevel->addrBrk = pLevel->addrNxt = sqlite3VdbeMakeLabel(pParse); addrCont = pLevel->addrCont = sqlite3VdbeMakeLabel(pParse); /* If this is the right table of a LEFT OUTER JOIN, allocate and @@ -163289,6 +161139,14 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( VdbeComment((v, "init LEFT JOIN match flag")); } + /* Compute a safe address to jump to if we discover that the table for + ** this loop is empty and can never contribute content. */ + for(j=iLevel; j>0; j--){ + if( pWInfo->a[j].iLeftJoin ) break; + if( pWInfo->a[j].pRJ ) break; + } + addrHalt = pWInfo->a[j].addrBrk; + /* Special case of a FROM clause subquery implemented as a co-routine */ if( pTabItem->fg.viaCoroutine ){ int regYield; @@ -163527,7 +161385,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( VdbeCoverageIf(v, pX->op==TK_GE); sqlite3ReleaseTempReg(pParse, rTemp); }else{ - sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur, pLevel->addrHalt); + sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur, addrHalt); VdbeCoverageIf(v, bRev==0); VdbeCoverageIf(v, bRev!=0); } @@ -163567,36 +161425,36 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC | SQLITE_JUMPIFNULL); } }else if( pLoop->wsFlags & WHERE_INDEXED ){ - /* Case 4: Search using an index. + /* Case 4: A scan using an index. ** - ** The WHERE clause may contain zero or more equality - ** terms ("==" or "IN" or "IS" operators) that refer to the N - ** left-most columns of the index. It may also contain - ** inequality constraints (>, <, >= or <=) on the indexed - ** column that immediately follows the N equalities. Only - ** the right-most column can be an inequality - the rest must - ** use the "==", "IN", or "IS" operators. For example, if the - ** index is on (x,y,z), then the following clauses are all - ** optimized: + ** The WHERE clause may contain zero or more equality + ** terms ("==" or "IN" operators) that refer to the N + ** left-most columns of the index. It may also contain + ** inequality constraints (>, <, >= or <=) on the indexed + ** column that immediately follows the N equalities. Only + ** the right-most column can be an inequality - the rest must + ** use the "==" and "IN" operators. For example, if the + ** index is on (x,y,z), then the following clauses are all + ** optimized: ** - ** x=5 - ** x=5 AND y=10 - ** x=5 AND y<10 - ** x=5 AND y>5 AND y<10 - ** x=5 AND y=5 AND z<=10 + ** x=5 + ** x=5 AND y=10 + ** x=5 AND y<10 + ** x=5 AND y>5 AND y<10 + ** x=5 AND y=5 AND z<=10 ** - ** The z<10 term of the following cannot be used, only - ** the x=5 term: + ** The z<10 term of the following cannot be used, only + ** the x=5 term: ** - ** x=5 AND z<10 + ** x=5 AND z<10 ** - ** N may be zero if there are inequality constraints. - ** If there are no inequality constraints, then N is at - ** least one. + ** N may be zero if there are inequality constraints. + ** If there are no inequality constraints, then N is at + ** least one. ** - ** This case is also used when there are no WHERE clause - ** constraints but an index is selected anyway, in order - ** to force the output order to conform to an ORDER BY. + ** This case is also used when there are no WHERE clause + ** constraints but an index is selected anyway, in order + ** to force the output order to conform to an ORDER BY. */ static const u8 aStartOp[] = { 0, @@ -164322,7 +162180,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( codeCursorHint(pTabItem, pWInfo, pLevel, 0); pLevel->op = aStep[bRev]; pLevel->p1 = iCur; - pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev],iCur,pLevel->addrHalt); + pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrHalt); VdbeCoverageIf(v, bRev==0); VdbeCoverageIf(v, bRev!=0); pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP; @@ -164594,10 +162452,7 @@ SQLITE_PRIVATE SQLITE_NOINLINE void sqlite3WhereRightJoinLoop( WhereLoop *pLoop = pLevel->pWLoop; SrcItem *pTabItem = &pWInfo->pTabList->a[pLevel->iFrom]; SrcList *pFrom; - union { - SrcList sSrc; - u8 fromSpace[SZ_SRCLIST_1]; - } uSrc; + u8 fromSpace[SZ_SRCLIST_1]; Bitmask mAll = 0; int k; @@ -164641,7 +162496,7 @@ SQLITE_PRIVATE SQLITE_NOINLINE void sqlite3WhereRightJoinLoop( sqlite3ExprDup(pParse->db, pTerm->pExpr, 0)); } } - pFrom = &uSrc.sSrc; + pFrom = (SrcList*)fromSpace; pFrom->nSrc = 1; pFrom->nAlloc = 1; memcpy(&pFrom->a[0], pTabItem, sizeof(SrcItem)); @@ -165636,7 +163491,7 @@ static int termIsEquivalence(Parse *pParse, Expr *pExpr, SrcList *pSrc){ if( ExprHasProperty(pExpr, EP_OuterON) ) return 0; /* (3) */ assert( pSrc!=0 ); if( pExpr->op==TK_IS - && pSrc->nSrc>=2 + && pSrc->nSrc && (pSrc->a[0].fg.jointype & JT_LTORJ)!=0 ){ return 0; /* (4) */ @@ -165812,9 +163667,6 @@ static void exprAnalyze( } assert( pWC->nTerm > idxTerm ); pTerm = &pWC->a[idxTerm]; -#ifdef SQLITE_DEBUG - pTerm->iTerm = idxTerm; -#endif pMaskSet = &pWInfo->sMaskSet; pExpr = pTerm->pExpr; assert( pExpr!=0 ); /* Because malloc() has not failed */ @@ -165858,7 +163710,21 @@ static void exprAnalyze( prereqAll |= x; extraRight = x-1; /* ON clause terms may not be used with an index ** on left table of a LEFT JOIN. Ticket #3015 */ + if( (prereqAll>>1)>=x ){ + sqlite3ErrorMsg(pParse, "ON clause references tables to its right"); + return; + } }else if( (prereqAll>>1)>=x ){ + /* The ON clause of an INNER JOIN references a table to its right. + ** Most other SQL database engines raise an error. But SQLite versions + ** 3.0 through 3.38 just put the ON clause constraint into the WHERE + ** clause and carried on. Beginning with 3.39, raise an error only + ** if there is a RIGHT or FULL JOIN in the query. This makes SQLite + ** more like other systems, and also preserves legacy. */ + if( ALWAYS(pSrc->nSrc>0) && (pSrc->a[0].fg.jointype & JT_LTORJ)!=0 ){ + sqlite3ErrorMsg(pParse, "ON clause references tables to its right"); + return; + } ExprClearProperty(pExpr, EP_InnerON); } } @@ -166215,7 +164081,7 @@ static void exprAnalyze( idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC); testcase( idxNew==0 ); pNewTerm = &pWC->a[idxNew]; - pNewTerm->prereqRight = prereqExpr | extraRight; + pNewTerm->prereqRight = prereqExpr; pNewTerm->leftCursor = pLeft->iTable; pNewTerm->u.x.leftColumn = pLeft->iColumn; pNewTerm->eOperator = WO_AUX; @@ -166326,7 +164192,7 @@ static void whereAddLimitExpr( ** ** 1. The SELECT statement has a LIMIT clause, and ** 2. The SELECT statement is not an aggregate or DISTINCT query, and -** 3. The SELECT statement has exactly one object in its FROM clause, and +** 3. The SELECT statement has exactly one object in its from clause, and ** that object is a virtual table, and ** 4. There are no terms in the WHERE clause that will not be passed ** to the virtual table xBestIndex method. @@ -166363,22 +164229,8 @@ SQLITE_PRIVATE void SQLITE_NOINLINE sqlite3WhereAddLimit(WhereClause *pWC, Selec ** (leftCursor==iCsr) test below. */ continue; } - if( pWC->a[ii].leftCursor==iCsr && pWC->a[ii].prereqRight==0 ) continue; - - /* If this term has a parent with exactly one child, and the parent will - ** be passed through to xBestIndex, then this term can be ignored. */ - if( pWC->a[ii].iParent>=0 ){ - WhereTerm *pParent = &pWC->a[ pWC->a[ii].iParent ]; - if( pParent->leftCursor==iCsr - && pParent->prereqRight==0 - && pParent->nChild==1 - ){ - continue; - } - } - - /* This term will not be passed through. Do not add a LIMIT clause. */ - return; + if( pWC->a[ii].leftCursor!=iCsr ) return; + if( pWC->a[ii].prereqRight!=0 ) return; } /* Check condition (5). Return early if it is not met. */ @@ -167042,11 +164894,11 @@ static WhereTerm *whereScanNext(WhereScan *pScan){ pScan->pWC = pWC; pScan->k = k+1; #ifdef WHERETRACE_ENABLED - if( (sqlite3WhereTrace & 0x20000)!=0 && pScan->nEquiv>1 ){ + if( sqlite3WhereTrace & 0x20000 ){ int ii; - sqlite3DebugPrintf("EQUIVALENT TO {%d:%d} (due to TERM-%d):", - pScan->aiCur[0], pScan->aiColumn[0], pTerm->iTerm); - for(ii=1; ii<pScan->nEquiv; ii++){ + sqlite3DebugPrintf("SCAN-TERM %p: nEquiv=%d", + pTerm, pScan->nEquiv); + for(ii=0; ii<pScan->nEquiv; ii++){ sqlite3DebugPrintf(" {%d:%d}", pScan->aiCur[ii], pScan->aiColumn[ii]); } @@ -167817,9 +165669,7 @@ static SQLITE_NOINLINE void constructAutomaticIndex( VdbeCoverage(v); VdbeComment((v, "next row of %s", pSrc->pSTab->zName)); }else{ - assert( pLevel->addrHalt ); - addrTop = sqlite3VdbeAddOp2(v, OP_Rewind,pLevel->iTabCur,pLevel->addrHalt); - VdbeCoverage(v); + addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, pLevel->iTabCur); VdbeCoverage(v); } if( pPartial ){ iContinue = sqlite3VdbeMakeLabel(pParse); @@ -167847,14 +165697,11 @@ static SQLITE_NOINLINE void constructAutomaticIndex( pSrc->u4.pSubq->regResult, pLevel->iIdxCur); sqlite3VdbeGoto(v, addrTop); pSrc->fg.viaCoroutine = 0; - sqlite3VdbeJumpHere(v, addrTop); }else{ sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1); VdbeCoverage(v); sqlite3VdbeChangeP5(v, SQLITE_STMTSTATUS_AUTOINDEX); - if( (pSrc->fg.jointype & JT_LEFT)!=0 ){ - sqlite3VdbeJumpHere(v, addrTop); - } } + sqlite3VdbeJumpHere(v, addrTop); sqlite3ReleaseTempReg(pParse, regRecord); /* Jump here when skipping the initialization */ @@ -169006,7 +166853,6 @@ SQLITE_PRIVATE void sqlite3WhereTermPrint(WhereTerm *pTerm, int iTerm){ }else{ sqlite3_snprintf(sizeof(zLeft),zLeft,"left=%d", pTerm->leftCursor); } - iTerm = pTerm->iTerm = MAX(iTerm,pTerm->iTerm); sqlite3DebugPrintf( "TERM-%-3d %p %s %-12s op=%03x wtFlags=%04x", iTerm, pTerm, zType, zLeft, pTerm->eOperator, pTerm->wtFlags); @@ -170148,7 +167994,6 @@ static int whereLoopAddBtreeIndex( && pProbe->hasStat1!=0 && OptimizationEnabled(db, SQLITE_SkipScan) && pProbe->aiRowLogEst[saved_nEq+1]>=42 /* TUNING: Minimum for skip-scan */ - && pSrc->fg.fromExists==0 && (rc = whereLoopResize(db, pNew, pNew->nLTerm+1))==SQLITE_OK ){ LogEst nIter; @@ -171720,10 +169565,6 @@ static i8 wherePathSatisfiesOrderBy( && ((wctrlFlags&(WHERE_DISTINCTBY|WHERE_SORTBYGROUP))!=WHERE_DISTINCTBY) ){ obSat = obDone; - }else{ - /* No further ORDER BY terms may be matched. So this call should - ** return >=0, not -1. Clear isOrderDistinct to ensure it does so. */ - isOrderDistinct = 0; } break; } @@ -172469,15 +170310,8 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ ** mxChoice best-so-far paths. ** ** First look for an existing path among best-so-far paths - ** that: - ** (1) covers the same set of loops, and - ** (2) has a compatible isOrdered value. - ** - ** "Compatible isOrdered value" means either - ** (A) both have isOrdered==-1, or - ** (B) both have isOrder>=0, or - ** (C) ordering does not matter because this is the last round - ** of the solver. + ** that covers the same set of loops and has the same isOrdered + ** setting as the current path candidate. ** ** The term "((pTo->isOrdered^isOrdered)&0x80)==0" is equivalent ** to (pTo->isOrdered==(-1))==(isOrdered==(-1))" for the range @@ -172486,7 +170320,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ testcase( nTo==0 ); for(jj=0, pTo=aTo; jj<nTo; jj++, pTo++){ if( pTo->maskLoop==maskNew - && ( ((pTo->isOrdered^isOrdered)&0x80)==0 || iLoop==nLoop-1 ) + && ((pTo->isOrdered^isOrdered)&0x80)==0 ){ testcase( jj==nTo-1 ); break; @@ -172641,10 +170475,11 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ return SQLITE_ERROR; } - /* Only one path is available, which is the best path */ - assert( nFrom==1 ); + /* Find the lowest cost path. pFrom will be left pointing to that path */ pFrom = aFrom; - + for(ii=1; ii<nFrom; ii++){ + if( pFrom->rCost>aFrom[ii].rCost ) pFrom = &aFrom[ii]; + } assert( pWInfo->nLevel==nLoop ); /* Load the lowest cost path into pWInfo */ for(iLoop=0; iLoop<nLoop; iLoop++){ @@ -172777,10 +170612,7 @@ static SQLITE_NOINLINE void whereInterstageHeuristic(WhereInfo *pWInfo){ for(i=0; i<pWInfo->nLevel; i++){ WhereLoop *p = pWInfo->a[i].pWLoop; if( p==0 ) break; - if( (p->wsFlags & WHERE_VIRTUALTABLE)!=0 ){ - /* Treat a vtab scan as similar to a full-table scan */ - break; - } + if( (p->wsFlags & WHERE_VIRTUALTABLE)!=0 ) continue; if( (p->wsFlags & (WHERE_COLUMN_EQ|WHERE_COLUMN_NULL|WHERE_COLUMN_IN))!=0 ){ u8 iTab = p->iTab; WhereLoop *pLoop; @@ -173718,14 +171550,6 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( pTab = pTabItem->pSTab; iDb = sqlite3SchemaToIndex(db, pTab->pSchema); pLoop = pLevel->pWLoop; - pLevel->addrBrk = sqlite3VdbeMakeLabel(pParse); - if( ii==0 || (pTabItem[0].fg.jointype & JT_LEFT)!=0 ){ - pLevel->addrHalt = pLevel->addrBrk; - }else if( pWInfo->a[ii-1].pRJ ){ - pLevel->addrHalt = pWInfo->a[ii-1].addrBrk; - }else{ - pLevel->addrHalt = pWInfo->a[ii-1].addrHalt; - } if( (pTab->tabFlags & TF_Ephemeral)!=0 || IsView(pTab) ){ /* Do nothing */ }else @@ -173777,13 +171601,6 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( sqlite3VdbeAddOp4Dup8(v, OP_ColumnsUsed, pTabItem->iCursor, 0, 0, (const u8*)&pTabItem->colUsed, P4_INT64); #endif - if( ii>=2 - && (pTabItem[0].fg.jointype & (JT_LTORJ|JT_LEFT))==0 - && pLevel->addrHalt==pWInfo->a[0].addrHalt - ){ - sqlite3VdbeAddOp2(v, OP_IfEmpty, pTabItem->iCursor, pWInfo->iBreak); - VdbeCoverage(v); - } }else{ sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); } @@ -174040,9 +171857,6 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ sqlite3VdbeAddOp2(v, OP_Goto, 1, pLevel->p2); } #endif /* SQLITE_DISABLE_SKIPAHEAD_DISTINCT */ - if( pTabList->a[pLevel->iFrom].fg.fromExists ){ - sqlite3VdbeAddOp2(v, OP_Goto, 0, sqlite3VdbeCurrentAddr(v)+2); - } /* The common case: Advance to the next row */ if( pLevel->addrCont ) sqlite3VdbeResolveLabel(v, pLevel->addrCont); sqlite3VdbeAddOp3(v, pLevel->op, pLevel->p1, pLevel->p2, pLevel->p3); @@ -176893,7 +174707,7 @@ static int windowExprGtZero(Parse *pParse, Expr *pExpr){ ** ** ROWS BETWEEN <expr1> FOLLOWING AND <expr2> FOLLOWING ** -** ... loop started by sqlite3WhereBegin() ... +** ... loop started by sqlite3WhereBegin() ... ** if( new partition ){ ** Gosub flush ** } @@ -177411,12 +175225,6 @@ SQLITE_PRIVATE void sqlite3WindowCodeStep( addrBreak2 = windowCodeOp(&s, WINDOW_AGGINVERSE, 0, 1); }else{ assert( pMWin->eEnd==TK_FOLLOWING ); - /* assert( regStart>=0 ); - ** regEnd = regEnd - regStart; - ** regStart = 0; */ - sqlite3VdbeAddOp3(v, OP_Subtract, regStart, regEnd, regEnd); - sqlite3VdbeAddOp2(v, OP_Integer, 0, regStart); - addrStart = sqlite3VdbeCurrentAddr(v); addrBreak1 = windowCodeOp(&s, WINDOW_RETURN_ROW, regEnd, 1); addrBreak2 = windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 1); @@ -183812,9 +181620,8 @@ static int analyzeFilterKeyword(const unsigned char *z, int lastToken){ ** Return the length (in bytes) of the token that begins at z[0]. ** Store the token type in *tokenType before returning. */ -SQLITE_PRIVATE i64 sqlite3GetToken(const unsigned char *z, int *tokenType){ - i64 i; - int c; +SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){ + int i, c; switch( aiClass[*z] ){ /* Switch on the character-class of the first byte ** of the token. See the comment on the CC_ defines ** above. */ @@ -184142,7 +181949,7 @@ SQLITE_PRIVATE i64 sqlite3GetToken(const unsigned char *z, int *tokenType){ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql){ int nErr = 0; /* Number of errors encountered */ void *pEngine; /* The LEMON-generated LALR(1) parser */ - i64 n = 0; /* Length of the next token token */ + int n = 0; /* Length of the next token token */ int tokenType; /* type of the next token */ int lastTokenParsed = -1; /* type of the previous token */ sqlite3 *db = pParse->db; /* The database connection */ @@ -184245,13 +182052,13 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql){ }else if( tokenType!=TK_QNUMBER ){ Token x; x.z = zSql; - x.n = (u32)n; + x.n = n; sqlite3ErrorMsg(pParse, "unrecognized token: \"%T\"", &x); break; } } pParse->sLastToken.z = zSql; - pParse->sLastToken.n = (u32)n; + pParse->sLastToken.n = n; sqlite3Parser(pEngine, tokenType, pParse->sLastToken); lastTokenParsed = tokenType; zSql += n; @@ -184327,7 +182134,7 @@ SQLITE_PRIVATE char *sqlite3Normalize( ){ sqlite3 *db; /* The database connection */ int i; /* Next unread byte of zSql[] */ - i64 n; /* length of current token */ + int n; /* length of current token */ int tokenType; /* type of current token */ int prevType = 0; /* Previous non-whitespace token */ int nParen; /* Number of nested levels of parentheses */ @@ -184905,6 +182712,9 @@ static int (*const sqlite3BuiltinExtensions[])(sqlite3*) = { sqlite3DbstatRegister, #endif sqlite3TestExtInit, +#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_JSON) + sqlite3JsonTableFunctions, +#endif #ifdef SQLITE_ENABLE_STMTVTAB sqlite3StmtVtabInit, #endif @@ -186360,9 +184170,6 @@ SQLITE_PRIVATE const char *sqlite3ErrName(int rc){ case SQLITE_OK: zName = "SQLITE_OK"; break; case SQLITE_ERROR: zName = "SQLITE_ERROR"; break; case SQLITE_ERROR_SNAPSHOT: zName = "SQLITE_ERROR_SNAPSHOT"; break; - case SQLITE_ERROR_RETRY: zName = "SQLITE_ERROR_RETRY"; break; - case SQLITE_ERROR_MISSING_COLLSEQ: - zName = "SQLITE_ERROR_MISSING_COLLSEQ"; break; case SQLITE_INTERNAL: zName = "SQLITE_INTERNAL"; break; case SQLITE_PERM: zName = "SQLITE_PERM"; break; case SQLITE_ABORT: zName = "SQLITE_ABORT"; break; @@ -187545,29 +185352,6 @@ SQLITE_API const char *sqlite3_errmsg(sqlite3 *db){ } /* -** Set the error code and error message associated with the database handle. -** -** This routine is intended to be called by outside extensions (ex: the -** Session extension). Internal logic should invoke sqlite3Error() or -** sqlite3ErrorWithMsg() directly. -*/ -SQLITE_API int sqlite3_set_errmsg(sqlite3 *db, int errcode, const char *zMsg){ - int rc = SQLITE_OK; - if( !sqlite3SafetyCheckSickOrOk(db) ){ - return SQLITE_MISUSE_BKPT; - } - sqlite3_mutex_enter(db->mutex); - if( zMsg ){ - sqlite3ErrorWithMsg(db, errcode, "%s", zMsg); - }else{ - sqlite3Error(db, errcode); - } - rc = sqlite3ApiExit(db, rc); - sqlite3_mutex_leave(db->mutex); - return rc; -} - -/* ** Return the byte offset of the most recent error */ SQLITE_API int sqlite3_error_offset(sqlite3 *db){ @@ -189391,15 +187175,13 @@ SQLITE_API int sqlite3_test_control(int op, ...){ break; } - /* sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, dbName, mode, tnum); + /* sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, dbName, onOff, tnum); ** ** This test control is used to create imposter tables. "db" is a pointer ** to the database connection. dbName is the database name (ex: "main" or - ** "temp") which will receive the imposter. "mode" turns imposter mode on - ** or off. mode==0 means imposter mode is off. mode==1 means imposter mode - ** is on. mode==2 means imposter mode is on but results in an imposter - ** table that is read-only unless writable_schema is on. "tnum" is the - ** root page of the b-tree to which the imposter table should connect. + ** "temp") which will receive the imposter. "onOff" turns imposter mode on + ** or off. "tnum" is the root page of the b-tree to which the imposter + ** table should connect. ** ** Enable imposter mode only when the schema has already been parsed. Then ** run a single CREATE TABLE statement to construct the imposter table in @@ -190636,13 +188418,6 @@ SQLITE_PRIVATE void sqlite3ConnectionClosed(sqlite3 *db){ #ifndef _FTSINT_H #define _FTSINT_H -/* -** Activate assert() only if SQLITE_TEST is enabled. -*/ -#if !defined(NDEBUG) && !defined(SQLITE_DEBUG) -# define NDEBUG 1 -#endif - /* #include <assert.h> */ /* #include <stdlib.h> */ /* #include <stddef.h> */ @@ -190650,6 +188425,10 @@ SQLITE_PRIVATE void sqlite3ConnectionClosed(sqlite3 *db){ /* #include <string.h> */ /* #include <stdarg.h> */ +#if !defined(NDEBUG) && !defined(SQLITE_DEBUG) +# define NDEBUG 1 +#endif + /* FTS3/FTS4 require virtual tables */ #ifdef SQLITE_OMIT_VIRTUALTABLE # undef SQLITE_ENABLE_FTS3 @@ -191093,6 +188872,13 @@ typedef sqlite3_int64 i64; /* 8-byte signed integer */ #define UNUSED_PARAMETER(x) (void)(x) /* +** Activate assert() only if SQLITE_TEST is enabled. +*/ +#if !defined(NDEBUG) && !defined(SQLITE_DEBUG) +# define NDEBUG 1 +#endif + +/* ** The TESTONLY macro is used to enclose variable declarations or ** other bits of code that are needed to support the arguments ** within testcase() and assert() macros. @@ -191112,7 +188898,7 @@ typedef sqlite3_int64 i64; /* 8-byte signed integer */ ** Macros needed to provide flexible arrays in a portable way */ #ifndef offsetof -# define offsetof(ST,M) ((size_t)((char*)&((ST*)0)->M - (char*)0)) +# define offsetof(STRUCTURE,FIELD) ((size_t)((char*)&((STRUCTURE*)0)->FIELD)) #endif #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) # define FLEXARRAY @@ -205366,8 +203152,8 @@ struct NodeWriter { ** to an appendable b-tree segment. */ struct IncrmergeWriter { - i64 nLeafEst; /* Space allocated for leaf blocks */ - i64 nWork; /* Number of leaf pages flushed */ + int nLeafEst; /* Space allocated for leaf blocks */ + int nWork; /* Number of leaf pages flushed */ sqlite3_int64 iAbsLevel; /* Absolute level of input segments */ int iIdx; /* Index of *output* segment in iAbsLevel+1 */ sqlite3_int64 iStart; /* Block number of first allocated block */ @@ -206113,7 +203899,7 @@ static int fts3IncrmergeWriter( ){ int rc; /* Return Code */ int i; /* Iterator variable */ - i64 nLeafEst = 0; /* Blocks allocated for leaf nodes */ + int nLeafEst = 0; /* Blocks allocated for leaf nodes */ sqlite3_stmt *pLeafEst = 0; /* SQL used to determine nLeafEst */ sqlite3_stmt *pFirstBlock = 0; /* SQL used to determine first block */ @@ -206123,7 +203909,7 @@ static int fts3IncrmergeWriter( sqlite3_bind_int64(pLeafEst, 1, iAbsLevel); sqlite3_bind_int64(pLeafEst, 2, pCsr->nSegment); if( SQLITE_ROW==sqlite3_step(pLeafEst) ){ - nLeafEst = sqlite3_column_int64(pLeafEst, 0); + nLeafEst = sqlite3_column_int(pLeafEst, 0); } rc = sqlite3_reset(pLeafEst); } @@ -207506,6 +205292,10 @@ SQLITE_PRIVATE int sqlite3Fts3Optimize(Fts3Table *p){ /* #include <string.h> */ /* #include <assert.h> */ +#ifndef SQLITE_AMALGAMATION +typedef sqlite3_int64 i64; +#endif + /* ** Characters that may appear in the second argument to matchinfo(). */ @@ -212359,7 +210149,7 @@ static u32 jsonTranslateBlobToText( jsonAppendChar(pOut, '\''); break; case 'v': - jsonAppendRawNZ(pOut, "\\u000b", 6); + jsonAppendRawNZ(pOut, "\\u0009", 6); break; case 'x': if( sz2<4 ){ @@ -213209,27 +210999,19 @@ static void jsonReturnTextJsonFromBlob( ** ** If the value is a primitive, return it as an SQL value. ** If the value is an array or object, return it as either -** JSON text or the BLOB encoding, depending on the eMode flag -** as follows: -** -** eMode==0 JSONB if the JSON_B flag is set in userdata or -** text if the JSON_B flag is omitted from userdata. -** -** eMode==1 Text -** -** eMode==2 JSONB +** JSON text or the BLOB encoding, depending on the JSON_B flag +** on the userdata. */ static void jsonReturnFromBlob( JsonParse *pParse, /* Complete JSON parse tree */ u32 i, /* Index of the node */ sqlite3_context *pCtx, /* Return value for this function */ - int eMode /* Format of return: text of JSONB */ + int textOnly /* return text JSON. Disregard user-data */ ){ u32 n, sz; int rc; sqlite3 *db = sqlite3_context_db_handle(pCtx); - assert( eMode>=0 && eMode<=2 ); n = jsonbPayloadSize(pParse, i, &sz); if( n==0 ){ sqlite3_result_error(pCtx, "malformed JSON", -1); @@ -213270,19 +211052,7 @@ static void jsonReturnFromBlob( rc = sqlite3DecOrHexToI64(z, &iRes); sqlite3DbFree(db, z); if( rc==0 ){ - if( iRes<0 ){ - /* A hexadecimal literal with 16 significant digits and with the - ** high-order bit set is a negative integer in SQLite (and hence - ** iRes comes back as negative) but should be interpreted as a - ** positive value if it occurs within JSON. The value is too - ** large to appear as an SQLite integer so it must be converted - ** into floating point. */ - double r; - r = (double)*(sqlite3_uint64*)&iRes; - sqlite3_result_double(pCtx, bNeg ? -r : r); - }else{ - sqlite3_result_int64(pCtx, bNeg ? -iRes : iRes); - } + sqlite3_result_int64(pCtx, bNeg ? -iRes : iRes); }else if( rc==3 && bNeg ){ sqlite3_result_int64(pCtx, SMALLEST_INT64); }else if( rc==1 ){ @@ -213360,14 +211130,8 @@ static void jsonReturnFromBlob( } case JSONB_ARRAY: case JSONB_OBJECT: { - if( eMode==0 ){ - if( (SQLITE_PTR_TO_INT(sqlite3_user_data(pCtx)) & JSON_BLOB)!=0 ){ - eMode = 2; - }else{ - eMode = 1; - } - } - if( eMode==2 ){ + int flags = textOnly ? 0 : SQLITE_PTR_TO_INT(sqlite3_user_data(pCtx)); + if( flags & JSON_BLOB ){ sqlite3_result_blob(pCtx, &pParse->aBlob[i], sz+n, SQLITE_TRANSIENT); }else{ jsonReturnTextJsonFromBlob(pCtx, &pParse->aBlob[i], sz+n); @@ -215014,7 +212778,6 @@ struct JsonEachCursor { u32 nRoot; /* Size of the root path in bytes */ u8 eType; /* Type of the container for element i */ u8 bRecursive; /* True for json_tree(). False for json_each() */ - u8 eMode; /* 1 for json_each(). 2 for jsonb_each() */ u32 nParent; /* Current nesting depth */ u32 nParentAlloc; /* Space allocated for aParent[] */ JsonParent *aParent; /* Parent elements of i */ @@ -215026,8 +212789,6 @@ typedef struct JsonEachConnection JsonEachConnection; struct JsonEachConnection { sqlite3_vtab base; /* Base class - must be first */ sqlite3 *db; /* Database connection */ - u8 eMode; /* 1 for json_each(). 2 for jsonb_each() */ - u8 bRecursive; /* True for json_tree(). False for json_each() */ }; @@ -215070,8 +212831,6 @@ static int jsonEachConnect( if( pNew==0 ) return SQLITE_NOMEM; sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS); pNew->db = db; - pNew->eMode = argv[0][4]=='b' ? 2 : 1; - pNew->bRecursive = argv[0][4+pNew->eMode]=='t'; } return rc; } @@ -215083,8 +212842,8 @@ static int jsonEachDisconnect(sqlite3_vtab *pVtab){ return SQLITE_OK; } -/* constructor for a JsonEachCursor object for json_each()/json_tree(). */ -static int jsonEachOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ +/* constructor for a JsonEachCursor object for json_each(). */ +static int jsonEachOpenEach(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ JsonEachConnection *pVtab = (JsonEachConnection*)p; JsonEachCursor *pCur; @@ -215092,13 +212851,21 @@ static int jsonEachOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ pCur = sqlite3DbMallocZero(pVtab->db, sizeof(*pCur)); if( pCur==0 ) return SQLITE_NOMEM; pCur->db = pVtab->db; - pCur->eMode = pVtab->eMode; - pCur->bRecursive = pVtab->bRecursive; jsonStringZero(&pCur->path); *ppCursor = &pCur->base; return SQLITE_OK; } +/* constructor for a JsonEachCursor object for json_tree(). */ +static int jsonEachOpenTree(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ + int rc = jsonEachOpenEach(p, ppCursor); + if( rc==SQLITE_OK ){ + JsonEachCursor *pCur = (JsonEachCursor*)*ppCursor; + pCur->bRecursive = 1; + } + return rc; +} + /* Reset a JsonEachCursor back to its original state. Free any memory ** held. */ static void jsonEachCursorReset(JsonEachCursor *p){ @@ -215303,7 +213070,7 @@ static int jsonEachColumn( } case JEACH_VALUE: { u32 i = jsonSkipLabel(p); - jsonReturnFromBlob(&p->sParse, i, ctx, p->eMode); + jsonReturnFromBlob(&p->sParse, i, ctx, 1); if( (p->sParse.aBlob[i] & 0x0f)>=JSONB_ARRAY ){ sqlite3_result_subtype(ctx, JSON_SUBTYPE); } @@ -215547,7 +213314,36 @@ static sqlite3_module jsonEachModule = { jsonEachBestIndex, /* xBestIndex */ jsonEachDisconnect, /* xDisconnect */ 0, /* xDestroy */ - jsonEachOpen, /* xOpen - open a cursor */ + jsonEachOpenEach, /* xOpen - open a cursor */ + jsonEachClose, /* xClose - close a cursor */ + jsonEachFilter, /* xFilter - configure scan constraints */ + jsonEachNext, /* xNext - advance a cursor */ + jsonEachEof, /* xEof - check for end of scan */ + jsonEachColumn, /* xColumn - read data */ + jsonEachRowid, /* xRowid - read data */ + 0, /* xUpdate */ + 0, /* xBegin */ + 0, /* xSync */ + 0, /* xCommit */ + 0, /* xRollback */ + 0, /* xFindMethod */ + 0, /* xRename */ + 0, /* xSavepoint */ + 0, /* xRelease */ + 0, /* xRollbackTo */ + 0, /* xShadowName */ + 0 /* xIntegrity */ +}; + +/* The methods of the json_tree virtual table. */ +static sqlite3_module jsonTreeModule = { + 0, /* iVersion */ + 0, /* xCreate */ + jsonEachConnect, /* xConnect */ + jsonEachBestIndex, /* xBestIndex */ + jsonEachDisconnect, /* xDisconnect */ + 0, /* xDestroy */ + jsonEachOpenTree, /* xOpen - open a cursor */ jsonEachClose, /* xClose - close a cursor */ jsonEachFilter, /* xFilter - configure scan constraints */ jsonEachNext, /* xNext - advance a cursor */ @@ -215636,21 +213432,22 @@ SQLITE_PRIVATE void sqlite3RegisterJsonFunctions(void){ #if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_JSON) /* -** Register the JSON table-valued function named zName and return a -** pointer to its Module object. Return NULL if something goes wrong. +** Register the JSON table-valued functions */ -SQLITE_PRIVATE Module *sqlite3JsonVtabRegister(sqlite3 *db, const char *zName){ - unsigned int i; - static const char *azModule[] = { - "json_each", "json_tree", "jsonb_each", "jsonb_tree" +SQLITE_PRIVATE int sqlite3JsonTableFunctions(sqlite3 *db){ + int rc = SQLITE_OK; + static const struct { + const char *zName; + sqlite3_module *pModule; + } aMod[] = { + { "json_each", &jsonEachModule }, + { "json_tree", &jsonTreeModule }, }; - assert( sqlite3HashFind(&db->aModule, zName)==0 ); - for(i=0; i<sizeof(azModule)/sizeof(azModule[0]); i++){ - if( sqlite3StrICmp(azModule[i],zName)==0 ){ - return sqlite3VtabCreateModule(db, azModule[i], &jsonEachModule, 0, 0); - } + unsigned int i; + for(i=0; i<sizeof(aMod)/sizeof(aMod[0]) && rc==SQLITE_OK; i++){ + rc = sqlite3_create_module(db, aMod[i].zName, aMod[i].pModule, 0); } - return 0; + return rc; } #endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_JSON) */ @@ -215720,7 +213517,7 @@ SQLITE_PRIVATE Module *sqlite3JsonVtabRegister(sqlite3 *db, const char *zName){ #else /* #include "sqlite3.h" */ #endif -SQLITE_PRIVATE sqlite3_int64 sqlite3GetToken(const unsigned char*,int*); /* In SQLite core */ +SQLITE_PRIVATE int sqlite3GetToken(const unsigned char*,int*); /* In the SQLite core */ /* #include <stddef.h> */ @@ -215755,7 +213552,7 @@ typedef unsigned int u32; # define NEVER(X) (X) #endif #ifndef offsetof -# define offsetof(ST,M) ((size_t)((char*)&((ST*)0)->M - (char*)0)) +#define offsetof(STRUCTURE,FIELD) ((size_t)((char*)&((STRUCTURE*)0)->FIELD)) #endif #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) # define FLEXARRAY @@ -216793,12 +214590,6 @@ static void resetCursor(RtreeCursor *pCsr){ pCsr->base.pVtab = (sqlite3_vtab*)pRtree; pCsr->pReadAux = pStmt; - /* The following will only fail if the previous sqlite3_step() call failed, - ** in which case the error has already been caught. This statement never - ** encounters an error within an sqlite3_column_xxx() function, as it - ** calls sqlite3_column_value(), which does not use malloc(). So it is safe - ** to ignore the error code here. */ - sqlite3_reset(pStmt); } /* @@ -229887,8 +227678,8 @@ typedef struct DbpageCursor DbpageCursor; struct DbpageCursor { sqlite3_vtab_cursor base; /* Base class. Must be first */ - Pgno pgno; /* Current page number */ - Pgno mxPgno; /* Last page to visit on this scan */ + int pgno; /* Current page number */ + int mxPgno; /* Last page to visit on this scan */ Pager *pPager; /* Pager being read/written */ DbPage *pPage1; /* Page 1 of the database */ int iDb; /* Index of database to analyze */ @@ -230025,7 +227816,7 @@ static int dbpageOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ }else{ memset(pCsr, 0, sizeof(DbpageCursor)); pCsr->base.pVtab = pVTab; - pCsr->pgno = 0; + pCsr->pgno = -1; } *ppCursor = (sqlite3_vtab_cursor *)pCsr; @@ -230078,8 +227869,7 @@ static int dbpageFilter( sqlite3 *db = pTab->db; Btree *pBt; - UNUSED_PARAMETER(idxStr); - UNUSED_PARAMETER(argc); + (void)idxStr; /* Default setting is no rows of result */ pCsr->pgno = 1; @@ -230125,12 +227915,12 @@ static int dbpageColumn( int rc = SQLITE_OK; switch( i ){ case 0: { /* pgno */ - sqlite3_result_int64(ctx, (sqlite3_int64)pCsr->pgno); + sqlite3_result_int(ctx, pCsr->pgno); break; } case 1: { /* data */ DbPage *pDbPage = 0; - if( pCsr->pgno==(Pgno)((PENDING_BYTE/pCsr->szPage)+1) ){ + if( pCsr->pgno==((PENDING_BYTE/pCsr->szPage)+1) ){ /* The pending byte page. Assume it is zeroed out. Attempting to ** request this page from the page is an SQLITE_CORRUPT error. */ sqlite3_result_zeroblob(ctx, pCsr->szPage); @@ -230204,10 +227994,10 @@ static int dbpageUpdate( goto update_fail; } if( sqlite3_value_type(argv[0])==SQLITE_NULL ){ - pgno = (Pgno)sqlite3_value_int64(argv[2]); + pgno = (Pgno)sqlite3_value_int(argv[2]); isInsert = 1; }else{ - pgno = (Pgno)sqlite3_value_int64(argv[0]); + pgno = sqlite3_value_int(argv[0]); if( (Pgno)sqlite3_value_int(argv[1])!=pgno ){ zErr = "cannot insert"; goto update_fail; @@ -230259,8 +228049,7 @@ static int dbpageUpdate( memcpy(aPage, pData, szPage); pTab->pgnoTrunc = 0; } - } - if( rc!=SQLITE_OK ){ + }else{ pTab->pgnoTrunc = 0; } sqlite3PagerUnref(pDbPage); @@ -230343,536 +228132,6 @@ SQLITE_PRIVATE int sqlite3DbpageRegister(sqlite3 *db){ return SQLITE_OK; } #endif /* SQLITE_ENABLE_DBSTAT_VTAB */ /************** End of dbpage.c **********************************************/ -/************** Begin file carray.c ******************************************/ -/* -** 2016-06-29 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** This file implements a table-valued-function that -** returns the values in a C-language array. -** Examples: -** -** SELECT * FROM carray($ptr,5) -** -** The query above returns 5 integers contained in a C-language array -** at the address $ptr. $ptr is a pointer to the array of integers. -** The pointer value must be assigned to $ptr using the -** sqlite3_bind_pointer() interface with a pointer type of "carray". -** For example: -** -** static int aX[] = { 53, 9, 17, 2231, 4, 99 }; -** int i = sqlite3_bind_parameter_index(pStmt, "$ptr"); -** sqlite3_bind_pointer(pStmt, i, aX, "carray", 0); -** -** There is an optional third parameter to determine the datatype of -** the C-language array. Allowed values of the third parameter are -** 'int32', 'int64', 'double', 'char*', 'struct iovec'. Example: -** -** SELECT * FROM carray($ptr,10,'char*'); -** -** The default value of the third parameter is 'int32'. -** -** HOW IT WORKS -** -** The carray "function" is really a virtual table with the -** following schema: -** -** CREATE TABLE carray( -** value, -** pointer HIDDEN, -** count HIDDEN, -** ctype TEXT HIDDEN -** ); -** -** If the hidden columns "pointer" and "count" are unconstrained, then -** the virtual table has no rows. Otherwise, the virtual table interprets -** the integer value of "pointer" as a pointer to the array and "count" -** as the number of elements in the array. The virtual table steps through -** the array, element by element. -*/ -#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_CARRAY) -/* #include "sqliteInt.h" */ -#if defined(_WIN32) || defined(__RTP__) || defined(_WRS_KERNEL) - struct iovec { - void *iov_base; - size_t iov_len; - }; -#else -# include <sys/uio.h> -#endif - -/* -** Names of allowed datatypes -*/ -static const char *azCarrayType[] = { - "int32", "int64", "double", "char*", "struct iovec" -}; - -/* -** Structure used to hold the sqlite3_carray_bind() information -*/ -typedef struct carray_bind carray_bind; -struct carray_bind { - void *aData; /* The data */ - int nData; /* Number of elements */ - int mFlags; /* Control flags */ - void (*xDel)(void*); /* Destructor for aData */ -}; - - -/* carray_cursor is a subclass of sqlite3_vtab_cursor which will -** serve as the underlying representation of a cursor that scans -** over rows of the result -*/ -typedef struct carray_cursor carray_cursor; -struct carray_cursor { - sqlite3_vtab_cursor base; /* Base class - must be first */ - sqlite3_int64 iRowid; /* The rowid */ - void *pPtr; /* Pointer to the array of values */ - sqlite3_int64 iCnt; /* Number of integers in the array */ - unsigned char eType; /* One of the CARRAY_type values */ -}; - -/* -** The carrayConnect() method is invoked to create a new -** carray_vtab that describes the carray virtual table. -** -** Think of this routine as the constructor for carray_vtab objects. -** -** All this routine needs to do is: -** -** (1) Allocate the carray_vtab object and initialize all fields. -** -** (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the -** result set of queries against carray will look like. -*/ -static int carrayConnect( - sqlite3 *db, - void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVtab, - char **pzErr -){ - sqlite3_vtab *pNew; - int rc; - -/* Column numbers */ -#define CARRAY_COLUMN_VALUE 0 -#define CARRAY_COLUMN_POINTER 1 -#define CARRAY_COLUMN_COUNT 2 -#define CARRAY_COLUMN_CTYPE 3 - - rc = sqlite3_declare_vtab(db, - "CREATE TABLE x(value,pointer hidden,count hidden,ctype hidden)"); - if( rc==SQLITE_OK ){ - pNew = *ppVtab = sqlite3_malloc( sizeof(*pNew) ); - if( pNew==0 ) return SQLITE_NOMEM; - memset(pNew, 0, sizeof(*pNew)); - } - return rc; -} - -/* -** This method is the destructor for carray_cursor objects. -*/ -static int carrayDisconnect(sqlite3_vtab *pVtab){ - sqlite3_free(pVtab); - return SQLITE_OK; -} - -/* -** Constructor for a new carray_cursor object. -*/ -static int carrayOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ - carray_cursor *pCur; - pCur = sqlite3_malloc( sizeof(*pCur) ); - if( pCur==0 ) return SQLITE_NOMEM; - memset(pCur, 0, sizeof(*pCur)); - *ppCursor = &pCur->base; - return SQLITE_OK; -} - -/* -** Destructor for a carray_cursor. -*/ -static int carrayClose(sqlite3_vtab_cursor *cur){ - sqlite3_free(cur); - return SQLITE_OK; -} - - -/* -** Advance a carray_cursor to its next row of output. -*/ -static int carrayNext(sqlite3_vtab_cursor *cur){ - carray_cursor *pCur = (carray_cursor*)cur; - pCur->iRowid++; - return SQLITE_OK; -} - -/* -** Return values of columns for the row at which the carray_cursor -** is currently pointing. -*/ -static int carrayColumn( - sqlite3_vtab_cursor *cur, /* The cursor */ - sqlite3_context *ctx, /* First argument to sqlite3_result_...() */ - int i /* Which column to return */ -){ - carray_cursor *pCur = (carray_cursor*)cur; - sqlite3_int64 x = 0; - switch( i ){ - case CARRAY_COLUMN_POINTER: return SQLITE_OK; - case CARRAY_COLUMN_COUNT: x = pCur->iCnt; break; - case CARRAY_COLUMN_CTYPE: { - sqlite3_result_text(ctx, azCarrayType[pCur->eType], -1, SQLITE_STATIC); - return SQLITE_OK; - } - default: { - switch( pCur->eType ){ - case CARRAY_INT32: { - int *p = (int*)pCur->pPtr; - sqlite3_result_int(ctx, p[pCur->iRowid-1]); - return SQLITE_OK; - } - case CARRAY_INT64: { - sqlite3_int64 *p = (sqlite3_int64*)pCur->pPtr; - sqlite3_result_int64(ctx, p[pCur->iRowid-1]); - return SQLITE_OK; - } - case CARRAY_DOUBLE: { - double *p = (double*)pCur->pPtr; - sqlite3_result_double(ctx, p[pCur->iRowid-1]); - return SQLITE_OK; - } - case CARRAY_TEXT: { - const char **p = (const char**)pCur->pPtr; - sqlite3_result_text(ctx, p[pCur->iRowid-1], -1, SQLITE_TRANSIENT); - return SQLITE_OK; - } - default: { - const struct iovec *p = (struct iovec*)pCur->pPtr; - assert( pCur->eType==CARRAY_BLOB ); - sqlite3_result_blob(ctx, p[pCur->iRowid-1].iov_base, - (int)p[pCur->iRowid-1].iov_len, SQLITE_TRANSIENT); - return SQLITE_OK; - } - } - } - } - sqlite3_result_int64(ctx, x); - return SQLITE_OK; -} - -/* -** Return the rowid for the current row. In this implementation, the -** rowid is the same as the output value. -*/ -static int carrayRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ - carray_cursor *pCur = (carray_cursor*)cur; - *pRowid = pCur->iRowid; - return SQLITE_OK; -} - -/* -** Return TRUE if the cursor has been moved off of the last -** row of output. -*/ -static int carrayEof(sqlite3_vtab_cursor *cur){ - carray_cursor *pCur = (carray_cursor*)cur; - return pCur->iRowid>pCur->iCnt; -} - -/* -** This method is called to "rewind" the carray_cursor object back -** to the first row of output. -*/ -static int carrayFilter( - sqlite3_vtab_cursor *pVtabCursor, - int idxNum, const char *idxStr, - int argc, sqlite3_value **argv -){ - carray_cursor *pCur = (carray_cursor *)pVtabCursor; - pCur->pPtr = 0; - pCur->iCnt = 0; - switch( idxNum ){ - case 1: { - carray_bind *pBind = sqlite3_value_pointer(argv[0], "carray-bind"); - if( pBind==0 ) break; - pCur->pPtr = pBind->aData; - pCur->iCnt = pBind->nData; - pCur->eType = pBind->mFlags & 0x07; - break; - } - case 2: - case 3: { - pCur->pPtr = sqlite3_value_pointer(argv[0], "carray"); - pCur->iCnt = pCur->pPtr ? sqlite3_value_int64(argv[1]) : 0; - if( idxNum<3 ){ - pCur->eType = CARRAY_INT32; - }else{ - unsigned char i; - const char *zType = (const char*)sqlite3_value_text(argv[2]); - for(i=0; i<sizeof(azCarrayType)/sizeof(azCarrayType[0]); i++){ - if( sqlite3_stricmp(zType, azCarrayType[i])==0 ) break; - } - if( i>=sizeof(azCarrayType)/sizeof(azCarrayType[0]) ){ - pVtabCursor->pVtab->zErrMsg = sqlite3_mprintf( - "unknown datatype: %Q", zType); - return SQLITE_ERROR; - }else{ - pCur->eType = i; - } - } - break; - } - } - pCur->iRowid = 1; - return SQLITE_OK; -} - -/* -** SQLite will invoke this method one or more times while planning a query -** that uses the carray virtual table. This routine needs to create -** a query plan for each invocation and compute an estimated cost for that -** plan. -** -** In this implementation idxNum is used to represent the -** query plan. idxStr is unused. -** -** idxNum is: -** -** 1 If only the pointer= constraint exists. In this case, the -** parameter must be bound using sqlite3_carray_bind(). -** -** 2 if the pointer= and count= constraints exist. -** -** 3 if the ctype= constraint also exists. -** -** idxNum is 0 otherwise and carray becomes an empty table. -*/ -static int carrayBestIndex( - sqlite3_vtab *tab, - sqlite3_index_info *pIdxInfo -){ - int i; /* Loop over constraints */ - int ptrIdx = -1; /* Index of the pointer= constraint, or -1 if none */ - int cntIdx = -1; /* Index of the count= constraint, or -1 if none */ - int ctypeIdx = -1; /* Index of the ctype= constraint, or -1 if none */ - unsigned seen = 0; /* Bitmask of == constrainted columns */ - - const struct sqlite3_index_constraint *pConstraint; - pConstraint = pIdxInfo->aConstraint; - for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){ - if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue; - if( pConstraint->iColumn>=0 ) seen |= 1 << pConstraint->iColumn; - if( pConstraint->usable==0 ) continue; - switch( pConstraint->iColumn ){ - case CARRAY_COLUMN_POINTER: - ptrIdx = i; - break; - case CARRAY_COLUMN_COUNT: - cntIdx = i; - break; - case CARRAY_COLUMN_CTYPE: - ctypeIdx = i; - break; - } - } - if( ptrIdx>=0 ){ - pIdxInfo->aConstraintUsage[ptrIdx].argvIndex = 1; - pIdxInfo->aConstraintUsage[ptrIdx].omit = 1; - pIdxInfo->estimatedCost = (double)1; - pIdxInfo->estimatedRows = 100; - pIdxInfo->idxNum = 1; - if( cntIdx>=0 ){ - pIdxInfo->aConstraintUsage[cntIdx].argvIndex = 2; - pIdxInfo->aConstraintUsage[cntIdx].omit = 1; - pIdxInfo->idxNum = 2; - if( ctypeIdx>=0 ){ - pIdxInfo->aConstraintUsage[ctypeIdx].argvIndex = 3; - pIdxInfo->aConstraintUsage[ctypeIdx].omit = 1; - pIdxInfo->idxNum = 3; - }else if( seen & (1<<CARRAY_COLUMN_CTYPE) ){ - /* In a three-argument carray(), we need to know the value of all - ** three arguments */ - return SQLITE_CONSTRAINT; - } - }else if( seen & (1<<CARRAY_COLUMN_COUNT) ){ - /* In a two-argument carray(), we need to know the value of both - ** arguments */ - return SQLITE_CONSTRAINT; - } - }else{ - pIdxInfo->estimatedCost = (double)2147483647; - pIdxInfo->estimatedRows = 2147483647; - pIdxInfo->idxNum = 0; - } - return SQLITE_OK; -} - -/* -** This following structure defines all the methods for the -** carray virtual table. -*/ -static sqlite3_module carrayModule = { - 0, /* iVersion */ - 0, /* xCreate */ - carrayConnect, /* xConnect */ - carrayBestIndex, /* xBestIndex */ - carrayDisconnect, /* xDisconnect */ - 0, /* xDestroy */ - carrayOpen, /* xOpen - open a cursor */ - carrayClose, /* xClose - close a cursor */ - carrayFilter, /* xFilter - configure scan constraints */ - carrayNext, /* xNext - advance a cursor */ - carrayEof, /* xEof - check for end of scan */ - carrayColumn, /* xColumn - read data */ - carrayRowid, /* xRowid - read data */ - 0, /* xUpdate */ - 0, /* xBegin */ - 0, /* xSync */ - 0, /* xCommit */ - 0, /* xRollback */ - 0, /* xFindMethod */ - 0, /* xRename */ - 0, /* xSavepoint */ - 0, /* xRelease */ - 0, /* xRollbackTo */ - 0, /* xShadow */ - 0 /* xIntegrity */ -}; - -/* -** Destructor for the carray_bind object -*/ -static void carrayBindDel(void *pPtr){ - carray_bind *p = (carray_bind*)pPtr; - if( p->xDel!=SQLITE_STATIC ){ - p->xDel(p->aData); - } - sqlite3_free(p); -} - -/* -** Invoke this interface in order to bind to the single-argument -** version of CARRAY(). -*/ -SQLITE_API int sqlite3_carray_bind( - sqlite3_stmt *pStmt, - int idx, - void *aData, - int nData, - int mFlags, - void (*xDestroy)(void*) -){ - carray_bind *pNew = 0; - int i; - int rc = SQLITE_OK; - - /* Ensure that the mFlags value is acceptable. */ - assert( CARRAY_INT32==0 && CARRAY_INT64==1 && CARRAY_DOUBLE==2 ); - assert( CARRAY_TEXT==3 && CARRAY_BLOB==4 ); - if( mFlags<CARRAY_INT32 || mFlags>CARRAY_BLOB ){ - rc = SQLITE_ERROR; - goto carray_bind_error; - } - - pNew = sqlite3_malloc64(sizeof(*pNew)); - if( pNew==0 ){ - rc = SQLITE_NOMEM; - goto carray_bind_error; - } - - pNew->nData = nData; - pNew->mFlags = mFlags; - if( xDestroy==SQLITE_TRANSIENT ){ - sqlite3_int64 sz = nData; - switch( mFlags ){ - case CARRAY_INT32: sz *= 4; break; - case CARRAY_INT64: sz *= 8; break; - case CARRAY_DOUBLE: sz *= 8; break; - case CARRAY_TEXT: sz *= sizeof(char*); break; - default: sz *= sizeof(struct iovec); break; - } - if( mFlags==CARRAY_TEXT ){ - for(i=0; i<nData; i++){ - const char *z = ((char**)aData)[i]; - if( z ) sz += strlen(z) + 1; - } - }else if( mFlags==CARRAY_BLOB ){ - for(i=0; i<nData; i++){ - sz += ((struct iovec*)aData)[i].iov_len; - } - } - - pNew->aData = sqlite3_malloc64( sz ); - if( pNew->aData==0 ){ - rc = SQLITE_NOMEM; - goto carray_bind_error; - } - - if( mFlags==CARRAY_TEXT ){ - char **az = (char**)pNew->aData; - char *z = (char*)&az[nData]; - for(i=0; i<nData; i++){ - const char *zData = ((char**)aData)[i]; - sqlite3_int64 n; - if( zData==0 ){ - az[i] = 0; - continue; - } - az[i] = z; - n = strlen(zData); - memcpy(z, zData, n+1); - z += n+1; - } - }else if( mFlags==CARRAY_BLOB ){ - struct iovec *p = (struct iovec*)pNew->aData; - unsigned char *z = (unsigned char*)&p[nData]; - for(i=0; i<nData; i++){ - size_t n = ((struct iovec*)aData)[i].iov_len; - p[i].iov_len = n; - p[i].iov_base = z; - z += n; - memcpy(p[i].iov_base, ((struct iovec*)aData)[i].iov_base, n); - } - }else{ - memcpy(pNew->aData, aData, sz); - } - pNew->xDel = sqlite3_free; - }else{ - pNew->aData = aData; - pNew->xDel = xDestroy; - } - return sqlite3_bind_pointer(pStmt, idx, pNew, "carray-bind", carrayBindDel); - - carray_bind_error: - if( xDestroy!=SQLITE_STATIC && xDestroy!=SQLITE_TRANSIENT ){ - xDestroy(aData); - } - sqlite3_free(pNew); - return rc; -} - -/* -** Invoke this routine to register the carray() function. -*/ -SQLITE_PRIVATE Module *sqlite3CarrayRegister(sqlite3 *db){ - return sqlite3VtabCreateModule(db, "carray", &carrayModule, 0, 0); -} - -#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_CARRAY) */ - -/************** End of carray.c **********************************************/ /************** Begin file sqlite3session.c **********************************/ #if defined(SQLITE_ENABLE_SESSION) && defined(SQLITE_ENABLE_PREUPDATE_HOOK) @@ -233691,19 +230950,6 @@ static int sessionAppendDelete( return rc; } -static int sessionPrepare( - sqlite3 *db, - sqlite3_stmt **pp, - char **pzErrmsg, - const char *zSql -){ - int rc = sqlite3_prepare_v2(db, zSql, -1, pp, 0); - if( pzErrmsg && rc!=SQLITE_OK ){ - *pzErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(db)); - } - return rc; -} - /* ** Formulate and prepare a SELECT statement to retrieve a row from table ** zTab in database zDb based on its primary key. i.e. @@ -233725,12 +230971,12 @@ static int sessionSelectStmt( int nCol, /* Number of columns in table */ const char **azCol, /* Names of table columns */ u8 *abPK, /* PRIMARY KEY array */ - sqlite3_stmt **ppStmt, /* OUT: Prepared SELECT statement */ - char **pzErrmsg /* OUT: Error message */ + sqlite3_stmt **ppStmt /* OUT: Prepared SELECT statement */ ){ int rc = SQLITE_OK; char *zSql = 0; const char *zSep = ""; + int nSql = -1; int i; SessionBuffer cols = {0, 0, 0}; @@ -233810,7 +231056,7 @@ static int sessionSelectStmt( #endif if( rc==SQLITE_OK ){ - rc = sessionPrepare(db, ppStmt, pzErrmsg, zSql); + rc = sqlite3_prepare_v2(db, zSql, nSql, ppStmt, 0); } sqlite3_free(zSql); sqlite3_free(nooptest.aBuf); @@ -233974,7 +231220,7 @@ static int sessionGenerateChangeset( /* Build and compile a statement to execute: */ if( rc==SQLITE_OK ){ rc = sessionSelectStmt(db, 0, pSession->zDb, - zName, pTab->bRowid, pTab->nCol, pTab->azCol, pTab->abPK, &pSel, 0 + zName, pTab->bRowid, pTab->nCol, pTab->azCol, pTab->abPK, &pSel ); } @@ -235183,7 +232429,6 @@ struct SessionApplyCtx { u8 bRebase; /* True to collect rebase information */ u8 bIgnoreNoop; /* True to ignore no-op conflicts */ int bRowid; - char *zErr; /* Error message, if any */ }; /* Number of prepared UPDATE statements to cache. */ @@ -235409,7 +232654,7 @@ static int sessionDeleteRow( } if( rc==SQLITE_OK ){ - rc = sessionPrepare(db, &p->pDelete, &p->zErr, (char*)buf.aBuf); + rc = sqlite3_prepare_v2(db, (char *)buf.aBuf, buf.nBuf, &p->pDelete, 0); } sqlite3_free(buf.aBuf); @@ -235436,7 +232681,7 @@ static int sessionSelectRow( ){ /* TODO */ return sessionSelectStmt(db, p->bIgnoreNoop, - "main", zTab, p->bRowid, p->nCol, p->azCol, p->abPK, &p->pSelect, &p->zErr + "main", zTab, p->bRowid, p->nCol, p->azCol, p->abPK, &p->pSelect ); } @@ -235473,12 +232718,16 @@ static int sessionInsertRow( sessionAppendStr(&buf, ")", &rc); if( rc==SQLITE_OK ){ - rc = sessionPrepare(db, &p->pInsert, &p->zErr, (char*)buf.aBuf); + rc = sqlite3_prepare_v2(db, (char *)buf.aBuf, buf.nBuf, &p->pInsert, 0); } sqlite3_free(buf.aBuf); return rc; } +static int sessionPrepare(sqlite3 *db, sqlite3_stmt **pp, const char *zSql){ + return sqlite3_prepare_v2(db, zSql, -1, pp, 0); +} + /* ** Prepare statements for applying changes to the sqlite_stat1 table. ** These are similar to those created by sessionSelectRow(), @@ -235488,14 +232737,14 @@ static int sessionInsertRow( static int sessionStat1Sql(sqlite3 *db, SessionApplyCtx *p){ int rc = sessionSelectRow(db, "sqlite_stat1", p); if( rc==SQLITE_OK ){ - rc = sessionPrepare(db, &p->pInsert, 0, + rc = sessionPrepare(db, &p->pInsert, "INSERT INTO main.sqlite_stat1 VALUES(?1, " "CASE WHEN length(?2)=0 AND typeof(?2)='blob' THEN NULL ELSE ?2 END, " "?3)" ); } if( rc==SQLITE_OK ){ - rc = sessionPrepare(db, &p->pDelete, 0, + rc = sessionPrepare(db, &p->pDelete, "DELETE FROM main.sqlite_stat1 WHERE tbl=?1 AND idx IS " "CASE WHEN length(?2)=0 AND typeof(?2)='blob' THEN NULL ELSE ?2 END " "AND (?4 OR stat IS ?3)" @@ -235719,7 +232968,7 @@ static int sessionConflictHandler( void *pCtx, /* First argument for conflict handler */ int *pbReplace /* OUT: Set to true if PK row is found */ ){ - int res = SQLITE_CHANGESET_OMIT;/* Value returned by conflict handler */ + int res = 0; /* Value returned by conflict handler */ int rc; int nCol; int op; @@ -235740,9 +232989,11 @@ static int sessionConflictHandler( if( rc==SQLITE_ROW ){ /* There exists another row with the new.* primary key. */ - if( 0==p->bIgnoreNoop - || 0==sqlite3_column_int(p->pSelect, sqlite3_column_count(p->pSelect)-1) + if( p->bIgnoreNoop + && sqlite3_column_int(p->pSelect, sqlite3_column_count(p->pSelect)-1) ){ + res = SQLITE_CHANGESET_OMIT; + }else{ pIter->pConflict = p->pSelect; res = xConflict(pCtx, eType, pIter); pIter->pConflict = 0; @@ -235756,9 +233007,7 @@ static int sessionConflictHandler( int nBlob = pIter->in.iNext - pIter->in.iCurrent; sessionAppendBlob(&p->constraints, aBlob, nBlob, &rc); return SQLITE_OK; - }else if( p->bIgnoreNoop==0 || op!=SQLITE_DELETE - || eType==SQLITE_CHANGESET_CONFLICT - ){ + }else{ /* No other row with the new.* primary key. */ res = xConflict(pCtx, eType+1, pIter); if( res==SQLITE_CHANGESET_REPLACE ) rc = SQLITE_MISUSE; @@ -235856,7 +233105,7 @@ static int sessionApplyOneOp( sqlite3_step(p->pDelete); rc = sqlite3_reset(p->pDelete); - if( rc==SQLITE_OK && sqlite3_changes(p->db)==0 ){ + if( rc==SQLITE_OK && sqlite3_changes(p->db)==0 && p->bIgnoreNoop==0 ){ rc = sessionConflictHandler( SQLITE_CHANGESET_DATA, p, pIter, xConflict, pCtx, pbRetry ); @@ -236068,10 +233317,6 @@ static int sessionChangesetApply( void *pCtx, /* Copy of sixth arg to _apply() */ const char *zTab /* Table name */ ), - int(*xFilterIter)( - void *pCtx, /* Copy of sixth arg to _apply() */ - sqlite3_changeset_iter *p - ), int(*xConflict)( void *pCtx, /* Copy of fifth arg to _apply() */ int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ @@ -236212,9 +233457,6 @@ static int sessionChangesetApply( ** next change. A log message has already been issued. */ if( schemaMismatch ) continue; - /* If this is a call to apply_v3(), invoke xFilterIter here. */ - if( xFilterIter && 0==xFilterIter(pCtx, pIter) ) continue; - rc = sessionApplyOneWithRetry(db, pIter, &sApply, xConflict, pCtx); } @@ -236261,7 +233503,6 @@ static int sessionChangesetApply( assert( sApply.bRebase || sApply.rebase.nBuf==0 ); if( rc==SQLITE_OK && bPatchset==0 && sApply.bRebase ){ - assert( ppRebase!=0 && pnRebase!=0 ); *ppRebase = (void*)sApply.rebase.aBuf; *pnRebase = sApply.rebase.nBuf; sApply.rebase.aBuf = 0; @@ -236279,74 +233520,22 @@ static int sessionChangesetApply( db->flags &= ~((u64)SQLITE_FkNoAction); db->aDb[0].pSchema->schema_cookie -= 32; } - - assert( rc!=SQLITE_OK || sApply.zErr==0 ); - sqlite3_set_errmsg(db, rc, sApply.zErr); - sqlite3_free(sApply.zErr); - sqlite3_mutex_leave(sqlite3_db_mutex(db)); return rc; } /* -** This function is called by all six sqlite3changeset_apply() variants: -** -** + sqlite3changeset_apply() -** + sqlite3changeset_apply_v2() -** + sqlite3changeset_apply_v3() -** + sqlite3changeset_apply_strm() -** + sqlite3changeset_apply_strm_v2() -** + sqlite3changeset_apply_strm_v3() -** -** Arguments passed to this function are as follows: -** -** db: -** Database handle to apply changeset to main database of. -** -** nChangeset/pChangeset: -** These are both passed zero for the streaming variants. For the normal -** apply() functions, these are passed the size of and the buffer containing -** the changeset, respectively. -** -** xInput/pIn: -** These are both passed zero for the normal variants. For the streaming -** apply() functions, these are passed the input callback and context -** pointer, respectively. -** -** xFilter: -** The filter function as passed to apply() or apply_v2() (to filter by -** table name), if any. This is always NULL for apply_v3() calls. -** -** xFilterIter: -** The filter function as passed to apply_v3(), if any. -** -** xConflict: -** The conflict handler callback (must not be NULL). -** -** pCtx: -** The context pointer passed to the xFilter and xConflict handler callbacks. -** -** ppRebase, pnRebase: -** Zero for apply(). The rebase changeset output pointers, if any, for -** apply_v2() and apply_v3(). -** -** flags: -** Zero for apply(). The flags parameter for apply_v2() and apply_v3(). +** Apply the changeset passed via pChangeset/nChangeset to the main +** database attached to handle "db". */ -static int sessionChangesetApplyV23( +SQLITE_API int sqlite3changeset_apply_v2( sqlite3 *db, /* Apply change to "main" db of this handle */ int nChangeset, /* Size of changeset in bytes */ void *pChangeset, /* Changeset blob */ - int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */ - void *pIn, /* First arg for xInput */ int(*xFilter)( void *pCtx, /* Copy of sixth arg to _apply() */ const char *zTab /* Table name */ ), - int(*xFilterIter)( - void *pCtx, /* Copy of sixth arg to _apply() */ - sqlite3_changeset_iter *p /* Handle describing current change */ - ), int(*xConflict)( void *pCtx, /* Copy of sixth arg to _apply() */ int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ @@ -236357,72 +233546,16 @@ static int sessionChangesetApplyV23( int flags ){ sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */ - int bInverse = !!(flags & SQLITE_CHANGESETAPPLY_INVERT); - int rc = sessionChangesetStart( - &pIter, xInput, pIn, nChangeset, pChangeset, bInverse, 1 - ); + int bInv = !!(flags & SQLITE_CHANGESETAPPLY_INVERT); + int rc = sessionChangesetStart(&pIter, 0, 0, nChangeset, pChangeset, bInv, 1); + if( rc==SQLITE_OK ){ - rc = sessionChangesetApply(db, pIter, - xFilter, xFilterIter, xConflict, pCtx, ppRebase, pnRebase, flags + rc = sessionChangesetApply( + db, pIter, xFilter, xConflict, pCtx, ppRebase, pnRebase, flags ); } - return rc; -} -/* -** Apply the changeset passed via pChangeset/nChangeset to the main -** database attached to handle "db". -*/ -SQLITE_API int sqlite3changeset_apply_v2( - sqlite3 *db, /* Apply change to "main" db of this handle */ - int nChangeset, /* Size of changeset in bytes */ - void *pChangeset, /* Changeset blob */ - int(*xFilter)( - void *pCtx, /* Copy of sixth arg to _apply() */ - const char *zTab /* Table name */ - ), - int(*xConflict)( - void *pCtx, /* Copy of sixth arg to _apply() */ - int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ - sqlite3_changeset_iter *p /* Handle describing change and conflict */ - ), - void *pCtx, /* First argument passed to xConflict */ - void **ppRebase, int *pnRebase, - int flags -){ - return sessionChangesetApplyV23(db, - nChangeset, pChangeset, 0, 0, - xFilter, 0, xConflict, pCtx, - ppRebase, pnRebase, flags - ); -} - -/* -** Apply the changeset passed via pChangeset/nChangeset to the main -** database attached to handle "db". -*/ -SQLITE_API int sqlite3changeset_apply_v3( - sqlite3 *db, /* Apply change to "main" db of this handle */ - int nChangeset, /* Size of changeset in bytes */ - void *pChangeset, /* Changeset blob */ - int(*xFilter)( - void *pCtx, /* Copy of sixth arg to _apply() */ - sqlite3_changeset_iter *p /* Handle describing current change */ - ), - int(*xConflict)( - void *pCtx, /* Copy of sixth arg to _apply() */ - int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ - sqlite3_changeset_iter *p /* Handle describing change and conflict */ - ), - void *pCtx, /* First argument passed to xConflict */ - void **ppRebase, int *pnRebase, - int flags -){ - return sessionChangesetApplyV23(db, - nChangeset, pChangeset, 0, 0, - 0, xFilter, xConflict, pCtx, - ppRebase, pnRebase, flags - ); + return rc; } /* @@ -236445,10 +233578,8 @@ SQLITE_API int sqlite3changeset_apply( ), void *pCtx /* First argument passed to xConflict */ ){ - return sessionChangesetApplyV23(db, - nChangeset, pChangeset, 0, 0, - xFilter, 0, xConflict, pCtx, - 0, 0, 0 + return sqlite3changeset_apply_v2( + db, nChangeset, pChangeset, xFilter, xConflict, pCtx, 0, 0, 0 ); } @@ -236457,29 +233588,6 @@ SQLITE_API int sqlite3changeset_apply( ** attached to handle "db". Invoke the supplied conflict handler callback ** to resolve any conflicts encountered while applying the change. */ -SQLITE_API int sqlite3changeset_apply_v3_strm( - sqlite3 *db, /* Apply change to "main" db of this handle */ - int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */ - void *pIn, /* First arg for xInput */ - int(*xFilter)( - void *pCtx, /* Copy of sixth arg to _apply() */ - sqlite3_changeset_iter *p - ), - int(*xConflict)( - void *pCtx, /* Copy of sixth arg to _apply() */ - int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ - sqlite3_changeset_iter *p /* Handle describing change and conflict */ - ), - void *pCtx, /* First argument passed to xConflict */ - void **ppRebase, int *pnRebase, - int flags -){ - return sessionChangesetApplyV23(db, - 0, 0, xInput, pIn, - 0, xFilter, xConflict, pCtx, - ppRebase, pnRebase, flags - ); -} SQLITE_API int sqlite3changeset_apply_v2_strm( sqlite3 *db, /* Apply change to "main" db of this handle */ int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */ @@ -236497,11 +233605,15 @@ SQLITE_API int sqlite3changeset_apply_v2_strm( void **ppRebase, int *pnRebase, int flags ){ - return sessionChangesetApplyV23(db, - 0, 0, xInput, pIn, - xFilter, 0, xConflict, pCtx, - ppRebase, pnRebase, flags - ); + sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */ + int bInverse = !!(flags & SQLITE_CHANGESETAPPLY_INVERT); + int rc = sessionChangesetStart(&pIter, xInput, pIn, 0, 0, bInverse, 1); + if( rc==SQLITE_OK ){ + rc = sessionChangesetApply( + db, pIter, xFilter, xConflict, pCtx, ppRebase, pnRebase, flags + ); + } + return rc; } SQLITE_API int sqlite3changeset_apply_strm( sqlite3 *db, /* Apply change to "main" db of this handle */ @@ -236518,10 +233630,8 @@ SQLITE_API int sqlite3changeset_apply_strm( ), void *pCtx /* First argument passed to xConflict */ ){ - return sessionChangesetApplyV23(db, - 0, 0, xInput, pIn, - xFilter, 0, xConflict, pCtx, - 0, 0, 0 + return sqlite3changeset_apply_v2_strm( + db, xInput, pIn, xFilter, xConflict, pCtx, 0, 0, 0 ); } @@ -238493,20 +235603,27 @@ typedef sqlite3_uint64 u64; # define LARGEST_INT64 (0xffffffff|(((i64)0x7fffffff)<<32)) # define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64) -/* -** This macro is used in a single assert() within fts5 to check that an -** allocation is aligned to an 8-byte boundary. But it is a complicated -** macro to get right for multiple platforms without generating warnings. -** So instead of reproducing the entire definition from sqliteInt.h, we -** just do without this assert() for the rare non-amalgamation builds. +/* The uptr type is an unsigned integer large enough to hold a pointer */ -#define EIGHT_BYTE_ALIGNMENT(x) 1 +#if defined(HAVE_STDINT_H) + typedef uintptr_t uptr; +#elif SQLITE_PTRSIZE==4 + typedef u32 uptr; +#else + typedef u64 uptr; +#endif + +#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC +# define EIGHT_BYTE_ALIGNMENT(X) ((((uptr)(X) - (uptr)0)&3)==0) +#else +# define EIGHT_BYTE_ALIGNMENT(X) ((((uptr)(X) - (uptr)0)&7)==0) +#endif /* ** Macros needed to provide flexible arrays in a portable way */ #ifndef offsetof -# define offsetof(ST,M) ((size_t)((char*)&((ST*)0)->M - (char*)0)) +# define offsetof(STRUCTURE,FIELD) ((size_t)((char*)&((STRUCTURE*)0)->FIELD)) #endif #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) # define FLEXARRAY @@ -239248,7 +236365,7 @@ static int sqlite3Fts5ExprPattern( ** i64 iRowid = sqlite3Fts5ExprRowid(pExpr); ** } */ -static int sqlite3Fts5ExprFirst(Fts5Expr*, Fts5Index *pIdx, i64 iMin, i64, int bDesc); +static int sqlite3Fts5ExprFirst(Fts5Expr*, Fts5Index *pIdx, i64 iMin, int bDesc); static int sqlite3Fts5ExprNext(Fts5Expr*, i64 iMax); static int sqlite3Fts5ExprEof(Fts5Expr*); static i64 sqlite3Fts5ExprRowid(Fts5Expr*); @@ -244817,13 +241934,7 @@ static int fts5ExprNodeFirst(Fts5Expr *pExpr, Fts5ExprNode *pNode){ ** Return SQLITE_OK if successful, or an SQLite error code otherwise. It ** is not considered an error if the query does not match any documents. */ -static int sqlite3Fts5ExprFirst( - Fts5Expr *p, - Fts5Index *pIdx, - i64 iFirst, - i64 iLast, - int bDesc -){ +static int sqlite3Fts5ExprFirst(Fts5Expr *p, Fts5Index *pIdx, i64 iFirst, int bDesc){ Fts5ExprNode *pRoot = p->pRoot; int rc; /* Return code */ @@ -244845,9 +241956,6 @@ static int sqlite3Fts5ExprFirst( assert( pRoot->bEof==0 ); rc = fts5ExprNodeNext(p, pRoot, 0, 0); } - if( fts5RowidCmp(p, pRoot->iRowid, iLast)>0 ){ - pRoot->bEof = 1; - } return rc; } @@ -247700,36 +244808,6 @@ struct Fts5SegIter { u8 bDel; /* True if the delete flag is set */ }; -static int fts5IndexCorruptRowid(Fts5Index *pIdx, i64 iRowid){ - pIdx->rc = FTS5_CORRUPT; - sqlite3Fts5ConfigErrmsg(pIdx->pConfig, - "fts5: corruption found reading blob %lld from table \"%s\"", - iRowid, pIdx->pConfig->zName - ); - return SQLITE_CORRUPT_VTAB; -} -#define FTS5_CORRUPT_ROWID(pIdx, iRowid) fts5IndexCorruptRowid(pIdx, iRowid) - -static int fts5IndexCorruptIter(Fts5Index *pIdx, Fts5SegIter *pIter){ - pIdx->rc = FTS5_CORRUPT; - sqlite3Fts5ConfigErrmsg(pIdx->pConfig, - "fts5: corruption on page %d, segment %d, table \"%s\"", - pIter->iLeafPgno, pIter->pSeg->iSegid, pIdx->pConfig->zName - ); - return SQLITE_CORRUPT_VTAB; -} -#define FTS5_CORRUPT_ITER(pIdx, pIter) fts5IndexCorruptIter(pIdx, pIter) - -static int fts5IndexCorruptIdx(Fts5Index *pIdx){ - pIdx->rc = FTS5_CORRUPT; - sqlite3Fts5ConfigErrmsg(pIdx->pConfig, - "fts5: corruption in table \"%s\"", pIdx->pConfig->zName - ); - return SQLITE_CORRUPT_VTAB; -} -#define FTS5_CORRUPT_IDX(pIdx) fts5IndexCorruptIdx(pIdx) - - /* ** Array of tombstone pages. Reference counted. */ @@ -248019,13 +245097,13 @@ static Fts5Data *fts5DataRead(Fts5Index *p, i64 iRowid){ ** All the reasons those functions might return SQLITE_ERROR - missing ** table, missing row, non-blob/text in block column - indicate ** backing store corruption. */ - if( rc==SQLITE_ERROR ) rc = FTS5_CORRUPT_ROWID(p, iRowid); + if( rc==SQLITE_ERROR ) rc = FTS5_CORRUPT; if( rc==SQLITE_OK ){ u8 *aOut = 0; /* Read blob data into this buffer */ - i64 nByte = sqlite3_blob_bytes(p->pReader); - i64 szData = (sizeof(Fts5Data) + 7) & ~7; - i64 nAlloc = szData + nByte + FTS5_DATA_PADDING; + int nByte = sqlite3_blob_bytes(p->pReader); + int szData = (sizeof(Fts5Data) + 7) & ~7; + sqlite3_int64 nAlloc = szData + nByte + FTS5_DATA_PADDING; pRet = (Fts5Data*)sqlite3_malloc64(nAlloc); if( pRet ){ pRet->nn = nByte; @@ -248069,7 +245147,7 @@ static Fts5Data *fts5LeafRead(Fts5Index *p, i64 iRowid){ Fts5Data *pRet = fts5DataRead(p, iRowid); if( pRet ){ if( pRet->nn<4 || pRet->szLeaf>pRet->nn ){ - FTS5_CORRUPT_ROWID(p, iRowid); + p->rc = FTS5_CORRUPT; fts5DataRelease(pRet); pRet = 0; } @@ -248428,14 +245506,8 @@ static Fts5Structure *fts5StructureReadUncached(Fts5Index *p){ /* TODO: Do we need this if the leaf-index is appended? Probably... */ memset(&pData->p[pData->nn], 0, FTS5_DATA_PADDING); p->rc = fts5StructureDecode(pData->p, pData->nn, &iCookie, &pRet); - if( p->rc==SQLITE_OK ){ - if( (pConfig->pgsz==0 || pConfig->iCookie!=iCookie) ){ - p->rc = sqlite3Fts5ConfigLoad(pConfig, iCookie); - } - }else if( p->rc==SQLITE_CORRUPT_VTAB ){ - sqlite3Fts5ConfigErrmsg(p->pConfig, - "fts5: corrupt structure record for table \"%s\"", p->pConfig->zName - ); + if( p->rc==SQLITE_OK && (pConfig->pgsz==0 || pConfig->iCookie!=iCookie) ){ + p->rc = sqlite3Fts5ConfigLoad(pConfig, iCookie); } fts5DataRelease(pData); if( p->rc!=SQLITE_OK ){ @@ -249058,7 +246130,7 @@ static void fts5SegIterLoadRowid(Fts5Index *p, Fts5SegIter *pIter){ while( iOff>=pIter->pLeaf->szLeaf ){ fts5SegIterNextPage(p, pIter); if( pIter->pLeaf==0 ){ - if( p->rc==SQLITE_OK ) FTS5_CORRUPT_ITER(p, pIter); + if( p->rc==SQLITE_OK ) p->rc = FTS5_CORRUPT; return; } iOff = 4; @@ -249090,7 +246162,7 @@ static void fts5SegIterLoadTerm(Fts5Index *p, Fts5SegIter *pIter, int nKeep){ iOff += fts5GetVarint32(&a[iOff], nNew); if( iOff+nNew>pIter->pLeaf->szLeaf || nKeep>pIter->term.n || nNew==0 ){ - FTS5_CORRUPT_ITER(p, pIter); + p->rc = FTS5_CORRUPT; return; } pIter->term.n = nKeep; @@ -249285,7 +246357,7 @@ static void fts5SegIterReverseNewPage(Fts5Index *p, Fts5SegIter *pIter){ iRowidOff = fts5LeafFirstRowidOff(pNew); if( iRowidOff ){ if( iRowidOff>=pNew->szLeaf ){ - FTS5_CORRUPT_ITER(p, pIter); + p->rc = FTS5_CORRUPT; }else{ pIter->pLeaf = pNew; pIter->iLeafOffset = iRowidOff; @@ -249519,7 +246591,7 @@ static void fts5SegIterNext( } assert_nc( iOff<pLeaf->szLeaf ); if( iOff>pLeaf->szLeaf ){ - FTS5_CORRUPT_ITER(p, pIter); + p->rc = FTS5_CORRUPT; return; } } @@ -249627,20 +246699,18 @@ static void fts5SegIterReverse(Fts5Index *p, Fts5SegIter *pIter){ fts5DataRelease(pIter->pLeaf); pIter->pLeaf = pLast; pIter->iLeafPgno = pgnoLast; - if( p->rc==SQLITE_OK ){ - iOff = fts5LeafFirstRowidOff(pLast); - if( iOff>pLast->szLeaf ){ - FTS5_CORRUPT_ITER(p, pIter); - return; - } - iOff += fts5GetVarint(&pLast->p[iOff], (u64*)&pIter->iRowid); - pIter->iLeafOffset = iOff; + iOff = fts5LeafFirstRowidOff(pLast); + if( iOff>pLast->szLeaf ){ + p->rc = FTS5_CORRUPT; + return; + } + iOff += fts5GetVarint(&pLast->p[iOff], (u64*)&pIter->iRowid); + pIter->iLeafOffset = iOff; - if( fts5LeafIsTermless(pLast) ){ - pIter->iEndofDoclist = pLast->nn+1; - }else{ - pIter->iEndofDoclist = fts5LeafFirstTermOff(pLast); - } + if( fts5LeafIsTermless(pLast) ){ + pIter->iEndofDoclist = pLast->nn+1; + }else{ + pIter->iEndofDoclist = fts5LeafFirstTermOff(pLast); } } @@ -249710,7 +246780,7 @@ static void fts5LeafSeek( iPgidx += fts5GetVarint32(&a[iPgidx], iTermOff); iOff = iTermOff; if( iOff>n ){ - FTS5_CORRUPT_ITER(p, pIter); + p->rc = FTS5_CORRUPT; return; } @@ -249753,7 +246823,7 @@ static void fts5LeafSeek( iOff = iTermOff; if( iOff>=n ){ - FTS5_CORRUPT_ITER(p, pIter); + p->rc = FTS5_CORRUPT; return; } @@ -249775,7 +246845,7 @@ static void fts5LeafSeek( iPgidx = (u32)pIter->pLeaf->szLeaf; iPgidx += fts5GetVarint32(&pIter->pLeaf->p[iPgidx], iOff); if( iOff<4 || (i64)iOff>=pIter->pLeaf->szLeaf ){ - FTS5_CORRUPT_ITER(p, pIter); + p->rc = FTS5_CORRUPT; return; }else{ nKeep = 0; @@ -249790,7 +246860,7 @@ static void fts5LeafSeek( search_success: if( (i64)iOff+nNew>n || nNew<1 ){ - FTS5_CORRUPT_ITER(p, pIter); + p->rc = FTS5_CORRUPT; return; } pIter->iLeafOffset = iOff + nNew; @@ -250255,7 +247325,7 @@ static void fts5SegIterGotoPage( assert( iLeafPgno>pIter->iLeafPgno ); if( iLeafPgno>pIter->pSeg->pgnoLast ){ - FTS5_CORRUPT_IDX(p); + p->rc = FTS5_CORRUPT; }else{ fts5DataRelease(pIter->pNextLeaf); pIter->pNextLeaf = 0; @@ -250270,7 +247340,7 @@ static void fts5SegIterGotoPage( u8 *a = pIter->pLeaf->p; int n = pIter->pLeaf->szLeaf; if( iOff<4 || iOff>=n ){ - FTS5_CORRUPT_IDX(p); + p->rc = FTS5_CORRUPT; }else{ iOff += fts5GetVarint(&a[iOff], (u64*)&pIter->iRowid); pIter->iLeafOffset = iOff; @@ -250749,7 +247819,7 @@ static void fts5ChunkIterate( if( nRem<=0 ){ break; }else if( pSeg->pSeg==0 ){ - FTS5_CORRUPT_IDX(p); + p->rc = FTS5_CORRUPT; return; }else{ pgno++; @@ -251852,7 +248922,7 @@ static void fts5TrimSegments(Fts5Index *p, Fts5Iter *pIter){ ** a single page has been assigned to more than one segment. In ** this case a prior iteration of this loop may have corrupted the ** segment currently being trimmed. */ - FTS5_CORRUPT_ROWID(p, iLeafRowid); + p->rc = FTS5_CORRUPT; }else{ fts5BufferZero(&buf); fts5BufferGrow(&p->rc, &buf, pData->nn); @@ -252319,7 +249389,7 @@ static void fts5SecureDeleteOverflow( }else if( bDetailNone ){ break; }else if( iNext>=pLeaf->szLeaf || pLeaf->nn<pLeaf->szLeaf || iNext<4 ){ - FTS5_CORRUPT_ROWID(p, iRowid); + p->rc = FTS5_CORRUPT; break; }else{ int nShift = iNext - 4; @@ -252339,7 +249409,7 @@ static void fts5SecureDeleteOverflow( i1 += fts5GetVarint32(&aPg[i1], iFirst); if( iFirst<iNext ){ - FTS5_CORRUPT_ROWID(p, iRowid); + p->rc = FTS5_CORRUPT; break; } aIdx = sqlite3Fts5MallocZero(&p->rc, (pLeaf->nn-pLeaf->szLeaf)+2); @@ -252562,14 +249632,14 @@ static void fts5DoSecureDelete( nSuffix = (nPrefix2 + nSuffix2) - nPrefix; if( (iKeyOff+nSuffix)>iPgIdx || (iNextOff+nSuffix2)>iPgIdx ){ - FTS5_CORRUPT_IDX(p); + p->rc = FTS5_CORRUPT; }else{ if( iKey!=1 ){ iOff += sqlite3Fts5PutVarint(&aPg[iOff], nPrefix); } iOff += sqlite3Fts5PutVarint(&aPg[iOff], nSuffix); if( nPrefix2>pSeg->term.n ){ - FTS5_CORRUPT_IDX(p); + p->rc = FTS5_CORRUPT; }else if( nPrefix2>nPrefix ){ memcpy(&aPg[iOff], &pSeg->term.p[nPrefix], nPrefix2-nPrefix); iOff += (nPrefix2-nPrefix); @@ -252993,7 +250063,7 @@ static Fts5Structure *fts5IndexOptimizeStruct( } nByte += (((i64)pStruct->nLevel)+1) * sizeof(Fts5StructureLevel); - assert( nByte==(i64)SZ_FTS5STRUCTURE(pStruct->nLevel+2) ); + assert( nByte==SZ_FTS5STRUCTURE(pStruct->nLevel+2) ); pNew = (Fts5Structure*)sqlite3Fts5MallocZero(&p->rc, nByte); if( pNew ){ @@ -253362,7 +250432,7 @@ static void fts5MergePrefixLists( } if( pHead==0 || pHead->pNext==0 ){ - FTS5_CORRUPT_IDX(p); + p->rc = FTS5_CORRUPT; break; } @@ -253399,7 +250469,7 @@ static void fts5MergePrefixLists( assert_nc( tmp.n+nTail<=nTmp ); assert( tmp.n+nTail<=nTmp+nMerge*10 ); if( tmp.n+nTail>nTmp-FTS5_DATA_ZERO_PADDING ){ - if( p->rc==SQLITE_OK ) FTS5_CORRUPT_IDX(p); + if( p->rc==SQLITE_OK ) p->rc = FTS5_CORRUPT; break; } fts5BufferSafeAppendVarint(&out, (tmp.n+nTail) * 2); @@ -253968,14 +251038,11 @@ static int sqlite3Fts5IndexRollback(Fts5Index *p){ */ static int sqlite3Fts5IndexReinit(Fts5Index *p){ Fts5Structure *pTmp; - union { - Fts5Structure sFts; - u8 tmpSpace[SZ_FTS5STRUCTURE(1)]; - } uFts; + u8 tmpSpace[SZ_FTS5STRUCTURE(1)]; fts5StructureInvalidate(p); fts5IndexDiscardData(p); - pTmp = &uFts.sFts; - memset(uFts.tmpSpace, 0, sizeof(uFts.tmpSpace)); + pTmp = (Fts5Structure*)tmpSpace; + memset(pTmp, 0, SZ_FTS5STRUCTURE(1)); if( p->pConfig->bContentlessDelete ){ pTmp->nOriginCntr = 1; } @@ -255435,27 +252502,19 @@ static int fts5TestUtf8(const char *z, int n){ /* ** This function is also purely an internal test. It does not contribute to ** FTS functionality, or even the integrity-check, in any way. -** -** This function sets output variable (*pbFail) to true if the test fails. Or -** leaves it unchanged if the test succeeds. */ static void fts5TestTerm( Fts5Index *p, Fts5Buffer *pPrev, /* Previous term */ const char *z, int n, /* Possibly new term to test */ u64 expected, - u64 *pCksum, - int *pbFail + u64 *pCksum ){ int rc = p->rc; if( pPrev->n==0 ){ fts5BufferSet(&rc, pPrev, n, (const u8*)z); }else - if( *pbFail==0 - && rc==SQLITE_OK - && (pPrev->n!=n || memcmp(pPrev->p, z, n)) - && (p->pHash==0 || p->pHash->nEntry==0) - ){ + if( rc==SQLITE_OK && (pPrev->n!=n || memcmp(pPrev->p, z, n)) ){ u64 cksum3 = *pCksum; const char *zTerm = (const char*)&pPrev->p[1]; /* term sans prefix-byte */ int nTerm = pPrev->n-1; /* Size of zTerm in bytes */ @@ -255505,7 +252564,7 @@ static void fts5TestTerm( fts5BufferSet(&rc, pPrev, n, (const u8*)z); if( rc==SQLITE_OK && cksum3!=expected ){ - *pbFail = 1; + rc = FTS5_CORRUPT; } *pCksum = cksum3; } @@ -255514,7 +252573,7 @@ static void fts5TestTerm( #else # define fts5TestDlidxReverse(x,y,z) -# define fts5TestTerm(t,u,v,w,x,y,z) +# define fts5TestTerm(u,v,w,x,y,z) #endif /* @@ -255539,17 +252598,14 @@ static void fts5IndexIntegrityCheckEmpty( for(i=iFirst; p->rc==SQLITE_OK && i<=iLast; i++){ Fts5Data *pLeaf = fts5DataRead(p, FTS5_SEGMENT_ROWID(pSeg->iSegid, i)); if( pLeaf ){ - if( !fts5LeafIsTermless(pLeaf) - || (i>=iNoRowid && 0!=fts5LeafFirstRowidOff(pLeaf)) - ){ - FTS5_CORRUPT_ROWID(p, FTS5_SEGMENT_ROWID(pSeg->iSegid, i)); - } + if( !fts5LeafIsTermless(pLeaf) ) p->rc = FTS5_CORRUPT; + if( i>=iNoRowid && 0!=fts5LeafFirstRowidOff(pLeaf) ) p->rc = FTS5_CORRUPT; } fts5DataRelease(pLeaf); } } -static void fts5IntegrityCheckPgidx(Fts5Index *p, i64 iRowid, Fts5Data *pLeaf){ +static void fts5IntegrityCheckPgidx(Fts5Index *p, Fts5Data *pLeaf){ i64 iTermOff = 0; int ii; @@ -255567,12 +252623,12 @@ static void fts5IntegrityCheckPgidx(Fts5Index *p, i64 iRowid, Fts5Data *pLeaf){ iOff = iTermOff; if( iOff>=pLeaf->szLeaf ){ - FTS5_CORRUPT_ROWID(p, iRowid); + p->rc = FTS5_CORRUPT; }else if( iTermOff==nIncr ){ int nByte; iOff += fts5GetVarint32(&pLeaf->p[iOff], nByte); if( (iOff+nByte)>pLeaf->szLeaf ){ - FTS5_CORRUPT_ROWID(p, iRowid); + p->rc = FTS5_CORRUPT; }else{ fts5BufferSet(&p->rc, &buf1, nByte, &pLeaf->p[iOff]); } @@ -255581,7 +252637,7 @@ static void fts5IntegrityCheckPgidx(Fts5Index *p, i64 iRowid, Fts5Data *pLeaf){ iOff += fts5GetVarint32(&pLeaf->p[iOff], nKeep); iOff += fts5GetVarint32(&pLeaf->p[iOff], nByte); if( nKeep>buf1.n || (iOff+nByte)>pLeaf->szLeaf ){ - FTS5_CORRUPT_ROWID(p, iRowid); + p->rc = FTS5_CORRUPT; }else{ buf1.n = nKeep; fts5BufferAppendBlob(&p->rc, &buf1, nByte, &pLeaf->p[iOff]); @@ -255589,7 +252645,7 @@ static void fts5IntegrityCheckPgidx(Fts5Index *p, i64 iRowid, Fts5Data *pLeaf){ if( p->rc==SQLITE_OK ){ res = fts5BufferCompare(&buf1, &buf2); - if( res<=0 ) FTS5_CORRUPT_ROWID(p, iRowid); + if( res<=0 ) p->rc = FTS5_CORRUPT; } } fts5BufferSet(&p->rc, &buf2, buf1.n, buf1.p); @@ -255650,7 +252706,7 @@ static void fts5IndexIntegrityCheckSegment( ** entry even if all the terms are removed from it by secure-delete ** operations. */ }else{ - FTS5_CORRUPT_ROWID(p, iRow); + p->rc = FTS5_CORRUPT; } }else{ @@ -255662,15 +252718,15 @@ static void fts5IndexIntegrityCheckSegment( iOff = fts5LeafFirstTermOff(pLeaf); iRowidOff = fts5LeafFirstRowidOff(pLeaf); if( iRowidOff>=iOff || iOff>=pLeaf->szLeaf ){ - FTS5_CORRUPT_ROWID(p, iRow); + p->rc = FTS5_CORRUPT; }else{ iOff += fts5GetVarint32(&pLeaf->p[iOff], nTerm); res = fts5Memcmp(&pLeaf->p[iOff], zIdxTerm, MIN(nTerm, nIdxTerm)); if( res==0 ) res = nTerm - nIdxTerm; - if( res<0 ) FTS5_CORRUPT_ROWID(p, iRow); + if( res<0 ) p->rc = FTS5_CORRUPT; } - fts5IntegrityCheckPgidx(p, iRow, pLeaf); + fts5IntegrityCheckPgidx(p, pLeaf); } fts5DataRelease(pLeaf); if( p->rc ) break; @@ -255700,7 +252756,7 @@ static void fts5IndexIntegrityCheckSegment( iKey = FTS5_SEGMENT_ROWID(iSegid, iPg); pLeaf = fts5DataRead(p, iKey); if( pLeaf ){ - if( fts5LeafFirstRowidOff(pLeaf)!=0 ) FTS5_CORRUPT_ROWID(p, iKey); + if( fts5LeafFirstRowidOff(pLeaf)!=0 ) p->rc = FTS5_CORRUPT; fts5DataRelease(pLeaf); } } @@ -255715,12 +252771,12 @@ static void fts5IndexIntegrityCheckSegment( int iRowidOff = fts5LeafFirstRowidOff(pLeaf); ASSERT_SZLEAF_OK(pLeaf); if( iRowidOff>=pLeaf->szLeaf ){ - FTS5_CORRUPT_ROWID(p, iKey); + p->rc = FTS5_CORRUPT; }else if( bSecureDelete==0 || iRowidOff>0 ){ i64 iDlRowid = fts5DlidxIterRowid(pDlidx); fts5GetVarint(&pLeaf->p[iRowidOff], (u64*)&iRowid); if( iRowid<iDlRowid || (bSecureDelete==0 && iRowid!=iDlRowid) ){ - FTS5_CORRUPT_ROWID(p, iKey); + p->rc = FTS5_CORRUPT; } } fts5DataRelease(pLeaf); @@ -255772,7 +252828,6 @@ static int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum, int bUseCksum /* Used by extra internal tests only run if NDEBUG is not defined */ u64 cksum3 = 0; /* Checksum based on contents of indexes */ Fts5Buffer term = {0,0,0}; /* Buffer used to hold most recent term */ - int bTestFail = 0; #endif const int flags = FTS5INDEX_QUERY_NOOUTPUT; @@ -255815,7 +252870,7 @@ static int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum, int bUseCksum char *z = (char*)fts5MultiIterTerm(pIter, &n); /* If this is a new term, query for it. Update cksum3 with the results. */ - fts5TestTerm(p, &term, z, n, cksum2, &cksum3, &bTestFail); + fts5TestTerm(p, &term, z, n, cksum2, &cksum3); if( p->rc ) break; if( eDetail==FTS5_DETAIL_NONE ){ @@ -255833,26 +252888,15 @@ static int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum, int bUseCksum } } } - fts5TestTerm(p, &term, 0, 0, cksum2, &cksum3, &bTestFail); + fts5TestTerm(p, &term, 0, 0, cksum2, &cksum3); fts5MultiIterFree(pIter); - if( p->rc==SQLITE_OK && bUseCksum && cksum!=cksum2 ){ - p->rc = FTS5_CORRUPT; - sqlite3Fts5ConfigErrmsg(p->pConfig, - "fts5: checksum mismatch for table \"%s\"", p->pConfig->zName - ); - } + if( p->rc==SQLITE_OK && bUseCksum && cksum!=cksum2 ) p->rc = FTS5_CORRUPT; + + fts5StructureRelease(pStruct); #ifdef SQLITE_DEBUG - /* In SQLITE_DEBUG builds, expensive extra checks were run as part of - ** the integrity-check above. If no other errors were detected, but one - ** of these tests failed, set the result to SQLITE_CORRUPT_VTAB here. */ - if( p->rc==SQLITE_OK && bTestFail ){ - p->rc = FTS5_CORRUPT; - } fts5BufferFree(&term); #endif - - fts5StructureRelease(pStruct); fts5BufferFree(&poslist); return fts5IndexReturn(p); } @@ -257196,17 +254240,6 @@ static void fts5SetUniqueFlag(sqlite3_index_info *pIdxInfo){ #endif } -static void fts5SetEstimatedRows(sqlite3_index_info *pIdxInfo, i64 nRow){ -#if SQLITE_VERSION_NUMBER>=3008002 -#ifndef SQLITE_CORE - if( sqlite3_libversion_number()>=3008002 ) -#endif - { - pIdxInfo->estimatedRows = nRow; - } -#endif -} - static int fts5UsePatternMatch( Fts5Config *pConfig, struct sqlite3_index_constraint *p @@ -257342,7 +254375,7 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ nSeenMatch++; idxStr[iIdxStr++] = 'M'; sqlite3_snprintf(6, &idxStr[iIdxStr], "%d", iCol); - iIdxStr += (int)strlen(&idxStr[iIdxStr]); + idxStr += strlen(&idxStr[iIdxStr]); assert( idxStr[iIdxStr]=='\0' ); } pInfo->aConstraintUsage[i].argvIndex = ++iCons; @@ -257361,7 +254394,6 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ idxStr[iIdxStr++] = '='; bSeenEq = 1; pInfo->aConstraintUsage[i].argvIndex = ++iCons; - pInfo->aConstraintUsage[i].omit = 1; } } } @@ -257409,21 +254441,17 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ /* Calculate the estimated cost based on the flags set in idxFlags. */ if( bSeenEq ){ - pInfo->estimatedCost = nSeenMatch ? 1000.0 : 25.0; - fts5SetUniqueFlag(pInfo); - fts5SetEstimatedRows(pInfo, 1); - }else{ - if( bSeenLt && bSeenGt ){ - pInfo->estimatedCost = nSeenMatch ? 5000.0 : 750000.0; - }else if( bSeenLt || bSeenGt ){ - pInfo->estimatedCost = nSeenMatch ? 7500.0 : 2250000.0; - }else{ - pInfo->estimatedCost = nSeenMatch ? 10000.0 : 3000000.0; - } - for(i=1; i<nSeenMatch; i++){ - pInfo->estimatedCost *= 0.4; - } - fts5SetEstimatedRows(pInfo, (i64)(pInfo->estimatedCost / 4.0)); + pInfo->estimatedCost = nSeenMatch ? 1000.0 : 10.0; + if( nSeenMatch==0 ) fts5SetUniqueFlag(pInfo); + }else if( bSeenLt && bSeenGt ){ + pInfo->estimatedCost = nSeenMatch ? 5000.0 : 250000.0; + }else if( bSeenLt || bSeenGt ){ + pInfo->estimatedCost = nSeenMatch ? 7500.0 : 750000.0; + }else{ + pInfo->estimatedCost = nSeenMatch ? 10000.0 : 1000000.0; + } + for(i=1; i<nSeenMatch; i++){ + pInfo->estimatedCost *= 0.4; } pInfo->idxNum = idxFlags; @@ -257622,9 +254650,7 @@ static int fts5CursorReseek(Fts5Cursor *pCsr, int *pbSkip){ int bDesc = pCsr->bDesc; i64 iRowid = sqlite3Fts5ExprRowid(pCsr->pExpr); - rc = sqlite3Fts5ExprFirst( - pCsr->pExpr, pTab->p.pIndex, iRowid, pCsr->iLastRowid, bDesc - ); + rc = sqlite3Fts5ExprFirst(pCsr->pExpr, pTab->p.pIndex, iRowid, bDesc); if( rc==SQLITE_OK && iRowid!=sqlite3Fts5ExprRowid(pCsr->pExpr) ){ *pbSkip = 1; } @@ -257796,9 +254822,7 @@ static int fts5CursorFirstSorted( static int fts5CursorFirst(Fts5FullTable *pTab, Fts5Cursor *pCsr, int bDesc){ int rc; Fts5Expr *pExpr = pCsr->pExpr; - rc = sqlite3Fts5ExprFirst( - pExpr, pTab->p.pIndex, pCsr->iFirstRowid, pCsr->iLastRowid, bDesc - ); + rc = sqlite3Fts5ExprFirst(pExpr, pTab->p.pIndex, pCsr->iFirstRowid, bDesc); if( sqlite3Fts5ExprEof(pExpr) ){ CsrFlagSet(pCsr, FTS5CSR_EOF); } @@ -260283,7 +257307,7 @@ static void fts5SourceIdFunc( ){ assert( nArg==0 ); UNUSED_PARAM2(nArg, apUnused); - sqlite3_result_text(pCtx, "fts5: 2025-11-04 19:38:17 fb2c931ae597f8d00a37574ff67aeed3eced4e5547f9120744ae4bfa8e74527b", -1, SQLITE_TRANSIENT); + sqlite3_result_text(pCtx, "fts5: 2025-07-30 19:33:53 4d8adfb30e03f9cf27f800a2c1ba3c48fb4ca1b08b0f5ed59a4d5ecbf45e20a3", -1, SQLITE_TRANSIENT); } /* @@ -260306,9 +257330,9 @@ static void fts5LocaleFunc( sqlite3_value **apArg /* Function arguments */ ){ const char *zLocale = 0; - i64 nLocale = 0; + int nLocale = 0; const char *zText = 0; - i64 nText = 0; + int nText = 0; assert( nArg==2 ); UNUSED_PARAM(nArg); @@ -260325,10 +257349,10 @@ static void fts5LocaleFunc( Fts5Global *p = (Fts5Global*)sqlite3_user_data(pCtx); u8 *pBlob = 0; u8 *pCsr = 0; - i64 nBlob = 0; + int nBlob = 0; nBlob = FTS5_LOCALE_HDR_SIZE + nLocale + 1 + nText; - pBlob = (u8*)sqlite3_malloc64(nBlob); + pBlob = (u8*)sqlite3_malloc(nBlob); if( pBlob==0 ){ sqlite3_result_error_nomem(pCtx); return; @@ -260406,9 +257430,8 @@ static int fts5IntegrityMethod( " FTS5 table %s.%s: %s", zSchema, zTabname, sqlite3_errstr(rc)); } - }else if( (rc&0xff)==SQLITE_CORRUPT ){ - rc = SQLITE_OK; } + sqlite3Fts5IndexCloseReader(pTab->p.pIndex); pTab->p.pConfig->pzErrmsg = 0; diff --git a/third_party/sqlite3/src/sqlite3.h b/third_party/sqlite3/src/sqlite3.h @@ -146,12 +146,9 @@ extern "C" { ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.51.0" -#define SQLITE_VERSION_NUMBER 3051000 -#define SQLITE_SOURCE_ID "2025-11-04 19:38:17 fb2c931ae597f8d00a37574ff67aeed3eced4e5547f9120744ae4bfa8e74527b" -#define SQLITE_SCM_BRANCH "trunk" -#define SQLITE_SCM_TAGS "release major-release version-3.51.0" -#define SQLITE_SCM_DATETIME "2025-11-04T19:38:17.314Z" +#define SQLITE_VERSION "3.50.4" +#define SQLITE_VERSION_NUMBER 3050004 +#define SQLITE_SOURCE_ID "2025-07-30 19:33:53 4d8adfb30e03f9cf27f800a2c1ba3c48fb4ca1b08b0f5ed59a4d5ecbf45e20a3" /* ** CAPI3REF: Run-Time Library Version Numbers @@ -171,9 +168,9 @@ extern "C" { ** assert( strcmp(sqlite3_libversion(),SQLITE_VERSION)==0 ); ** </pre></blockquote>)^ ** -** ^The sqlite3_version[] string constant contains the text of the -** [SQLITE_VERSION] macro. ^The sqlite3_libversion() function returns a -** pointer to the sqlite3_version[] string constant. The sqlite3_libversion() +** ^The sqlite3_version[] string constant contains the text of [SQLITE_VERSION] +** macro. ^The sqlite3_libversion() function returns a pointer to the +** to the sqlite3_version[] string constant. The sqlite3_libversion() ** function is provided for use in DLLs since DLL users usually do not have ** direct access to string constants within the DLL. ^The ** sqlite3_libversion_number() function returns an integer equal to @@ -373,7 +370,7 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**); ** without having to use a lot of C code. ** ** ^The sqlite3_exec() interface runs zero or more UTF-8 encoded, -** semicolon-separated SQL statements passed into its 2nd argument, +** semicolon-separate SQL statements passed into its 2nd argument, ** in the context of the [database connection] passed in as its 1st ** argument. ^If the callback function of the 3rd argument to ** sqlite3_exec() is not NULL, then it is invoked for each result row @@ -406,7 +403,7 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**); ** result row is NULL then the corresponding string pointer for the ** sqlite3_exec() callback is a NULL pointer. ^The 4th argument to the ** sqlite3_exec() callback is an array of pointers to strings where each -** entry represents the name of a corresponding result column as obtained +** entry represents the name of corresponding result column as obtained ** from [sqlite3_column_name()]. ** ** ^If the 2nd parameter to sqlite3_exec() is a NULL pointer, a pointer @@ -500,9 +497,6 @@ SQLITE_API int sqlite3_exec( #define SQLITE_ERROR_MISSING_COLLSEQ (SQLITE_ERROR | (1<<8)) #define SQLITE_ERROR_RETRY (SQLITE_ERROR | (2<<8)) #define SQLITE_ERROR_SNAPSHOT (SQLITE_ERROR | (3<<8)) -#define SQLITE_ERROR_RESERVESIZE (SQLITE_ERROR | (4<<8)) -#define SQLITE_ERROR_KEY (SQLITE_ERROR | (5<<8)) -#define SQLITE_ERROR_UNABLE (SQLITE_ERROR | (6<<8)) #define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8)) #define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8)) #define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3<<8)) @@ -537,8 +531,6 @@ SQLITE_API int sqlite3_exec( #define SQLITE_IOERR_DATA (SQLITE_IOERR | (32<<8)) #define SQLITE_IOERR_CORRUPTFS (SQLITE_IOERR | (33<<8)) #define SQLITE_IOERR_IN_PAGE (SQLITE_IOERR | (34<<8)) -#define SQLITE_IOERR_BADKEY (SQLITE_IOERR | (35<<8)) -#define SQLITE_IOERR_CODEC (SQLITE_IOERR | (36<<8)) #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8)) #define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8)) #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) @@ -597,7 +589,7 @@ SQLITE_API int sqlite3_exec( ** Note in particular that passing the SQLITE_OPEN_EXCLUSIVE flag into ** [sqlite3_open_v2()] does *not* cause the underlying database file ** to be opened using O_EXCL. Passing SQLITE_OPEN_EXCLUSIVE into -** [sqlite3_open_v2()] has historically been a no-op and might become an +** [sqlite3_open_v2()] has historically be a no-op and might become an ** error in future versions of SQLite. */ #define SQLITE_OPEN_READONLY 0x00000001 /* Ok for sqlite3_open_v2() */ @@ -691,7 +683,7 @@ SQLITE_API int sqlite3_exec( ** SQLite uses one of these integer values as the second ** argument to calls it makes to the xLock() and xUnlock() methods ** of an [sqlite3_io_methods] object. These values are ordered from -** least restrictive to most restrictive. +** lest restrictive to most restrictive. ** ** The argument to xLock() is always SHARED or higher. The argument to ** xUnlock is either SHARED or NONE. @@ -932,7 +924,7 @@ struct sqlite3_io_methods { ** connection. See also [SQLITE_FCNTL_FILE_POINTER]. ** ** <li>[[SQLITE_FCNTL_SYNC_OMITTED]] -** The SQLITE_FCNTL_SYNC_OMITTED file-control is no longer used. +** No longer in use. ** ** <li>[[SQLITE_FCNTL_SYNC]] ** The [SQLITE_FCNTL_SYNC] opcode is generated internally by SQLite and @@ -1007,7 +999,7 @@ struct sqlite3_io_methods { ** ** <li>[[SQLITE_FCNTL_VFSNAME]] ** ^The [SQLITE_FCNTL_VFSNAME] opcode can be used to obtain the names of -** all [VFSes] in the VFS stack. The names of all VFS shims and the +** all [VFSes] in the VFS stack. The names are of all VFS shims and the ** final bottom-level VFS are written into memory obtained from ** [sqlite3_malloc()] and the result is stored in the char* variable ** that the fourth parameter of [sqlite3_file_control()] points to. @@ -1021,7 +1013,7 @@ struct sqlite3_io_methods { ** ^The [SQLITE_FCNTL_VFS_POINTER] opcode finds a pointer to the top-level ** [VFSes] currently in use. ^(The argument X in ** sqlite3_file_control(db,SQLITE_FCNTL_VFS_POINTER,X) must be -** of type "[sqlite3_vfs] **". This opcode will set *X +** of type "[sqlite3_vfs] **". This opcodes will set *X ** to a pointer to the top-level VFS.)^ ** ^When there are multiple VFS shims in the stack, this opcode finds the ** upper-most shim only. @@ -1211,7 +1203,7 @@ struct sqlite3_io_methods { ** <li>[[SQLITE_FCNTL_EXTERNAL_READER]] ** The EXPERIMENTAL [SQLITE_FCNTL_EXTERNAL_READER] opcode is used to detect ** whether or not there is a database client in another process with a wal-mode -** transaction open on the database or not. It is only available on unix. The +** transaction open on the database or not. It is only available on unix.The ** (void*) argument passed with this file-control should be a pointer to a ** value of type (int). The integer value is set to 1 if the database is a wal ** mode database and there exists at least one client in another process that @@ -1229,15 +1221,6 @@ struct sqlite3_io_methods { ** database is not a temp db, then the [SQLITE_FCNTL_RESET_CACHE] file-control ** purges the contents of the in-memory page cache. If there is an open ** transaction, or if the db is a temp-db, this opcode is a no-op, not an error. -** -** <li>[[SQLITE_FCNTL_FILESTAT]] -** The [SQLITE_FCNTL_FILESTAT] opcode returns low-level diagnostic information -** about the [sqlite3_file] objects used access the database and journal files -** for the given schema. The fourth parameter to [sqlite3_file_control()] -** should be an initialized [sqlite3_str] pointer. JSON text describing -** various aspects of the sqlite3_file object is appended to the sqlite3_str. -** The SQLITE_FCNTL_FILESTAT opcode is usually a no-op, unless compile-time -** options are used to enable it. ** </ul> */ #define SQLITE_FCNTL_LOCKSTATE 1 @@ -1283,7 +1266,6 @@ struct sqlite3_io_methods { #define SQLITE_FCNTL_RESET_CACHE 42 #define SQLITE_FCNTL_NULL_IO 43 #define SQLITE_FCNTL_BLOCK_ON_CONNECT 44 -#define SQLITE_FCNTL_FILESTAT 45 /* deprecated names */ #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE @@ -1646,7 +1628,7 @@ struct sqlite3_vfs { ** SQLite interfaces so that an application usually does not need to ** invoke sqlite3_initialize() directly. For example, [sqlite3_open()] ** calls sqlite3_initialize() so the SQLite library will be automatically -** initialized when [sqlite3_open()] is called if it has not been initialized +** initialized when [sqlite3_open()] is called if it has not be initialized ** already. ^However, if SQLite is compiled with the [SQLITE_OMIT_AUTOINIT] ** compile-time option, then the automatic calls to sqlite3_initialize() ** are omitted and the application must call sqlite3_initialize() directly @@ -1903,21 +1885,21 @@ struct sqlite3_mem_methods { ** The [sqlite3_mem_methods] ** structure is filled with the currently defined memory allocation routines.)^ ** This option can be used to overload the default memory allocation -** routines with a wrapper that simulates memory allocation failure or +** routines with a wrapper that simulations memory allocation failure or ** tracks memory usage, for example. </dd> ** ** [[SQLITE_CONFIG_SMALL_MALLOC]] <dt>SQLITE_CONFIG_SMALL_MALLOC</dt> -** <dd> ^The SQLITE_CONFIG_SMALL_MALLOC option takes a single argument of +** <dd> ^The SQLITE_CONFIG_SMALL_MALLOC option takes single argument of ** type int, interpreted as a boolean, which if true provides a hint to ** SQLite that it should avoid large memory allocations if possible. ** SQLite will run faster if it is free to make large memory allocations, -** but some applications might prefer to run slower in exchange for +** but some application might prefer to run slower in exchange for ** guarantees about memory fragmentation that are possible if large ** allocations are avoided. This hint is normally off. ** </dd> ** ** [[SQLITE_CONFIG_MEMSTATUS]] <dt>SQLITE_CONFIG_MEMSTATUS</dt> -** <dd> ^The SQLITE_CONFIG_MEMSTATUS option takes a single argument of type int, +** <dd> ^The SQLITE_CONFIG_MEMSTATUS option takes single argument of type int, ** interpreted as a boolean, which enables or disables the collection of ** memory allocation statistics. ^(When memory allocation statistics are ** disabled, the following SQLite interfaces become non-operational: @@ -1962,7 +1944,7 @@ struct sqlite3_mem_methods { ** ^If pMem is NULL and N is non-zero, then each database connection ** does an initial bulk allocation for page cache memory ** from [sqlite3_malloc()] sufficient for N cache lines if N is positive or -** of -1024*N bytes if N is negative. ^If additional +** of -1024*N bytes if N is negative, . ^If additional ** page cache memory is needed beyond what is provided by the initial ** allocation, then SQLite goes to [sqlite3_malloc()] separately for each ** additional cache line. </dd> @@ -1991,7 +1973,7 @@ struct sqlite3_mem_methods { ** <dd> ^(The SQLITE_CONFIG_MUTEX option takes a single argument which is a ** pointer to an instance of the [sqlite3_mutex_methods] structure. ** The argument specifies alternative low-level mutex routines to be used -** in place of the mutex routines built into SQLite.)^ ^SQLite makes a copy of +** in place the mutex routines built into SQLite.)^ ^SQLite makes a copy of ** the content of the [sqlite3_mutex_methods] structure before the call to ** [sqlite3_config()] returns. ^If SQLite is compiled with ** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then @@ -2033,7 +2015,7 @@ struct sqlite3_mem_methods { ** ** [[SQLITE_CONFIG_GETPCACHE2]] <dt>SQLITE_CONFIG_GETPCACHE2</dt> ** <dd> ^(The SQLITE_CONFIG_GETPCACHE2 option takes a single argument which -** is a pointer to an [sqlite3_pcache_methods2] object. SQLite copies off +** is a pointer to an [sqlite3_pcache_methods2] object. SQLite copies of ** the current page cache implementation into that object.)^ </dd> ** ** [[SQLITE_CONFIG_LOG]] <dt>SQLITE_CONFIG_LOG</dt> @@ -2050,7 +2032,7 @@ struct sqlite3_mem_methods { ** the logger function is a copy of the first parameter to the corresponding ** [sqlite3_log()] call and is intended to be a [result code] or an ** [extended result code]. ^The third parameter passed to the logger is -** a log message after formatting via [sqlite3_snprintf()]. +** log message after formatting via [sqlite3_snprintf()]. ** The SQLite logging interface is not reentrant; the logger function ** supplied by the application must not invoke any SQLite interface. ** In a multi-threaded application, the application-defined logger @@ -2241,7 +2223,7 @@ struct sqlite3_mem_methods { ** These constants are the available integer configuration options that ** can be passed as the second parameter to the [sqlite3_db_config()] interface. ** -** The [sqlite3_db_config()] interface is a var-args function. It takes a +** The [sqlite3_db_config()] interface is a var-args functions. It takes a ** variable number of parameters, though always at least two. The number of ** parameters passed into sqlite3_db_config() depends on which of these ** constants is given as the second parameter. This documentation page @@ -2353,20 +2335,17 @@ struct sqlite3_mem_methods { ** ** [[SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER]] ** <dt>SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER</dt> -** <dd> ^This option is used to enable or disable using the -** [fts3_tokenizer()] function - part of the [FTS3] full-text search engine -** extension - without using bound parameters as the parameters. Doing so -** is disabled by default. There must be two additional arguments. The first -** argument is an integer. If it is passed 0, then using fts3_tokenizer() -** without bound parameters is disabled. If it is passed a positive value, -** then calling fts3_tokenizer without bound parameters is enabled. If it -** is passed a negative value, this setting is not modified - this can be -** used to query for the current setting. The second parameter is a pointer -** to an integer into which is written 0 or 1 to indicate the current value -** of this setting (after it is modified, if applicable). The second -** parameter may be a NULL pointer, in which case the value of the setting -** is not reported back. Refer to [FTS3] documentation for further details. -** </dd> +** <dd> ^This option is used to enable or disable the +** [fts3_tokenizer()] function which is part of the +** [FTS3] full-text search engine extension. +** There must be two additional arguments. +** The first argument is an integer which is 0 to disable fts3_tokenizer() or +** positive to enable fts3_tokenizer() or negative to leave the setting +** unchanged. +** The second parameter is a pointer to an integer into which +** is written 0 or 1 to indicate whether fts3_tokenizer is disabled or enabled +** following this call. The second parameter may be a NULL pointer, in +** which case the new setting is not reported back. </dd> ** ** [[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION]] ** <dt>SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION</dt> @@ -2378,8 +2357,8 @@ struct sqlite3_mem_methods { ** When the first argument to this interface is 1, then only the C-API is ** enabled and the SQL function remains disabled. If the first argument to ** this interface is 0, then both the C-API and the SQL function are disabled. -** If the first argument is -1, then no changes are made to the state of either -** the C-API or the SQL function. +** If the first argument is -1, then no changes are made to state of either the +** C-API or the SQL function. ** The second parameter is a pointer to an integer into which ** is written 0 or 1 to indicate whether [sqlite3_load_extension()] interface ** is disabled or enabled following this call. The second parameter may @@ -2497,7 +2476,7 @@ struct sqlite3_mem_methods { ** [[SQLITE_DBCONFIG_LEGACY_ALTER_TABLE]] ** <dt>SQLITE_DBCONFIG_LEGACY_ALTER_TABLE</dt> ** <dd>The SQLITE_DBCONFIG_LEGACY_ALTER_TABLE option activates or deactivates -** the legacy behavior of the [ALTER TABLE RENAME] command such that it +** the legacy behavior of the [ALTER TABLE RENAME] command such it ** behaves as it did prior to [version 3.24.0] (2018-06-04). See the ** "Compatibility Notice" on the [ALTER TABLE RENAME documentation] for ** additional information. This feature can also be turned on and off @@ -2546,7 +2525,7 @@ struct sqlite3_mem_methods { ** <dt>SQLITE_DBCONFIG_LEGACY_FILE_FORMAT</dt> ** <dd>The SQLITE_DBCONFIG_LEGACY_FILE_FORMAT option activates or deactivates ** the legacy file format flag. When activated, this flag causes all newly -** created database files to have a schema format version number (the 4-byte +** created database file to have a schema format version number (the 4-byte ** integer found at offset 44 into the database header) of 1. This in turn ** means that the resulting database file will be readable and writable by ** any SQLite version back to 3.0.0 ([dateof:3.0.0]). Without this setting, @@ -2573,7 +2552,7 @@ struct sqlite3_mem_methods { ** the database handle both when the SQL statement is prepared and when it ** is stepped. The flag is set (collection of statistics is enabled) ** by default. <p>This option takes two arguments: an integer and a pointer to -** an integer. The first argument is 1, 0, or -1 to enable, disable, or +** an integer.. The first argument is 1, 0, or -1 to enable, disable, or ** leave unchanged the statement scanstatus option. If the second argument ** is not NULL, then the value of the statement scanstatus setting after ** processing the first argument is written into the integer that the second @@ -2616,8 +2595,8 @@ struct sqlite3_mem_methods { ** <dd>The SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE option enables or disables the ** ability of the [ATTACH DATABASE] SQL command to open a database for writing. ** This capability is enabled by default. Applications can disable or -** reenable this capability using the current DBCONFIG option. If -** this capability is disabled, the [ATTACH] command will still work, +** reenable this capability using the current DBCONFIG option. If the +** the this capability is disabled, the [ATTACH] command will still work, ** but the database will be opened read-only. If this option is disabled, ** then the ability to create a new database using [ATTACH] is also disabled, ** regardless of the value of the [SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE] @@ -2651,7 +2630,7 @@ struct sqlite3_mem_methods { ** ** <p>Most of the SQLITE_DBCONFIG options take two arguments, so that the ** overall call to [sqlite3_db_config()] has a total of four parameters. -** The first argument (the third parameter to sqlite3_db_config()) is an integer. +** The first argument (the third parameter to sqlite3_db_config()) is a integer. ** The second argument is a pointer to an integer. If the first argument is 1, ** then the option becomes enabled. If the first integer argument is 0, then the ** option is disabled. If the first argument is -1, then the option setting @@ -2941,7 +2920,7 @@ SQLITE_API int sqlite3_is_interrupted(sqlite3*); ** ^These routines return 0 if the statement is incomplete. ^If a ** memory allocation fails, then SQLITE_NOMEM is returned. ** -** ^These routines do not parse the SQL statements and thus +** ^These routines do not parse the SQL statements thus ** will not detect syntactically incorrect SQL. ** ** ^(If SQLite has not been initialized using [sqlite3_initialize()] prior @@ -3058,7 +3037,7 @@ SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms); ** indefinitely if possible. The results of passing any other negative value ** are undefined. ** -** Internally, each SQLite database handle stores two timeout values - the +** Internally, each SQLite database handle store two timeout values - the ** busy-timeout (used for rollback mode databases, or if the VFS does not ** support blocking locks) and the setlk-timeout (used for blocking locks ** on wal-mode databases). The sqlite3_busy_timeout() method sets both @@ -3088,7 +3067,7 @@ SQLITE_API int sqlite3_setlk_timeout(sqlite3*, int ms, int flags); ** This is a legacy interface that is preserved for backwards compatibility. ** Use of this interface is not recommended. ** -** Definition: A <b>result table</b> is a memory data structure created by the +** Definition: A <b>result table</b> is memory data structure created by the ** [sqlite3_get_table()] interface. A result table records the ** complete query results from one or more queries. ** @@ -3231,7 +3210,7 @@ SQLITE_API char *sqlite3_vsnprintf(int,char*,const char*, va_list); ** ^Calling sqlite3_free() with a pointer previously returned ** by sqlite3_malloc() or sqlite3_realloc() releases that memory so ** that it might be reused. ^The sqlite3_free() routine is -** a no-op if it is called with a NULL pointer. Passing a NULL pointer +** a no-op if is called with a NULL pointer. Passing a NULL pointer ** to sqlite3_free() is harmless. After being freed, memory ** should neither be read nor written. Even reading previously freed ** memory might result in a segmentation fault or other severe error. @@ -3249,13 +3228,13 @@ SQLITE_API char *sqlite3_vsnprintf(int,char*,const char*, va_list); ** sqlite3_free(X). ** ^sqlite3_realloc(X,N) returns a pointer to a memory allocation ** of at least N bytes in size or NULL if insufficient memory is available. -** ^If M is the size of the prior allocation, then min(N,M) bytes of the -** prior allocation are copied into the beginning of the buffer returned +** ^If M is the size of the prior allocation, then min(N,M) bytes +** of the prior allocation are copied into the beginning of buffer returned ** by sqlite3_realloc(X,N) and the prior allocation is freed. ** ^If sqlite3_realloc(X,N) returns NULL and N is positive, then the ** prior allocation is not freed. ** -** ^The sqlite3_realloc64(X,N) interface works the same as +** ^The sqlite3_realloc64(X,N) interfaces works the same as ** sqlite3_realloc(X,N) except that N is a 64-bit unsigned integer instead ** of a 32-bit signed integer. ** @@ -3305,7 +3284,7 @@ SQLITE_API sqlite3_uint64 sqlite3_msize(void*); ** was last reset. ^The values returned by [sqlite3_memory_used()] and ** [sqlite3_memory_highwater()] include any overhead ** added by SQLite in its implementation of [sqlite3_malloc()], -** but not overhead added by any underlying system library +** but not overhead added by the any underlying system library ** routines that [sqlite3_malloc()] may call. ** ** ^The memory high-water mark is reset to the current value of @@ -3757,7 +3736,7 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); ** there is no harm in trying.) ** ** ^(<dt>[SQLITE_OPEN_SHAREDCACHE]</dt> -** <dd>The database is opened with [shared cache] enabled, overriding +** <dd>The database is opened [shared cache] enabled, overriding ** the default shared cache setting provided by ** [sqlite3_enable_shared_cache()].)^ ** The [use of shared cache mode is discouraged] and hence shared cache @@ -3765,7 +3744,7 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); ** this option is a no-op. ** ** ^(<dt>[SQLITE_OPEN_PRIVATECACHE]</dt> -** <dd>The database is opened with [shared cache] disabled, overriding +** <dd>The database is opened [shared cache] disabled, overriding ** the default shared cache setting provided by ** [sqlite3_enable_shared_cache()].)^ ** @@ -4183,7 +4162,7 @@ SQLITE_API void sqlite3_free_filename(sqlite3_filename); ** subsequent calls to other SQLite interface functions.)^ ** ** ^The sqlite3_errstr(E) interface returns the English-language text -** that describes the [result code] E, as UTF-8, or NULL if E is not a +** that describes the [result code] E, as UTF-8, or NULL if E is not an ** result code for which a text error message is available. ** ^(Memory to hold the error message string is managed internally ** and must not be freed by the application)^. @@ -4191,7 +4170,7 @@ SQLITE_API void sqlite3_free_filename(sqlite3_filename); ** ^If the most recent error references a specific token in the input ** SQL, the sqlite3_error_offset() interface returns the byte offset ** of the start of that token. ^The byte offset returned by -** sqlite3_error_offset() assumes that the input SQL is UTF-8. +** sqlite3_error_offset() assumes that the input SQL is UTF8. ** ^If the most recent error does not reference a specific token in the input ** SQL, then the sqlite3_error_offset() function returns -1. ** @@ -4217,34 +4196,6 @@ SQLITE_API const char *sqlite3_errstr(int); SQLITE_API int sqlite3_error_offset(sqlite3 *db); /* -** CAPI3REF: Set Error Codes And Message -** METHOD: sqlite3 -** -** Set the error code of the database handle passed as the first argument -** to errcode, and the error message to a copy of nul-terminated string -** zErrMsg. If zErrMsg is passed NULL, then the error message is set to -** the default message associated with the supplied error code. Subsequent -** calls to [sqlite3_errcode()] and [sqlite3_errmsg()] and similar will -** return the values set by this routine in place of what was previously -** set by SQLite itself. -** -** This function returns SQLITE_OK if the error code and error message are -** successfully set, SQLITE_NOMEM if an OOM occurs, and SQLITE_MISUSE if -** the database handle is NULL or invalid. -** -** The error code and message set by this routine remains in effect until -** they are changed, either by another call to this routine or until they are -** changed to by SQLite itself to reflect the result of some subsquent -** API call. -** -** This function is intended for use by SQLite extensions or wrappers. The -** idea is that an extension or wrapper can use this routine to set error -** messages and error codes and thus behave more like a core SQLite -** feature from the point of view of an application. -*/ -SQLITE_API int sqlite3_set_errmsg(sqlite3 *db, int errcode, const char *zErrMsg); - -/* ** CAPI3REF: Prepared Statement Object ** KEYWORDS: {prepared statement} {prepared statements} ** @@ -4318,8 +4269,8 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); ** ** These constants define various performance limits ** that can be lowered at run-time using [sqlite3_limit()]. -** A concise description of these limits follows, and additional information -** is available at [limits | Limits in SQLite]. +** The synopsis of the meanings of the various limits is shown below. +** Additional information is available at [limits | Limits in SQLite]. ** ** <dl> ** [[SQLITE_LIMIT_LENGTH]] ^(<dt>SQLITE_LIMIT_LENGTH</dt> @@ -4384,7 +4335,7 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); /* ** CAPI3REF: Prepare Flags ** -** These constants define various flags that can be passed into the +** These constants define various flags that can be passed into ** "prepFlags" parameter of the [sqlite3_prepare_v3()] and ** [sqlite3_prepare16_v3()] interfaces. ** @@ -4471,7 +4422,7 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); ** there is a small performance advantage to passing an nByte parameter that ** is the number of bytes in the input string <i>including</i> ** the nul-terminator. -** Note that nByte measures the length of the input in bytes, not +** Note that nByte measure the length of the input in bytes, not ** characters, even for the UTF-16 interfaces. ** ** ^If pzTail is not NULL then *pzTail is made to point to the first byte @@ -4605,7 +4556,7 @@ SQLITE_API int sqlite3_prepare16_v3( ** ** ^The sqlite3_expanded_sql() interface returns NULL if insufficient memory ** is available to hold the result, or if the result would exceed the -** maximum string length determined by the [SQLITE_LIMIT_LENGTH]. +** the maximum string length determined by the [SQLITE_LIMIT_LENGTH]. ** ** ^The [SQLITE_TRACE_SIZE_LIMIT] compile-time option limits the size of ** bound parameter expansions. ^The [SQLITE_OMIT_TRACE] compile-time @@ -4793,7 +4744,7 @@ typedef struct sqlite3_value sqlite3_value; ** ** The context in which an SQL function executes is stored in an ** sqlite3_context object. ^A pointer to an sqlite3_context object -** is always the first parameter to [application-defined SQL functions]. +** is always first parameter to [application-defined SQL functions]. ** The application-defined SQL function implementation will pass this ** pointer through into calls to [sqlite3_result_int | sqlite3_result()], ** [sqlite3_aggregate_context()], [sqlite3_user_data()], @@ -4917,11 +4868,9 @@ typedef struct sqlite3_context sqlite3_context; ** associated with the pointer P of type T. ^D is either a NULL pointer or ** a pointer to a destructor function for P. ^SQLite will invoke the ** destructor D with a single argument of P when it is finished using -** P, even if the call to sqlite3_bind_pointer() fails. Due to a -** historical design quirk, results are undefined if D is -** SQLITE_TRANSIENT. The T parameter should be a static string, -** preferably a string literal. The sqlite3_bind_pointer() routine is -** part of the [pointer passing interface] added for SQLite 3.20.0. +** P. The T parameter should be a static string, preferably a string +** literal. The sqlite3_bind_pointer() routine is part of the +** [pointer passing interface] added for SQLite 3.20.0. ** ** ^If any of the sqlite3_bind_*() routines are called with a NULL pointer ** for the [prepared statement] or with a prepared statement for which @@ -5532,7 +5481,7 @@ SQLITE_API int sqlite3_column_type(sqlite3_stmt*, int iCol); ** ** ^The sqlite3_finalize() function is called to delete a [prepared statement]. ** ^If the most recent evaluation of the statement encountered no errors -** or if the statement has never been evaluated, then sqlite3_finalize() returns +** or if the statement is never been evaluated, then sqlite3_finalize() returns ** SQLITE_OK. ^If the most recent evaluation of statement S failed, then ** sqlite3_finalize(S) returns the appropriate [error code] or ** [extended error code]. @@ -5764,7 +5713,7 @@ SQLITE_API int sqlite3_create_window_function( /* ** CAPI3REF: Text Encodings ** -** These constants define integer codes that represent the various +** These constant define integer codes that represent the various ** text encodings supported by SQLite. */ #define SQLITE_UTF8 1 /* IMP: R-37514-35566 */ @@ -5856,7 +5805,7 @@ SQLITE_API int sqlite3_create_window_function( ** result. ** Every function that invokes [sqlite3_result_subtype()] should have this ** property. If it does not, then the call to [sqlite3_result_subtype()] -** might become a no-op if the function is used as a term in an +** might become a no-op if the function is used as term in an ** [expression index]. On the other hand, SQL functions that never invoke ** [sqlite3_result_subtype()] should avoid setting this property, as the ** purpose of this property is to disable certain optimizations that are @@ -5983,7 +5932,7 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6 ** sqlite3_value_nochange(X) interface returns true if and only if ** the column corresponding to X is unchanged by the UPDATE operation ** that the xUpdate method call was invoked to implement and if -** the prior [xColumn] method call that was invoked to extract +** and the prior [xColumn] method call that was invoked to extracted ** the value for that column returned without setting a result (probably ** because it queried [sqlite3_vtab_nochange()] and found that the column ** was unchanging). ^Within an [xUpdate] method, any value for which @@ -6256,7 +6205,6 @@ SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(voi ** or a NULL pointer if there were no prior calls to ** sqlite3_set_clientdata() with the same values of D and N. ** Names are compared using strcmp() and are thus case sensitive. -** It returns 0 on success and SQLITE_NOMEM on allocation failure. ** ** If P and X are both non-NULL, then the destructor X is invoked with ** argument P on the first of the following occurrences: @@ -8933,18 +8881,9 @@ SQLITE_API int sqlite3_status64( ** ^The sqlite3_db_status() routine returns SQLITE_OK on success and a ** non-zero [error code] on failure. ** -** ^The sqlite3_db_status64(D,O,C,H,R) routine works exactly the same -** way as sqlite3_db_status(D,O,C,H,R) routine except that the C and H -** parameters are pointer to 64-bit integers (type: sqlite3_int64) instead -** of pointers to 32-bit integers, which allows larger status values -** to be returned. If a status value exceeds 2,147,483,647 then -** sqlite3_db_status() will truncate the value whereas sqlite3_db_status64() -** will return the full value. -** ** See also: [sqlite3_status()] and [sqlite3_stmt_status()]. */ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg); -SQLITE_API int sqlite3_db_status64(sqlite3*,int,sqlite3_int64*,sqlite3_int64*,int); /* ** CAPI3REF: Status Parameters for database connections @@ -9041,10 +8980,6 @@ SQLITE_API int sqlite3_db_status64(sqlite3*,int,sqlite3_int64*,sqlite3_int64*,in ** If an IO or other error occurs while writing a page to disk, the effect ** on subsequent SQLITE_DBSTATUS_CACHE_WRITE requests is undefined.)^ ^The ** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0. -** <p> -** ^(There is overlap between the quantities measured by this parameter -** (SQLITE_DBSTATUS_CACHE_WRITE) and SQLITE_DBSTATUS_TEMPBUF_SPILL. -** Resetting one will reduce the other.)^ ** </dd> ** ** [[SQLITE_DBSTATUS_CACHE_SPILL]] ^(<dt>SQLITE_DBSTATUS_CACHE_SPILL</dt> @@ -9060,18 +8995,6 @@ SQLITE_API int sqlite3_db_status64(sqlite3*,int,sqlite3_int64*,sqlite3_int64*,in ** <dd>This parameter returns zero for the current value if and only if ** all foreign key constraints (deferred or immediate) have been ** resolved.)^ ^The highwater mark is always 0. -** -** [[SQLITE_DBSTATUS_TEMPBUF_SPILL] ^(<dt>SQLITE_DBSTATUS_TEMPBUF_SPILL</dt> -** <dd>^(This parameter returns the number of bytes written to temporary -** files on disk that could have been kept in memory had sufficient memory -** been available. This value includes writes to intermediate tables that -** are part of complex queries, external sorts that spill to disk, and -** writes to TEMP tables.)^ -** ^The highwater mark is always 0. -** <p> -** ^(There is overlap between the quantities measured by this parameter -** (SQLITE_DBSTATUS_TEMPBUF_SPILL) and SQLITE_DBSTATUS_CACHE_WRITE. -** Resetting one will reduce the other.)^ ** </dd> ** </dl> */ @@ -9088,8 +9011,7 @@ SQLITE_API int sqlite3_db_status64(sqlite3*,int,sqlite3_int64*,sqlite3_int64*,in #define SQLITE_DBSTATUS_DEFERRED_FKS 10 #define SQLITE_DBSTATUS_CACHE_USED_SHARED 11 #define SQLITE_DBSTATUS_CACHE_SPILL 12 -#define SQLITE_DBSTATUS_TEMPBUF_SPILL 13 -#define SQLITE_DBSTATUS_MAX 13 /* Largest defined DBSTATUS */ +#define SQLITE_DBSTATUS_MAX 12 /* Largest defined DBSTATUS */ /* @@ -9854,7 +9776,7 @@ SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...); ** is the number of pages currently in the write-ahead log file, ** including those that were just committed. ** -** ^The callback function should normally return [SQLITE_OK]. ^If an error +** The callback function should normally return [SQLITE_OK]. ^If an error ** code is returned, that error will propagate back up through the ** SQLite code base to cause the statement that provoked the callback ** to report an error, though the commit will have still occurred. If the @@ -9862,26 +9784,13 @@ SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...); ** that does not correspond to any valid SQLite error code, the results ** are undefined. ** -** ^A single database handle may have at most a single write-ahead log -** callback registered at one time. ^Calling [sqlite3_wal_hook()] -** replaces the default behavior or previously registered write-ahead -** log callback. -** -** ^The return value is a copy of the third parameter from the -** previous call, if any, or 0. -** -** ^The [sqlite3_wal_autocheckpoint()] interface and the -** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and -** will overwrite any prior [sqlite3_wal_hook()] settings. -** -** ^If a write-ahead log callback is set using this function then -** [sqlite3_wal_checkpoint_v2()] or [PRAGMA wal_checkpoint] -** should be invoked periodically to keep the write-ahead log file -** from growing without bound. -** -** ^Passing a NULL pointer for the callback disables automatic -** checkpointing entirely. To re-enable the default behavior, call -** sqlite3_wal_autocheckpoint(db,1000) or use [PRAGMA wal_checkpoint]. +** A single database handle may have at most a single write-ahead log callback +** registered at one time. ^Calling [sqlite3_wal_hook()] replaces any +** previously registered write-ahead log callback. ^The return value is +** a copy of the third parameter from the previous call, if any, or 0. +** ^Note that the [sqlite3_wal_autocheckpoint()] interface and the +** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and will +** overwrite any prior [sqlite3_wal_hook()] settings. */ SQLITE_API void *sqlite3_wal_hook( sqlite3*, @@ -9898,7 +9807,7 @@ SQLITE_API void *sqlite3_wal_hook( ** to automatically [checkpoint] ** after committing a transaction if there are N or ** more frames in the [write-ahead log] file. ^Passing zero or -** a negative value as the N parameter disables automatic +** a negative value as the nFrame parameter disables automatic ** checkpoints entirely. ** ** ^The callback registered by this function replaces any existing callback @@ -9914,10 +9823,9 @@ SQLITE_API void *sqlite3_wal_hook( ** ** ^Every new [database connection] defaults to having the auto-checkpoint ** enabled with a threshold of 1000 or [SQLITE_DEFAULT_WAL_AUTOCHECKPOINT] -** pages. -** -** ^The use of this interface is only necessary if the default setting -** is found to be suboptimal for a particular application. +** pages. The use of this interface +** is only necessary if the default setting is found to be suboptimal +** for a particular application. */ SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N); @@ -9982,11 +9890,6 @@ SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb); ** ^This mode works the same way as SQLITE_CHECKPOINT_RESTART with the ** addition that it also truncates the log file to zero bytes just prior ** to a successful return. -** -** <dt>SQLITE_CHECKPOINT_NOOP<dd> -** ^This mode always checkpoints zero frames. The only reason to invoke -** a NOOP checkpoint is to access the values returned by -** sqlite3_wal_checkpoint_v2() via output parameters *pnLog and *pnCkpt. ** </dl> ** ** ^If pnLog is not NULL, then *pnLog is set to the total number of frames in @@ -10057,7 +9960,6 @@ SQLITE_API int sqlite3_wal_checkpoint_v2( ** See the [sqlite3_wal_checkpoint_v2()] documentation for details on the ** meaning of each of these checkpoint modes. */ -#define SQLITE_CHECKPOINT_NOOP -1 /* Do no work at all */ #define SQLITE_CHECKPOINT_PASSIVE 0 /* Do as much as possible w/o blocking */ #define SQLITE_CHECKPOINT_FULL 1 /* Wait for writers, then checkpoint */ #define SQLITE_CHECKPOINT_RESTART 2 /* Like FULL but wait for readers */ @@ -10885,7 +10787,7 @@ typedef struct sqlite3_snapshot { ** The [sqlite3_snapshot_get()] interface is only available when the ** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used. */ -SQLITE_API int sqlite3_snapshot_get( +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_get( sqlite3 *db, const char *zSchema, sqlite3_snapshot **ppSnapshot @@ -10934,7 +10836,7 @@ SQLITE_API int sqlite3_snapshot_get( ** The [sqlite3_snapshot_open()] interface is only available when the ** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used. */ -SQLITE_API int sqlite3_snapshot_open( +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_open( sqlite3 *db, const char *zSchema, sqlite3_snapshot *pSnapshot @@ -10951,7 +10853,7 @@ SQLITE_API int sqlite3_snapshot_open( ** The [sqlite3_snapshot_free()] interface is only available when the ** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used. */ -SQLITE_API void sqlite3_snapshot_free(sqlite3_snapshot*); +SQLITE_API SQLITE_EXPERIMENTAL void sqlite3_snapshot_free(sqlite3_snapshot*); /* ** CAPI3REF: Compare the ages of two snapshot handles. @@ -10978,7 +10880,7 @@ SQLITE_API void sqlite3_snapshot_free(sqlite3_snapshot*); ** This interface is only available if SQLite is compiled with the ** [SQLITE_ENABLE_SNAPSHOT] option. */ -SQLITE_API int sqlite3_snapshot_cmp( +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp( sqlite3_snapshot *p1, sqlite3_snapshot *p2 ); @@ -11006,7 +10908,7 @@ SQLITE_API int sqlite3_snapshot_cmp( ** This interface is only available if SQLite is compiled with the ** [SQLITE_ENABLE_SNAPSHOT] option. */ -SQLITE_API int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb); +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb); /* ** CAPI3REF: Serialize a database @@ -11080,13 +10982,12 @@ SQLITE_API unsigned char *sqlite3_serialize( ** ** The sqlite3_deserialize(D,S,P,N,M,F) interface causes the ** [database connection] D to disconnect from database S and then -** reopen S as an in-memory database based on the serialization -** contained in P. If S is a NULL pointer, the main database is -** used. The serialized database P is N bytes in size. M is the size -** of the buffer P, which might be larger than N. If M is larger than -** N, and the SQLITE_DESERIALIZE_READONLY bit is not set in F, then -** SQLite is permitted to add content to the in-memory database as -** long as the total size does not exceed M bytes. +** reopen S as an in-memory database based on the serialization contained +** in P. The serialized database P is N bytes in size. M is the size of +** the buffer P, which might be larger than N. If M is larger than N, and +** the SQLITE_DESERIALIZE_READONLY bit is not set in F, then SQLite is +** permitted to add content to the in-memory database as long as the total +** size does not exceed M bytes. ** ** If the SQLITE_DESERIALIZE_FREEONCLOSE bit is set in F, then SQLite will ** invoke sqlite3_free() on the serialization buffer when the database @@ -11154,54 +11055,6 @@ SQLITE_API int sqlite3_deserialize( #define SQLITE_DESERIALIZE_READONLY 4 /* Database is read-only */ /* -** CAPI3REF: Bind array values to the CARRAY table-valued function -** -** The sqlite3_carray_bind(S,I,P,N,F,X) interface binds an array value to -** one of the first argument of the [carray() table-valued function]. The -** S parameter is a pointer to the [prepared statement] that uses the carray() -** functions. I is the parameter index to be bound. P is a pointer to the -** array to be bound, and N is the number of eements in the array. The -** F argument is one of constants [SQLITE_CARRAY_INT32], [SQLITE_CARRAY_INT64], -** [SQLITE_CARRAY_DOUBLE], [SQLITE_CARRAY_TEXT], or [SQLITE_CARRAY_BLOB] to -** indicate the datatype of the array being bound. The X argument is not a -** NULL pointer, then SQLite will invoke the function X on the P parameter -** after it has finished using P, even if the call to -** sqlite3_carray_bind() fails. The special-case finalizer -** SQLITE_TRANSIENT has no effect here. -*/ -SQLITE_API int sqlite3_carray_bind( - sqlite3_stmt *pStmt, /* Statement to be bound */ - int i, /* Parameter index */ - void *aData, /* Pointer to array data */ - int nData, /* Number of data elements */ - int mFlags, /* CARRAY flags */ - void (*xDel)(void*) /* Destructor for aData */ -); - -/* -** CAPI3REF: Datatypes for the CARRAY table-valued function -** -** The fifth argument to the [sqlite3_carray_bind()] interface musts be -** one of the following constants, to specify the datatype of the array -** that is being bound into the [carray table-valued function]. -*/ -#define SQLITE_CARRAY_INT32 0 /* Data is 32-bit signed integers */ -#define SQLITE_CARRAY_INT64 1 /* Data is 64-bit signed integers */ -#define SQLITE_CARRAY_DOUBLE 2 /* Data is doubles */ -#define SQLITE_CARRAY_TEXT 3 /* Data is char* */ -#define SQLITE_CARRAY_BLOB 4 /* Data is struct iovec */ - -/* -** Versions of the above #defines that omit the initial SQLITE_, for -** legacy compatibility. -*/ -#define CARRAY_INT32 0 /* Data is 32-bit signed integers */ -#define CARRAY_INT64 1 /* Data is 64-bit signed integers */ -#define CARRAY_DOUBLE 2 /* Data is doubles */ -#define CARRAY_TEXT 3 /* Data is char* */ -#define CARRAY_BLOB 4 /* Data is struct iovec */ - -/* ** Undo the hack that converts floating point types to integer for ** builds on processors without floating point support. */ @@ -12460,32 +12313,14 @@ SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*); ** update the "main" database attached to handle db with the changes found in ** the changeset passed via the second and third arguments. ** -** All changes made by these functions are enclosed in a savepoint transaction. -** If any other error (aside from a constraint failure when attempting to -** write to the target database) occurs, then the savepoint transaction is -** rolled back, restoring the target database to its original state, and an -** SQLite error code returned. Additionally, starting with version 3.51.0, -** an error code and error message that may be accessed using the -** [sqlite3_errcode()] and [sqlite3_errmsg()] APIs are left in the database -** handle. -** ** The fourth argument (xFilter) passed to these functions is the "filter -** callback". This may be passed NULL, in which case all changes in the -** changeset are applied to the database. For sqlite3changeset_apply() and -** sqlite3_changeset_apply_v2(), if it is not NULL, then it is invoked once -** for each table affected by at least one change in the changeset. In this -** case the table name is passed as the second argument, and a copy of -** the context pointer passed as the sixth argument to apply() or apply_v2() -** as the first. If the "filter callback" returns zero, then no attempt is -** made to apply any changes to the table. Otherwise, if the return value is -** non-zero, all changes related to the table are attempted. -** -** For sqlite3_changeset_apply_v3(), the xFilter callback is invoked once -** per change. The second argument in this case is an sqlite3_changeset_iter -** that may be queried using the usual APIs for the details of the current -** change. If the "filter callback" returns zero in this case, then no attempt -** is made to apply the current change. If it returns non-zero, the change -** is applied. +** callback". If it is not NULL, then for each table affected by at least one +** change in the changeset, the filter callback is invoked with +** the table name as the second argument, and a copy of the context pointer +** passed as the sixth argument as the first. If the "filter callback" +** returns zero, then no attempt is made to apply any changes to the table. +** Otherwise, if the return value is non-zero or the xFilter argument to +** is NULL, all changes related to the table are attempted. ** ** For each table that is not excluded by the filter callback, this function ** tests that the target database contains a compatible table. A table is @@ -12506,11 +12341,11 @@ SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*); ** one such warning is issued for each table in the changeset. ** ** For each change for which there is a compatible table, an attempt is made -** to modify the table contents according to each UPDATE, INSERT or DELETE -** change that is not excluded by a filter callback. If a change cannot be -** applied cleanly, the conflict handler function passed as the fifth argument -** to sqlite3changeset_apply() may be invoked. A description of exactly when -** the conflict handler is invoked for each type of change is below. +** to modify the table contents according to the UPDATE, INSERT or DELETE +** change. If a change cannot be applied cleanly, the conflict handler +** function passed as the fifth argument to sqlite3changeset_apply() may be +** invoked. A description of exactly when the conflict handler is invoked for +** each type of change is below. ** ** Unlike the xFilter argument, xConflict may not be passed NULL. The results ** of passing anything other than a valid function pointer as the xConflict @@ -12606,6 +12441,12 @@ SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*); ** This can be used to further customize the application's conflict ** resolution strategy. ** +** All changes made by these functions are enclosed in a savepoint transaction. +** If any other error (aside from a constraint failure when attempting to +** write to the target database) occurs, then the savepoint transaction is +** rolled back, restoring the target database to its original state, and an +** SQLite error code returned. +** ** If the output parameters (ppRebase) and (pnRebase) are non-NULL and ** the input is a changeset (not a patchset), then sqlite3changeset_apply_v2() ** may set (*ppRebase) to point to a "rebase" that may be used with the @@ -12655,23 +12496,6 @@ SQLITE_API int sqlite3changeset_apply_v2( void **ppRebase, int *pnRebase, /* OUT: Rebase data */ int flags /* SESSION_CHANGESETAPPLY_* flags */ ); -SQLITE_API int sqlite3changeset_apply_v3( - sqlite3 *db, /* Apply change to "main" db of this handle */ - int nChangeset, /* Size of changeset in bytes */ - void *pChangeset, /* Changeset blob */ - int(*xFilter)( - void *pCtx, /* Copy of sixth arg to _apply() */ - sqlite3_changeset_iter *p /* Handle describing change */ - ), - int(*xConflict)( - void *pCtx, /* Copy of sixth arg to _apply() */ - int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ - sqlite3_changeset_iter *p /* Handle describing change and conflict */ - ), - void *pCtx, /* First argument passed to xConflict */ - void **ppRebase, int *pnRebase, /* OUT: Rebase data */ - int flags /* SESSION_CHANGESETAPPLY_* flags */ -); /* ** CAPI3REF: Flags for sqlite3changeset_apply_v2 @@ -13091,23 +12915,6 @@ SQLITE_API int sqlite3changeset_apply_v2_strm( void **ppRebase, int *pnRebase, int flags ); -SQLITE_API int sqlite3changeset_apply_v3_strm( - sqlite3 *db, /* Apply change to "main" db of this handle */ - int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */ - void *pIn, /* First arg for xInput */ - int(*xFilter)( - void *pCtx, /* Copy of sixth arg to _apply() */ - sqlite3_changeset_iter *p - ), - int(*xConflict)( - void *pCtx, /* Copy of sixth arg to _apply() */ - int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ - sqlite3_changeset_iter *p /* Handle describing change and conflict */ - ), - void *pCtx, /* First argument passed to xConflict */ - void **ppRebase, int *pnRebase, - int flags -); SQLITE_API int sqlite3changeset_concat_strm( int (*xInputA)(void *pIn, void *pData, int *pnData), void *pInA, diff --git a/third_party/sqlite3/vendor.sh b/third_party/sqlite3/vendor.sh @@ -68,9 +68,9 @@ rm -f "preprocessed.zip" # If the extension is hosted on Github or other supported platforms, you want # to use `mach vendor` for it, rather than manually downloading it here. -# The same is valid for SQLite owned extensions that don't need preprocessing. -# In general anything that is in sqlite-src archive is also in the official -# Github repo (https://github.com/sqlite/sqlite). +# The same is valid for SQLite owned extensions that don't need preprocessing +# (e.g. carray.c/h). In general anything that is in sqlite-src archive is also +# in their official Github repo. echo "" echo "Update complete, please commit and check in your changes." diff --git a/toolkit/xre/AutoSQLiteLifetime.cpp b/toolkit/xre/AutoSQLiteLifetime.cpp @@ -6,6 +6,7 @@ #include "nsDebug.h" #include "AutoSQLiteLifetime.h" #include "sqlite3.h" +#include "sqlite3_static_ext.h" #include "mozilla/Atomics.h" #ifdef MOZ_MEMORY @@ -141,6 +142,11 @@ void AutoSQLiteLifetime::Init() { // have figured the impact on our consumers and memory. ::sqlite3_config(SQLITE_CONFIG_PAGECACHE, NULL, 0, 0); + // Load the carray extension. + DebugOnly<int> srv = + ::sqlite3_auto_extension((void (*)(void))sqlite3_carray_init); + MOZ_ASSERT(srv == SQLITE_OK, "Should succeed loading carray extension"); + // Explicitly initialize sqlite3. Although this is implicitly called by // various sqlite3 functions (and the sqlite3_open calls in our case), // the documentation suggests calling this directly. So we do.