diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/sqlite.h.in | 7 | ||||
-rw-r--r-- | src/tclsqlite.c | 2 | ||||
-rw-r--r-- | src/test_config.c | 6 | ||||
-rw-r--r-- | src/where.c | 24 | ||||
-rw-r--r-- | src/whereInt.h | 4 |
5 files changed, 34 insertions, 9 deletions
diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 4a66626b8..21e200486 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -956,13 +956,16 @@ struct sqlite3_io_methods { ** pointed to by the pArg argument. This capability is used during testing ** and only needs to be supported when SQLITE_TEST is defined. ** -** <li>[[SQLITE_FCNTL_WAL_BLOCK]] +* <li>[[SQLITE_FCNTL_WAL_BLOCK]] ** The [SQLITE_FCNTL_WAL_BLOCK] is a signal to the VFS layer that it might ** be advantageous to block on the next WAL lock if the lock is not immediately ** available. The WAL subsystem issues this signal during rare ** circumstances in order to fix a problem with priority inversion. ** Applications should <em>not</em> use this file-control. ** +** <li>[[SQLITE_FCNTL_ZIPVFS]] +** The [SQLITE_FCNTL_ZIPVFS] opcode is implemented by zipvfs only. All other +** VFS should return SQLITE_NOTFOUND for this opcode. ** </ul> */ #define SQLITE_FCNTL_LOCKSTATE 1 @@ -988,6 +991,8 @@ struct sqlite3_io_methods { #define SQLITE_FCNTL_COMMIT_PHASETWO 22 #define SQLITE_FCNTL_WIN32_SET_HANDLE 23 #define SQLITE_FCNTL_WAL_BLOCK 24 +#define SQLITE_FCNTL_ZIPVFS 25 +#define SQLITE_FCNTL_OTA 26 /* deprecated names */ #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE diff --git a/src/tclsqlite.c b/src/tclsqlite.c index b44f5b8fa..24114e92f 100644 --- a/src/tclsqlite.c +++ b/src/tclsqlite.c @@ -3760,6 +3760,7 @@ static void init_all(Tcl_Interp *interp){ extern int Sqlitemultiplex_Init(Tcl_Interp*); extern int SqliteSuperlock_Init(Tcl_Interp*); extern int SqlitetestSyscall_Init(Tcl_Interp*); + extern int SqliteOta_Init(Tcl_Interp*); #if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) extern int Sqlitetestfts3_Init(Tcl_Interp *interp); @@ -3803,6 +3804,7 @@ static void init_all(Tcl_Interp *interp){ Sqlitemultiplex_Init(interp); SqliteSuperlock_Init(interp); SqlitetestSyscall_Init(interp); + SqliteOta_Init(interp); #if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) Sqlitetestfts3_Init(interp); diff --git a/src/test_config.c b/src/test_config.c index 0be2a23d3..03ec8fe57 100644 --- a/src/test_config.c +++ b/src/test_config.c @@ -430,6 +430,12 @@ Tcl_SetVar2(interp, "sqlite_options", "mergesort", "1", TCL_GLOBAL_ONLY); Tcl_SetVar2(interp, "sqlite_options", "or_opt", "1", TCL_GLOBAL_ONLY); #endif +#ifdef SQLITE_ENABLE_OTA + Tcl_SetVar2(interp, "sqlite_options", "ota", "1", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "ota", "0", TCL_GLOBAL_ONLY); +#endif + #ifdef SQLITE_OMIT_PAGER_PRAGMAS Tcl_SetVar2(interp, "sqlite_options", "pager_pragmas", "0", TCL_GLOBAL_ONLY); #else diff --git a/src/where.c b/src/where.c index 85eb00b46..a89aba7c8 100644 --- a/src/where.c +++ b/src/where.c @@ -363,7 +363,7 @@ static int allowedOp(int op){ assert( TK_LT>TK_EQ && TK_LT<TK_GE ); assert( TK_LE>TK_EQ && TK_LE<TK_GE ); assert( TK_GE==TK_EQ+4 ); - return op==TK_IN || (op>=TK_EQ && op<=TK_GE) || op==TK_ISNULL; + return op==TK_IN || (op>=TK_EQ && op<=TK_GE) || op==TK_ISNULL || op==TK_IS; } /* @@ -416,6 +416,8 @@ static u16 operatorMask(int op){ c = WO_IN; }else if( op==TK_ISNULL ){ c = WO_ISNULL; + }else if( op==TK_IS ){ + c = WO_IS; }else{ assert( (WO_EQ<<(op-TK_EQ)) < 0x7fff ); c = (u16)(WO_EQ<<(op-TK_EQ)); @@ -2792,7 +2794,7 @@ static int codeEqualityTerm( int iReg; /* Register holding results */ assert( iTarget>0 ); - if( pX->op==TK_EQ ){ + if( pX->op==TK_EQ || pX->op==TK_IS ){ iReg = sqlite3ExprCodeTarget(pParse, pX->pRight, iTarget); }else if( pX->op==TK_ISNULL ){ iReg = iTarget; @@ -2977,7 +2979,7 @@ static int codeAllEqualityTerms( testcase( pTerm->eOperator & WO_IN ); if( (pTerm->eOperator & (WO_ISNULL|WO_IN))==0 ){ Expr *pRight = pTerm->pExpr->pRight; - if( sqlite3ExprCanBeNull(pRight) ){ + if( sqlite3ExprCanBeNull(pRight) && pTerm->eOperator!=WO_IS ){ sqlite3VdbeAddOp2(v, OP_IsNull, regBase+j, pLevel->addrBrk); VdbeCoverage(v); } @@ -4315,6 +4317,9 @@ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){ pWInfo->pLoops = p->pNextLoop; whereLoopDelete(db, p); } + if( pWInfo->bShortcut ){ + whereLoopClear(db, pWInfo->a[0].pWLoop); + } sqlite3DbFree(db, pWInfo); } } @@ -5565,7 +5570,6 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){ /* Loop over the tables in the join, from left to right */ pNew = pBuilder->pNew; - whereLoopInit(pNew); for(iTab=0, pItem=pTabList->a; iTab<nTabList; iTab++, pItem++){ pNew->iTab = iTab; pNew->maskSelf = getMask(&pWInfo->sMaskSet, pItem->iCursor); @@ -6281,7 +6285,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ ** no-frills query planner. Return zero if this query needs the ** general-purpose query planner. */ -static int whereShortCut(WhereLoopBuilder *pBuilder){ +static int whereShortCut(sqlite3 *db, WhereLoopBuilder *pBuilder){ WhereInfo *pWInfo; struct SrcList_item *pItem; WhereClause *pWC; @@ -6314,13 +6318,18 @@ static int whereShortCut(WhereLoopBuilder *pBuilder){ pLoop->rRun = 33; /* 33==sqlite3LogEst(10) */ }else{ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ + u32 mask = WO_EQ; assert( pLoop->aLTermSpace==pLoop->aLTerm ); + if( HasRowid(pTab)==0 && IsPrimaryKeyIndex(pIdx) ){ + mask |= WO_IS; + if( whereLoopResize(db, pLoop, pIdx->nKeyCol) ) return 1; + }else if( !IsUniqueIndex(pIdx) || pIdx->pPartIdxWhere!=0 || pIdx->nKeyCol>ArraySize(pLoop->aLTermSpace) ) continue; for(j=0; j<pIdx->nKeyCol; j++){ - pTerm = findTerm(pWC, iCur, pIdx->aiColumn[j], 0, WO_EQ, pIdx); + pTerm = findTerm(pWC, iCur, pIdx->aiColumn[j], 0, mask, pIdx); if( pTerm==0 ) break; pLoop->aLTerm[j] = pTerm; } @@ -6350,6 +6359,7 @@ static int whereShortCut(WhereLoopBuilder *pBuilder){ #ifdef SQLITE_DEBUG pLoop->cId = '0'; #endif + pWInfo->bShortcut = 1; return 1; } return 0; @@ -6620,7 +6630,7 @@ WhereInfo *sqlite3WhereBegin( } #endif - if( nTabList!=1 || whereShortCut(&sWLB)==0 ){ + if( nTabList!=1 || whereShortCut(db, &sWLB)==0 ){ rc = whereLoopAddAll(&sWLB); if( rc ) goto whereBeginError; diff --git a/src/whereInt.h b/src/whereInt.h index 04cc2029d..ccef368eb 100644 --- a/src/whereInt.h +++ b/src/whereInt.h @@ -412,6 +412,7 @@ struct WhereInfo { u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */ u8 eDistinct; /* One of the WHERE_DISTINCT_* values below */ u8 nLevel; /* Number of nested loop */ + u8 bShortcut; /* Plan generated by whereShortCut() */ int iTop; /* The very beginning of the WHERE loop */ int iContinue; /* Jump here to continue with next record */ int iBreak; /* Jump here to break out of the loop */ @@ -440,8 +441,9 @@ struct WhereInfo { #define WO_AND 0x200 /* Two or more AND-connected terms */ #define WO_EQUIV 0x400 /* Of the form A==B, both columns */ #define WO_NOOP 0x800 /* This term does not restrict search space */ +#define WO_IS 0x1000 /* The IS operator */ -#define WO_ALL 0xfff /* Mask of all possible WO_* values */ +#define WO_ALL 0x1fff /* Mask of all possible WO_* values */ #define WO_SINGLE 0x0ff /* Mask of all non-compound WO_* values */ /* |