aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/alter.c4
-rw-r--r--src/bitvec.c114
-rw-r--r--src/btree.c63
-rw-r--r--src/btree.h1
-rw-r--r--src/build.c15
-rw-r--r--src/dbpage.c13
-rw-r--r--src/expr.c272
-rw-r--r--src/func.c6
-rw-r--r--src/insert.c5
-rw-r--r--src/json.c18
-rw-r--r--src/loadext.c4
-rw-r--r--src/main.c2
-rw-r--r--src/os_unix.c11
-rw-r--r--src/os_win.c125
-rw-r--r--src/pager.c9
-rw-r--r--src/parse.y19
-rw-r--r--src/printf.c8
-rw-r--r--src/resolve.c5
-rw-r--r--src/select.c169
-rw-r--r--src/shell.c.in76
-rw-r--r--src/sqlite.h.in274
-rw-r--r--src/sqlite3ext.h4
-rw-r--r--src/sqliteInt.h57
-rw-r--r--src/tclsqlite.c142
-rw-r--r--src/test1.c5
-rw-r--r--src/test_fs.c12
-rw-r--r--src/test_windirent.c162
-rw-r--r--src/test_windirent.h158
-rw-r--r--src/tokenize.c2
-rw-r--r--src/utf.c2
-rw-r--r--src/vacuum.c3
-rw-r--r--src/vdbe.c107
-rw-r--r--src/vdbe.h2
-rw-r--r--src/vdbeInt.h4
-rw-r--r--src/vdbeapi.c7
-rw-r--r--src/vdbeaux.c26
-rw-r--r--src/vdbeblob.c33
-rw-r--r--src/vdbesort.c16
-rw-r--r--src/wal.c7
-rw-r--r--src/where.c56
-rw-r--r--src/whereInt.h4
-rw-r--r--src/wherecode.c140
-rw-r--r--src/whereexpr.c59
43 files changed, 1292 insertions, 929 deletions
diff --git a/src/alter.c b/src/alter.c
index f3108cbf9..a7255e75e 100644
--- a/src/alter.c
+++ b/src/alter.c
@@ -1223,10 +1223,10 @@ static int renameEditSql(
}
assert( nQuot>=nNew && nSql>=0 && nNew>=0 );
- zOut = sqlite3DbMallocZero(db, (u64)(nSql + pRename->nList*nQuot + 1));
+ zOut = sqlite3DbMallocZero(db, (u64)nSql + pRename->nList*(u64)nQuot + 1);
}else{
assert( nSql>0 );
- zOut = (char*)sqlite3DbMallocZero(db, (u64)(nSql*2+1) * 3);
+ zOut = (char*)sqlite3DbMallocZero(db, (2*(u64)nSql + 1) * 3);
if( zOut ){
zBuf1 = &zOut[nSql*2+1];
zBuf2 = &zOut[nSql*4+2];
diff --git a/src/bitvec.c b/src/bitvec.c
index 30c4dc7b8..7c5fa71d9 100644
--- a/src/bitvec.c
+++ b/src/bitvec.c
@@ -107,6 +107,7 @@ 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
@@ -216,7 +217,9 @@ bitvec_set_rehash:
}else{
memcpy(aiValues, p->u.aHash, sizeof(p->u.aHash));
memset(p->u.apSub, 0, sizeof(p->u.apSub));
- p->iDivisor = (p->iSize + BITVEC_NPTR - 1)/BITVEC_NPTR;
+ p->iDivisor = p->iSize/BITVEC_NPTR;
+ if( (p->iSize%BITVEC_NPTR)!=0 ) p->iDivisor++;
+ if( p->iDivisor<BITVEC_NBIT ) p->iDivisor = BITVEC_NBIT;
rc = sqlite3BitvecSet(p, i);
for(j=0; j<BITVEC_NINT; j++){
if( aiValues[j] ) rc |= sqlite3BitvecSet(p, aiValues[j]);
@@ -293,6 +296,52 @@ 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);
+ }
+ }
+}
+void sqlite3ShowBitvec(Bitvec *p){
+ showBitvec(p, 0, 0);
+}
+#endif
+
#ifndef SQLITE_UNTESTABLE
/*
** Let V[] be an array of unsigned characters sufficient to hold
@@ -304,6 +353,7 @@ u32 sqlite3BitvecSize(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.
**
@@ -312,7 +362,7 @@ u32 sqlite3BitvecSize(Bitvec *p){
** by 0, 1, or 3 operands, depending on the opcode. Another
** opcode follows immediately after the last operand.
**
-** There are 6 opcodes numbered from 0 through 5. 0 is the
+** There are opcodes numbered starting with 0. 0 is the
** "halt" opcode and causes the test to end.
**
** 0 Halt and return the number of errors
@@ -321,18 +371,25 @@ u32 sqlite3BitvecSize(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.
+** 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.
**
** 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.
*/
int sqlite3BitvecBuiltinTest(int sz, int *aOp){
Bitvec *pBitvec = 0;
@@ -343,10 +400,15 @@ int sqlite3BitvecBuiltinTest(int sz, int *aOp){
/* Allocate the Bitvec to be tested and a linear array of
** bits to act as the reference */
- pBitvec = sqlite3BitvecCreate( sz );
- pV = sqlite3MallocZero( (7+(i64)sz)/8 + 1 );
+ if( sz<=0 ){
+ pBitvec = sqlite3BitvecCreate( 2*(unsigned)(-sz) );
+ pV = 0;
+ }else{
+ pBitvec = sqlite3BitvecCreate( sz );
+ pV = sqlite3MallocZero( (7+(i64)sz)/8 + 1 );
+ }
pTmpSpace = sqlite3_malloc64(BITVEC_SZ);
- if( pBitvec==0 || pV==0 || pTmpSpace==0 ) goto bitvec_end;
+ if( pBitvec==0 || pTmpSpace==0 || (pV==0 && sz>0) ) goto bitvec_end;
/* NULL pBitvec tests */
sqlite3BitvecSet(0, 1);
@@ -355,6 +417,24 @@ 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:
@@ -376,12 +456,12 @@ int sqlite3BitvecBuiltinTest(int sz, int *aOp){
pc += nx;
i = (i & 0x7fffffff)%sz;
if( (op & 1)!=0 ){
- SETBIT(pV, (i+1));
+ if( pV ) SETBIT(pV, (i+1));
if( op!=5 ){
if( sqlite3BitvecSet(pBitvec, i+1) ) goto bitvec_end;
}
}else{
- CLEARBIT(pV, (i+1));
+ if( pV ) CLEARBIT(pV, (i+1));
sqlite3BitvecClear(pBitvec, i+1, pTmpSpace);
}
}
@@ -391,14 +471,18 @@ int sqlite3BitvecBuiltinTest(int sz, int *aOp){
** match (rc==0). Change rc to non-zero if a discrepancy
** is found.
*/
- 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;
+ 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;
+ }
}
+ }else{
+ rc = 0;
}
/* Free allocated structure */
diff --git a/src/btree.c b/src/btree.c
index 1bd59a1b1..a931b0d12 100644
--- a/src/btree.c
+++ b/src/btree.c
@@ -872,7 +872,7 @@ static int btreeMoveto(
assert( nKey==(i64)(int)nKey );
pIdxKey = sqlite3VdbeAllocUnpackedRecord(pKeyInfo);
if( pIdxKey==0 ) return SQLITE_NOMEM_BKPT;
- sqlite3VdbeRecordUnpack(pKeyInfo, (int)nKey, pKey, pIdxKey);
+ sqlite3VdbeRecordUnpack((int)nKey, pKey, pIdxKey);
if( pIdxKey->nField==0 || pIdxKey->nField>pKeyInfo->nAllField ){
rc = SQLITE_CORRUPT_BKPT;
}else{
@@ -1929,10 +1929,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 <= pPage->pBt->usableSize );
+ assert( CORRUPT_DB || iEnd <= (int)pPage->pBt->usableSize );
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
assert( iSize>=4 ); /* Minimum cell size is 4 */
- assert( CORRUPT_DB || iStart<=pPage->pBt->usableSize-4 );
+ assert( CORRUPT_DB || iStart<=(int)pPage->pBt->usableSize-4 );
/* The list of freeblocks must be in ascending order. Find the
** spot on the list where iStart should be inserted.
@@ -2856,6 +2856,7 @@ static int removeFromSharingList(BtShared *pBt){
sqlite3_mutex_leave(pMainMtx);
return removed;
#else
+ UNUSED_PARAMETER( pBt );
return 1;
#endif
}
@@ -3073,6 +3074,10 @@ int sqlite3BtreeSetPageSize(Btree *p, int pageSize, int nReserve, int iFix){
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);
@@ -3697,6 +3702,13 @@ static SQLITE_NOINLINE int btreeBeginTrans(
(void)sqlite3PagerWalWriteLock(pPager, 0);
unlockBtreeIfUnused(pBt);
}
+#if defined(SQLITE_ENABLE_SETLK_TIMEOUT)
+ if( rc==SQLITE_BUSY_TIMEOUT ){
+ /* If a blocking lock timed out, break out of the loop here so that
+ ** the busy-handler is not invoked. */
+ break;
+ }
+#endif
}while( (rc&0xFF)==SQLITE_BUSY && pBt->inTransaction==TRANS_NONE &&
btreeInvokeBusyHandler(pBt) );
sqlite3PagerWalDb(pPager, 0);
@@ -5655,6 +5667,30 @@ 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.
+*/
+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.
@@ -5874,8 +5910,8 @@ moveto_table_finish:
}
/*
-** Compare the "idx"-th cell on the page the cursor pCur is currently
-** pointing to to pIdxKey using xRecordCompare. Return negative or
+** Compare the "idx"-th cell on the page pPage against the key
+** pointing to by pIdxKey using xRecordCompare. Return negative or
** zero if the cell is less than or equal pIdxKey. Return positive
** if unknown.
**
@@ -5890,12 +5926,11 @@ moveto_table_finish:
** a positive value as that will cause the optimization to be skipped.
*/
static int indexCellCompare(
- BtCursor *pCur,
+ MemPage *pPage,
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);
@@ -6004,14 +6039,14 @@ int sqlite3BtreeIndexMoveto(
){
int c;
if( pCur->ix==pCur->pPage->nCell-1
- && (c = indexCellCompare(pCur, pCur->ix, pIdxKey, xRecordCompare))<=0
+ && (c = indexCellCompare(pCur->pPage,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, 0, pIdxKey, xRecordCompare)<=0
+ && indexCellCompare(pCur->pPage, 0, pIdxKey, xRecordCompare)<=0
&& pIdxKey->errCode==SQLITE_OK
){
pCur->curFlags &= ~(BTCF_ValidOvfl|BTCF_AtLast);
@@ -6228,7 +6263,7 @@ i64 sqlite3BtreeRowCountEst(BtCursor *pCur){
n = pCur->pPage->nCell;
for(i=0; i<pCur->iPage; i++){
- n *= pCur->apPage[i]->nCell;
+ n *= pCur->apPage[i]->nCell+1;
}
return n;
}
@@ -8685,7 +8720,12 @@ 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 = (nNew>nOld ? apNew : apOld)[nOld-1];
+ MemPage *pOld;
+ if( nNew>nOld ){
+ pOld = apNew[nOld-1];
+ }else{
+ pOld = apOld[nOld-1];
+ }
memcpy(&apNew[nNew-1]->aData[8], &pOld->aData[8], 4);
}
@@ -11317,6 +11357,7 @@ void *sqlite3BtreeSchema(Btree *p, int nBytes, void(*xFree)(void *)){
*/
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);
diff --git a/src/btree.h b/src/btree.h
index 241261dc6..96f4c4c60 100644
--- a/src/btree.h
+++ b/src/btree.h
@@ -317,6 +317,7 @@ struct BtreePayload {
int sqlite3BtreeInsert(BtCursor*, const BtreePayload *pPayload,
int flags, int seekResult);
int sqlite3BtreeFirst(BtCursor*, int *pRes);
+int sqlite3BtreeIsEmpty(BtCursor *pCur, int *pRes);
int sqlite3BtreeLast(BtCursor*, int *pRes);
int sqlite3BtreeNext(BtCursor*, int flags);
int sqlite3BtreeEof(BtCursor*);
diff --git a/src/build.c b/src/build.c
index 5bd3aac3c..5495cef18 100644
--- a/src/build.c
+++ b/src/build.c
@@ -4219,7 +4219,6 @@ void sqlite3CreateIndex(
assert( j<=0x7fff );
if( j<0 ){
j = pTab->iPKey;
- pIndex->bIdxRowid = 1;
}else{
if( pTab->aCol[j].notNull==0 ){
pIndex->uniqNotNull = 0;
@@ -5138,16 +5137,22 @@ void sqlite3SrcListIndexedBy(Parse *pParse, SrcList *p, Token *pIndexedBy){
** are deleted by this function.
*/
SrcList *sqlite3SrcListAppendList(Parse *pParse, SrcList *p1, SrcList *p2){
- assert( p1 && p1->nSrc==1 );
+ assert( p1 );
+ assert( p2 || pParse->nErr );
+ assert( p2==0 || p2->nSrc>=1 );
+ testcase( p1->nSrc==0 );
if( p2 ){
- SrcList *pNew = sqlite3SrcListEnlarge(pParse, p1, p2->nSrc, 1);
+ int nOld = p1->nSrc;
+ SrcList *pNew = sqlite3SrcListEnlarge(pParse, p1, p2->nSrc, nOld);
if( pNew==0 ){
sqlite3SrcListDelete(pParse->db, p2);
}else{
p1 = pNew;
- memcpy(&p1->a[1], p2->a, p2->nSrc*sizeof(SrcItem));
+ 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);
sqlite3DbFree(pParse->db, p2);
- p1->a[0].fg.jointype |= (JT_LTORJ & p1->a[1].fg.jointype);
}
}
return p1;
diff --git a/src/dbpage.c b/src/dbpage.c
index f9fdcc5a3..4e2addad9 100644
--- a/src/dbpage.c
+++ b/src/dbpage.c
@@ -227,7 +227,7 @@ static int dbpageEof(sqlite3_vtab_cursor *pCursor){
** idxStr is not used
*/
static int dbpageFilter(
- sqlite3_vtab_cursor *pCursor,
+ sqlite3_vtab_cursor *pCursor,
int idxNum, const char *idxStr,
int argc, sqlite3_value **argv
){
@@ -237,10 +237,11 @@ static int dbpageFilter(
sqlite3 *db = pTab->db;
Btree *pBt;
- (void)idxStr;
-
+ UNUSED_PARAMETER(idxStr);
+ UNUSED_PARAMETER(argc);
+
/* Default setting is no rows of result */
- pCsr->pgno = 1;
+ pCsr->pgno = 1;
pCsr->mxPgno = 0;
if( idxNum & 2 ){
@@ -275,8 +276,8 @@ static int dbpageFilter(
}
static int dbpageColumn(
- sqlite3_vtab_cursor *pCursor,
- sqlite3_context *ctx,
+ sqlite3_vtab_cursor *pCursor,
+ sqlite3_context *ctx,
int i
){
DbpageCursor *pCsr = (DbpageCursor *)pCursor;
diff --git a/src/expr.c b/src/expr.c
index 12c94362f..3f040309a 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -73,7 +73,9 @@ char sqlite3ExprAffinity(const Expr *pExpr){
pExpr->pLeft->x.pSelect->pEList->a[pExpr->iColumn].pExpr
);
}
- if( op==TK_VECTOR ){
+ if( op==TK_VECTOR
+ || (op==TK_FUNCTION && pExpr->affExpr==SQLITE_AFF_DEFER)
+ ){
assert( ExprUseXList(pExpr) );
return sqlite3ExprAffinity(pExpr->x.pList->a[0].pExpr);
}
@@ -266,7 +268,9 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, const Expr *pExpr){
p = p->pLeft;
continue;
}
- if( op==TK_VECTOR ){
+ if( op==TK_VECTOR
+ || (op==TK_FUNCTION && p->affExpr==SQLITE_AFF_DEFER)
+ ){
assert( ExprUseXList(p) );
p = p->x.pList->a[0].pExpr;
continue;
@@ -1140,7 +1144,7 @@ Expr *sqlite3ExprAnd(Parse *pParse, Expr *pLeft, Expr *pRight){
return pLeft;
}else{
u32 f = pLeft->flags | pRight->flags;
- if( (f&(EP_OuterON|EP_InnerON|EP_IsFalse))==EP_IsFalse
+ if( (f&(EP_OuterON|EP_InnerON|EP_IsFalse|EP_HasFunc))==EP_IsFalse
&& !IN_RENAME_OBJECT
){
sqlite3ExprDeferredDelete(pParse, pLeft);
@@ -2370,6 +2374,86 @@ 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 check the left operand do
+ ** an IsNull 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:
@@ -3813,17 +3897,23 @@ 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 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;
+ /* 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;
+ }
}else{
/* If there is no pre-existing limit add a limit of 1 */
pLimit = sqlite3Expr(pParse->db, TK_INTEGER, "1");
@@ -4265,7 +4355,12 @@ void sqlite3ExprCodeGeneratedColumn(
iAddr = 0;
}
sqlite3ExprCodeCopy(pParse, sqlite3ColumnExpr(pTab,pCol), regOut);
- if( pCol->affinity>=SQLITE_AFF_TEXT ){
+ 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 ){
sqlite3VdbeAddOp4(v, OP_Affinity, regOut, 1, 0, &pCol->affinity, 1);
}
if( iAddr ) sqlite3VdbeJumpHere(v, iAddr);
@@ -4952,11 +5047,17 @@ 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{
- r1 = sqlite3ExprCodeTemp(pParse, pLeft, &regFree1);
- r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
+ if( ExprHasProperty(pExpr, EP_Subquery) && p5!=SQLITE_NULLEQ ){
+ addrIsNull = exprComputeOperands(pParse, pExpr,
+ &r1, &r2, &regFree1, &regFree2);
+ }else{
+ r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
+ r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
+ }
sqlite3VdbeAddOp2(v, OP_Integer, 1, inReg);
codeCompare(pParse, pLeft, pExpr->pRight, op, r1, r2,
sqlite3VdbeCurrentAddr(v)+2, p5,
@@ -4971,9 +5072,15 @@ 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 );
+
}
break;
}
@@ -4989,6 +5096,7 @@ 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 );
@@ -5000,11 +5108,23 @@ 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 );
- r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
- r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
+ if( ExprHasProperty(pExpr, EP_Subquery) ){
+ addrIsNull = exprComputeOperands(pParse, pExpr,
+ &r1, &r2, &regFree1, &regFree2);
+ }else{
+ r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
+ r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
+ addrIsNull = 0;
+ }
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: {
@@ -5853,17 +5973,27 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
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{
- testcase( jumpIfNull==0 );
- sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull);
- sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
+ 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);
+ }
}
break;
}
@@ -5902,10 +6032,16 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
case TK_GE:
case TK_NE:
case TK_EQ: {
+ int addrIsNull;
if( sqlite3ExprIsVector(pExpr->pLeft) ) goto default_expr;
- testcase( jumpIfNull==0 );
- r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
- r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
+ if( ExprHasProperty(pExpr, EP_Subquery) && jumpIfNull!=SQLITE_NULLEQ ){
+ addrIsNull = exprComputeOperands(pParse, pExpr,
+ &r1, &r2, &regFree1, &regFree2);
+ }else{
+ r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
+ r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
+ addrIsNull = 0;
+ }
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);
@@ -5920,6 +6056,13 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
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:
@@ -6027,17 +6170,27 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
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{
- int d2 = sqlite3VdbeMakeLabel(pParse);
- testcase( jumpIfNull==0 );
- sqlite3ExprIfTrue(pParse, pExpr->pLeft, d2,
- jumpIfNull^SQLITE_JUMPIFNULL);
- sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
- sqlite3VdbeResolveLabel(v, d2);
+ 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);
+ }
}
break;
}
@@ -6079,10 +6232,16 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
case TK_GE:
case TK_NE:
case TK_EQ: {
+ int addrIsNull;
if( sqlite3ExprIsVector(pExpr->pLeft) ) goto default_expr;
- testcase( jumpIfNull==0 );
- r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
- r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
+ if( ExprHasProperty(pExpr, EP_Subquery) && jumpIfNull!=SQLITE_NULLEQ ){
+ addrIsNull = exprComputeOperands(pParse, pExpr,
+ &r1, &r2, &regFree1, &regFree2);
+ }else{
+ r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
+ r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
+ addrIsNull = 0;
+ }
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);
@@ -6097,6 +6256,13 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
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:
@@ -7006,7 +7172,9 @@ static void findOrCreateAggInfoColumn(
){
struct AggInfo_col *pCol;
int k;
+ int mxTerm = pParse->db->aLimit[SQLITE_LIMIT_COLUMN];
+ assert( mxTerm <= SMXV(i16) );
assert( pAggInfo->iFirstReg==0 );
pCol = pAggInfo->aCol;
for(k=0; k<pAggInfo->nColumn; k++, pCol++){
@@ -7024,6 +7192,10 @@ static void findOrCreateAggInfoColumn(
assert( pParse->db->mallocFailed );
return;
}
+ if( k>mxTerm ){
+ sqlite3ErrorMsg(pParse, "more than %d aggregate terms", mxTerm);
+ k = mxTerm;
+ }
pCol = &pAggInfo->aCol[k];
assert( ExprUseYTab(pExpr) );
pCol->pTab = pExpr->y.pTab;
@@ -7057,6 +7229,7 @@ fix_up_expr:
if( pExpr->op==TK_COLUMN ){
pExpr->op = TK_AGG_COLUMN;
}
+ assert( k <= SMXV(pExpr->iAgg) );
pExpr->iAgg = (i16)k;
}
@@ -7141,13 +7314,19 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
** function that is already in the pAggInfo structure
*/
struct AggInfo_func *pItem = pAggInfo->aFunc;
+ int mxTerm = pParse->db->aLimit[SQLITE_LIMIT_COLUMN];
+ assert( mxTerm <= SMXV(i16) );
for(i=0; i<pAggInfo->nFunc; i++, pItem++){
if( NEVER(pItem->pFExpr==pExpr) ) break;
if( sqlite3ExprCompare(0, pItem->pFExpr, pExpr, -1)==0 ){
break;
}
}
- if( i>=pAggInfo->nFunc ){
+ if( i>mxTerm ){
+ sqlite3ErrorMsg(pParse, "more than %d aggregate terms", mxTerm);
+ i = mxTerm;
+ assert( i<pAggInfo->nFunc );
+ }else if( i>=pAggInfo->nFunc ){
/* pExpr is original. Make a new entry in pAggInfo->aFunc[]
*/
u8 enc = ENC(pParse->db);
@@ -7201,6 +7380,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
*/
assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) );
ExprSetVVAProperty(pExpr, EP_NoReduce);
+ assert( i <= SMXV(pExpr->iAgg) );
pExpr->iAgg = (i16)i;
pExpr->pAggInfo = pAggInfo;
return WRC_Prune;
diff --git a/src/func.c b/src/func.c
index 9e2839336..b0a1359b7 100644
--- a/src/func.c
+++ b/src/func.c
@@ -1667,7 +1667,7 @@ static void concatFuncCore(
int nSep,
const char *zSep
){
- i64 j, k, n = 0;
+ i64 j, n = 0;
int i;
char *z;
for(i=0; i<argc; i++){
@@ -1681,8 +1681,8 @@ static void concatFuncCore(
}
j = 0;
for(i=0; i<argc; i++){
- k = sqlite3_value_bytes(argv[i]);
- if( k>0 ){
+ if( sqlite3_value_type(argv[i])!=SQLITE_NULL ){
+ int k = sqlite3_value_bytes(argv[i]);
const char *v = (const char*)sqlite3_value_text(argv[i]);
if( v!=0 ){
if( j>0 && nSep>0 ){
diff --git a/src/insert.c b/src/insert.c
index fdd9c8da2..f0c56a7a8 100644
--- a/src/insert.c
+++ b/src/insert.c
@@ -185,12 +185,15 @@ 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;
- sqlite3VdbeAddOp3(v, OP_MakeRecord, pPrev->p1, pPrev->p2, pPrev->p3);
+ p3 = pPrev->p3;
+ pPrev->p3 = 0;
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, pPrev->p1, pPrev->p2, p3);
}else{
/* Insert an isolated OP_Typecheck */
sqlite3VdbeAddOp2(v, OP_TypeCheck, iReg, pTab->nNVCol);
diff --git a/src/json.c b/src/json.c
index ee4cf1cbc..3078be34b 100644
--- a/src/json.c
+++ b/src/json.c
@@ -1285,8 +1285,10 @@ static int jsonBlobChangePayloadSize(
nExtra = 1;
}else if( szType==13 ){
nExtra = 2;
- }else{
+ }else if( szType==14 ){
nExtra = 4;
+ }else{
+ nExtra = 8;
}
if( szPayload<=11 ){
nNeeded = 0;
@@ -4850,18 +4852,20 @@ static void jsonObjectStep(
UNUSED_PARAMETER(argc);
pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr));
if( pStr ){
+ z = (const char*)sqlite3_value_text(argv[0]);
+ n = sqlite3Strlen30(z);
if( pStr->zBuf==0 ){
jsonStringInit(pStr, ctx);
jsonAppendChar(pStr, '{');
- }else if( pStr->nUsed>1 ){
+ }else if( pStr->nUsed>1 && z!=0 ){
jsonAppendChar(pStr, ',');
}
pStr->pCtx = ctx;
- z = (const char*)sqlite3_value_text(argv[0]);
- n = sqlite3Strlen30(z);
- jsonAppendString(pStr, z, n);
- jsonAppendChar(pStr, ':');
- jsonAppendSqlValue(pStr, argv[1]);
+ if( z!=0 ){
+ jsonAppendString(pStr, z, n);
+ jsonAppendChar(pStr, ':');
+ jsonAppendSqlValue(pStr, argv[1]);
+ }
}
}
static void jsonObjectCompute(sqlite3_context *ctx, int isFinal){
diff --git a/src/loadext.c b/src/loadext.c
index 7e0ae2543..40d4f3128 100644
--- a/src/loadext.c
+++ b/src/loadext.c
@@ -517,7 +517,9 @@ static const sqlite3_api_routines sqlite3Apis = {
sqlite3_stmt_explain,
/* Version 3.44.0 and later */
sqlite3_get_clientdata,
- sqlite3_set_clientdata
+ sqlite3_set_clientdata,
+ /* Version 3.50.0 and later */
+ sqlite3_setlk_timeout
};
/* True if x is the directory separator character
diff --git a/src/main.c b/src/main.c
index 9b67de815..0dd9926fe 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1861,6 +1861,7 @@ int sqlite3_setlk_timeout(sqlite3 *db, int ms, int flags){
#endif
if( ms<-1 ) return SQLITE_RANGE;
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ sqlite3_mutex_enter(db->mutex);
db->setlkTimeout = ms;
db->setlkFlags = flags;
sqlite3BtreeEnterAll(db);
@@ -1872,6 +1873,7 @@ int sqlite3_setlk_timeout(sqlite3 *db, int ms, int flags){
}
}
sqlite3BtreeLeaveAll(db);
+ sqlite3_mutex_leave(db->mutex);
#endif
#if !defined(SQLITE_ENABLE_API_ARMOR) && !defined(SQLITE_ENABLE_SETLK_TIMEOUT)
UNUSED_PARAMETER(db);
diff --git a/src/os_unix.c b/src/os_unix.c
index 1146545fe..784bc3517 100644
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -5035,21 +5035,20 @@ static int unixShmLock(
/* Check that, if this to be a blocking lock, no locks that occur later
** in the following list than the lock being obtained are already held:
**
- ** 1. Checkpointer lock (ofst==1).
- ** 2. Write lock (ofst==0).
- ** 3. Read locks (ofst>=3 && ofst<SQLITE_SHM_NLOCK).
+ ** 1. Recovery lock (ofst==2).
+ ** 2. Checkpointer lock (ofst==1).
+ ** 3. Write lock (ofst==0).
+ ** 4. Read locks (ofst>=3 && ofst<SQLITE_SHM_NLOCK).
**
** In other words, if this is a blocking lock, none of the locks that
** occur later in the above list than the lock being obtained may be
** held.
- **
- ** It is not permitted to block on the RECOVER lock.
*/
#if defined(SQLITE_ENABLE_SETLK_TIMEOUT) && defined(SQLITE_DEBUG)
{
u16 lockMask = (p->exclMask|p->sharedMask);
assert( (flags & SQLITE_SHM_UNLOCK) || pDbFd->iBusyTimeout==0 || (
- (ofst!=2) /* not RECOVER */
+ (ofst!=2 || lockMask==0)
&& (ofst!=1 || lockMask==0 || lockMask==2)
&& (ofst!=0 || lockMask<3)
&& (ofst<3 || lockMask<(1<<ofst))
diff --git a/src/os_win.c b/src/os_win.c
index 0dd56af58..c7c923e77 100644
--- a/src/os_win.c
+++ b/src/os_win.c
@@ -2722,7 +2722,11 @@ static int winHandleLockTimeout(
if( res==WAIT_OBJECT_0 ){
ret = TRUE;
}else if( res==WAIT_TIMEOUT ){
+#if SQLITE_ENABLE_SETLK_TIMEOUT==1
rc = SQLITE_BUSY_TIMEOUT;
+#else
+ rc = SQLITE_BUSY;
+#endif
}else{
/* Some other error has occurred */
rc = SQLITE_IOERR_LOCK;
@@ -4208,13 +4212,13 @@ static void *winConvertFromUtf8Filename(const char *zFilename){
if( osCygwin_conv_path && !(winIsDriveLetterAndColon(zFilename)
&& winIsDirSep(zFilename[2])) ){
- int nByte;
+ i64 nByte;
int convertflag = CCP_POSIX_TO_WIN_W;
if( !strchr(zFilename, '/') ) convertflag |= CCP_RELATIVE;
- nByte = (int)osCygwin_conv_path(convertflag,
+ nByte = (i64)osCygwin_conv_path(convertflag,
zFilename, 0, 0);
if( nByte>0 ){
- zConverted = sqlite3MallocZero(nByte+12);
+ zConverted = sqlite3MallocZero(12+(u64)nByte);
if ( zConverted==0 ){
return zConverted;
}
@@ -4533,21 +4537,20 @@ static int winShmLock(
/* Check that, if this to be a blocking lock, no locks that occur later
** in the following list than the lock being obtained are already held:
**
- ** 1. Checkpointer lock (ofst==1).
- ** 2. Write lock (ofst==0).
- ** 3. Read locks (ofst>=3 && ofst<SQLITE_SHM_NLOCK).
+ ** 1. Recovery lock (ofst==2).
+ ** 2. Checkpointer lock (ofst==1).
+ ** 3. Write lock (ofst==0).
+ ** 4. Read locks (ofst>=3 && ofst<SQLITE_SHM_NLOCK).
**
** In other words, if this is a blocking lock, none of the locks that
** occur later in the above list than the lock being obtained may be
** held.
- **
- ** It is not permitted to block on the RECOVER lock.
*/
#if defined(SQLITE_ENABLE_SETLK_TIMEOUT) && defined(SQLITE_DEBUG)
{
u16 lockMask = (p->exclMask|p->sharedMask);
assert( (flags & SQLITE_SHM_UNLOCK) || pDbFd->iBusyTimeout==0 || (
- (ofst!=2) /* not RECOVER */
+ (ofst!=2 || lockMask==0)
&& (ofst!=1 || lockMask==0 || lockMask==2)
&& (ofst!=0 || lockMask<3)
&& (ofst<3 || lockMask<(1<<ofst))
@@ -5097,27 +5100,6 @@ static winVfsAppData winNolockAppData = {
** sqlite3_vfs object.
*/
-#if 0 /* No longer necessary */
-/*
-** Convert a filename from whatever the underlying operating system
-** supports for filenames into UTF-8. Space to hold the result is
-** obtained from malloc and must be freed by the calling function.
-*/
-static char *winConvertToUtf8Filename(const void *zFilename){
- char *zConverted = 0;
- if( osIsNT() ){
- zConverted = winUnicodeToUtf8(zFilename);
- }
-#ifdef SQLITE_WIN32_HAS_ANSI
- else{
- zConverted = winMbcsToUtf8(zFilename, osAreFileApisANSI());
- }
-#endif
- /* caller will handle out of memory */
- return zConverted;
-}
-#endif
-
/*
** This function returns non-zero if the specified UTF-8 string buffer
** ends with a directory separator character or one was successfully
@@ -5257,42 +5239,6 @@ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){
break;
}
sqlite3_free(zConverted);
-#if 0 /* No longer necessary */
- }else{
- zConverted = sqlite3MallocZero( nMax+1 );
- if( !zConverted ){
- sqlite3_free(zBuf);
- OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
- return SQLITE_IOERR_NOMEM_BKPT;
- }
- if( osCygwin_conv_path(
- CCP_POSIX_TO_WIN_W, zDir,
- zConverted, nMax+1)<0 ){
- sqlite3_free(zConverted);
- sqlite3_free(zBuf);
- OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_CONVPATH\n"));
- return winLogError(SQLITE_IOERR_CONVPATH, (DWORD)errno,
- "winGetTempname2", zDir);
- }
- if( winIsDir(zConverted) ){
- /* At this point, we know the candidate directory exists and should
- ** be used. However, we may need to convert the string containing
- ** its name into UTF-8 (i.e. if it is UTF-16 right now).
- */
- char *zUtf8 = winConvertToUtf8Filename(zConverted);
- if( !zUtf8 ){
- sqlite3_free(zConverted);
- sqlite3_free(zBuf);
- OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
- return SQLITE_IOERR_NOMEM_BKPT;
- }
- sqlite3_snprintf(nMax, zBuf, "%s", zUtf8);
- sqlite3_free(zUtf8);
- sqlite3_free(zConverted);
- break;
- }
- sqlite3_free(zConverted);
-#endif /* No longer necessary */
}
}
}
@@ -6191,34 +6137,6 @@ static int winFullPathnameNoMutex(
}
}
#endif /* __CYGWIN__ */
-#if 0 /* This doesn't work correctly at all! See:
- <https://marc.info/?l=sqlite-users&m=139299149416314&w=2>
-*/
- SimulateIOError( return SQLITE_ERROR );
- UNUSED_PARAMETER(nFull);
- assert( nFull>=pVfs->mxPathname );
- char *zOut = sqlite3MallocZero( pVfs->mxPathname+1 );
- if( !zOut ){
- return SQLITE_IOERR_NOMEM_BKPT;
- }
- if( osCygwin_conv_path(
- CCP_POSIX_TO_WIN_W,
- zRelative, zOut, pVfs->mxPathname+1)<0 ){
- sqlite3_free(zOut);
- return winLogError(SQLITE_CANTOPEN_CONVPATH, (DWORD)errno,
- "winFullPathname2", zRelative);
- }else{
- char *zUtf8 = winConvertToUtf8Filename(zOut);
- if( !zUtf8 ){
- sqlite3_free(zOut);
- return SQLITE_IOERR_NOMEM_BKPT;
- }
- sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zUtf8);
- sqlite3_free(zUtf8);
- sqlite3_free(zOut);
- }
- return SQLITE_OK;
-#endif
#if (SQLITE_OS_WINCE || SQLITE_OS_WINRT) && defined(_WIN32)
SimulateIOError( return SQLITE_ERROR );
@@ -6364,27 +6282,8 @@ static int winFullPathname(
*/
static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){
HANDLE h;
-#if 0 /* This doesn't work correctly at all! See:
- <https://marc.info/?l=sqlite-users&m=139299149416314&w=2>
-*/
- int nFull = pVfs->mxPathname+1;
- char *zFull = sqlite3MallocZero( nFull );
- void *zConverted = 0;
- if( zFull==0 ){
- OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0));
- return 0;
- }
- if( winFullPathname(pVfs, zFilename, nFull, zFull)!=SQLITE_OK ){
- sqlite3_free(zFull);
- OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0));
- return 0;
- }
- zConverted = winConvertFromUtf8Filename(zFull);
- sqlite3_free(zFull);
-#else
void *zConverted = winConvertFromUtf8Filename(zFilename);
UNUSED_PARAMETER(pVfs);
-#endif
if( zConverted==0 ){
OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0));
return 0;
diff --git a/src/pager.c b/src/pager.c
index 21f3ac5f6..1850ba37b 100644
--- a/src/pager.c
+++ b/src/pager.c
@@ -700,6 +700,9 @@ struct Pager {
Wal *pWal; /* Write-ahead log used by "journal_mode=wal" */
char *zWal; /* File name for write-ahead log */
#endif
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ sqlite3 *dbWal;
+#endif
};
/*
@@ -7581,6 +7584,11 @@ static int pagerOpenWal(Pager *pPager){
pPager->fd, pPager->zWal, pPager->exclusiveMode,
pPager->journalSizeLimit, &pPager->pWal
);
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ if( rc==SQLITE_OK ){
+ sqlite3WalDb(pPager->pWal, pPager->dbWal);
+ }
+#endif
}
pagerFixMaplimit(pPager);
@@ -7700,6 +7708,7 @@ int sqlite3PagerWalWriteLock(Pager *pPager, int bLock){
** blocking locks are required.
*/
void sqlite3PagerWalDb(Pager *pPager, sqlite3 *db){
+ pPager->dbWal = db;
if( pagerUseWal(pPager) ){
sqlite3WalDb(pPager->pWal, db);
}
diff --git a/src/parse.y b/src/parse.y
index a5691cad4..617eb7303 100644
--- a/src/parse.y
+++ b/src/parse.y
@@ -1429,12 +1429,21 @@ expr(A) ::= expr(A) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
** expr1 IN ()
** expr1 NOT IN ()
**
- ** simplify to constants 0 (false) and 1 (true), respectively,
- ** regardless of the value of expr1.
+ ** simplify to constants 0 (false) and 1 (true), respectively.
+ **
+ ** Except, do not apply this optimization if expr1 contains a function
+ ** because that function might be an aggregate (we don't know yet whether
+ ** it is or not) and if it is an aggregate, that could change the meaning
+ ** of the whole query.
*/
- sqlite3ExprUnmapAndDelete(pParse, A);
- A = sqlite3Expr(pParse->db, TK_STRING, N ? "true" : "false");
- if( A ) sqlite3ExprIdToTrueFalse(A);
+ Expr *pB = sqlite3Expr(pParse->db, TK_STRING, N ? "true" : "false");
+ if( pB ) sqlite3ExprIdToTrueFalse(pB);
+ if( !ExprHasProperty(A, EP_HasFunc) ){
+ sqlite3ExprUnmapAndDelete(pParse, A);
+ A = pB;
+ }else{
+ A = sqlite3PExpr(pParse, N ? TK_OR : TK_AND, pB, A);
+ }
}else{
Expr *pRHS = Y->a[0].pExpr;
if( Y->nExpr==1 && sqlite3ExprIsConstant(pParse,pRHS) && A->op!=TK_VECTOR ){
diff --git a/src/printf.c b/src/printf.c
index 8cb5a43c5..669ca26b0 100644
--- a/src/printf.c
+++ b/src/printf.c
@@ -416,6 +416,14 @@ 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);
diff --git a/src/resolve.c b/src/resolve.c
index 3961a2009..57ccd0c07 100644
--- a/src/resolve.c
+++ b/src/resolve.c
@@ -1358,11 +1358,13 @@ 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 );
@@ -1370,6 +1372,7 @@ 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{
diff --git a/src/select.c b/src/select.c
index 3b951afff..1b1266313 100644
--- a/src/select.c
+++ b/src/select.c
@@ -384,7 +384,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].pTab->aCol[] here */
+ int *piCol, /* Write index of pSrc->a[*piTab].pSTab->aCol[] here */
int bIgnoreHidden /* Ignore hidden columns */
){
int i; /* For looping over tables in pSrc */
@@ -596,7 +596,7 @@ static int sqlite3ProcessJoin(Parse *pParse, Select *p){
}
pE1 = sqlite3CreateColumnExpr(db, pSrc, iLeft, iLeftCol);
sqlite3SrcItemColumnUsed(&pSrc->a[iLeft], iLeftCol);
- if( (pSrc->a[0].fg.jointype & JT_LTORJ)!=0 ){
+ if( (pSrc->a[0].fg.jointype & JT_LTORJ)!=0 && pParse->nErr==0 ){
/* This branch runs if the query contains one or more RIGHT or FULL
** JOINs. If only a single table on the left side of this join
** contains the zName column, then this branch is a no-op.
@@ -612,6 +612,8 @@ static int sqlite3ProcessJoin(Parse *pParse, Select *p){
*/
ExprList *pFuncArgs = 0; /* Arguments to the coalesce() */
static const Token tkCoalesce = { "coalesce", 8 };
+ assert( pE1!=0 );
+ ExprSetProperty(pE1, EP_CanBeNull);
while( tableAndColumnIndex(pSrc, iLeft+1, i, zName, &iLeft, &iLeftCol,
pRight->fg.isSynthUsing)!=0 ){
if( pSrc->a[iLeft].fg.isUsing==0
@@ -628,7 +630,13 @@ static int sqlite3ProcessJoin(Parse *pParse, Select *p){
if( pFuncArgs ){
pFuncArgs = sqlite3ExprListAppend(pParse, pFuncArgs, pE1);
pE1 = sqlite3ExprFunction(pParse, pFuncArgs, &tkCoalesce, 0);
+ if( pE1 ){
+ pE1->affExpr = SQLITE_AFF_DEFER;
+ }
}
+ }else if( (pSrc->a[i+1].fg.jointype & JT_LEFT)!=0 && pParse->nErr==0 ){
+ assert( pE1!=0 );
+ ExprSetProperty(pE1, EP_CanBeNull);
}
pE2 = sqlite3CreateColumnExpr(db, pSrc, i+1, iRightCol);
sqlite3SrcItemColumnUsed(pRight, iRightCol);
@@ -2105,6 +2113,10 @@ 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) */
}
@@ -3024,7 +3036,9 @@ 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 );
@@ -3063,6 +3077,8 @@ 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;
@@ -3083,6 +3099,7 @@ 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;
@@ -3113,9 +3130,10 @@ static int multiSelect(
int tab1, tab2;
int iCont, iBreak, iStart;
Expr *pLimit;
- int addr;
+ int addr, iLimit, iOffset;
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
@@ -3139,15 +3157,29 @@ static int multiSelect(
if( rc ){
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;
- p->pPrior = 0;
+
+ /* 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;
p->pLimit = 0;
+ p->iLimit = 0;
+ p->iOffset = 0;
+
intersectdest.iSDParm = tab2;
ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE",
sqlite3SelectOpName(p->op)));
@@ -3160,19 +3192,21 @@ 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 );
- iBreak = sqlite3VdbeMakeLabel(pParse);
- iCont = sqlite3VdbeMakeLabel(pParse);
- computeLimitRegisters(pParse, p, iBreak);
- sqlite3VdbeAddOp2(v, OP_Rewind, tab1, iBreak); VdbeCoverage(v);
+ sqlite3VdbeAddOp1(v, OP_Rewind, tab1);
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);
@@ -3182,6 +3216,7 @@ 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;
}
@@ -3860,6 +3895,7 @@ 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;
@@ -3967,6 +4003,9 @@ 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) ){
@@ -4004,6 +4043,7 @@ static void substSelect(
SrcItem *pItem;
int i;
if( !p ) return;
+ pSubst->nSelDepth++;
do{
substExprList(pSubst, p->pEList);
substExprList(pSubst, p->pGroupBy);
@@ -4021,6 +4061,7 @@ static void substSelect(
}
}
}while( doPrior && (p = p->pPrior)!=0 );
+ pSubst->nSelDepth--;
}
#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
@@ -4236,9 +4277,9 @@ static int compoundHasDifferentAffinities(Select *p){
** from 2015-02-09.)
**
** (3) If the subquery is the right operand of a LEFT JOIN then
-** (3a) the subquery may not be a join and
-** (3b) the FROM clause of the subquery may not contain a virtual
-** table and
+** (3a) the subquery may not be a join
+** (**) Was (3b): "the FROM clause of the subquery may not contain
+** a virtual table"
** (**) Was: "The outer query may not have a GROUP BY." This case
** is now managed correctly
** (3d) the outer query may not be DISTINCT.
@@ -4454,7 +4495,7 @@ static int flattenSubquery(
*/
if( (pSubitem->fg.jointype & (JT_OUTER|JT_LTORJ))!=0 ){
if( pSubSrc->nSrc>1 /* (3a) */
- || IsVirtual(pSubSrc->a[0].pSTab) /* (3b) */
+ /**** || IsVirtual(pSubSrc->a[0].pSTab) (3b)-omitted */
|| (p->selFlags & SF_Distinct)!=0 /* (3d) */
|| (pSubitem->fg.jointype & JT_RIGHT)!=0 /* (26) */
){
@@ -4632,7 +4673,7 @@ static int flattenSubquery(
** complete, since there may still exist Expr.pTab entries that
** refer to the subquery even after flattening. Ticket #3346.
**
- ** pSubitem->pTab is always non-NULL by test restrictions and tests above.
+ ** pSubitem->pSTab is always non-NULL by test restrictions and tests above.
*/
if( ALWAYS(pSubitem->pSTab!=0) ){
Table *pTabToDel = pSubitem->pSTab;
@@ -4762,6 +4803,7 @@ 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);
@@ -5347,6 +5389,7 @@ 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);
@@ -5744,7 +5787,7 @@ 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->pTab
+** If pFrom matches a CTE according to either of these two above, pFrom->pSTab
** and other fields are populated accordingly.
**
** Return 0 if no match is found.
@@ -7372,6 +7415,83 @@ 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
+ ){
+ 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);
+ }
+ }
+ }
+}
+
+/*
** Generate byte-code for the SELECT statement given in the p argument.
**
** The results are returned according to the SelectDest structure.
@@ -7739,6 +7859,13 @@ 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
@@ -8525,12 +8652,12 @@ int sqlite3Select(
** for the next GROUP BY batch.
*/
sqlite3VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow);
- VdbeComment((v, "output one row"));
+ VdbeComment((v, "output one row of %d", p->selId));
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"));
+ VdbeComment((v, "reset accumulator %d", p->selId));
/* Update the aggregate accumulators based on the content of
** the current row
@@ -8538,7 +8665,7 @@ int sqlite3Select(
sqlite3VdbeJumpHere(v, addr1);
updateAccumulator(pParse, iUseFlag, pAggInfo, eDist);
sqlite3VdbeAddOp2(v, OP_Integer, 1, iUseFlag);
- VdbeComment((v, "indicate data in accumulator"));
+ VdbeComment((v, "indicate data in accumulator %d", p->selId));
/* End of the loop
*/
@@ -8555,7 +8682,7 @@ int sqlite3Select(
/* Output the final row of result
*/
sqlite3VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow);
- VdbeComment((v, "output final row"));
+ VdbeComment((v, "output final row of %d", p->selId));
/* Jump over the subroutines
*/
@@ -8576,7 +8703,7 @@ int sqlite3Select(
addrOutputRow = sqlite3VdbeCurrentAddr(v);
sqlite3VdbeAddOp2(v, OP_IfPos, iUseFlag, addrOutputRow+2);
VdbeCoverage(v);
- VdbeComment((v, "Groupby result generator entry point"));
+ VdbeComment((v, "Groupby result generator entry point %d", p->selId));
sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
finalizeAggFunctions(pParse, pAggInfo);
sqlite3ExprIfFalse(pParse, pHaving, addrOutputRow+1, SQLITE_JUMPIFNULL);
@@ -8584,14 +8711,14 @@ int sqlite3Select(
&sDistinct, pDest,
addrOutputRow+1, addrSetAbort);
sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
- VdbeComment((v, "end groupby result generator"));
+ VdbeComment((v, "end groupby result generator %d", p->selId));
/* 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 empty"));
+ VdbeComment((v, "indicate accumulator %d empty", p->selId));
sqlite3VdbeAddOp1(v, OP_Return, regReset);
if( distFlag!=0 && eDist!=WHERE_DISTINCT_NOOP ){
diff --git a/src/shell.c.in b/src/shell.c.in
index 8660bd78a..5cda6a1a1 100644
--- a/src/shell.c.in
+++ b/src/shell.c.in
@@ -887,12 +887,21 @@ static int strlen30(const char *z){
/*
** Return the length of a string in characters. Multibyte UTF8 characters
-** count as a single character.
+** count as a single character for single-width characters, or as two
+** characters for double-width characters.
*/
static int strlenChar(const char *z){
int n = 0;
while( *z ){
- if( (0xc0&*(z++))!=0x80 ) n++;
+ if( (0x80&z[0])==0 ){
+ n++;
+ z++;
+ }else{
+ int u = 0;
+ int len = decodeUtf8((const u8*)z, &u);
+ z += len;
+ n += cli_wcwidth(u);
+ }
}
return n;
}
@@ -1325,11 +1334,7 @@ static void shellAddSchemaName(
#define SQLITE_EXTENSION_INIT1
#define SQLITE_EXTENSION_INIT2(X) (void)(X)
-#if defined(_WIN32) && defined(_MSC_VER)
-INCLUDE test_windirent.h
-INCLUDE test_windirent.c
-#define dirent DIRENT
-#endif
+INCLUDE ../ext/misc/windirent.h
INCLUDE ../ext/misc/memtrace.c
INCLUDE ../ext/misc/pcachetrace.c
INCLUDE ../ext/misc/shathree.c
@@ -9323,7 +9328,8 @@ static int do_meta_command(char *zLine, ShellState *p){
" (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x"
" FROM sqlite_schema UNION ALL"
" SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_schema) "
- "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' "
+ "WHERE type!='meta' AND sql NOTNULL"
+ " AND name NOT LIKE 'sqlite__%' ESCAPE '_' "
"ORDER BY x",
callback, &data, 0
);
@@ -10799,7 +10805,7 @@ static int do_meta_command(char *zLine, ShellState *p){
sqlite3_free(zQarg);
}
if( bNoSystemTabs ){
- appendText(&sSelect, "name NOT LIKE 'sqlite_%%' AND ", 0);
+ appendText(&sSelect, "name NOT LIKE 'sqlite__%%' ESCAPE '_' AND ", 0);
}
appendText(&sSelect, "sql IS NOT NULL"
" ORDER BY snum, rowid", 0);
@@ -11230,7 +11236,7 @@ static int do_meta_command(char *zLine, ShellState *p){
}else{
zSql = "SELECT lower(name) as tname FROM sqlite_schema"
" WHERE type='table' AND coalesce(rootpage,0)>1"
- " AND name NOT LIKE 'sqlite_%'"
+ " AND name NOT LIKE 'sqlite__%' ESCAPE '_'"
" ORDER BY 1 collate nocase";
}
sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
@@ -11295,7 +11301,7 @@ static int do_meta_command(char *zLine, ShellState *p){
char *zRevText = /* Query for reversible to-blob-to-text check */
"SELECT lower(name) as tname FROM sqlite_schema\n"
"WHERE type='table' AND coalesce(rootpage,0)>1\n"
- "AND name NOT LIKE 'sqlite_%%'%s\n"
+ "AND name NOT LIKE 'sqlite__%%' ESCAPE '_'%s\n"
"ORDER BY 1 collate nocase";
zRevText = sqlite3_mprintf(zRevText, zLike? " AND name LIKE $tspec" : "");
zRevText = sqlite3_mprintf(
@@ -11491,7 +11497,7 @@ static int do_meta_command(char *zLine, ShellState *p){
appendText(&s, ".sqlite_schema ", 0);
if( c=='t' ){
appendText(&s," WHERE type IN ('table','view')"
- " AND name NOT LIKE 'sqlite_%'"
+ " AND name NOT LIKE 'sqlite__%' ESCAPE '_'"
" AND name LIKE ?1", 0);
}else{
appendText(&s," WHERE type='index'"
@@ -11585,7 +11591,7 @@ static int do_meta_command(char *zLine, ShellState *p){
{"always", SQLITE_TESTCTRL_ALWAYS, 1, "BOOLEAN" },
{"assert", SQLITE_TESTCTRL_ASSERT, 1, "BOOLEAN" },
/*{"benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS,1, "" },*/
- /*{"bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST, 1, "" },*/
+ {"bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST, 1, "SIZE INT-ARRAY"},
{"byteorder", SQLITE_TESTCTRL_BYTEORDER, 0, "" },
{"extra_schema_checks",SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS,0,"BOOLEAN" },
{"fault_install", SQLITE_TESTCTRL_FAULT_INSTALL, 1,"args..." },
@@ -11704,6 +11710,7 @@ static int do_meta_command(char *zLine, ShellState *p){
{ 0x08000000, 1, "OnePass" },
{ 0x10000000, 1, "OrderBySubq" },
{ 0x20000000, 1, "StarQuery" },
+ { 0x40000000, 1, "ExistsToJoin" },
{ 0xffffffff, 0, "All" },
};
unsigned int curOpt;
@@ -11923,6 +11930,49 @@ static int do_meta_command(char *zLine, ShellState *p){
}
sqlite3_test_control(testctrl, &rc2);
break;
+ case SQLITE_TESTCTRL_BITVEC_TEST: {
+ /* Examples:
+ ** .testctrl bitvec_test 100 6,1 -- Show BITVEC constants
+ ** .testctrl bitvec_test 1000 1,12,7,3 -- Simple test
+ ** ---- --------
+ ** size of Bitvec -----^ ^--- aOp array. 0 added at end.
+ **
+ ** See comments on sqlite3BitvecBuiltinTest() for more information
+ ** about the aOp[] array.
+ */
+ int iSize;
+ const char *zTestArg;
+ int nOp;
+ int ii, jj, x;
+ int *aOp;
+ if( nArg!=4 ){
+ sqlite3_fprintf(stderr,
+ "ERROR - should be: \".testctrl bitvec_test SIZE INT-ARRAY\"\n"
+ );
+ rc = 1;
+ goto meta_command_exit;
+ }
+ isOk = 3;
+ iSize = (int)integerValue(azArg[2]);
+ zTestArg = azArg[3];
+ nOp = (int)strlen(zTestArg)+1;
+ aOp = malloc( sizeof(int)*(nOp+1) );
+ shell_check_oom(aOp);
+ memset(aOp, 0, sizeof(int)*(nOp+1) );
+ for(ii = jj = x = 0; zTestArg[ii]!=0; ii++){
+ if( IsDigit(zTestArg[ii]) ){
+ x = x*10 + zTestArg[ii] - '0';
+ }else{
+ aOp[jj++] = x;
+ x = 0;
+ }
+ }
+ aOp[jj] = x;
+ x = sqlite3_test_control(testctrl, iSize, aOp);
+ sqlite3_fprintf(p->out, "result: %d\n", x);
+ free(aOp);
+ break;
+ }
case SQLITE_TESTCTRL_FAULT_INSTALL: {
int kk;
int bShowHelp = nArg<=2;
diff --git a/src/sqlite.h.in b/src/sqlite.h.in
index d3164d906..836c09e2a 100644
--- a/src/sqlite.h.in
+++ b/src/sqlite.h.in
@@ -168,9 +168,9 @@ extern "C" {
** assert( strcmp(sqlite3_libversion(),SQLITE_VERSION)==0 );
** </pre></blockquote>)^
**
-** ^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()
+** ^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()
** 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
@@ -370,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-separate SQL statements passed into its 2nd argument,
+** semicolon-separated 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
@@ -403,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 corresponding result column as obtained
+** entry represents the name of a corresponding result column as obtained
** from [sqlite3_column_name()].
**
** ^If the 2nd parameter to sqlite3_exec() is a NULL pointer, a pointer
@@ -589,7 +589,7 @@ 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 be a no-op and might become an
+** [sqlite3_open_v2()] has historically been a no-op and might become an
** error in future versions of SQLite.
*/
#define SQLITE_OPEN_READONLY 0x00000001 /* Ok for sqlite3_open_v2() */
@@ -683,7 +683,7 @@ 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
-** lest restrictive to most restrictive.
+** least restrictive to most restrictive.
**
** The argument to xLock() is always SHARED or higher. The argument to
** xUnlock is either SHARED or NONE.
@@ -999,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 are of all VFS shims and the
+** all [VFSes] in the VFS stack. The names 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.
@@ -1013,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 opcodes will set *X
+** of type "[sqlite3_vfs] **". This opcode 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.
@@ -1203,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
@@ -1628,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 be initialized
+** initialized when [sqlite3_open()] is called if it has not been 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
@@ -1885,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 simulations memory allocation failure or
+** routines with a wrapper that simulates 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 single argument of
+** <dd> ^The SQLITE_CONFIG_SMALL_MALLOC option takes a 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 application might prefer to run slower in exchange for
+** but some applications 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 single argument of type int,
+** <dd> ^The SQLITE_CONFIG_MEMSTATUS option takes a 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:
@@ -1944,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>
@@ -1973,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 the mutex routines built into SQLite.)^ ^SQLite makes a copy of
+** in place of 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
@@ -2015,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 of
+** is a pointer to an [sqlite3_pcache_methods2] object. SQLite copies off
** the current page cache implementation into that object.)^ </dd>
**
** [[SQLITE_CONFIG_LOG]] <dt>SQLITE_CONFIG_LOG</dt>
@@ -2032,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
-** log message after formatting via [sqlite3_snprintf()].
+** a 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
@@ -2223,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 functions. It takes a
+** The [sqlite3_db_config()] interface is a var-args function. 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
@@ -2357,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 state of either the
-** C-API or the SQL function.
+** If the first argument is -1, then no changes are made to the 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
@@ -2476,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 it
+** the legacy behavior of the [ALTER TABLE RENAME] command such that 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
@@ -2525,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 file to have a schema format version number (the 4-byte
+** created database files 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,
@@ -2552,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
@@ -2595,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 the
-** the this capability is disabled, the [ATTACH] command will still work,
+** reenable this capability using the current DBCONFIG option. If
+** 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]
@@ -2630,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 a integer.
+** The first argument (the third parameter to sqlite3_db_config()) is an 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
@@ -2920,7 +2920,7 @@ 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 thus
+** ^These routines do not parse the SQL statements and thus
** will not detect syntactically incorrect SQL.
**
** ^(If SQLite has not been initialized using [sqlite3_initialize()] prior
@@ -3037,7 +3037,7 @@ 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 store two timeout values - the
+** Internally, each SQLite database handle stores 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
@@ -3067,7 +3067,7 @@ 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 memory data structure created by the
+** Definition: A <b>result table</b> is a memory data structure created by the
** [sqlite3_get_table()] interface. A result table records the
** complete query results from one or more queries.
**
@@ -3210,7 +3210,7 @@ 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 is called with a NULL pointer. Passing a NULL pointer
+** a no-op if it 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.
@@ -3228,13 +3228,13 @@ 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 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 the 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) interfaces works the same as
+** ^The sqlite3_realloc64(X,N) interface works the same as
** sqlite3_realloc(X,N) except that N is a 64-bit unsigned integer instead
** of a 32-bit signed integer.
**
@@ -3284,7 +3284,7 @@ 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 the any underlying system library
+** but not overhead added by any underlying system library
** routines that [sqlite3_malloc()] may call.
**
** ^The memory high-water mark is reset to the current value of
@@ -3736,7 +3736,7 @@ 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 [shared cache] enabled, overriding
+** <dd>The database is opened with [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
@@ -3744,7 +3744,7 @@ 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 [shared cache] disabled, overriding
+** <dd>The database is opened with [shared cache] disabled, overriding
** the default shared cache setting provided by
** [sqlite3_enable_shared_cache()].)^
**
@@ -4079,7 +4079,7 @@ sqlite3_file *sqlite3_database_file_object(const char*);
**
** The sqlite3_create_filename(D,J,W,N,P) allocates memory to hold a version of
** database filename D with corresponding journal file J and WAL file W and
-** with N URI parameters key/values pairs in the array P. The result from
+** an array P of N URI Key/Value pairs. The result from
** sqlite3_create_filename(D,J,W,N,P) is a pointer to a database filename that
** is safe to pass to routines like:
** <ul>
@@ -4162,7 +4162,7 @@ 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 an
+** that describes the [result code] E, as UTF-8, or NULL if E is not a
** 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)^.
@@ -4170,7 +4170,7 @@ 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 UTF8.
+** sqlite3_error_offset() assumes that the input SQL is UTF-8.
** ^If the most recent error does not reference a specific token in the input
** SQL, then the sqlite3_error_offset() function returns -1.
**
@@ -4269,8 +4269,8 @@ int sqlite3_limit(sqlite3*, int id, int newVal);
**
** These constants define various performance limits
** that can be lowered at run-time using [sqlite3_limit()].
-** The synopsis of the meanings of the various limits is shown below.
-** Additional information is available at [limits | Limits in SQLite].
+** A concise description of these limits follows, and additional information
+** is available at [limits | Limits in SQLite].
**
** <dl>
** [[SQLITE_LIMIT_LENGTH]] ^(<dt>SQLITE_LIMIT_LENGTH</dt>
@@ -4335,7 +4335,7 @@ int sqlite3_limit(sqlite3*, int id, int newVal);
/*
** CAPI3REF: Prepare Flags
**
-** These constants define various flags that can be passed into
+** These constants define various flags that can be passed into the
** "prepFlags" parameter of the [sqlite3_prepare_v3()] and
** [sqlite3_prepare16_v3()] interfaces.
**
@@ -4422,7 +4422,7 @@ 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 measure the length of the input in bytes, not
+** Note that nByte measures 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
@@ -4556,7 +4556,7 @@ 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
-** the maximum string length determined by the [SQLITE_LIMIT_LENGTH].
+** 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
@@ -4744,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 first parameter to [application-defined SQL functions].
+** is always the 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()],
@@ -4760,7 +4760,7 @@ typedef struct sqlite3_context sqlite3_context;
** METHOD: sqlite3_stmt
**
** ^(In the SQL statement text input to [sqlite3_prepare_v2()] and its variants,
-** literals may be replaced by a [parameter] that matches one of following
+** literals may be replaced by a [parameter] that matches one of the following
** templates:
**
** <ul>
@@ -4805,7 +4805,7 @@ typedef struct sqlite3_context sqlite3_context;
**
** [[byte-order determination rules]] ^The byte-order of
** UTF16 input text is determined by the byte-order mark (BOM, U+FEFF)
-** found in first character, which is removed, or in the absence of a BOM
+** found in the first character, which is removed, or in the absence of a BOM
** the byte order is the native byte order of the host
** machine for sqlite3_bind_text16() or the byte order specified in
** the 6th parameter for sqlite3_bind_text64().)^
@@ -4825,7 +4825,7 @@ typedef struct sqlite3_context sqlite3_context;
** or sqlite3_bind_text16() or sqlite3_bind_text64() then
** that parameter must be the byte offset
** where the NUL terminator would occur assuming the string were NUL
-** terminated. If any NUL characters occurs at byte offsets less than
+** terminated. If any NUL characters occur at byte offsets less than
** the value of the fourth parameter then the resulting string value will
** contain embedded NULs. The result of expressions involving strings
** with embedded NULs is undefined.
@@ -5037,7 +5037,7 @@ const void *sqlite3_column_name16(sqlite3_stmt*, int N);
** METHOD: sqlite3_stmt
**
** ^These routines provide a means to determine the database, table, and
-** table column that is the origin of a particular result column in
+** table column that is the origin of a particular result column in a
** [SELECT] statement.
** ^The name of the database or table or column can be returned as
** either a UTF-8 or UTF-16 string. ^The _database_ routines return
@@ -5481,7 +5481,7 @@ 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 is never been evaluated, then sqlite3_finalize() returns
+** or if the statement has 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].
@@ -5606,8 +5606,8 @@ int sqlite3_reset(sqlite3_stmt *pStmt);
**
** For best security, the [SQLITE_DIRECTONLY] flag is recommended for
** all application-defined SQL functions that do not need to be
-** used inside of triggers, view, CHECK constraints, or other elements of
-** the database schema. This flags is especially recommended for SQL
+** used inside of triggers, views, CHECK constraints, or other elements of
+** the database schema. This flag is especially recommended for SQL
** functions that have side effects or reveal internal application state.
** Without this flag, an attacker might be able to modify the schema of
** a database file to include invocations of the function with parameters
@@ -5638,7 +5638,7 @@ int sqlite3_reset(sqlite3_stmt *pStmt);
** [user-defined window functions|available here].
**
** ^(If the final parameter to sqlite3_create_function_v2() or
-** sqlite3_create_window_function() is not NULL, then it is destructor for
+** sqlite3_create_window_function() is not NULL, then it is the destructor for
** the application data pointer. The destructor is invoked when the function
** is deleted, either by being overloaded or when the database connection
** closes.)^ ^The destructor is also invoked if the call to
@@ -5713,7 +5713,7 @@ int sqlite3_create_window_function(
/*
** CAPI3REF: Text Encodings
**
-** These constant define integer codes that represent the various
+** These constants define integer codes that represent the various
** text encodings supported by SQLite.
*/
#define SQLITE_UTF8 1 /* IMP: R-37514-35566 */
@@ -5805,7 +5805,7 @@ 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 term in an
+** might become a no-op if the function is used as a 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
@@ -5932,7 +5932,7 @@ SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),
** 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
-** and the prior [xColumn] method call that was invoked to extracted
+** the prior [xColumn] method call that was invoked to extract
** 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
@@ -6038,7 +6038,7 @@ unsigned int sqlite3_value_subtype(sqlite3_value*);
** METHOD: sqlite3_value
**
** ^The sqlite3_value_dup(V) interface makes a copy of the [sqlite3_value]
-** object D and returns a pointer to that copy. ^The [sqlite3_value] returned
+** object V and returns a pointer to that copy. ^The [sqlite3_value] returned
** is a [protected sqlite3_value] object even if the input is not.
** ^The sqlite3_value_dup(V) interface returns NULL if V is NULL or if a
** memory allocation fails. ^If V is a [pointer value], then the result
@@ -6076,7 +6076,7 @@ void sqlite3_value_free(sqlite3_value*);
** allocation error occurs.
**
** ^(The amount of space allocated by sqlite3_aggregate_context(C,N) is
-** determined by the N parameter on first successful call. Changing the
+** determined by the N parameter on the first successful call. Changing the
** value of N in any subsequent call to sqlite3_aggregate_context() within
** the same aggregate function instance will not resize the memory
** allocation.)^ Within the xFinal callback, it is customary to set
@@ -6238,7 +6238,7 @@ void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*));
**
** Security Warning: These interfaces should not be exposed in scripting
** languages or in other circumstances where it might be possible for an
-** an attacker to invoke them. Any agent that can invoke these interfaces
+** attacker to invoke them. Any agent that can invoke these interfaces
** can probably also take control of the process.
**
** Database connection client data is only available for SQLite
@@ -6352,7 +6352,7 @@ typedef void (*sqlite3_destructor_type)(void*);
** pointed to by the 2nd parameter are taken as the application-defined
** function result. If the 3rd parameter is non-negative, then it
** must be the byte offset into the string where the NUL terminator would
-** appear if the string where NUL terminated. If any NUL characters occur
+** appear if the string were NUL terminated. If any NUL characters occur
** in the string at a byte offset that is less than the value of the 3rd
** parameter, then the resulting string will contain embedded NULs and the
** result of expressions operating on strings with embedded NULs is undefined.
@@ -6410,7 +6410,7 @@ typedef void (*sqlite3_destructor_type)(void*);
** string and preferably a string literal. The sqlite3_result_pointer()
** routine is part of the [pointer passing interface] added for SQLite 3.20.0.
**
-** If these routines are called from within the different thread
+** If these routines are called from within a different thread
** than the one containing the application-defined function that received
** the [sqlite3_context] pointer, the results are undefined.
*/
@@ -6816,7 +6816,7 @@ sqlite3 *sqlite3_db_handle(sqlite3_stmt*);
** METHOD: sqlite3
**
** ^The sqlite3_db_name(D,N) interface returns a pointer to the schema name
-** for the N-th database on database connection D, or a NULL pointer of N is
+** for the N-th database on database connection D, or a NULL pointer if N is
** out of range. An N value of 0 means the main database file. An N of 1 is
** the "temp" schema. Larger values of N correspond to various ATTACH-ed
** databases.
@@ -6911,7 +6911,7 @@ int sqlite3_txn_state(sqlite3*,const char *zSchema);
** <dd>The SQLITE_TXN_READ state means that the database is currently
** in a read transaction. Content has been read from the database file
** but nothing in the database file has changed. The transaction state
-** will advanced to SQLITE_TXN_WRITE if any changes occur and there are
+** will be advanced to SQLITE_TXN_WRITE if any changes occur and there are
** no other conflicting concurrent write transactions. The transaction
** state will revert to SQLITE_TXN_NONE following a [ROLLBACK] or
** [COMMIT].</dd>
@@ -6920,7 +6920,7 @@ int sqlite3_txn_state(sqlite3*,const char *zSchema);
** <dd>The SQLITE_TXN_WRITE state means that the database is currently
** in a write transaction. Content has been written to the database file
** but has not yet committed. The transaction state will change to
-** to SQLITE_TXN_NONE at the next [ROLLBACK] or [COMMIT].</dd>
+** SQLITE_TXN_NONE at the next [ROLLBACK] or [COMMIT].</dd>
*/
#define SQLITE_TXN_NONE 0
#define SQLITE_TXN_READ 1
@@ -7201,7 +7201,7 @@ int sqlite3_db_release_memory(sqlite3*);
** CAPI3REF: Impose A Limit On Heap Size
**
** These interfaces impose limits on the amount of heap memory that will be
-** by all database connections within a single process.
+** used by all database connections within a single process.
**
** ^The sqlite3_soft_heap_limit64() interface sets and/or queries the
** soft limit on the amount of heap memory that may be allocated by SQLite.
@@ -7259,7 +7259,7 @@ int sqlite3_db_release_memory(sqlite3*);
** </ul>)^
**
** The circumstances under which SQLite will enforce the heap limits may
-** changes in future releases of SQLite.
+** change in future releases of SQLite.
*/
sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 N);
sqlite3_int64 sqlite3_hard_heap_limit64(sqlite3_int64 N);
@@ -7374,8 +7374,8 @@ int sqlite3_table_column_metadata(
** ^The entry point is zProc.
** ^(zProc may be 0, in which case SQLite will try to come up with an
** entry point name on its own. It first tries "sqlite3_extension_init".
-** If that does not work, it constructs a name "sqlite3_X_init" where the
-** X is consists of the lower-case equivalent of all ASCII alphabetic
+** If that does not work, it constructs a name "sqlite3_X_init" where
+** X consists of the lower-case equivalent of all ASCII alphabetic
** characters in the filename from the last "/" to the first following
** "." and omitting any initial "lib".)^
** ^The sqlite3_load_extension() interface returns
@@ -7446,7 +7446,7 @@ int sqlite3_enable_load_extension(sqlite3 *db, int onoff);
** ^(Even though the function prototype shows that xEntryPoint() takes
** no arguments and returns void, SQLite invokes xEntryPoint() with three
** arguments and expects an integer result as if the signature of the
-** entry point where as follows:
+** entry point were as follows:
**
** <blockquote><pre>
** &nbsp; int xEntryPoint(
@@ -7610,7 +7610,7 @@ struct sqlite3_module {
** virtual table and might not be checked again by the byte code.)^ ^(The
** aConstraintUsage[].omit flag is an optimization hint. When the omit flag
** is left in its default setting of false, the constraint will always be
-** checked separately in byte code. If the omit flag is change to true, then
+** checked separately in byte code. If the omit flag is changed to true, then
** the constraint may or may not be checked in byte code. In other words,
** when the omit flag is true there is no guarantee that the constraint will
** not be checked again using byte code.)^
@@ -7636,7 +7636,7 @@ struct sqlite3_module {
** The xBestIndex method may optionally populate the idxFlags field with a
** mask of SQLITE_INDEX_SCAN_* flags. One such flag is
** [SQLITE_INDEX_SCAN_HEX], which if set causes the [EXPLAIN QUERY PLAN]
-** output to show the idxNum has hex instead of as decimal. Another flag is
+** output to show the idxNum as hex instead of as decimal. Another flag is
** SQLITE_INDEX_SCAN_UNIQUE, which if set indicates that the query plan will
** return at most one row.
**
@@ -7777,7 +7777,7 @@ struct sqlite3_index_info {
** the implementation of the [virtual table module]. ^The fourth
** parameter is an arbitrary client data pointer that is passed through
** into the [xCreate] and [xConnect] methods of the virtual table module
-** when a new virtual table is be being created or reinitialized.
+** when a new virtual table is being created or reinitialized.
**
** ^The sqlite3_create_module_v2() interface has a fifth parameter which
** is a pointer to a destructor for the pClientData. ^SQLite will
@@ -7942,7 +7942,7 @@ typedef struct sqlite3_blob sqlite3_blob;
** in *ppBlob. Otherwise an [error code] is returned and, unless the error
** code is SQLITE_MISUSE, *ppBlob is set to NULL.)^ ^This means that, provided
** the API is not misused, it is always safe to call [sqlite3_blob_close()]
-** on *ppBlob after this function it returns.
+** on *ppBlob after this function returns.
**
** This function fails with SQLITE_ERROR if any of the following are true:
** <ul>
@@ -8062,7 +8062,7 @@ int sqlite3_blob_close(sqlite3_blob *);
**
** ^Returns the size in bytes of the BLOB accessible via the
** successfully opened [BLOB handle] in its only argument. ^The
-** incremental blob I/O routines can only read or overwriting existing
+** incremental blob I/O routines can only read or overwrite existing
** blob content; they cannot change the size of a blob.
**
** This routine only works on a [BLOB handle] which has been created
@@ -8212,7 +8212,7 @@ int sqlite3_vfs_unregister(sqlite3_vfs*);
** ^The sqlite3_mutex_alloc() routine allocates a new
** mutex and returns a pointer to it. ^The sqlite3_mutex_alloc()
** routine returns NULL if it is unable to allocate the requested
-** mutex. The argument to sqlite3_mutex_alloc() must one of these
+** mutex. The argument to sqlite3_mutex_alloc() must be one of these
** integer constants:
**
** <ul>
@@ -8445,7 +8445,7 @@ int sqlite3_mutex_notheld(sqlite3_mutex*);
** CAPI3REF: Retrieve the mutex for a database connection
** METHOD: sqlite3
**
-** ^This interface returns a pointer the [sqlite3_mutex] object that
+** ^This interface returns a pointer to the [sqlite3_mutex] object that
** serializes access to the [database connection] given in the argument
** when the [threading mode] is Serialized.
** ^If the [threading mode] is Single-thread or Multi-thread then this
@@ -8568,7 +8568,7 @@ int sqlite3_test_control(int op, ...);
** CAPI3REF: SQL Keyword Checking
**
** These routines provide access to the set of SQL language keywords
-** recognized by SQLite. Applications can uses these routines to determine
+** recognized by SQLite. Applications can use these routines to determine
** whether or not a specific identifier needs to be escaped (for example,
** by enclosing in double-quotes) so as not to confuse the parser.
**
@@ -8736,7 +8736,7 @@ void sqlite3_str_reset(sqlite3_str*);
** content of the dynamic string under construction in X. The value
** returned by [sqlite3_str_value(X)] is managed by the sqlite3_str object X
** and might be freed or altered by any subsequent method on the same
-** [sqlite3_str] object. Applications must not used the pointer returned
+** [sqlite3_str] object. Applications must not use the pointer returned by
** [sqlite3_str_value(X)] after any subsequent method call on the same
** object. ^Applications may change the content of the string returned
** by [sqlite3_str_value(X)] as long as they do not write into any bytes
@@ -8822,7 +8822,7 @@ int sqlite3_status64(
** allocation which could not be satisfied by the [SQLITE_CONFIG_PAGECACHE]
** buffer and where forced to overflow to [sqlite3_malloc()]. The
** returned value includes allocations that overflowed because they
-** where too large (they were larger than the "sz" parameter to
+** were too large (they were larger than the "sz" parameter to
** [SQLITE_CONFIG_PAGECACHE]) and allocations that overflowed because
** no space was left in the page cache.</dd>)^
**
@@ -8906,28 +8906,29 @@ int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
** [[SQLITE_DBSTATUS_LOOKASIDE_HIT]] ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_HIT</dt>
** <dd>This parameter returns the number of malloc attempts that were
** satisfied using lookaside memory. Only the high-water value is meaningful;
-** the current value is always zero.)^
+** the current value is always zero.</dd>)^
**
** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE]]
** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE</dt>
-** <dd>This parameter returns the number malloc attempts that might have
+** <dd>This parameter returns the number of malloc attempts that might have
** been satisfied using lookaside memory but failed due to the amount of
** memory requested being larger than the lookaside slot size.
** Only the high-water value is meaningful;
-** the current value is always zero.)^
+** the current value is always zero.</dd>)^
**
** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL]]
** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL</dt>
-** <dd>This parameter returns the number malloc attempts that might have
+** <dd>This parameter returns the number of malloc attempts that might have
** been satisfied using lookaside memory but failed due to all lookaside
** memory already being in use.
** Only the high-water value is meaningful;
-** the current value is always zero.)^
+** the current value is always zero.</dd>)^
**
** [[SQLITE_DBSTATUS_CACHE_USED]] ^(<dt>SQLITE_DBSTATUS_CACHE_USED</dt>
** <dd>This parameter returns the approximate number of bytes of heap
** memory used by all pager caches associated with the database connection.)^
** ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_USED is always 0.
+** </dd>
**
** [[SQLITE_DBSTATUS_CACHE_USED_SHARED]]
** ^(<dt>SQLITE_DBSTATUS_CACHE_USED_SHARED</dt>
@@ -8936,10 +8937,10 @@ int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
** memory used by that pager cache is divided evenly between the attached
** connections.)^ In other words, if none of the pager caches associated
** with the database connection are shared, this request returns the same
-** value as DBSTATUS_CACHE_USED. Or, if one or more or the pager caches are
+** value as DBSTATUS_CACHE_USED. Or, if one or more of the pager caches are
** shared, the value returned by this call will be smaller than that returned
** by DBSTATUS_CACHE_USED. ^The highwater mark associated with
-** SQLITE_DBSTATUS_CACHE_USED_SHARED is always 0.
+** SQLITE_DBSTATUS_CACHE_USED_SHARED is always 0.</dd>
**
** [[SQLITE_DBSTATUS_SCHEMA_USED]] ^(<dt>SQLITE_DBSTATUS_SCHEMA_USED</dt>
** <dd>This parameter returns the approximate number of bytes of heap
@@ -8949,6 +8950,7 @@ int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
** schema memory is shared with other database connections due to
** [shared cache mode] being enabled.
** ^The highwater mark associated with SQLITE_DBSTATUS_SCHEMA_USED is always 0.
+** </dd>
**
** [[SQLITE_DBSTATUS_STMT_USED]] ^(<dt>SQLITE_DBSTATUS_STMT_USED</dt>
** <dd>This parameter returns the approximate number of bytes of heap
@@ -8985,7 +8987,7 @@ int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
** been written to disk in the middle of a transaction due to the page
** cache overflowing. Transactions are more efficient if they are written
** to disk all at once. When pages spill mid-transaction, that introduces
-** additional overhead. This parameter can be used help identify
+** additional overhead. This parameter can be used to help identify
** inefficiencies that can be resolved by increasing the cache size.
** </dd>
**
@@ -9056,13 +9058,13 @@ int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
** [[SQLITE_STMTSTATUS_SORT]] <dt>SQLITE_STMTSTATUS_SORT</dt>
** <dd>^This is the number of sort operations that have occurred.
** A non-zero value in this counter may indicate an opportunity to
-** improvement performance through careful use of indices.</dd>
+** improve performance through careful use of indices.</dd>
**
** [[SQLITE_STMTSTATUS_AUTOINDEX]] <dt>SQLITE_STMTSTATUS_AUTOINDEX</dt>
** <dd>^This is the number of rows inserted into transient indices that
** were created automatically in order to help joins run faster.
** A non-zero value in this counter may indicate an opportunity to
-** improvement performance by adding permanent indices that do not
+** improve performance by adding permanent indices that do not
** need to be reinitialized each time the statement is run.</dd>
**
** [[SQLITE_STMTSTATUS_VM_STEP]] <dt>SQLITE_STMTSTATUS_VM_STEP</dt>
@@ -9071,19 +9073,19 @@ int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
** to 2147483647. The number of virtual machine operations can be
** used as a proxy for the total work done by the prepared statement.
** If the number of virtual machine operations exceeds 2147483647
-** then the value returned by this statement status code is undefined.
+** then the value returned by this statement status code is undefined.</dd>
**
** [[SQLITE_STMTSTATUS_REPREPARE]] <dt>SQLITE_STMTSTATUS_REPREPARE</dt>
** <dd>^This is the number of times that the prepare statement has been
** automatically regenerated due to schema changes or changes to
-** [bound parameters] that might affect the query plan.
+** [bound parameters] that might affect the query plan.</dd>
**
** [[SQLITE_STMTSTATUS_RUN]] <dt>SQLITE_STMTSTATUS_RUN</dt>
** <dd>^This is the number of times that the prepared statement has
** been run. A single "run" for the purposes of this counter is one
** or more calls to [sqlite3_step()] followed by a call to [sqlite3_reset()].
** The counter is incremented on the first [sqlite3_step()] call of each
-** cycle.
+** cycle.</dd>
**
** [[SQLITE_STMTSTATUS_FILTER_MISS]]
** [[SQLITE_STMTSTATUS_FILTER HIT]]
@@ -9093,7 +9095,7 @@ int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
** step was bypassed because a Bloom filter returned not-found. The
** corresponding SQLITE_STMTSTATUS_FILTER_MISS value is the number of
** times that the Bloom filter returned a find, and thus the join step
-** had to be processed as normal.
+** had to be processed as normal.</dd>
**
** [[SQLITE_STMTSTATUS_MEMUSED]] <dt>SQLITE_STMTSTATUS_MEMUSED</dt>
** <dd>^This is the approximate number of bytes of heap memory
@@ -9198,9 +9200,9 @@ struct sqlite3_pcache_page {
** SQLite will typically create one cache instance for each open database file,
** though this is not guaranteed. ^The
** first parameter, szPage, is the size in bytes of the pages that must
-** be allocated by the cache. ^szPage will always a power of two. ^The
+** be allocated by the cache. ^szPage will always be a power of two. ^The
** second parameter szExtra is a number of bytes of extra storage
-** associated with each page cache entry. ^The szExtra parameter will
+** associated with each page cache entry. ^The szExtra parameter will be
** a number less than 250. SQLite will use the
** extra szExtra bytes on each page to store metadata about the underlying
** database page on disk. The value passed into szExtra depends
@@ -9208,17 +9210,17 @@ struct sqlite3_pcache_page {
** ^The third argument to xCreate(), bPurgeable, is true if the cache being
** created will be used to cache database pages of a file stored on disk, or
** false if it is used for an in-memory database. The cache implementation
-** does not have to do anything special based with the value of bPurgeable;
+** does not have to do anything special based upon the value of bPurgeable;
** it is purely advisory. ^On a cache where bPurgeable is false, SQLite will
** never invoke xUnpin() except to deliberately delete a page.
** ^In other words, calls to xUnpin() on a cache with bPurgeable set to
** false will always have the "discard" flag set to true.
-** ^Hence, a cache created with bPurgeable false will
+** ^Hence, a cache created with bPurgeable set to false will
** never contain any unpinned pages.
**
** [[the xCachesize() page cache method]]
** ^(The xCachesize() method may be called at any time by SQLite to set the
-** suggested maximum cache-size (number of pages stored by) the cache
+** suggested maximum cache-size (number of pages stored) for the cache
** instance passed as the first argument. This is the value configured using
** the SQLite "[PRAGMA cache_size]" command.)^ As with the bPurgeable
** parameter, the implementation is not required to do anything with this
@@ -9245,12 +9247,12 @@ struct sqlite3_pcache_page {
** implementation must return a pointer to the page buffer with its content
** intact. If the requested page is not already in the cache, then the
** cache implementation should use the value of the createFlag
-** parameter to help it determined what action to take:
+** parameter to help it determine what action to take:
**
** <table border=1 width=85% align=center>
** <tr><th> createFlag <th> Behavior when page is not already in cache
** <tr><td> 0 <td> Do not allocate a new page. Return NULL.
-** <tr><td> 1 <td> Allocate a new page if it easy and convenient to do so.
+** <tr><td> 1 <td> Allocate a new page if it is easy and convenient to do so.
** Otherwise return NULL.
** <tr><td> 2 <td> Make every effort to allocate a new page. Only return
** NULL if allocating a new page is effectively impossible.
@@ -9267,7 +9269,7 @@ struct sqlite3_pcache_page {
** as its second argument. If the third parameter, discard, is non-zero,
** then the page must be evicted from the cache.
** ^If the discard parameter is
-** zero, then the page may be discarded or retained at the discretion of
+** zero, then the page may be discarded or retained at the discretion of the
** page cache implementation. ^The page cache implementation
** may choose to evict unpinned pages at any time.
**
@@ -9285,7 +9287,7 @@ struct sqlite3_pcache_page {
** When SQLite calls the xTruncate() method, the cache must discard all
** existing cache entries with page numbers (keys) greater than or equal
** to the value of the iLimit parameter passed to xTruncate(). If any
-** of these pages are pinned, they are implicitly unpinned, meaning that
+** of these pages are pinned, they become implicitly unpinned, meaning that
** they can be safely discarded.
**
** [[the xDestroy() page cache method]]
@@ -9465,7 +9467,7 @@ typedef struct sqlite3_backup sqlite3_backup;
** external process or via a database connection other than the one being
** used by the backup operation, then the backup will be automatically
** restarted by the next call to sqlite3_backup_step(). ^If the source
-** database is modified by the using the same database connection as is used
+** database is modified by using the same database connection as is used
** by the backup operation, then the backup database is automatically
** updated at the same time.
**
@@ -9482,7 +9484,7 @@ typedef struct sqlite3_backup sqlite3_backup;
** and may not be used following a call to sqlite3_backup_finish().
**
** ^The value returned by sqlite3_backup_finish is [SQLITE_OK] if no
-** sqlite3_backup_step() errors occurred, regardless or whether or not
+** sqlite3_backup_step() errors occurred, regardless of whether or not
** sqlite3_backup_step() completed.
** ^If an out-of-memory condition or IO error occurred during any prior
** sqlite3_backup_step() call on the same [sqlite3_backup] object, then
@@ -9584,7 +9586,7 @@ int sqlite3_backup_pagecount(sqlite3_backup *p);
** application receives an SQLITE_LOCKED error, it may call the
** sqlite3_unlock_notify() method with the blocked connection handle as
** the first argument to register for a callback that will be invoked
-** when the blocking connections current transaction is concluded. ^The
+** when the blocking connection's current transaction is concluded. ^The
** callback is invoked from within the [sqlite3_step] or [sqlite3_close]
** call that concludes the blocking connection's transaction.
**
@@ -9604,7 +9606,7 @@ int sqlite3_backup_pagecount(sqlite3_backup *p);
** blocked connection already has a registered unlock-notify callback,
** then the new callback replaces the old.)^ ^If sqlite3_unlock_notify() is
** called with a NULL pointer as its second argument, then any existing
-** unlock-notify callback is canceled. ^The blocked connections
+** unlock-notify callback is canceled. ^The blocked connection's
** unlock-notify callback may also be canceled by closing the blocked
** connection using [sqlite3_close()].
**
@@ -10002,7 +10004,7 @@ int sqlite3_vtab_config(sqlite3*, int op, ...);
** support constraints. In this configuration (which is the default) if
** a call to the [xUpdate] method returns [SQLITE_CONSTRAINT], then the entire
** statement is rolled back as if [ON CONFLICT | OR ABORT] had been
-** specified as part of the users SQL statement, regardless of the actual
+** specified as part of the user's SQL statement, regardless of the actual
** ON CONFLICT mode specified.
**
** If X is non-zero, then the virtual table implementation guarantees
@@ -10036,7 +10038,7 @@ int sqlite3_vtab_config(sqlite3*, int op, ...);
** [[SQLITE_VTAB_INNOCUOUS]]<dt>SQLITE_VTAB_INNOCUOUS</dt>
** <dd>Calls of the form
** [sqlite3_vtab_config](db,SQLITE_VTAB_INNOCUOUS) from within the
-** the [xConnect] or [xCreate] methods of a [virtual table] implementation
+** [xConnect] or [xCreate] methods of a [virtual table] implementation
** identify that virtual table as being safe to use from within triggers
** and views. Conceptually, the SQLITE_VTAB_INNOCUOUS tag means that the
** virtual table can do no serious harm even if it is controlled by a
@@ -10204,7 +10206,7 @@ const char *sqlite3_vtab_collation(sqlite3_index_info*,int);
** </table>
**
** ^For the purposes of comparing virtual table output values to see if the
-** values are same value for sorting purposes, two NULL values are considered
+** values are the same value for sorting purposes, two NULL values are considered
** to be the same. In other words, the comparison operator is "IS"
** (or "IS NOT DISTINCT FROM") and not "==".
**
@@ -10214,7 +10216,7 @@ const char *sqlite3_vtab_collation(sqlite3_index_info*,int);
**
** ^A virtual table implementation is always free to return rows in any order
** it wants, as long as the "orderByConsumed" flag is not set. ^When the
-** the "orderByConsumed" flag is unset, the query planner will add extra
+** "orderByConsumed" flag is unset, the query planner will add extra
** [bytecode] to ensure that the final results returned by the SQL query are
** ordered correctly. The use of the "orderByConsumed" flag and the
** sqlite3_vtab_distinct() interface is merely an optimization. ^Careful
@@ -10311,7 +10313,7 @@ int sqlite3_vtab_in(sqlite3_index_info*, int iCons, int bHandle);
** sqlite3_vtab_in_next(X,P) should be one of the parameters to the
** xFilter method which invokes these routines, and specifically
** a parameter that was previously selected for all-at-once IN constraint
-** processing use the [sqlite3_vtab_in()] interface in the
+** processing using the [sqlite3_vtab_in()] interface in the
** [xBestIndex|xBestIndex method]. ^(If the X parameter is not
** an xFilter argument that was selected for all-at-once IN constraint
** processing, then these routines return [SQLITE_ERROR].)^
@@ -10366,7 +10368,7 @@ int sqlite3_vtab_in_next(sqlite3_value *pVal, sqlite3_value **ppOut);
** and only if *V is set to a value. ^The sqlite3_vtab_rhs_value(P,J,V)
** inteface returns SQLITE_NOTFOUND if the right-hand side of the J-th
** constraint is not available. ^The sqlite3_vtab_rhs_value() interface
-** can return an result code other than SQLITE_OK or SQLITE_NOTFOUND if
+** can return a result code other than SQLITE_OK or SQLITE_NOTFOUND if
** something goes wrong.
**
** The sqlite3_vtab_rhs_value() interface is usually only successful if
@@ -10394,8 +10396,8 @@ int sqlite3_vtab_rhs_value(sqlite3_index_info*, int, sqlite3_value **ppVal);
** KEYWORDS: {conflict resolution mode}
**
** These constants are returned by [sqlite3_vtab_on_conflict()] to
-** inform a [virtual table] implementation what the [ON CONFLICT] mode
-** is for the SQL statement being evaluated.
+** inform a [virtual table] implementation of the [ON CONFLICT] mode
+** for the SQL statement being evaluated.
**
** Note that the [SQLITE_IGNORE] constant is also used as a potential
** return value from the [sqlite3_set_authorizer()] callback and that
@@ -10435,39 +10437,39 @@ int sqlite3_vtab_rhs_value(sqlite3_index_info*, int, sqlite3_value **ppVal);
** [[SQLITE_SCANSTAT_EST]] <dt>SQLITE_SCANSTAT_EST</dt>
** <dd>^The "double" variable pointed to by the V parameter will be set to the
** query planner's estimate for the average number of rows output from each
-** iteration of the X-th loop. If the query planner's estimates was accurate,
+** iteration of the X-th loop. If the query planner's estimate was accurate,
** then this value will approximate the quotient NVISIT/NLOOP and the
** product of this value for all prior loops with the same SELECTID will
-** be the NLOOP value for the current loop.
+** be the NLOOP value for the current loop.</dd>
**
** [[SQLITE_SCANSTAT_NAME]] <dt>SQLITE_SCANSTAT_NAME</dt>
** <dd>^The "const char *" variable pointed to by the V parameter will be set
** to a zero-terminated UTF-8 string containing the name of the index or table
-** used for the X-th loop.
+** used for the X-th loop.</dd>
**
** [[SQLITE_SCANSTAT_EXPLAIN]] <dt>SQLITE_SCANSTAT_EXPLAIN</dt>
** <dd>^The "const char *" variable pointed to by the V parameter will be set
** to a zero-terminated UTF-8 string containing the [EXPLAIN QUERY PLAN]
-** description for the X-th loop.
+** description for the X-th loop.</dd>
**
** [[SQLITE_SCANSTAT_SELECTID]] <dt>SQLITE_SCANSTAT_SELECTID</dt>
** <dd>^The "int" variable pointed to by the V parameter will be set to the
** id for the X-th query plan element. The id value is unique within the
** statement. The select-id is the same value as is output in the first
-** column of an [EXPLAIN QUERY PLAN] query.
+** column of an [EXPLAIN QUERY PLAN] query.</dd>
**
** [[SQLITE_SCANSTAT_PARENTID]] <dt>SQLITE_SCANSTAT_PARENTID</dt>
** <dd>The "int" variable pointed to by the V parameter will be set to the
-** the id of the parent of the current query element, if applicable, or
+** id of the parent of the current query element, if applicable, or
** to zero if the query element has no parent. This is the same value as
-** returned in the second column of an [EXPLAIN QUERY PLAN] query.
+** returned in the second column of an [EXPLAIN QUERY PLAN] query.</dd>
**
** [[SQLITE_SCANSTAT_NCYCLE]] <dt>SQLITE_SCANSTAT_NCYCLE</dt>
** <dd>The sqlite3_int64 output value is set to the number of cycles,
** according to the processor time-stamp counter, that elapsed while the
** query element was being processed. This value is not available for
** all query elements - if it is unavailable the output variable is
-** set to -1.
+** set to -1.</dd>
** </dl>
*/
#define SQLITE_SCANSTAT_NLOOP 0
@@ -10508,8 +10510,8 @@ int sqlite3_vtab_rhs_value(sqlite3_index_info*, int, sqlite3_value **ppVal);
** sqlite3_stmt_scanstatus_v2() with a zeroed flags parameter.
**
** Parameter "idx" identifies the specific query element to retrieve statistics
-** for. Query elements are numbered starting from zero. A value of -1 may be
-** to query for statistics regarding the entire query. ^If idx is out of range
+** for. Query elements are numbered starting from zero. A value of -1 may
+** retrieve statistics for the entire query. ^If idx is out of range
** - less than -1 or greater than or equal to the total number of query
** elements used to implement the statement - a non-zero value is returned and
** the variable that pOut points to is unchanged.
@@ -10521,14 +10523,14 @@ int sqlite3_stmt_scanstatus(
int idx, /* Index of loop to report on */
int iScanStatusOp, /* Information desired. SQLITE_SCANSTAT_* */
void *pOut /* Result written here */
-);
+);
int sqlite3_stmt_scanstatus_v2(
sqlite3_stmt *pStmt, /* Prepared statement for which info desired */
int idx, /* Index of loop to report on */
int iScanStatusOp, /* Information desired. SQLITE_SCANSTAT_* */
int flags, /* Mask of flags defined below */
void *pOut /* Result written here */
-);
+);
/*
** CAPI3REF: Prepared Statement Scan Status
@@ -10552,7 +10554,7 @@ void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*);
** METHOD: sqlite3
**
** ^If a write-transaction is open on [database connection] D when the
-** [sqlite3_db_cacheflush(D)] interface invoked, any dirty
+** [sqlite3_db_cacheflush(D)] interface is invoked, any dirty
** pages in the pager-cache that are not currently in use are written out
** to disk. A dirty page may be in use if a database cursor created by an
** active SQL statement is reading from it, or if it is page 1 of a database
@@ -10666,8 +10668,8 @@ int sqlite3_db_cacheflush(sqlite3*);
** triggers; and so forth.
**
** When the [sqlite3_blob_write()] API is used to update a blob column,
-** the pre-update hook is invoked with SQLITE_DELETE. This is because the
-** in this case the new values are not available. In this case, when a
+** the pre-update hook is invoked with SQLITE_DELETE, because
+** the new values are not yet available. In this case, when a
** callback made with op==SQLITE_DELETE is actually a write using the
** sqlite3_blob_write() API, the [sqlite3_preupdate_blobwrite()] returns
** the index of the column being written. In other cases, where the
@@ -10920,7 +10922,7 @@ SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb);
** For an ordinary on-disk database file, the serialization is just a
** copy of the disk file. For an in-memory database or a "TEMP" database,
** the serialization is the same sequence of bytes which would be written
-** to disk if that database where backed up to disk.
+** to disk if that database were backed up to disk.
**
** The usual case is that sqlite3_serialize() copies the serialization of
** the database into memory obtained from [sqlite3_malloc64()] and returns
@@ -10929,7 +10931,7 @@ SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb);
** contains the SQLITE_SERIALIZE_NOCOPY bit, then no memory allocations
** are made, and the sqlite3_serialize() function will return a pointer
** to the contiguous memory representation of the database that SQLite
-** is currently using for that database, or NULL if the no such contiguous
+** is currently using for that database, or NULL if no such contiguous
** memory representation of the database exists. A contiguous memory
** representation of the database will usually only exist if there has
** been a prior call to [sqlite3_deserialize(D,S,...)] with the same
@@ -11000,7 +11002,7 @@ unsigned char *sqlite3_serialize(
** database is currently in a read transaction or is involved in a backup
** operation.
**
-** It is not possible to deserialized into the TEMP database. If the
+** It is not possible to deserialize into the TEMP database. If the
** S argument to sqlite3_deserialize(D,S,P,N,M,F) is "temp" then the
** function returns SQLITE_ERROR.
**
@@ -11022,7 +11024,7 @@ int sqlite3_deserialize(
sqlite3 *db, /* The database connection */
const char *zSchema, /* Which DB to reopen with the deserialization */
unsigned char *pData, /* The serialized database content */
- sqlite3_int64 szDb, /* Number bytes in the deserialization */
+ sqlite3_int64 szDb, /* Number of bytes in the deserialization */
sqlite3_int64 szBuf, /* Total size of buffer pData[] */
unsigned mFlags /* Zero or more SQLITE_DESERIALIZE_* flags */
);
@@ -11030,7 +11032,7 @@ int sqlite3_deserialize(
/*
** CAPI3REF: Flags for sqlite3_deserialize()
**
-** The following are allowed values for 6th argument (the F argument) to
+** The following are allowed values for the 6th argument (the F argument) to
** the [sqlite3_deserialize(D,S,P,N,M,F)] interface.
**
** The SQLITE_DESERIALIZE_FREEONCLOSE means that the database serialization
diff --git a/src/sqlite3ext.h b/src/sqlite3ext.h
index ae0949baf..cf775dfbd 100644
--- a/src/sqlite3ext.h
+++ b/src/sqlite3ext.h
@@ -366,6 +366,8 @@ struct sqlite3_api_routines {
/* Version 3.44.0 and later */
void *(*get_clientdata)(sqlite3*,const char*);
int (*set_clientdata)(sqlite3*, const char*, void*, void(*)(void*));
+ /* Version 3.50.0 and later */
+ int (*setlk_timeout)(sqlite3*,int,int);
};
/*
@@ -699,6 +701,8 @@ typedef int (*sqlite3_loadext_entry)(
/* Version 3.44.0 and later */
#define sqlite3_get_clientdata sqlite3_api->get_clientdata
#define sqlite3_set_clientdata sqlite3_api->set_clientdata
+/* Version 3.50.0 and later */
+#define sqlite3_setlk_timeout sqlite3_api->setlk_timeout
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index af7ed4a4c..7b914d958 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -765,7 +765,7 @@
** ourselves.
*/
#ifndef offsetof
-#define offsetof(STRUCTURE,FIELD) ((size_t)((char*)&((STRUCTURE*)0)->FIELD))
+# define offsetof(ST,M) ((size_t)((char*)&((ST*)0)->M - (char*)0))
#endif
/*
@@ -1031,8 +1031,8 @@ typedef INT16_TYPE LogEst;
** assuming n is a signed integer type. UMXV(n) is similar for unsigned
** integer types.
*/
-#define SMXV(n) ((((i64)1)<<(sizeof(n)-1))-1)
-#define UMXV(n) ((((i64)1)<<(sizeof(n)))-1)
+#define SMXV(n) ((((i64)1)<<(sizeof(n)*8-1))-1)
+#define UMXV(n) ((((i64)1)<<(sizeof(n)*8))-1)
/*
** Round up a number to the next larger multiple of 8. This is used
@@ -1153,6 +1153,8 @@ extern 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
*/
/*
@@ -1197,6 +1199,7 @@ extern u32 sqlite3WhereTrace;
** 0x00020000 Show WHERE terms returned from whereScanNext()
** 0x00040000 Solver overview messages
** 0x00080000 Star-query heuristic
+** 0x00100000 Pointers are all shown as zero
*/
@@ -1269,7 +1272,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)sqlite3OomClear)
+#define SQLITE_DYNAMIC ((sqlite3_destructor_type)sqlite3RowSetClear)
/*
** When SQLITE_OMIT_WSD is defined, it means that the target platform does
@@ -1924,6 +1927,7 @@ 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 */
/*
@@ -2329,6 +2333,7 @@ struct CollSeq {
#define SQLITE_AFF_INTEGER 0x44 /* 'D' */
#define SQLITE_AFF_REAL 0x45 /* 'E' */
#define SQLITE_AFF_FLEXNUM 0x46 /* 'F' */
+#define SQLITE_AFF_DEFER 0x58 /* 'X' - defer computation until later */
#define sqlite3IsNumericAffinity(X) ((X)>=SQLITE_AFF_NUMERIC)
@@ -2644,9 +2649,15 @@ struct FKey {
** argument to sqlite3VdbeKeyCompare and is used to control the
** comparison of the two index keys.
**
-** 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.
+** 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.
*/
struct KeyInfo {
u32 nRef; /* Number of references to this KeyInfo object */
@@ -2658,9 +2669,18 @@ 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 */
+/* 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[]. */
#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.
*/
@@ -2679,9 +2699,8 @@ 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 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.
+** 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.
**
** 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
@@ -2691,7 +2710,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 pKeyInfo->nFields,) then default_rc can be set to -1 to
+** at the first nField elements) 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.
**
@@ -2703,8 +2722,8 @@ struct KeyInfo {
** b-tree.
*/
struct UnpackedRecord {
- KeyInfo *pKeyInfo; /* Collation and sort-order information */
- Mem *aMem; /* Values */
+ KeyInfo *pKeyInfo; /* Comparison info for the index that is unpacked */
+ Mem *aMem; /* Values for columns of the index */
union {
char *z; /* Cache of aMem[0].z for vdbeRecordCompareString() */
i64 i; /* Cache of aMem[0].u.i for vdbeRecordCompareInt() */
@@ -2791,7 +2810,6 @@ struct Index {
unsigned hasStat1:1; /* aiRowLogEst values come from sqlite_stat1 */
unsigned bNoQuery:1; /* Do not use this index to optimize queries */
unsigned bAscKeyBug:1; /* True if the bba7b69f9849b5bf bug applies */
- unsigned bIdxRowid:1; /* One or more of the index keys is the ROWID */
unsigned bHasVCol:1; /* Index references one or more VIRTUAL columns */
unsigned bHasExpr:1; /* Index contains an expression, either a literal
** expression, or a reference to a VIRTUAL column */
@@ -2879,7 +2897,7 @@ struct AggInfo {
** from source tables rather than from accumulators */
u8 useSortingIdx; /* In direct mode, reference the sorting index rather
** than the source table */
- u16 nSortingColumn; /* Number of columns in the sorting index */
+ u32 nSortingColumn; /* Number of columns in the sorting index */
int sortingIdx; /* Cursor number of the sorting index */
int sortingIdxPTab; /* Cursor number of pseudo-table */
int iFirstReg; /* First register in range for aCol[] and aFunc[] */
@@ -2888,8 +2906,8 @@ struct AggInfo {
Table *pTab; /* Source table */
Expr *pCExpr; /* The original expression */
int iTable; /* Cursor number of the source table */
- i16 iColumn; /* Column number within the source table */
- i16 iSorterColumn; /* Column number in the sorting index */
+ int iColumn; /* Column number within the source table */
+ int iSorterColumn; /* Column number in the sorting index */
} *aCol;
int nColumn; /* Number of used entries in aCol[] */
int nAccumulator; /* Number of columns that show through to the output.
@@ -3353,6 +3371,7 @@ 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 */
@@ -3883,6 +3902,7 @@ 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 */
@@ -4879,6 +4899,7 @@ char *sqlite3VMPrintf(sqlite3*,const char*, va_list);
void sqlite3ShowWindow(const Window*);
void sqlite3ShowWinFunc(const Window*);
#endif
+ void sqlite3ShowBitvec(Bitvec*);
#endif
void sqlite3SetString(char **, sqlite3*, const char*);
diff --git a/src/tclsqlite.c b/src/tclsqlite.c
index 7675a9125..02a4d84e4 100644
--- a/src/tclsqlite.c
+++ b/src/tclsqlite.c
@@ -49,6 +49,10 @@
# define CONST const
#elif !defined(Tcl_Size)
typedef int Tcl_Size;
+# ifndef Tcl_BounceRefCount
+# define Tcl_BounceRefCount(X) Tcl_IncrRefCount(X); Tcl_DecrRefCount(X)
+ /* https://www.tcl-lang.org/man/tcl9.0/TclLib/Object.html */
+# endif
#endif
/**** End copy of tclsqlite.h ****/
@@ -1084,7 +1088,9 @@ static void tclSqlFunc(sqlite3_context *context, int argc, sqlite3_value**argv){
Tcl_DecrRefCount(pCmd);
}
- if( rc && rc!=TCL_RETURN ){
+ if( TCL_BREAK==rc ){
+ sqlite3_result_null(context);
+ }else if( rc && rc!=TCL_RETURN ){
sqlite3_result_error(context, Tcl_GetStringResult(p->interp), -1);
}else{
Tcl_Obj *pVar = Tcl_GetObjResult(p->interp);
@@ -1102,7 +1108,7 @@ static void tclSqlFunc(sqlite3_context *context, int argc, sqlite3_value**argv){
}else if( (c=='b' && pVar->bytes==0 && strcmp(zType,"boolean")==0 )
|| (c=='b' && pVar->bytes==0 && strcmp(zType,"booleanString")==0 )
|| (c=='w' && strcmp(zType,"wideInt")==0)
- || (c=='i' && strcmp(zType,"int")==0)
+ || (c=='i' && strcmp(zType,"int")==0)
){
eType = SQLITE_INTEGER;
}else if( c=='d' && strcmp(zType,"double")==0 ){
@@ -1616,11 +1622,12 @@ struct DbEvalContext {
SqlPreparedStmt *pPreStmt; /* Current statement */
int nCol; /* Number of columns returned by pStmt */
int evalFlags; /* Flags used */
- Tcl_Obj *pArray; /* Name of array variable */
+ Tcl_Obj *pVarName; /* Name of target array/dict variable */
Tcl_Obj **apColName; /* Array of column names */
};
#define SQLITE_EVAL_WITHOUTNULLS 0x00001 /* Unset array(*) for NULL */
+#define SQLITE_EVAL_ASDICT 0x00002 /* Use dict instead of array */
/*
** Release any cache of column names currently held as part of
@@ -1641,20 +1648,20 @@ static void dbReleaseColumnNames(DbEvalContext *p){
/*
** Initialize a DbEvalContext structure.
**
-** If pArray is not NULL, then it contains the name of a Tcl array
+** If pVarName is not NULL, then it contains the name of a Tcl array
** variable. The "*" member of this array is set to a list containing
** the names of the columns returned by the statement as part of each
** call to dbEvalStep(), in order from left to right. e.g. if the names
** of the returned columns are a, b and c, it does the equivalent of the
** tcl command:
**
-** set ${pArray}(*) {a b c}
+** set ${pVarName}(*) {a b c}
*/
static void dbEvalInit(
DbEvalContext *p, /* Pointer to structure to initialize */
SqliteDb *pDb, /* Database handle */
Tcl_Obj *pSql, /* Object containing SQL script */
- Tcl_Obj *pArray, /* Name of Tcl array to set (*) element of */
+ Tcl_Obj *pVarName, /* Name of Tcl array to set (*) element of */
int evalFlags /* Flags controlling evaluation */
){
memset(p, 0, sizeof(DbEvalContext));
@@ -1662,9 +1669,9 @@ static void dbEvalInit(
p->zSql = Tcl_GetString(pSql);
p->pSql = pSql;
Tcl_IncrRefCount(pSql);
- if( pArray ){
- p->pArray = pArray;
- Tcl_IncrRefCount(pArray);
+ if( pVarName ){
+ p->pVarName = pVarName;
+ Tcl_IncrRefCount(pVarName);
}
p->evalFlags = evalFlags;
addDatabaseRef(p->pDb);
@@ -1687,7 +1694,7 @@ static void dbEvalRowInfo(
Tcl_Obj **apColName = 0; /* Array of column names */
p->nCol = nCol = sqlite3_column_count(pStmt);
- if( nCol>0 && (papColName || p->pArray) ){
+ if( nCol>0 && (papColName || p->pVarName) ){
apColName = (Tcl_Obj**)Tcl_Alloc( sizeof(Tcl_Obj*)*nCol );
for(i=0; i<nCol; i++){
apColName[i] = Tcl_NewStringObj(sqlite3_column_name(pStmt,i), -1);
@@ -1696,20 +1703,35 @@ static void dbEvalRowInfo(
p->apColName = apColName;
}
- /* If results are being stored in an array variable, then create
- ** the array(*) entry for that array
+ /* If results are being stored in a variable then create the
+ ** array(*) or dict(*) entry for that variable.
*/
- if( p->pArray ){
+ if( p->pVarName ){
Tcl_Interp *interp = p->pDb->interp;
Tcl_Obj *pColList = Tcl_NewObj();
Tcl_Obj *pStar = Tcl_NewStringObj("*", -1);
+ Tcl_IncrRefCount(pColList);
+ Tcl_IncrRefCount(pStar);
for(i=0; i<nCol; i++){
Tcl_ListObjAppendElement(interp, pColList, apColName[i]);
}
- Tcl_IncrRefCount(pStar);
- Tcl_ObjSetVar2(interp, p->pArray, pStar, pColList, 0);
+ if( 0==(SQLITE_EVAL_ASDICT & p->evalFlags) ){
+ Tcl_ObjSetVar2(interp, p->pVarName, pStar, pColList, 0);
+ }else{
+ Tcl_Obj * pDict = Tcl_ObjGetVar2(interp, p->pVarName, NULL, 0);
+ if( !pDict ){
+ pDict = Tcl_NewDictObj();
+ }else if( Tcl_IsShared(pDict) ){
+ pDict = Tcl_DuplicateObj(pDict);
+ }
+ if( Tcl_DictObjPut(interp, pDict, pStar, pColList)==TCL_OK ){
+ Tcl_ObjSetVar2(interp, p->pVarName, NULL, pDict, 0);
+ }
+ Tcl_BounceRefCount(pDict);
+ }
Tcl_DecrRefCount(pStar);
+ Tcl_DecrRefCount(pColList);
}
}
@@ -1751,7 +1773,7 @@ static int dbEvalStep(DbEvalContext *p){
if( rcs==SQLITE_ROW ){
return TCL_OK;
}
- if( p->pArray ){
+ if( p->pVarName ){
dbEvalRowInfo(p, 0, 0);
}
rcs = sqlite3_reset(pStmt);
@@ -1802,9 +1824,9 @@ static void dbEvalFinalize(DbEvalContext *p){
dbReleaseStmt(p->pDb, p->pPreStmt, 0);
p->pPreStmt = 0;
}
- if( p->pArray ){
- Tcl_DecrRefCount(p->pArray);
- p->pArray = 0;
+ if( p->pVarName ){
+ Tcl_DecrRefCount(p->pVarName);
+ p->pVarName = 0;
}
Tcl_DecrRefCount(p->pSql);
dbReleaseColumnNames(p);
@@ -1879,7 +1901,7 @@ static int DbUseNre(void){
/*
** This function is part of the implementation of the command:
**
-** $db eval SQL ?ARRAYNAME? SCRIPT
+** $db eval SQL ?TGT-NAME? SCRIPT
*/
static int SQLITE_TCLAPI DbEvalNextCmd(
ClientData data[], /* data[0] is the (DbEvalContext*) */
@@ -1893,8 +1915,8 @@ static int SQLITE_TCLAPI DbEvalNextCmd(
** is a pointer to a Tcl_Obj containing the script to run for each row
** returned by the queries encapsulated in data[0]. */
DbEvalContext *p = (DbEvalContext *)data[0];
- Tcl_Obj *pScript = (Tcl_Obj *)data[1];
- Tcl_Obj *pArray = p->pArray;
+ Tcl_Obj * const pScript = (Tcl_Obj *)data[1];
+ Tcl_Obj * const pVarName = p->pVarName;
while( (rc==TCL_OK || rc==TCL_CONTINUE) && TCL_OK==(rc = dbEvalStep(p)) ){
int i;
@@ -1902,15 +1924,46 @@ static int SQLITE_TCLAPI DbEvalNextCmd(
Tcl_Obj **apColName;
dbEvalRowInfo(p, &nCol, &apColName);
for(i=0; i<nCol; i++){
- if( pArray==0 ){
+ if( pVarName==0 ){
Tcl_ObjSetVar2(interp, apColName[i], 0, dbEvalColumnValue(p,i), 0);
}else if( (p->evalFlags & SQLITE_EVAL_WITHOUTNULLS)!=0
- && sqlite3_column_type(p->pPreStmt->pStmt, i)==SQLITE_NULL
+ && sqlite3_column_type(p->pPreStmt->pStmt, i)==SQLITE_NULL
){
- Tcl_UnsetVar2(interp, Tcl_GetString(pArray),
- Tcl_GetString(apColName[i]), 0);
+ /* Remove NULL-containing column from the target container... */
+ if( 0==(SQLITE_EVAL_ASDICT & p->evalFlags) ){
+ /* Target is an array */
+ Tcl_UnsetVar2(interp, Tcl_GetString(pVarName),
+ Tcl_GetString(apColName[i]), 0);
+ }else{
+ /* Target is a dict */
+ Tcl_Obj *pDict = Tcl_ObjGetVar2(interp, pVarName, NULL, 0);
+ if( pDict ){
+ if( Tcl_IsShared(pDict) ){
+ pDict = Tcl_DuplicateObj(pDict);
+ }
+ if( Tcl_DictObjRemove(interp, pDict, apColName[i])==TCL_OK ){
+ Tcl_ObjSetVar2(interp, pVarName, NULL, pDict, 0);
+ }
+ Tcl_BounceRefCount(pDict);
+ }
+ }
+ }else if( 0==(SQLITE_EVAL_ASDICT & p->evalFlags) ){
+ /* Target is an array: set target(colName) = colValue */
+ Tcl_ObjSetVar2(interp, pVarName, apColName[i],
+ dbEvalColumnValue(p,i), 0);
}else{
- Tcl_ObjSetVar2(interp, pArray, apColName[i], dbEvalColumnValue(p,i), 0);
+ /* Target is a dict: set target(colName) = colValue */
+ Tcl_Obj *pDict = Tcl_ObjGetVar2(interp, pVarName, NULL, 0);
+ if( !pDict ){
+ pDict = Tcl_NewDictObj();
+ }else if( Tcl_IsShared(pDict) ){
+ pDict = Tcl_DuplicateObj(pDict);
+ }
+ if( Tcl_DictObjPut(interp, pDict, apColName[i],
+ dbEvalColumnValue(p,i))==TCL_OK ){
+ Tcl_ObjSetVar2(interp, pVarName, NULL, pDict, 0);
+ }
+ Tcl_BounceRefCount(pDict);
}
}
@@ -2019,7 +2072,7 @@ static int SQLITE_TCLAPI DbObjCmd(
"timeout", "total_changes", "trace",
"trace_v2", "transaction", "unlock_notify",
"update_hook", "version", "wal_hook",
- 0
+ 0
};
enum DB_enum {
DB_AUTHORIZER, DB_BACKUP, DB_BIND_FALLBACK,
@@ -2853,13 +2906,15 @@ deserialize_error:
}
/*
- ** $db eval ?options? $sql ?array? ?{ ...code... }?
+ ** $db eval ?options? $sql ?varName? ?{ ...code... }?
**
- ** The SQL statement in $sql is evaluated. For each row, the values are
- ** placed in elements of the array named "array" and ...code... is executed.
- ** If "array" and "code" are omitted, then no callback is every invoked.
- ** If "array" is an empty string, then the values are placed in variables
- ** that have the same name as the fields extracted by the query.
+ ** The SQL statement in $sql is evaluated. For each row, the values
+ ** are placed in elements of the array or dict named $varName and
+ ** ...code... is executed. If $varName and $code are omitted, then
+ ** no callback is ever invoked. If $varName is an empty string,
+ ** then the values are placed in variables that have the same name
+ ** as the fields extracted by the query, and those variables are
+ ** accessible during the eval of $code.
*/
case DB_EVAL: {
int evalFlags = 0;
@@ -2867,8 +2922,9 @@ deserialize_error:
while( objc>3 && (zOpt = Tcl_GetString(objv[2]))!=0 && zOpt[0]=='-' ){
if( strcmp(zOpt, "-withoutnulls")==0 ){
evalFlags |= SQLITE_EVAL_WITHOUTNULLS;
- }
- else{
+ }else if( strcmp(zOpt, "-asdict")==0 ){
+ evalFlags |= SQLITE_EVAL_ASDICT;
+ }else{
Tcl_AppendResult(interp, "unknown option: \"", zOpt, "\"", (void*)0);
return TCL_ERROR;
}
@@ -2876,8 +2932,8 @@ deserialize_error:
objv++;
}
if( objc<3 || objc>5 ){
- Tcl_WrongNumArgs(interp, 2, objv,
- "?OPTIONS? SQL ?ARRAY-NAME? ?SCRIPT?");
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "?OPTIONS? SQL ?VAR-NAME? ?SCRIPT?");
return TCL_ERROR;
}
@@ -2903,17 +2959,17 @@ deserialize_error:
}else{
ClientData cd2[2];
DbEvalContext *p;
- Tcl_Obj *pArray = 0;
+ Tcl_Obj *pVarName = 0;
Tcl_Obj *pScript;
if( objc>=5 && *(char *)Tcl_GetString(objv[3]) ){
- pArray = objv[3];
+ pVarName = objv[3];
}
pScript = objv[objc-1];
Tcl_IncrRefCount(pScript);
p = (DbEvalContext *)Tcl_Alloc(sizeof(DbEvalContext));
- dbEvalInit(p, pDb, objv[2], pArray, evalFlags);
+ dbEvalInit(p, pDb, objv[2], pVarName, evalFlags);
cd2[0] = (void *)p;
cd2[1] = (void *)pScript;
@@ -4044,8 +4100,8 @@ EXTERN int sqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp);}
#if defined(TCLSH)
/* This is the main routine for an ordinary TCL shell. If there are
-** are arguments, run the first argument as a script. Otherwise,
-** read TCL commands from standard input
+** arguments, run the first argument as a script. Otherwise, read TCL
+** commands from standard input
*/
static const char *tclsh_main_loop(void){
static const char zMainloop[] =
diff --git a/src/test1.c b/src/test1.c
index bb2f2d3b9..1c363ca3b 100644
--- a/src/test1.c
+++ b/src/test1.c
@@ -8458,7 +8458,12 @@ static int SQLITE_TCLAPI test_sqlite3_db_config(
{ "DQS_DML", SQLITE_DBCONFIG_DQS_DML },
{ "DQS_DDL", SQLITE_DBCONFIG_DQS_DDL },
{ "LEGACY_FILE_FORMAT", SQLITE_DBCONFIG_LEGACY_FILE_FORMAT },
+ { "TRUSTED_SCHEMA", SQLITE_DBCONFIG_TRUSTED_SCHEMA },
{ "STMT_SCANSTATUS", SQLITE_DBCONFIG_STMT_SCANSTATUS },
+ { "REVERSE_SCANORDER", SQLITE_DBCONFIG_REVERSE_SCANORDER },
+ { "ATTACH_CREATE", SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE },
+ { "ATTACH_WRITE", SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE },
+ { "COMMENTS", SQLITE_DBCONFIG_ENABLE_COMMENTS },
};
int i;
int v = 0;
diff --git a/src/test_fs.c b/src/test_fs.c
index 1c47bbaac..6879f8273 100644
--- a/src/test_fs.c
+++ b/src/test_fs.c
@@ -72,12 +72,8 @@
#if !defined(_WIN32) || defined(__MSVCRT__)
# include <unistd.h>
# include <dirent.h>
-# ifndef DIRENT
-# define DIRENT dirent
-# endif
#else
-# include <io.h>
-# include "test_windirent.h"
+# include "windirent.h"
# ifndef S_ISREG
# define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
# endif
@@ -121,7 +117,7 @@ struct FsdirCsr {
char *zDir; /* Buffer containing directory scanned */
DIR *pDir; /* Open directory */
sqlite3_int64 iRowid;
- struct DIRENT *pEntry;
+ struct dirent *pEntry;
};
/*
@@ -483,9 +479,9 @@ static int fstreeFilter(
char aWild[2] = { '\0', '\0' };
#ifdef _WIN32
- const char *zDrive = windirent_getenv("fstreeDrive");
+ const char *zDrive = getenv("fstreeDrive");
if( zDrive==0 ){
- zDrive = windirent_getenv("SystemDrive");
+ zDrive = getenv("SystemDrive");
}
zRoot = sqlite3_mprintf("%s%c", zDrive, '/');
nRoot = sqlite3Strlen30(zRoot);
diff --git a/src/test_windirent.c b/src/test_windirent.c
deleted file mode 100644
index de4192d7c..000000000
--- a/src/test_windirent.c
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
-** 2015 November 30
-**
-** 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 contains code to implement most of the opendir() family of
-** POSIX functions on Win32 using the MSVCRT.
-*/
-
-#if defined(_WIN32) && defined(_MSC_VER)
-#include "test_windirent.h"
-
-/*
-** Implementation of the POSIX getenv() function using the Win32 API.
-** This function is not thread-safe.
-*/
-const char *windirent_getenv(
- const char *name
-){
- static char value[32768]; /* Maximum length, per MSDN */
- DWORD dwSize = sizeof(value) / sizeof(char); /* Size in chars */
- DWORD dwRet; /* Value returned by GetEnvironmentVariableA() */
-
- memset(value, 0, sizeof(value));
- dwRet = GetEnvironmentVariableA(name, value, dwSize);
- if( dwRet==0 || dwRet>dwSize ){
- /*
- ** The function call to GetEnvironmentVariableA() failed -OR-
- ** the buffer is not large enough. Either way, return NULL.
- */
- return 0;
- }else{
- /*
- ** The function call to GetEnvironmentVariableA() succeeded
- ** -AND- the buffer contains the entire value.
- */
- return value;
- }
-}
-
-/*
-** Implementation of the POSIX opendir() function using the MSVCRT.
-*/
-LPDIR opendir(
- const char *dirname /* Directory name, UTF8 encoding */
-){
- struct _wfinddata_t data;
- LPDIR dirp = (LPDIR)sqlite3_malloc(sizeof(DIR));
- SIZE_T namesize = sizeof(data.name) / sizeof(data.name[0]);
- wchar_t *b1;
- sqlite3_int64 sz;
-
- if( dirp==NULL ) return NULL;
- memset(dirp, 0, sizeof(DIR));
-
- /* TODO: Remove this if Unix-style root paths are not used. */
- if( sqlite3_stricmp(dirname, "/")==0 ){
- dirname = windirent_getenv("SystemDrive");
- }
-
- memset(&data, 0, sizeof(data));
- sz = strlen(dirname);
- b1 = sqlite3_malloc64( (sz+3)*sizeof(b1[0]) );
- if( b1==0 ){
- closedir(dirp);
- return NULL;
- }
- sz = MultiByteToWideChar(CP_UTF8, 0, dirname, sz, b1, sz);
- b1[sz++] = '\\';
- b1[sz++] = '*';
- b1[sz] = 0;
- if( sz+1>(sqlite3_int64)namesize ){
- closedir(dirp);
- sqlite3_free(b1);
- return NULL;
- }
- memcpy(data.name, b1, (sz+1)*sizeof(b1[0]));
- sqlite3_free(b1);
- dirp->d_handle = _wfindfirst(data.name, &data);
-
- if( dirp->d_handle==BAD_INTPTR_T ){
- closedir(dirp);
- return NULL;
- }
-
- /* TODO: Remove this block to allow hidden and/or system files. */
- if( is_filtered(data) ){
-next:
-
- memset(&data, 0, sizeof(data));
- if( _wfindnext(dirp->d_handle, &data)==-1 ){
- closedir(dirp);
- return NULL;
- }
-
- /* TODO: Remove this block to allow hidden and/or system files. */
- if( is_filtered(data) ) goto next;
- }
-
- dirp->d_first.d_attributes = data.attrib;
- WideCharToMultiByte(CP_UTF8, 0, data.name, -1,
- dirp->d_first.d_name, DIRENT_NAME_MAX, 0, 0);
- return dirp;
-}
-
-/*
-** Implementation of the POSIX readdir() function using the MSVCRT.
-*/
-LPDIRENT readdir(
- LPDIR dirp
-){
- struct _wfinddata_t data;
-
- if( dirp==NULL ) return NULL;
-
- if( dirp->d_first.d_ino==0 ){
- dirp->d_first.d_ino++;
- dirp->d_next.d_ino++;
-
- return &dirp->d_first;
- }
-
-next:
-
- memset(&data, 0, sizeof(data));
- if( _wfindnext(dirp->d_handle, &data)==-1 ) return NULL;
-
- /* TODO: Remove this block to allow hidden and/or system files. */
- if( is_filtered(data) ) goto next;
-
- dirp->d_next.d_ino++;
- dirp->d_next.d_attributes = data.attrib;
- WideCharToMultiByte(CP_UTF8, 0, data.name, -1,
- dirp->d_next.d_name, DIRENT_NAME_MAX, 0, 0);
- return &dirp->d_next;
-}
-
-/*
-** Implementation of the POSIX closedir() function using the MSVCRT.
-*/
-INT closedir(
- LPDIR dirp
-){
- INT result = 0;
-
- if( dirp==NULL ) return EINVAL;
-
- if( dirp->d_handle!=NULL_INTPTR_T && dirp->d_handle!=BAD_INTPTR_T ){
- result = _findclose(dirp->d_handle);
- }
-
- sqlite3_free(dirp);
- return result;
-}
-
-#endif /* defined(WIN32) && defined(_MSC_VER) */
diff --git a/src/test_windirent.h b/src/test_windirent.h
deleted file mode 100644
index 527dfaa8f..000000000
--- a/src/test_windirent.h
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
-** 2015 November 30
-**
-** 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 contains declarations for most of the opendir() family of
-** POSIX functions on Win32 using the MSVCRT.
-*/
-
-#if defined(_WIN32) && defined(_MSC_VER) && !defined(SQLITE_WINDIRENT_H)
-#define SQLITE_WINDIRENT_H
-
-/*
-** We need several data types from the Windows SDK header.
-*/
-
-#ifndef WIN32_LEAN_AND_MEAN
-#define WIN32_LEAN_AND_MEAN
-#endif
-
-#include "windows.h"
-
-/*
-** We need several support functions from the SQLite core.
-*/
-
-#include "sqlite3.h"
-
-/*
-** We need several things from the ANSI and MSVCRT headers.
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <io.h>
-#include <limits.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-/*
-** We may need several defines that should have been in "sys/stat.h".
-*/
-
-#ifndef S_ISREG
-#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
-#endif
-
-#ifndef S_ISDIR
-#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
-#endif
-
-#ifndef S_ISLNK
-#define S_ISLNK(mode) (0)
-#endif
-
-/*
-** We may need to provide the "mode_t" type.
-*/
-
-#ifndef MODE_T_DEFINED
- #define MODE_T_DEFINED
- typedef unsigned short mode_t;
-#endif
-
-/*
-** We may need to provide the "ino_t" type.
-*/
-
-#ifndef INO_T_DEFINED
- #define INO_T_DEFINED
- typedef unsigned short ino_t;
-#endif
-
-/*
-** We need to define "NAME_MAX" if it was not present in "limits.h".
-*/
-
-#ifndef NAME_MAX
-# ifdef FILENAME_MAX
-# define NAME_MAX (FILENAME_MAX)
-# else
-# define NAME_MAX (260)
-# endif
-# define DIRENT_NAME_MAX (NAME_MAX)
-#endif
-
-/*
-** We need to define "NULL_INTPTR_T" and "BAD_INTPTR_T".
-*/
-
-#ifndef NULL_INTPTR_T
-# define NULL_INTPTR_T ((intptr_t)(0))
-#endif
-
-#ifndef BAD_INTPTR_T
-# define BAD_INTPTR_T ((intptr_t)(-1))
-#endif
-
-/*
-** We need to provide the necessary structures and related types.
-*/
-
-#ifndef DIRENT_DEFINED
-#define DIRENT_DEFINED
-typedef struct DIRENT DIRENT;
-typedef DIRENT *LPDIRENT;
-struct DIRENT {
- ino_t d_ino; /* Sequence number, do not use. */
- unsigned d_attributes; /* Win32 file attributes. */
- char d_name[NAME_MAX + 1]; /* Name within the directory. */
-};
-#endif
-
-#ifndef DIR_DEFINED
-#define DIR_DEFINED
-typedef struct DIR DIR;
-typedef DIR *LPDIR;
-struct DIR {
- intptr_t d_handle; /* Value returned by "_findfirst". */
- DIRENT d_first; /* DIRENT constructed based on "_findfirst". */
- DIRENT d_next; /* DIRENT constructed based on "_findnext". */
-};
-#endif
-
-/*
-** Provide a macro, for use by the implementation, to determine if a
-** particular directory entry should be skipped over when searching for
-** the next directory entry that should be returned by the readdir().
-*/
-
-#ifndef is_filtered
-# define is_filtered(a) ((((a).attrib)&_A_HIDDEN) || (((a).attrib)&_A_SYSTEM))
-#endif
-
-/*
-** Provide the function prototype for the POSIX compatible getenv()
-** function. This function is not thread-safe.
-*/
-
-extern const char *windirent_getenv(const char *name);
-
-/*
-** Finally, we can provide the function prototypes for the opendir(),
-** readdir(), and closedir() POSIX functions.
-*/
-
-extern LPDIR opendir(const char *dirname);
-extern LPDIRENT readdir(LPDIR dirp);
-extern INT closedir(LPDIR dirp);
-
-#endif /* defined(WIN32) && defined(_MSC_VER) */
diff --git a/src/tokenize.c b/src/tokenize.c
index e4d9f5371..6f7bab35b 100644
--- a/src/tokenize.c
+++ b/src/tokenize.c
@@ -199,7 +199,7 @@ static int getToken(const unsigned char **pz){
int t; /* Token type to return */
do {
z += sqlite3GetToken(z, &t);
- }while( t==TK_SPACE );
+ }while( t==TK_SPACE || t==TK_COMMENT );
if( t==TK_ID
|| t==TK_STRING
|| t==TK_JOIN_KW
diff --git a/src/utf.c b/src/utf.c
index e24e1586b..2efcd6791 100644
--- a/src/utf.c
+++ b/src/utf.c
@@ -108,7 +108,7 @@ static const unsigned char sqlite3Utf8Trans1[] = {
/*
** Write a single UTF8 character whose value is v into the
** buffer starting at zOut. zOut must be sized to hold at
-** least for bytes. Return the number of bytes needed
+** least four bytes. Return the number of bytes needed
** to encode the new character.
*/
int sqlite3AppendOneUtf8Character(char *zOut, u32 v){
diff --git a/src/vacuum.c b/src/vacuum.c
index 96d77e5bc..1b4838040 100644
--- a/src/vacuum.c
+++ b/src/vacuum.c
@@ -195,7 +195,8 @@ SQLITE_NOINLINE int sqlite3RunVacuum(
saved_nChange = db->nChange;
saved_nTotalChange = db->nTotalChange;
saved_mTrace = db->mTrace;
- db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks | SQLITE_Comments;
+ db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks | SQLITE_Comments
+ | SQLITE_AttachCreate | SQLITE_AttachWrite;
db->mDbFlags |= DBFLAG_PreferBuiltin | DBFLAG_Vacuum;
db->flags &= ~(u64)(SQLITE_ForeignKeys | SQLITE_ReverseOrder
| SQLITE_Defensive | SQLITE_CountRows);
diff --git a/src/vdbe.c b/src/vdbe.c
index 29b6f9a65..9e456a1cd 100644
--- a/src/vdbe.c
+++ b/src/vdbe.c
@@ -792,6 +792,36 @@ 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
@@ -1317,8 +1347,7 @@ case OP_Halt: {
}else{
sqlite3VdbeError(p, "%s", pOp->p4.z);
}
- pcx = (int)(pOp - aOp);
- sqlite3_log(pOp->p1, "abort at %d: %s; [%s]", pcx, p->zErrMsg, p->zSql);
+ sqlite3VdbeLogAbort(p, pOp->p1, pOp, aOp);
}
rc = sqlite3VdbeHalt(p);
assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR );
@@ -2476,6 +2505,7 @@ 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
@@ -3238,6 +3268,15 @@ 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".
@@ -3251,8 +3290,8 @@ op_column_corrupt:
**
** <ul>
** <li> P2 should be the number of non-virtual columns in the
-** table of P4.
-** <li> Table P4 should be a STRICT table.
+** table of P4 unless P3>1, in which case P2 will be 1.
+** <li> Table P4 is a STRICT table.
** </ul>
**
** If any precondition is false, an assertion fault occurs.
@@ -3261,16 +3300,28 @@ 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( pTab->nNVCol==pOp->p2 );
+ assert( pOp->p3>=0 && pOp->p3<pTab->nCol+2 );
aCol = pTab->aCol;
pIn1 = &aMem[pOp->p1];
- for(i=0; i<pTab->nCol; i++){
- if( aCol[i].colFlags & COLFLAG_GENERATED ){
- if( aCol[i].colFlags & COLFLAG_VIRTUAL ) continue;
+ 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;
if( pOp->p3 ){ pIn1++; continue; }
}
assert( pIn1 < &aMem[pOp->p1+pOp->p2] );
@@ -5349,7 +5400,7 @@ case OP_Found: { /* jump, in3, ncycle */
if( rc ) goto no_mem;
pIdxKey = sqlite3VdbeAllocUnpackedRecord(pC->pKeyInfo);
if( pIdxKey==0 ) goto no_mem;
- sqlite3VdbeRecordUnpack(pC->pKeyInfo, r.aMem->n, r.aMem->z, pIdxKey);
+ sqlite3VdbeRecordUnpack(r.aMem->n, r.aMem->z, pIdxKey);
pIdxKey->default_rc = 0;
rc = sqlite3BtreeIndexMoveto(pC->uc.pCursor, pIdxKey, &pC->seekResult);
sqlite3DbFreeNN(db, pIdxKey);
@@ -6347,6 +6398,32 @@ 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
@@ -8218,7 +8295,14 @@ case OP_VOpen: { /* ncycle */
const sqlite3_module *pModule;
assert( p->bIsReader );
- pCur = 0;
+ 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;
+ }
pVCur = 0;
pVtab = pOp->p4.pVtab->pVtab;
if( pVtab==0 || NEVER(pVtab->pModule==0) ){
@@ -9160,8 +9244,7 @@ abort_due_to_error:
p->rc = rc;
sqlite3SystemError(db, rc);
testcase( sqlite3GlobalConfig.xLog!=0 );
- sqlite3_log(rc, "statement aborts at %d: %s; [%s]",
- (int)(pOp - aOp), p->zErrMsg, p->zSql);
+ sqlite3VdbeLogAbort(p, rc, pOp, aOp);
if( p->eVdbeState==VDBE_RUN_STATE ) sqlite3VdbeHalt(p);
if( rc==SQLITE_IOERR_NOMEM ) sqlite3OomFault(db);
if( rc==SQLITE_CORRUPT && db->autoCommit==0 ){
diff --git a/src/vdbe.h b/src/vdbe.h
index dc98e270e..a7aedfbb0 100644
--- a/src/vdbe.h
+++ b/src/vdbe.h
@@ -301,7 +301,7 @@ void sqlite3VdbeSetVarmask(Vdbe*, int);
int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
int sqlite3BlobCompare(const Mem*, const Mem*);
-void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*);
+void sqlite3VdbeRecordUnpack(int,const void*,UnpackedRecord*);
int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*);
int sqlite3VdbeRecordCompareWithSkip(int, const void *, UnpackedRecord *, int);
UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo*);
diff --git a/src/vdbeInt.h b/src/vdbeInt.h
index 13262cd4e..07160f590 100644
--- a/src/vdbeInt.h
+++ b/src/vdbeInt.h
@@ -288,7 +288,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.i extra 0x00 bytes at the end.
+** Mem.u.nZero extra 0x00 bytes at the end.
**
** * MEM_Int Integer stored in Mem.u.i.
**
@@ -557,7 +557,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 */
- u8 keyinfoSpace[SZ_KEYINFO(0)]; /* Space to hold pKeyinfo[0] content */
+ u8 keyinfoSpace[SZ_KEYINFO_0]; /* Space to hold pKeyinfo[0] content */
};
/*
diff --git a/src/vdbeapi.c b/src/vdbeapi.c
index ed9549462..af90d4497 100644
--- a/src/vdbeapi.c
+++ b/src/vdbeapi.c
@@ -2163,7 +2163,7 @@ static UnpackedRecord *vdbeUnpackRecord(
pRet = sqlite3VdbeAllocUnpackedRecord(pKeyInfo);
if( pRet ){
memset(pRet->aMem, 0, sizeof(Mem)*(pKeyInfo->nKeyField+1));
- sqlite3VdbeRecordUnpack(pKeyInfo, nKey, pKey, pRet);
+ sqlite3VdbeRecordUnpack(nKey, pKey, pRet);
}
return pRet;
}
@@ -2192,6 +2192,9 @@ int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppValue){
}
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);
}
@@ -2347,6 +2350,8 @@ int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppValue){
}
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);
}
diff --git a/src/vdbeaux.c b/src/vdbeaux.c
index a6798e62d..8a900aeff 100644
--- a/src/vdbeaux.c
+++ b/src/vdbeaux.c
@@ -4202,30 +4202,22 @@ void sqlite3VdbeSerialGet(
return;
}
/*
-** 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.
+** Allocate sufficient space for an UnpackedRecord structure large enough
+** to hold a decoded index record for 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.
-**
-** If an OOM error occurs, NULL is returned.
+** The space is allocated using sqlite3DbMallocRaw(). If an OOM error
+** occurs, NULL is returned.
*/
UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(
KeyInfo *pKeyInfo /* Description of the record */
){
UnpackedRecord *p; /* Unpacked record to return */
- int nByte; /* Number of bytes required for *p */
+ u64 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;
@@ -4237,7 +4229,6 @@ UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(
** contents of the decoded record.
*/
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. */
@@ -4248,6 +4239,7 @@ 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) );
@@ -4275,6 +4267,8 @@ void sqlite3VdbeRecordUnpack(
** warnings from MSAN. */
sqlite3VdbeMemSetNull(pMem-1);
}
+ testcase( u == pKeyInfo->nKeyField + 1 );
+ testcase( u < pKeyInfo->nKeyField + 1 );
assert( u<=pKeyInfo->nKeyField + 1 );
p->nField = u;
}
@@ -5134,6 +5128,7 @@ 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] ){
@@ -5492,7 +5487,6 @@ 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 ){
@@ -5531,7 +5525,7 @@ void sqlite3VdbePreUpdateHook(
preupdate.pKeyinfo->db = db;
preupdate.pKeyinfo->enc = ENC(db);
preupdate.pKeyinfo->nKeyField = pTab->nCol;
- preupdate.pKeyinfo->aSortFlags = (u8*)&fakeSortOrder;
+ preupdate.pKeyinfo->aSortFlags = 0; /* Indicate .aColl, .nAllField uninit */
preupdate.iKey1 = iKey1;
preupdate.iKey2 = iKey2;
preupdate.pTab = pTab;
diff --git a/src/vdbeblob.c b/src/vdbeblob.c
index 42edcf7de..a15fec6c4 100644
--- a/src/vdbeblob.c
+++ b/src/vdbeblob.c
@@ -385,7 +385,7 @@ static int blobReadWrite(
int iOffset,
int (*xCall)(BtCursor*, u32, u32, void*)
){
- int rc;
+ int rc = SQLITE_OK;
Incrblob *p = (Incrblob *)pBlob;
Vdbe *v;
sqlite3 *db;
@@ -425,17 +425,32 @@ static int blobReadWrite(
** using the incremental-blob API, this works. For the sessions module
** anyhow.
*/
- 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( 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);
+ }
+#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);
diff --git a/src/vdbesort.c b/src/vdbesort.c
index 9a7e0760c..39661eb4c 100644
--- a/src/vdbesort.c
+++ b/src/vdbesort.c
@@ -766,7 +766,7 @@ static int vdbeSorterCompareTail(
){
UnpackedRecord *r2 = pTask->pUnpacked;
if( *pbKey2Cached==0 ){
- sqlite3VdbeRecordUnpack(pTask->pSorter->pKeyInfo, nKey2, pKey2, r2);
+ sqlite3VdbeRecordUnpack(nKey2, pKey2, r2);
*pbKey2Cached = 1;
}
return sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, r2, 1);
@@ -793,7 +793,7 @@ static int vdbeSorterCompare(
){
UnpackedRecord *r2 = pTask->pUnpacked;
if( !*pbKey2Cached ){
- sqlite3VdbeRecordUnpack(pTask->pSorter->pKeyInfo, nKey2, pKey2, r2);
+ sqlite3VdbeRecordUnpack(nKey2, pKey2, r2);
*pbKey2Cached = 1;
}
return sqlite3VdbeRecordCompare(nKey1, pKey1, r2);
@@ -833,6 +833,7 @@ 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;
@@ -896,6 +897,7 @@ static int vdbeSorterCompareInt(
}
}
+ assert( pTask->pSorter->pKeyInfo->aSortFlags!=0 );
if( res==0 ){
if( pTask->pSorter->pKeyInfo->nKeyField>1 ){
res = vdbeSorterCompareTail(
@@ -969,7 +971,8 @@ int sqlite3VdbeSorterInit(
assert( pCsr->eCurType==CURTYPE_SORTER );
assert( sizeof(KeyInfo) + UMXV(pCsr->pKeyInfo->nKeyField)*sizeof(CollSeq*)
< 0x7fffffff );
- szKeyInfo = SZ_KEYINFO(pCsr->pKeyInfo->nKeyField+1);
+ assert( pCsr->pKeyInfo->nKeyField<=pCsr->pKeyInfo->nAllField );
+ szKeyInfo = SZ_KEYINFO(pCsr->pKeyInfo->nAllField);
sz = SZ_VDBESORTER(nWorker+1);
pSorter = (VdbeSorter*)sqlite3DbMallocZero(db, sz + szKeyInfo);
@@ -983,7 +986,12 @@ 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);
@@ -2763,7 +2771,7 @@ int sqlite3VdbeSorterCompare(
assert( r2->nField==nKeyCol );
pKey = vdbeSorterRowkey(pSorter, &nKey);
- sqlite3VdbeRecordUnpack(pKeyInfo, nKey, pKey, r2);
+ sqlite3VdbeRecordUnpack(nKey, pKey, r2);
for(i=0; i<nKeyCol; i++){
if( r2->aMem[i].flags & MEM_Null ){
*pRes = -1;
diff --git a/src/wal.c b/src/wal.c
index 5fe2296d6..41018b584 100644
--- a/src/wal.c
+++ b/src/wal.c
@@ -3062,7 +3062,6 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int *pCnt){
rc = walIndexReadHdr(pWal, pChanged);
}
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
- walDisableBlocking(pWal);
if( rc==SQLITE_BUSY_TIMEOUT ){
rc = SQLITE_BUSY;
*pCnt |= WAL_RETRY_BLOCKED_MASK;
@@ -3077,6 +3076,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int *pCnt){
** WAL_RETRY this routine will be called again and will probably be
** right on the second iteration.
*/
+ (void)walEnableBlocking(pWal);
if( pWal->apWiData[0]==0 ){
/* This branch is taken when the xShmMap() method returns SQLITE_BUSY.
** We assume this is a transient condition, so return WAL_RETRY. The
@@ -3093,6 +3093,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int *pCnt){
rc = SQLITE_BUSY_RECOVERY;
}
}
+ walDisableBlocking(pWal);
if( rc!=SQLITE_OK ){
return rc;
}
@@ -3780,6 +3781,7 @@ int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *pUndoCtx){
if( iMax!=pWal->hdr.mxFrame ) walCleanupHash(pWal);
}
SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; )
+ pWal->iReCksum = 0;
}
return rc;
}
@@ -3827,6 +3829,9 @@ int sqlite3WalSavepointUndo(Wal *pWal, u32 *aWalData){
walCleanupHash(pWal);
}
SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; )
+ if( pWal->iReCksum>pWal->hdr.mxFrame ){
+ pWal->iReCksum = 0;
+ }
}
return rc;
diff --git a/src/where.c b/src/where.c
index 0103db5e8..ab1b419a2 100644
--- a/src/where.c
+++ b/src/where.c
@@ -426,11 +426,11 @@ static WhereTerm *whereScanNext(WhereScan *pScan){
pScan->pWC = pWC;
pScan->k = k+1;
#ifdef WHERETRACE_ENABLED
- if( sqlite3WhereTrace & 0x20000 ){
+ if( (sqlite3WhereTrace & 0x20000)!=0 && pScan->nEquiv>1 ){
int ii;
- sqlite3DebugPrintf("SCAN-TERM %p: nEquiv=%d",
- pTerm, pScan->nEquiv);
- for(ii=0; ii<pScan->nEquiv; 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(" {%d:%d}",
pScan->aiCur[ii], pScan->aiColumn[ii]);
}
@@ -1201,7 +1201,9 @@ static SQLITE_NOINLINE void constructAutomaticIndex(
VdbeCoverage(v);
VdbeComment((v, "next row of %s", pSrc->pSTab->zName));
}else{
- addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, pLevel->iTabCur); VdbeCoverage(v);
+ assert( pLevel->addrHalt );
+ addrTop = sqlite3VdbeAddOp2(v, OP_Rewind,pLevel->iTabCur,pLevel->addrHalt);
+ VdbeCoverage(v);
}
if( pPartial ){
iContinue = sqlite3VdbeMakeLabel(pParse);
@@ -1229,11 +1231,14 @@ 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 */
@@ -2385,6 +2390,7 @@ 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);
@@ -3233,6 +3239,7 @@ static int whereLoopAddBtreeIndex(
if( ExprUseXSelect(pExpr) ){
/* "x IN (SELECT ...)": TUNING: the SELECT returns 25 rows */
int i;
+ int bRedundant = 0;
nIn = 46; assert( 46==sqlite3LogEst(25) );
/* The expression may actually be of the form (x, y) IN (SELECT...).
@@ -3241,7 +3248,20 @@ static int whereLoopAddBtreeIndex(
** for each such term. The following loop checks that pTerm is the
** first such term in use, and sets nIn back to 0 if it is not. */
for(i=0; i<pNew->nLTerm-1; i++){
- if( pNew->aLTerm[i] && pNew->aLTerm[i]->pExpr==pExpr ) nIn = 0;
+ if( pNew->aLTerm[i] && pNew->aLTerm[i]->pExpr==pExpr ){
+ nIn = 0;
+ if( pNew->aLTerm[i]->u.x.iField == pTerm->u.x.iField ){
+ /* Detect when two or more columns of an index match the same
+ ** column of a vector IN operater, and avoid adding the column
+ ** to the WhereLoop more than once. See tag-20250707-01
+ ** in test/rowvalue.test */
+ bRedundant = 1;
+ }
+ }
+ }
+ if( bRedundant ){
+ pNew->nLTerm--;
+ continue;
}
}else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){
/* "x IN (value, value, ...)" */
@@ -3473,7 +3493,7 @@ static int whereLoopAddBtreeIndex(
if( (pNew->wsFlags & WHERE_TOP_LIMIT)==0
&& pNew->u.btree.nEq<pProbe->nColumn
&& (pNew->u.btree.nEq<pProbe->nKeyCol ||
- (pProbe->idxType!=SQLITE_IDXTYPE_PRIMARYKEY && !pProbe->bIdxRowid))
+ pProbe->idxType!=SQLITE_IDXTYPE_PRIMARYKEY)
){
if( pNew->u.btree.nEq>3 ){
sqlite3ProgressCheck(pParse);
@@ -3512,6 +3532,7 @@ 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;
@@ -3602,6 +3623,7 @@ static int whereUsablePartialIndex(
if( (!ExprHasProperty(pExpr, EP_OuterON) || pExpr->w.iJoin==iTab)
&& ((jointype & JT_OUTER)==0 || ExprHasProperty(pExpr, EP_OuterON))
&& sqlite3ExprImpliesExpr(pParse, pExpr, pWhere, iTab)
+ && !sqlite3ExprImpliesExpr(pParse, pExpr, pWhere, -1)
&& (pTerm->wtFlags & TERM_VNULL)==0
){
return 1;
@@ -7068,6 +7090,14 @@ 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
@@ -7119,6 +7149,13 @@ 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);
}
@@ -7375,6 +7412,9 @@ 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);
diff --git a/src/whereInt.h b/src/whereInt.h
index 40a720ab9..09e02c8c7 100644
--- a/src/whereInt.h
+++ b/src/whereInt.h
@@ -75,6 +75,7 @@ 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 */
@@ -280,6 +281,9 @@ 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>" */
diff --git a/src/wherecode.c b/src/wherecode.c
index 014f697d9..43a669d81 100644
--- a/src/wherecode.c
+++ b/src/wherecode.c
@@ -110,7 +110,7 @@ static void explainIndexRange(StrAccum *pStr, WhereLoop *pLoop){
}
/*
-** This function sets the P4 value of an existing OP_Explain opcode to
+** This function sets the P4 value of an existing OP_Explain opcode to
** text describing the loop in pLevel. If the OP_Explain opcode already has
** a P4 value, it is freed before it is overwritten.
*/
@@ -126,7 +126,6 @@ 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. */
@@ -149,7 +148,10 @@ void sqlite3WhereAddExplainText(
sqlite3StrAccumInit(&str, db, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH);
str.printfFlags = SQLITE_PRINTF_INTERNAL;
- sqlite3_str_appendf(&str, "%s %S", isSearch ? "SEARCH" : "SCAN", pItem);
+ sqlite3_str_appendf(&str, "%s %S%s",
+ isSearch ? "SEARCH" : "SCAN",
+ pItem,
+ pItem->fg.fromExists ? " EXISTS" : "");
if( (flags & (WHERE_IPK|WHERE_VIRTUALTABLE))==0 ){
const char *zFmt = 0;
Index *pIdx;
@@ -598,9 +600,11 @@ static Expr *removeUnindexableInClauseTerms(
int iField;
assert( (pLoop->aLTerm[i]->eOperator & (WO_OR|WO_AND))==0 );
iField = pLoop->aLTerm[i]->u.x.iField - 1;
- if( pOrigRhs->a[iField].pExpr==0 ) continue; /* Duplicate PK column */
+ if( NEVER(pOrigRhs->a[iField].pExpr==0) ){
+ continue; /* Duplicate PK column */
+ }
pRhs = sqlite3ExprListAppend(pParse, pRhs, pOrigRhs->a[iField].pExpr);
- pOrigRhs->a[iField].pExpr = 0;
+ pOrigRhs->a[iField].pExpr = 0;
if( pRhs ) pRhs->a[pRhs->nExpr-1].u.x.iOrderByCol = iField+1;
if( pOrigLhs ){
assert( pOrigLhs->a[iField].pExpr!=0 );
@@ -695,7 +699,7 @@ static SQLITE_NOINLINE void codeINTerm(
return;
}
}
- for(i=iEq;i<pLoop->nLTerm; i++){
+ for(i=iEq; i<pLoop->nLTerm; i++){
assert( pLoop->aLTerm[i]!=0 );
if( pLoop->aLTerm[i]->pExpr==pX ) nEq++;
}
@@ -704,22 +708,13 @@ static SQLITE_NOINLINE void codeINTerm(
if( !ExprUseXSelect(pX) || pX->x.pSelect->pEList->nExpr==1 ){
eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, 0, &iTab);
}else{
- Expr *pExpr = pTerm->pExpr;
- if( pExpr->iTable==0 || !ExprHasProperty(pExpr, EP_Subrtn) ){
- sqlite3 *db = pParse->db;
- pX = removeUnindexableInClauseTerms(pParse, iEq, pLoop, pX);
- if( !db->mallocFailed ){
- aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*nEq);
- eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap,&iTab);
- pExpr->iTable = iTab;
- }
- sqlite3ExprDelete(db, pX);
- }else{
- int n = sqlite3ExprVectorSize(pX->pLeft);
- aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*MAX(nEq,n));
- eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap, &iTab);
+ sqlite3 *db = pParse->db;
+ Expr *pXMod = removeUnindexableInClauseTerms(pParse, iEq, pLoop, pX);
+ if( !db->mallocFailed ){
+ aiMap = (int*)sqlite3DbMallocZero(db, sizeof(int)*nEq);
+ eType = sqlite3FindInIndex(pParse, pXMod, IN_INDEX_LOOP, 0, aiMap, &iTab);
}
- pX = pExpr;
+ sqlite3ExprDelete(db, pXMod);
}
if( eType==IN_INDEX_INDEX_DESC ){
@@ -749,7 +744,7 @@ static SQLITE_NOINLINE void codeINTerm(
if( pIn ){
int iMap = 0; /* Index in aiMap[] */
pIn += i;
- for(i=iEq;i<pLoop->nLTerm; i++){
+ for(i=iEq; i<pLoop->nLTerm; i++){
if( pLoop->aLTerm[i]->pExpr==pX ){
int iOut = iTarget + i - iEq;
if( eType==IN_INDEX_ROWID ){
@@ -948,7 +943,7 @@ static int codeAllEqualityTerms(
testcase( pIdx->aiColumn[j]==XN_EXPR );
VdbeComment((v, "%s", explainIndexColumnName(pIdx, j)));
}
- }
+ }
/* Evaluate the equality constraints
*/
@@ -1289,7 +1284,7 @@ static void codeDeferredSeek(
assert( iIdxCur>0 );
assert( pIdx->aiColumn[pIdx->nColumn-1]==-1 );
-
+
pWInfo->bDeferredSeek = 1;
sqlite3VdbeAddOp3(v, OP_DeferredSeek, iIdxCur, 0, iCur);
if( (pWInfo->wctrlFlags & (WHERE_OR_SUBCLAUSE|WHERE_RIGHT_JOIN))
@@ -1400,6 +1395,7 @@ 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;
@@ -1408,7 +1404,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;
- assert( pLevel->addrBrk==0 );
+ saved_addrBrk = pLevel->addrBrk;
pLevel->addrBrk = addrNxt;
if( pLoop->wsFlags & WHERE_IPK ){
WhereTerm *pTerm = pLoop->aLTerm[0];
@@ -1438,19 +1434,19 @@ static SQLITE_NOINLINE void filterPullDown(
VdbeCoverage(pParse->pVdbe);
}
pLevel->regFilter = 0;
- pLevel->addrBrk = 0;
+ pLevel->addrBrk = saved_addrBrk;
}
}
/*
-** Loop pLoop is a WHERE_INDEXED level that uses at least one IN(...)
-** operator. Return true if level pLoop is guaranteed to visit only one
+** Loop pLoop is a WHERE_INDEXED level that uses at least one IN(...)
+** operator. Return true if level pLoop is guaranteed to visit only one
** row for each key generated for the index.
*/
static int whereLoopIsOneRow(WhereLoop *pLoop){
- if( pLoop->u.btree.pIndex->onError
- && pLoop->nSkip==0
- && pLoop->u.btree.nEq==pLoop->u.btree.pIndex->nKeyCol
+ if( pLoop->u.btree.pIndex->onError
+ && pLoop->nSkip==0
+ && pLoop->u.btree.nEq==pLoop->u.btree.pIndex->nKeyCol
){
int ii;
for(ii=0; ii<pLoop->u.btree.nEq; ii++){
@@ -1485,7 +1481,6 @@ 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 */
@@ -1529,7 +1524,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
** there are no IN operators in the constraints, the "addrNxt" label
** is the same as "addrBrk".
*/
- addrBrk = pLevel->addrBrk = pLevel->addrNxt = sqlite3VdbeMakeLabel(pParse);
+ addrBrk = pLevel->addrNxt = pLevel->addrBrk;
addrCont = pLevel->addrCont = sqlite3VdbeMakeLabel(pParse);
/* If this is the right table of a LEFT OUTER JOIN, allocate and
@@ -1545,14 +1540,6 @@ 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;
@@ -1791,7 +1778,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
VdbeCoverageIf(v, pX->op==TK_GE);
sqlite3ReleaseTempReg(pParse, rTemp);
}else{
- sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur, addrHalt);
+ sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur, pLevel->addrHalt);
VdbeCoverageIf(v, bRev==0);
VdbeCoverageIf(v, bRev!=0);
}
@@ -1831,37 +1818,37 @@ Bitmask sqlite3WhereCodeOneLoopStart(
sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC | SQLITE_JUMPIFNULL);
}
}else if( pLoop->wsFlags & WHERE_INDEXED ){
- /* Case 4: A scan using an index.
+ /* Case 4: Search using an index.
**
- ** 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:
+ ** 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:
**
- ** 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,
0,
@@ -2015,7 +2002,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
}
if( zStartAff ){
updateRangeAffinityStr(pRight, nBtm, &zStartAff[nEq]);
- }
+ }
nConstraint += nBtm;
testcase( pRangeStart->wtFlags & TERM_VIRTUAL );
if( sqlite3ExprIsVector(pRight)==0 ){
@@ -2201,12 +2188,13 @@ Bitmask sqlite3WhereCodeOneLoopStart(
if( pLevel->iLeftJoin==0 ){
/* If a partial index is driving the loop, try to eliminate WHERE clause
** terms from the query that must be true due to the WHERE clause of
- ** the partial index.
+ ** the partial index. This optimization does not work on an outer join,
+ ** as shown by:
**
- ** 2019-11-02 ticket 623eff57e76d45f6: This optimization does not work
- ** for a LEFT JOIN.
+ ** 2019-11-02 ticket 623eff57e76d45f6 (LEFT JOIN)
+ ** 2025-05-29 forum post 7dee41d32506c4ae (RIGHT JOIN)
*/
- if( pIdx->pPartIdxWhere ){
+ if( pIdx->pPartIdxWhere && pLevel->pRJ==0 ){
whereApplyPartialIndexConstraints(pIdx->pPartIdxWhere, iCur, pWC);
}
}else{
@@ -2216,7 +2204,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
** a LEFT JOIN: */
assert( (pWInfo->wctrlFlags & (WHERE_OR_SUBCLAUSE|WHERE_RIGHT_JOIN))==0 );
}
-
+
/* Record the instruction used to terminate the loop. */
if( (pLoop->wsFlags & WHERE_ONEROW)
|| (pLevel->u.in.nIn && regBignull==0 && whereLoopIsOneRow(pLoop))
@@ -2585,7 +2573,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
codeCursorHint(pTabItem, pWInfo, pLevel, 0);
pLevel->op = aStep[bRev];
pLevel->p1 = iCur;
- pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrHalt);
+ pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev],iCur,pLevel->addrHalt);
VdbeCoverageIf(v, bRev==0);
VdbeCoverageIf(v, bRev!=0);
pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP;
@@ -2605,7 +2593,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
**
** iLoop==1: Code only expressions that are entirely covered by pIdx.
** iLoop==2: Code remaining expressions that do not contain correlated
- ** sub-queries.
+ ** sub-queries.
** iLoop==3: Code all remaining expressions.
**
** An effort is made to skip unnecessary iterations of the loop.
@@ -2876,7 +2864,7 @@ SQLITE_NOINLINE void sqlite3WhereRightJoinLoop(
pSubq = pRight->u4.pSubq;
assert( pSubq->pSelect!=0 && pSubq->pSelect->pEList!=0 );
sqlite3VdbeAddOp3(
- v, OP_Null, 0, pSubq->regResult,
+ v, OP_Null, 0, pSubq->regResult,
pSubq->regResult + pSubq->pSelect->pEList->nExpr-1
);
}
diff --git a/src/whereexpr.c b/src/whereexpr.c
index 4a24dadd2..e9fa4a143 100644
--- a/src/whereexpr.c
+++ b/src/whereexpr.c
@@ -931,30 +931,42 @@ static void exprAnalyzeOrTerm(
** 1. The SQLITE_Transitive optimization must be enabled
** 2. Must be either an == or an IS operator
** 3. Not originating in the ON clause of an OUTER JOIN
-** 4. The affinities of A and B must be compatible
-** 5a. Both operands use the same collating sequence OR
-** 5b. The overall collating sequence is BINARY
+** 4. The operator is not IS or else the query does not contain RIGHT JOIN
+** 5. The affinities of A and B must be compatible
+** 6a. Both operands use the same collating sequence OR
+** 6b. The overall collating sequence is BINARY
** If this routine returns TRUE, that means that the RHS can be substituted
** for the LHS anyplace else in the WHERE clause where the LHS column occurs.
** This is an optimization. No harm comes from returning 0. But if 1 is
** returned when it should not be, then incorrect answers might result.
*/
-static int termIsEquivalence(Parse *pParse, Expr *pExpr){
+static int termIsEquivalence(Parse *pParse, Expr *pExpr, SrcList *pSrc){
char aff1, aff2;
CollSeq *pColl;
- if( !OptimizationEnabled(pParse->db, SQLITE_Transitive) ) return 0;
- if( pExpr->op!=TK_EQ && pExpr->op!=TK_IS ) return 0;
- if( ExprHasProperty(pExpr, EP_OuterON) ) return 0;
+ if( !OptimizationEnabled(pParse->db, SQLITE_Transitive) ) return 0; /* (1) */
+ if( pExpr->op!=TK_EQ && pExpr->op!=TK_IS ) return 0; /* (2) */
+ if( ExprHasProperty(pExpr, EP_OuterON) ) return 0; /* (3) */
+ assert( pSrc!=0 );
+ if( pExpr->op==TK_IS
+ && pSrc->nSrc>=2
+ && (pSrc->a[0].fg.jointype & JT_LTORJ)!=0
+ ){
+ return 0; /* (4) */
+ }
aff1 = sqlite3ExprAffinity(pExpr->pLeft);
aff2 = sqlite3ExprAffinity(pExpr->pRight);
if( aff1!=aff2
&& (!sqlite3IsNumericAffinity(aff1) || !sqlite3IsNumericAffinity(aff2))
){
- return 0;
+ return 0; /* (5) */
}
pColl = sqlite3ExprCompareCollSeq(pParse, pExpr);
- if( sqlite3IsBinary(pColl) ) return 1;
- return sqlite3ExprCollSeqMatch(pParse, pExpr->pLeft, pExpr->pRight);
+ if( !sqlite3IsBinary(pColl)
+ && !sqlite3ExprCollSeqMatch(pParse, pExpr->pLeft, pExpr->pRight)
+ ){
+ return 0; /* (6) */
+ }
+ return 1;
}
/*
@@ -1112,6 +1124,9 @@ 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 */
@@ -1219,8 +1234,8 @@ static void exprAnalyze(
if( op==TK_IS ) pNew->wtFlags |= TERM_IS;
pTerm = &pWC->a[idxTerm];
pTerm->wtFlags |= TERM_COPIED;
-
- if( termIsEquivalence(pParse, pDup) ){
+ assert( pWInfo->pTabList!=0 );
+ if( termIsEquivalence(pParse, pDup, pWInfo->pTabList) ){
pTerm->eOperator |= WO_EQUIV;
eExtraOp = WO_EQUIV;
}
@@ -1637,7 +1652,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.
@@ -1674,8 +1689,22 @@ void SQLITE_NOINLINE sqlite3WhereAddLimit(WhereClause *pWC, Select *p){
** (leftCursor==iCsr) test below. */
continue;
}
- if( pWC->a[ii].leftCursor!=iCsr ) return;
- if( pWC->a[ii].prereqRight!=0 ) return;
+ 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;
}
/* Check condition (5). Return early if it is not met. */