|
|
@@ -400,7 +400,7 @@ extern "C" {
|
|
|
*/
|
|
|
#define SQLITE_VERSION "3.19.0"
|
|
|
#define SQLITE_VERSION_NUMBER 3019000
|
|
|
-#define SQLITE_SOURCE_ID "2017-04-26 04:32:17 304689f8acb53d68e1afed6e6c4332e78132e3d57071b8f94df0d13515b3b3d8"
|
|
|
+#define SQLITE_SOURCE_ID "2017-05-02 16:55:07 47cbb471d056c8e1834a5ca72491404a3bfb273b5ff7bdd84b98d263938ea874"
|
|
|
|
|
|
/*
|
|
|
** CAPI3REF: Run-Time Library Version Numbers
|
|
|
@@ -1149,7 +1149,7 @@ struct sqlite3_io_methods {
|
|
|
** opcode allows these two values (10 retries and 25 milliseconds of delay)
|
|
|
** to be adjusted. The values are changed for all database connections
|
|
|
** within the same process. The argument is a pointer to an array of two
|
|
|
-** integers where the first integer i the new retry count and the second
|
|
|
+** integers where the first integer is the new retry count and the second
|
|
|
** integer is the delay. If either integer is negative, then the setting
|
|
|
** is not changed but instead the prior value of that setting is written
|
|
|
** into the array entry, allowing the current retry settings to be
|
|
|
@@ -16155,15 +16155,17 @@ struct Walker {
|
|
|
int walkerDepth; /* Number of subqueries */
|
|
|
u8 eCode; /* A small processing code */
|
|
|
union { /* Extra data for callback */
|
|
|
- NameContext *pNC; /* Naming context */
|
|
|
- int n; /* A counter */
|
|
|
- int iCur; /* A cursor number */
|
|
|
- SrcList *pSrcList; /* FROM clause */
|
|
|
- struct SrcCount *pSrcCount; /* Counting column references */
|
|
|
- struct CCurHint *pCCurHint; /* Used by codeCursorHint() */
|
|
|
- int *aiCol; /* array of column indexes */
|
|
|
- struct IdxCover *pIdxCover; /* Check for index coverage */
|
|
|
- struct IdxExprTrans *pIdxTrans; /* Convert indexed expr to column */
|
|
|
+ NameContext *pNC; /* Naming context */
|
|
|
+ int n; /* A counter */
|
|
|
+ int iCur; /* A cursor number */
|
|
|
+ SrcList *pSrcList; /* FROM clause */
|
|
|
+ struct SrcCount *pSrcCount; /* Counting column references */
|
|
|
+ struct CCurHint *pCCurHint; /* Used by codeCursorHint() */
|
|
|
+ int *aiCol; /* array of column indexes */
|
|
|
+ struct IdxCover *pIdxCover; /* Check for index coverage */
|
|
|
+ struct IdxExprTrans *pIdxTrans; /* Convert indexed expr to column */
|
|
|
+ ExprList *pGroupBy; /* GROUP BY clause */
|
|
|
+ struct HavingToWhereCtx *pHavingCtx; /* HAVING to WHERE clause ctx */
|
|
|
} u;
|
|
|
};
|
|
|
|
|
|
@@ -16635,6 +16637,7 @@ SQLITE_PRIVATE void sqlite3LeaveMutexAndCloseZombie(sqlite3*);
|
|
|
SQLITE_PRIVATE int sqlite3ExprIsConstant(Expr*);
|
|
|
SQLITE_PRIVATE int sqlite3ExprIsConstantNotJoin(Expr*);
|
|
|
SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr*, u8);
|
|
|
+SQLITE_PRIVATE int sqlite3ExprIsConstantOrGroupBy(Parse*, Expr*, ExprList*);
|
|
|
SQLITE_PRIVATE int sqlite3ExprIsTableConstant(Expr*,int);
|
|
|
#ifdef SQLITE_ENABLE_CURSOR_HINTS
|
|
|
SQLITE_PRIVATE int sqlite3ExprContainsSubquery(Expr*);
|
|
|
@@ -67394,6 +67397,7 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
|
|
|
}else if( loc<0 && pPage->nCell>0 ){
|
|
|
assert( pPage->leaf );
|
|
|
idx = ++pCur->ix;
|
|
|
+ pCur->curFlags &= ~BTCF_ValidNKey;
|
|
|
}else{
|
|
|
assert( pPage->leaf );
|
|
|
}
|
|
|
@@ -68518,6 +68522,7 @@ static int checkTreePage(
|
|
|
checkAppendMsg(pCheck, "Rowid %lld out of order", info.nKey);
|
|
|
}
|
|
|
maxKey = info.nKey;
|
|
|
+ keyCanBeEqual = 0; /* Only the first key on the page may ==maxKey */
|
|
|
}
|
|
|
|
|
|
/* Check the content overflow list */
|
|
|
@@ -79633,7 +79638,7 @@ jump_to_p2_and_check_for_interrupt:
|
|
|
pOp = &aOp[pOp->p2 - 1];
|
|
|
|
|
|
/* Opcodes that are used as the bottom of a loop (OP_Next, OP_Prev,
|
|
|
- ** OP_VNext, OP_RowSetNext, or OP_SorterNext) all jump here upon
|
|
|
+ ** OP_VNext, or OP_SorterNext) all jump here upon
|
|
|
** completion. Check to see if sqlite3_interrupt() has been called
|
|
|
** or if the progress callback needs to be invoked.
|
|
|
**
|
|
|
@@ -80456,7 +80461,7 @@ arithmetic_result_is_null:
|
|
|
|
|
|
/* Opcode: CollSeq P1 * * P4
|
|
|
**
|
|
|
-** P4 is a pointer to a CollSeq struct. If the next call to a user function
|
|
|
+** P4 is a pointer to a CollSeq object. If the next call to a user function
|
|
|
** or aggregate calls sqlite3GetFuncCollSeq(), this collation sequence will
|
|
|
** be returned. This is used by the built-in min(), max() and nullif()
|
|
|
** functions.
|
|
|
@@ -80743,11 +80748,11 @@ case OP_RealAffinity: { /* in1 */
|
|
|
** Force the value in register P1 to be the type defined by P2.
|
|
|
**
|
|
|
** <ul>
|
|
|
-** <li value="97"> TEXT
|
|
|
-** <li value="98"> BLOB
|
|
|
-** <li value="99"> NUMERIC
|
|
|
-** <li value="100"> INTEGER
|
|
|
-** <li value="101"> REAL
|
|
|
+** <li> P2=='A' → BLOB
|
|
|
+** <li> P2=='B' → TEXT
|
|
|
+** <li> P2=='C' → NUMERIC
|
|
|
+** <li> P2=='D' → INTEGER
|
|
|
+** <li> P2=='E' → REAL
|
|
|
** </ul>
|
|
|
**
|
|
|
** A NULL value is not changed by this routine. It remains NULL.
|
|
|
@@ -81628,8 +81633,8 @@ op_column_out:
|
|
|
**
|
|
|
** Apply affinities to a range of P2 registers starting with P1.
|
|
|
**
|
|
|
-** P4 is a string that is P2 characters long. The nth character of the
|
|
|
-** string indicates the column affinity that should be used for the nth
|
|
|
+** P4 is a string that is P2 characters long. The N-th character of the
|
|
|
+** string indicates the column affinity that should be used for the N-th
|
|
|
** memory cell in the range.
|
|
|
*/
|
|
|
case OP_Affinity: {
|
|
|
@@ -81658,8 +81663,8 @@ case OP_Affinity: {
|
|
|
** use as a data record in a database table or as a key
|
|
|
** in an index. The OP_Column opcode can decode the record later.
|
|
|
**
|
|
|
-** P4 may be a string that is P2 characters long. The nth character of the
|
|
|
-** string indicates the column affinity that should be used for the nth
|
|
|
+** P4 may be a string that is P2 characters long. The N-th character of the
|
|
|
+** string indicates the column affinity that should be used for the N-th
|
|
|
** field of the index key.
|
|
|
**
|
|
|
** The mapping from character to affinity is given by the SQLITE_AFF_
|
|
|
@@ -84729,7 +84734,7 @@ case OP_IntegrityCk: {
|
|
|
/* Opcode: RowSetAdd P1 P2 * * *
|
|
|
** Synopsis: rowset(P1)=r[P2]
|
|
|
**
|
|
|
-** Insert the integer value held by register P2 into a boolean index
|
|
|
+** Insert the integer value held by register P2 into a RowSet object
|
|
|
** held in register P1.
|
|
|
**
|
|
|
** An assertion fails if P2 is not an integer.
|
|
|
@@ -84749,8 +84754,9 @@ case OP_RowSetAdd: { /* in1, in2 */
|
|
|
/* Opcode: RowSetRead P1 P2 P3 * *
|
|
|
** Synopsis: r[P3]=rowset(P1)
|
|
|
**
|
|
|
-** Extract the smallest value from boolean index P1 and put that value into
|
|
|
-** register P3. Or, if boolean index P1 is initially empty, leave P3
|
|
|
+** Extract the smallest value from the RowSet object in P1
|
|
|
+** and put that value into register P3.
|
|
|
+** Or, if RowSet object P1 is initially empty, leave P3
|
|
|
** unchanged and jump to instruction P2.
|
|
|
*/
|
|
|
case OP_RowSetRead: { /* jump, in1, out3 */
|
|
|
@@ -84783,15 +84789,14 @@ case OP_RowSetRead: { /* jump, in1, out3 */
|
|
|
** integer in P3 into the RowSet and continue on to the
|
|
|
** next opcode.
|
|
|
**
|
|
|
-** The RowSet object is optimized for the case where successive sets
|
|
|
-** of integers, where each set contains no duplicates. Each set
|
|
|
-** of values is identified by a unique P4 value. The first set
|
|
|
-** must have P4==0, the final set P4=-1. P4 must be either -1 or
|
|
|
-** non-negative. For non-negative values of P4 only the lower 4
|
|
|
-** bits are significant.
|
|
|
+** The RowSet object is optimized for the case where sets of integers
|
|
|
+** are inserted in distinct phases, which each set contains no duplicates.
|
|
|
+** Each set is identified by a unique P4 value. The first set
|
|
|
+** must have P4==0, the final set must have P4==-1, and for all other sets
|
|
|
+** must have P4>0.
|
|
|
**
|
|
|
** This allows optimizations: (a) when P4==0 there is no need to test
|
|
|
-** the rowset object for P3, as it is guaranteed not to contain it,
|
|
|
+** the RowSet object for P3, as it is guaranteed not to contain it,
|
|
|
** (b) when P4==-1 there is no need to insert the value, as it will
|
|
|
** never be tested for, and (c) when a value that is part of set X is
|
|
|
** inserted, there is no need to search to see if the same value was
|
|
|
@@ -93414,6 +93419,65 @@ SQLITE_PRIVATE int sqlite3ExprIsTableConstant(Expr *p, int iCur){
|
|
|
return exprIsConst(p, 3, iCur);
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+/*
|
|
|
+** sqlite3WalkExpr() callback used by sqlite3ExprIsConstantOrGroupBy().
|
|
|
+*/
|
|
|
+static int exprNodeIsConstantOrGroupBy(Walker *pWalker, Expr *pExpr){
|
|
|
+ ExprList *pGroupBy = pWalker->u.pGroupBy;
|
|
|
+ int i;
|
|
|
+
|
|
|
+ /* Check if pExpr is identical to any GROUP BY term. If so, consider
|
|
|
+ ** it constant. */
|
|
|
+ for(i=0; i<pGroupBy->nExpr; i++){
|
|
|
+ Expr *p = pGroupBy->a[i].pExpr;
|
|
|
+ if( sqlite3ExprCompare(pExpr, p, -1)<2 ){
|
|
|
+ CollSeq *pColl = sqlite3ExprCollSeq(pWalker->pParse, p);
|
|
|
+ if( pColl==0 || sqlite3_stricmp("BINARY", pColl->zName)==0 ){
|
|
|
+ return WRC_Prune;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Check if pExpr is a sub-select. If so, consider it variable. */
|
|
|
+ if( ExprHasProperty(pExpr, EP_xIsSelect) ){
|
|
|
+ pWalker->eCode = 0;
|
|
|
+ return WRC_Abort;
|
|
|
+ }
|
|
|
+
|
|
|
+ return exprNodeIsConstant(pWalker, pExpr);
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+** Walk the expression tree passed as the first argument. Return non-zero
|
|
|
+** if the expression consists entirely of constants or copies of terms
|
|
|
+** in pGroupBy that sort with the BINARY collation sequence.
|
|
|
+**
|
|
|
+** This routine is used to determine if a term of the HAVING clause can
|
|
|
+** be promoted into the WHERE clause. In order for such a promotion to work,
|
|
|
+** the value of the HAVING clause term must be the same for all members of
|
|
|
+** a "group". The requirement that the GROUP BY term must be BINARY
|
|
|
+** assumes that no other collating sequence will have a finer-grained
|
|
|
+** grouping than binary. In other words (A=B COLLATE binary) implies
|
|
|
+** A=B in every other collating sequence. The requirement that the
|
|
|
+** GROUP BY be BINARY is stricter than necessary. It would also work
|
|
|
+** to promote HAVING clauses that use the same alternative collating
|
|
|
+** sequence as the GROUP BY term, but that is much harder to check,
|
|
|
+** alternative collating sequences are uncommon, and this is only an
|
|
|
+** optimization, so we take the easy way out and simply require the
|
|
|
+** GROUP BY to use the BINARY collating sequence.
|
|
|
+*/
|
|
|
+SQLITE_PRIVATE int sqlite3ExprIsConstantOrGroupBy(Parse *pParse, Expr *p, ExprList *pGroupBy){
|
|
|
+ Walker w;
|
|
|
+ memset(&w, 0, sizeof(w));
|
|
|
+ w.eCode = 1;
|
|
|
+ w.xExprCallback = exprNodeIsConstantOrGroupBy;
|
|
|
+ w.u.pGroupBy = pGroupBy;
|
|
|
+ w.pParse = pParse;
|
|
|
+ sqlite3WalkExpr(&w, p);
|
|
|
+ return w.eCode;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
** Walk an expression tree. Return non-zero if the expression is constant
|
|
|
** or a function call with constant arguments. Return and 0 if there
|
|
|
@@ -122164,6 +122228,77 @@ static void explainSimpleCount(
|
|
|
# define explainSimpleCount(a,b,c)
|
|
|
#endif
|
|
|
|
|
|
+/*
|
|
|
+** Context object for havingToWhereExprCb().
|
|
|
+*/
|
|
|
+struct HavingToWhereCtx {
|
|
|
+ Expr **ppWhere;
|
|
|
+ ExprList *pGroupBy;
|
|
|
+};
|
|
|
+
|
|
|
+/*
|
|
|
+** sqlite3WalkExpr() callback used by havingToWhere().
|
|
|
+**
|
|
|
+** If the node passed to the callback is a TK_AND node, return
|
|
|
+** WRC_Continue to tell sqlite3WalkExpr() to iterate through child nodes.
|
|
|
+**
|
|
|
+** Otherwise, return WRC_Prune. In this case, also check if the
|
|
|
+** sub-expression matches the criteria for being moved to the WHERE
|
|
|
+** clause. If so, add it to the WHERE clause and replace the sub-expression
|
|
|
+** within the HAVING expression with a constant "1".
|
|
|
+*/
|
|
|
+static int havingToWhereExprCb(Walker *pWalker, Expr *pExpr){
|
|
|
+ if( pExpr->op!=TK_AND ){
|
|
|
+ struct HavingToWhereCtx *p = pWalker->u.pHavingCtx;
|
|
|
+ if( sqlite3ExprIsConstantOrGroupBy(pWalker->pParse, pExpr, p->pGroupBy) ){
|
|
|
+ sqlite3 *db = pWalker->pParse->db;
|
|
|
+ Expr *pNew = sqlite3ExprAlloc(db, TK_INTEGER, &sqlite3IntTokens[1], 0);
|
|
|
+ if( pNew ){
|
|
|
+ Expr *pWhere = *(p->ppWhere);
|
|
|
+ SWAP(Expr, *pNew, *pExpr);
|
|
|
+ pNew = sqlite3ExprAnd(db, pWhere, pNew);
|
|
|
+ *(p->ppWhere) = pNew;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return WRC_Prune;
|
|
|
+ }
|
|
|
+ return WRC_Continue;
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+** Transfer eligible terms from the HAVING clause of a query, which is
|
|
|
+** processed after grouping, to the WHERE clause, which is processed before
|
|
|
+** grouping. For example, the query:
|
|
|
+**
|
|
|
+** SELECT * FROM <tables> WHERE a=? GROUP BY b HAVING b=? AND c=?
|
|
|
+**
|
|
|
+** can be rewritten as:
|
|
|
+**
|
|
|
+** SELECT * FROM <tables> WHERE a=? AND b=? GROUP BY b HAVING c=?
|
|
|
+**
|
|
|
+** A term of the HAVING expression is eligible for transfer if it consists
|
|
|
+** entirely of constants and expressions that are also GROUP BY terms that
|
|
|
+** use the "BINARY" collation sequence.
|
|
|
+*/
|
|
|
+static void havingToWhere(
|
|
|
+ Parse *pParse,
|
|
|
+ ExprList *pGroupBy,
|
|
|
+ Expr *pHaving,
|
|
|
+ Expr **ppWhere
|
|
|
+){
|
|
|
+ struct HavingToWhereCtx sCtx;
|
|
|
+ Walker sWalker;
|
|
|
+
|
|
|
+ sCtx.ppWhere = ppWhere;
|
|
|
+ sCtx.pGroupBy = pGroupBy;
|
|
|
+
|
|
|
+ memset(&sWalker, 0, sizeof(sWalker));
|
|
|
+ sWalker.pParse = pParse;
|
|
|
+ sWalker.xExprCallback = havingToWhereExprCb;
|
|
|
+ sWalker.u.pHavingCtx = &sCtx;
|
|
|
+ sqlite3WalkExpr(&sWalker, pHaving);
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
** Generate code for the SELECT statement given in the p argument.
|
|
|
**
|
|
|
@@ -122320,6 +122455,10 @@ SQLITE_PRIVATE int sqlite3Select(
|
|
|
** to be invoked again. */
|
|
|
if( pItem->addrFillSub ){
|
|
|
if( pItem->fg.viaCoroutine==0 ){
|
|
|
+ /* The subroutine that manifests the view might be a one-time routine,
|
|
|
+ ** or it might need to be rerun on each iteration because it
|
|
|
+ ** encodes a correlated subquery. */
|
|
|
+ testcase( sqlite3VdbeGetOp(v, pItem->addrFillSub)->opcode==OP_Once );
|
|
|
sqlite3VdbeAddOp2(v, OP_Gosub, pItem->regReturn, pItem->addrFillSub);
|
|
|
}
|
|
|
continue;
|
|
|
@@ -122628,6 +122767,11 @@ SQLITE_PRIVATE int sqlite3Select(
|
|
|
sqlite3ExprAnalyzeAggList(&sNC, pEList);
|
|
|
sqlite3ExprAnalyzeAggList(&sNC, sSort.pOrderBy);
|
|
|
if( pHaving ){
|
|
|
+ if( pGroupBy ){
|
|
|
+ assert( pWhere==p->pWhere );
|
|
|
+ havingToWhere(pParse, pGroupBy, pHaving, &p->pWhere);
|
|
|
+ pWhere = p->pWhere;
|
|
|
+ }
|
|
|
sqlite3ExprAnalyzeAggregates(&sNC, pHaving);
|
|
|
}
|
|
|
sAggInfo.nAccumulator = sAggInfo.nColumn;
|
|
|
@@ -128536,6 +128680,8 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
|
|
|
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 */
|
|
|
+ Index *pIdx = 0; /* Index used by loop (if any) */
|
|
|
+ int loopAgain; /* True if constraint generator loop should repeat */
|
|
|
|
|
|
pParse = pWInfo->pParse;
|
|
|
v = pParse->pVdbe;
|
|
|
@@ -128861,7 +129007,6 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
|
|
|
int endEq; /* True if range end uses ==, >= or <= */
|
|
|
int start_constraints; /* Start of range is constrained */
|
|
|
int nConstraint; /* Number of constraint terms */
|
|
|
- Index *pIdx; /* The index we will be using */
|
|
|
int iIdxCur; /* The VDBE cursor for the index */
|
|
|
int nExtraReg = 0; /* Number of extra registers needed */
|
|
|
int op; /* Instruction opcode */
|
|
|
@@ -129112,6 +129257,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
|
|
|
}else{
|
|
|
assert( pLevel->p5==0 );
|
|
|
}
|
|
|
+ if( omitTable ) pIdx = 0;
|
|
|
}else
|
|
|
|
|
|
#ifndef SQLITE_OMIT_OR_OPTIMIZATION
|
|
|
@@ -129429,43 +129575,56 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
|
|
|
|
|
|
/* Insert code to test every subexpression that can be completely
|
|
|
** computed using the current set of tables.
|
|
|
+ **
|
|
|
+ ** This loop may run either once (pIdx==0) or twice (pIdx!=0). If
|
|
|
+ ** it is run twice, then the first iteration codes those sub-expressions
|
|
|
+ ** that can be computed using columns from pIdx only (without seeking
|
|
|
+ ** the main table cursor).
|
|
|
*/
|
|
|
- for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){
|
|
|
- Expr *pE;
|
|
|
- int skipLikeAddr = 0;
|
|
|
- testcase( pTerm->wtFlags & TERM_VIRTUAL );
|
|
|
- testcase( pTerm->wtFlags & TERM_CODED );
|
|
|
- if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
|
|
|
- if( (pTerm->prereqAll & pLevel->notReady)!=0 ){
|
|
|
- testcase( pWInfo->untestedTerms==0
|
|
|
- && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)!=0 );
|
|
|
- pWInfo->untestedTerms = 1;
|
|
|
- continue;
|
|
|
- }
|
|
|
- pE = pTerm->pExpr;
|
|
|
- assert( pE!=0 );
|
|
|
- if( pLevel->iLeftJoin && !ExprHasProperty(pE, EP_FromJoin) ){
|
|
|
- continue;
|
|
|
- }
|
|
|
- if( pTerm->wtFlags & TERM_LIKECOND ){
|
|
|
- /* If the TERM_LIKECOND flag is set, that means that the range search
|
|
|
- ** is sufficient to guarantee that the LIKE operator is true, so we
|
|
|
- ** can skip the call to the like(A,B) function. But this only works
|
|
|
- ** for strings. So do not skip the call to the function on the pass
|
|
|
- ** that compares BLOBs. */
|
|
|
+ do{
|
|
|
+ loopAgain = 0;
|
|
|
+ for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){
|
|
|
+ Expr *pE;
|
|
|
+ int skipLikeAddr = 0;
|
|
|
+ testcase( pTerm->wtFlags & TERM_VIRTUAL );
|
|
|
+ testcase( pTerm->wtFlags & TERM_CODED );
|
|
|
+ if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
|
|
|
+ if( (pTerm->prereqAll & pLevel->notReady)!=0 ){
|
|
|
+ testcase( pWInfo->untestedTerms==0
|
|
|
+ && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)!=0 );
|
|
|
+ pWInfo->untestedTerms = 1;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ pE = pTerm->pExpr;
|
|
|
+ assert( pE!=0 );
|
|
|
+ if( pLevel->iLeftJoin && !ExprHasProperty(pE, EP_FromJoin) ){
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if( pIdx && !sqlite3ExprCoveredByIndex(pE, pLevel->iTabCur, pIdx) ){
|
|
|
+ loopAgain = 1;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if( pTerm->wtFlags & TERM_LIKECOND ){
|
|
|
+ /* If the TERM_LIKECOND flag is set, that means that the range search
|
|
|
+ ** is sufficient to guarantee that the LIKE operator is true, so we
|
|
|
+ ** can skip the call to the like(A,B) function. But this only works
|
|
|
+ ** for strings. So do not skip the call to the function on the pass
|
|
|
+ ** that compares BLOBs. */
|
|
|
#ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS
|
|
|
- continue;
|
|
|
+ continue;
|
|
|
#else
|
|
|
- u32 x = pLevel->iLikeRepCntr;
|
|
|
- assert( x>0 );
|
|
|
- skipLikeAddr = sqlite3VdbeAddOp1(v, (x&1)? OP_IfNot : OP_If, (int)(x>>1));
|
|
|
- VdbeCoverage(v);
|
|
|
+ u32 x = pLevel->iLikeRepCntr;
|
|
|
+ assert( x>0 );
|
|
|
+ skipLikeAddr = sqlite3VdbeAddOp1(v, (x&1)?OP_IfNot:OP_If, (int)(x>>1));
|
|
|
+ VdbeCoverage(v);
|
|
|
#endif
|
|
|
+ }
|
|
|
+ sqlite3ExprIfFalse(pParse, pE, addrCont, SQLITE_JUMPIFNULL);
|
|
|
+ if( skipLikeAddr ) sqlite3VdbeJumpHere(v, skipLikeAddr);
|
|
|
+ pTerm->wtFlags |= TERM_CODED;
|
|
|
}
|
|
|
- sqlite3ExprIfFalse(pParse, pE, addrCont, SQLITE_JUMPIFNULL);
|
|
|
- if( skipLikeAddr ) sqlite3VdbeJumpHere(v, skipLikeAddr);
|
|
|
- pTerm->wtFlags |= TERM_CODED;
|
|
|
- }
|
|
|
+ pIdx = 0;
|
|
|
+ }while( loopAgain );
|
|
|
|
|
|
/* Insert code to test for implied constraints based on transitivity
|
|
|
** of the "==" operator.
|