Index: third_party/sqlite/src/src/whereexpr.c |
diff --git a/third_party/sqlite/src/src/whereexpr.c b/third_party/sqlite/src/src/whereexpr.c |
index 99a97079be378d654311847305e2b4cd93460208..826d329b7f1d8f91c942e053ef531e38815093b3 100644 |
--- a/third_party/sqlite/src/src/whereexpr.c |
+++ b/third_party/sqlite/src/src/whereexpr.c |
@@ -64,7 +64,7 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, u16 wtFlags){ |
if( pWC->nTerm>=pWC->nSlot ){ |
WhereTerm *pOld = pWC->a; |
sqlite3 *db = pWC->pWInfo->pParse->db; |
- pWC->a = sqlite3DbMallocRaw(db, sizeof(pWC->a[0])*pWC->nSlot*2 ); |
+ pWC->a = sqlite3DbMallocRawNN(db, sizeof(pWC->a[0])*pWC->nSlot*2 ); |
if( pWC->a==0 ){ |
if( wtFlags & TERM_DYNAMIC ){ |
sqlite3ExprDelete(db, p); |
@@ -77,7 +77,6 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, u16 wtFlags){ |
sqlite3DbFree(db, pOld); |
} |
pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]); |
- memset(&pWC->a[pWC->nTerm], 0, sizeof(pWC->a[0])*(pWC->nSlot-pWC->nTerm)); |
} |
pTerm = &pWC->a[idx = pWC->nTerm++]; |
if( p && ExprHasProperty(p, EP_Unlikely) ){ |
@@ -89,13 +88,15 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, u16 wtFlags){ |
pTerm->wtFlags = wtFlags; |
pTerm->pWC = pWC; |
pTerm->iParent = -1; |
+ memset(&pTerm->eOperator, 0, |
+ sizeof(WhereTerm) - offsetof(WhereTerm,eOperator)); |
return idx; |
} |
/* |
** Return TRUE if the given operator is one of the operators that is |
** allowed for an indexable WHERE clause term. The allowed operators are |
-** "=", "<", ">", "<=", ">=", "IN", and "IS NULL" |
+** "=", "<", ">", "<=", ">=", "IN", "IS", and "IS NULL" |
*/ |
static int allowedOp(int op){ |
assert( TK_GT>TK_EQ && TK_GT<TK_GE ); |
@@ -202,6 +203,7 @@ static int isLikeOrGlob( |
sqlite3 *db = pParse->db; /* Database connection */ |
sqlite3_value *pVal = 0; |
int op; /* Opcode of pRight */ |
+ int rc; /* Result code to return */ |
if( !sqlite3IsLikeFunction(db, pExpr, pnoCase, wc) ){ |
return 0; |
@@ -267,8 +269,9 @@ static int isLikeOrGlob( |
} |
} |
+ rc = (z!=0); |
sqlite3ValueFree(pVal); |
- return (z!=0); |
+ return rc; |
} |
#endif /* SQLITE_OMIT_LIKE_OPTIMIZATION */ |
@@ -288,7 +291,7 @@ static int isMatchOfColumn( |
Expr *pExpr, /* Test this expression */ |
unsigned char *peOp2 /* OUT: 0 for MATCH, or else an op2 value */ |
){ |
- struct Op2 { |
+ static const struct Op2 { |
const char *zOp; |
unsigned char eOp2; |
} aOp[] = { |
@@ -531,6 +534,7 @@ static void exprAnalyzeOrTerm( |
if( pOrInfo==0 ) return; |
pTerm->wtFlags |= TERM_ORINFO; |
pOrWc = &pOrInfo->wc; |
+ memset(pOrWc->aStatic, 0, sizeof(pOrWc->aStatic)); |
sqlite3WhereClauseInit(pOrWc, pWInfo); |
sqlite3WhereSplit(pOrWc, pExpr, TK_OR); |
sqlite3WhereExprAnalyze(pSrc, pOrWc); |
@@ -547,7 +551,7 @@ static void exprAnalyzeOrTerm( |
WhereAndInfo *pAndInfo; |
assert( (pOrTerm->wtFlags & (TERM_ANDINFO|TERM_ORINFO))==0 ); |
chngToIN = 0; |
- pAndInfo = sqlite3DbMallocRaw(db, sizeof(*pAndInfo)); |
+ pAndInfo = sqlite3DbMallocRawNN(db, sizeof(*pAndInfo)); |
if( pAndInfo ){ |
WhereClause *pAndWC; |
WhereTerm *pAndTerm; |
@@ -557,15 +561,17 @@ static void exprAnalyzeOrTerm( |
pOrTerm->wtFlags |= TERM_ANDINFO; |
pOrTerm->eOperator = WO_AND; |
pAndWC = &pAndInfo->wc; |
+ memset(pAndWC->aStatic, 0, sizeof(pAndWC->aStatic)); |
sqlite3WhereClauseInit(pAndWC, pWC->pWInfo); |
sqlite3WhereSplit(pAndWC, pOrTerm->pExpr, TK_AND); |
sqlite3WhereExprAnalyze(pSrc, pAndWC); |
pAndWC->pOuter = pWC; |
- testcase( db->mallocFailed ); |
if( !db->mallocFailed ){ |
for(j=0, pAndTerm=pAndWC->a; j<pAndWC->nTerm; j++, pAndTerm++){ |
assert( pAndTerm->pExpr ); |
- if( allowedOp(pAndTerm->pExpr->op) ){ |
+ if( allowedOp(pAndTerm->pExpr->op) |
+ || pAndTerm->eOperator==WO_MATCH |
+ ){ |
b |= sqlite3WhereGetMask(&pWInfo->sMaskSet, pAndTerm->leftCursor); |
} |
} |
@@ -728,7 +734,7 @@ static void exprAnalyzeOrTerm( |
} |
assert( pLeft!=0 ); |
pDup = sqlite3ExprDup(db, pLeft, 0); |
- pNew = sqlite3PExpr(pParse, TK_IN, pDup, 0, 0); |
+ pNew = sqlite3PExpr(pParse, TK_IN, pDup, 0); |
if( pNew ){ |
int idxNew; |
transferJoinMarkings(pNew, pExpr); |
@@ -780,12 +786,10 @@ static int termIsEquivalence(Parse *pParse, Expr *pExpr){ |
pColl = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft, pExpr->pRight); |
if( pColl==0 || sqlite3StrICmp(pColl->zName, "BINARY")==0 ) return 1; |
pColl = sqlite3ExprCollSeq(pParse, pExpr->pLeft); |
- /* Since pLeft and pRight are both a column references, their collating |
- ** sequence should always be defined. */ |
- zColl1 = ALWAYS(pColl) ? pColl->zName : 0; |
+ zColl1 = pColl ? pColl->zName : 0; |
pColl = sqlite3ExprCollSeq(pParse, pExpr->pRight); |
- zColl2 = ALWAYS(pColl) ? pColl->zName : 0; |
- return sqlite3StrICmp(zColl1, zColl2)==0; |
+ zColl2 = pColl ? pColl->zName : 0; |
+ return sqlite3_stricmp(zColl1, zColl2)==0; |
} |
/* |
@@ -820,7 +824,8 @@ static Bitmask exprSelectUsage(WhereMaskSet *pMaskSet, Select *pS){ |
** in any index. Return TRUE (1) if pExpr is an indexed term and return |
** FALSE (0) if not. If TRUE is returned, also set *piCur to the cursor |
** number of the table that is indexed and *piColumn to the column number |
-** of the column that is indexed, or -2 if an expression is being indexed. |
+** of the column that is indexed, or XN_EXPR (-2) if an expression is being |
+** indexed. |
** |
** If pExpr is a TK_COLUMN column reference, then this routine always returns |
** true even if that particular column is not indexed, because the column |
@@ -828,6 +833,7 @@ static Bitmask exprSelectUsage(WhereMaskSet *pMaskSet, Select *pS){ |
*/ |
static int exprMightBeIndexed( |
SrcList *pFrom, /* The FROM clause */ |
+ int op, /* The specific comparison operator */ |
Bitmask mPrereq, /* Bitmask of FROM clause terms referenced by pExpr */ |
Expr *pExpr, /* An operand of a comparison operator */ |
int *piCur, /* Write the referenced table cursor number here */ |
@@ -836,6 +842,17 @@ static int exprMightBeIndexed( |
Index *pIdx; |
int i; |
int iCur; |
+ |
+ /* If this expression is a vector to the left or right of a |
+ ** inequality constraint (>, <, >= or <=), perform the processing |
+ ** on the first element of the vector. */ |
+ assert( TK_GT+1==TK_LE && TK_GT+2==TK_LT && TK_GT+3==TK_GE ); |
+ assert( TK_IS<TK_GE && TK_ISNULL<TK_GE && TK_IN<TK_GE ); |
+ assert( op<=TK_GE ); |
+ if( pExpr->op==TK_VECTOR && (op>=TK_GT && ALWAYS(op<=TK_GE)) ){ |
+ pExpr = pExpr->x.pList->a[0].pExpr; |
+ } |
+ |
if( pExpr->op==TK_COLUMN ){ |
*piCur = pExpr->iTable; |
*piColumn = pExpr->iColumn; |
@@ -848,10 +865,10 @@ static int exprMightBeIndexed( |
for(pIdx=pFrom->a[i].pTab->pIndex; pIdx; pIdx=pIdx->pNext){ |
if( pIdx->aColExpr==0 ) continue; |
for(i=0; i<pIdx->nKeyCol; i++){ |
- if( pIdx->aiColumn[i]!=(-2) ) continue; |
+ if( pIdx->aiColumn[i]!=XN_EXPR ) continue; |
if( sqlite3ExprCompare(pExpr, pIdx->aColExpr->a[i].pExpr, iCur)==0 ){ |
*piCur = iCur; |
- *piColumn = -2; |
+ *piColumn = XN_EXPR; |
return 1; |
} |
} |
@@ -896,6 +913,7 @@ static void exprAnalyze( |
Parse *pParse = pWInfo->pParse; /* Parsing context */ |
sqlite3 *db = pParse->db; /* Database connection */ |
unsigned char eOp2; /* op2 value for LIKE/REGEXP/GLOB */ |
+ int nLeft; /* Number of elements on left side vector */ |
if( db->mallocFailed ){ |
return; |
@@ -908,6 +926,7 @@ static void exprAnalyze( |
op = pExpr->op; |
if( op==TK_IN ){ |
assert( pExpr->pRight==0 ); |
+ if( sqlite3ExprCheckIN(pParse, pExpr) ) return; |
if( ExprHasProperty(pExpr, EP_xIsSelect) ){ |
pTerm->prereqRight = exprSelectUsage(pMaskSet, pExpr->x.pSelect); |
}else{ |
@@ -924,6 +943,10 @@ static void exprAnalyze( |
prereqAll |= x; |
extraRight = x-1; /* ON clause terms may not be used with an index |
** on left table of a LEFT JOIN. Ticket #3015 */ |
+ if( (prereqAll>>1)>=x ){ |
+ sqlite3ErrorMsg(pParse, "ON clause references tables to its right"); |
+ return; |
+ } |
} |
pTerm->prereqAll = prereqAll; |
pTerm->leftCursor = -1; |
@@ -934,18 +957,26 @@ static void exprAnalyze( |
Expr *pLeft = sqlite3ExprSkipCollate(pExpr->pLeft); |
Expr *pRight = sqlite3ExprSkipCollate(pExpr->pRight); |
u16 opMask = (pTerm->prereqRight & prereqLeft)==0 ? WO_ALL : WO_EQUIV; |
- if( exprMightBeIndexed(pSrc, prereqLeft, pLeft, &iCur, &iColumn) ){ |
+ |
+ if( pTerm->iField>0 ){ |
+ assert( op==TK_IN ); |
+ assert( pLeft->op==TK_VECTOR ); |
+ pLeft = pLeft->x.pList->a[pTerm->iField-1].pExpr; |
+ } |
+ |
+ if( exprMightBeIndexed(pSrc, op, prereqLeft, pLeft, &iCur, &iColumn) ){ |
pTerm->leftCursor = iCur; |
pTerm->u.leftColumn = iColumn; |
pTerm->eOperator = operatorMask(op) & opMask; |
} |
if( op==TK_IS ) pTerm->wtFlags |= TERM_IS; |
if( pRight |
- && exprMightBeIndexed(pSrc, pTerm->prereqRight, pRight, &iCur, &iColumn) |
+ && exprMightBeIndexed(pSrc, op, pTerm->prereqRight, pRight, &iCur,&iColumn) |
){ |
WhereTerm *pNew; |
Expr *pDup; |
u16 eExtraOp = 0; /* Extra bits for pNew->eOperator */ |
+ assert( pTerm->iField==0 ); |
if( pTerm->leftCursor>=0 ){ |
int idxNew; |
pDup = sqlite3ExprDup(db, pExpr, 0); |
@@ -1006,7 +1037,7 @@ static void exprAnalyze( |
int idxNew; |
pNewExpr = sqlite3PExpr(pParse, ops[i], |
sqlite3ExprDup(db, pExpr->pLeft, 0), |
- sqlite3ExprDup(db, pList->a[i].pExpr, 0), 0); |
+ sqlite3ExprDup(db, pList->a[i].pExpr, 0)); |
transferJoinMarkings(pNewExpr, pExpr); |
idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC); |
testcase( idxNew==0 ); |
@@ -1091,7 +1122,7 @@ static void exprAnalyze( |
pNewExpr1 = sqlite3ExprDup(db, pLeft, 0); |
pNewExpr1 = sqlite3PExpr(pParse, TK_GE, |
sqlite3ExprAddCollateString(pParse,pNewExpr1,zCollSeqName), |
- pStr1, 0); |
+ pStr1); |
transferJoinMarkings(pNewExpr1, pExpr); |
idxNew1 = whereClauseInsert(pWC, pNewExpr1, wtFlags); |
testcase( idxNew1==0 ); |
@@ -1099,7 +1130,7 @@ static void exprAnalyze( |
pNewExpr2 = sqlite3ExprDup(db, pLeft, 0); |
pNewExpr2 = sqlite3PExpr(pParse, TK_LT, |
sqlite3ExprAddCollateString(pParse,pNewExpr2,zCollSeqName), |
- pStr2, 0); |
+ pStr2); |
transferJoinMarkings(pNewExpr2, pExpr); |
idxNew2 = whereClauseInsert(pWC, pNewExpr2, wtFlags); |
testcase( idxNew2==0 ); |
@@ -1119,7 +1150,7 @@ static void exprAnalyze( |
** virtual tables. The native query optimizer does not attempt |
** to do anything with MATCH functions. |
*/ |
- if( isMatchOfColumn(pExpr, &eOp2) ){ |
+ if( pWC->op==TK_AND && isMatchOfColumn(pExpr, &eOp2) ){ |
int idxNew; |
Expr *pRight, *pLeft; |
WhereTerm *pNewTerm; |
@@ -1132,7 +1163,7 @@ static void exprAnalyze( |
if( (prereqExpr & prereqColumn)==0 ){ |
Expr *pNewExpr; |
pNewExpr = sqlite3PExpr(pParse, TK_MATCH, |
- 0, sqlite3ExprDup(db, pRight, 0), 0); |
+ 0, sqlite3ExprDup(db, pRight, 0)); |
idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC); |
testcase( idxNew==0 ); |
pNewTerm = &pWC->a[idxNew]; |
@@ -1149,6 +1180,59 @@ static void exprAnalyze( |
} |
#endif /* SQLITE_OMIT_VIRTUALTABLE */ |
+ /* If there is a vector == or IS term - e.g. "(a, b) == (?, ?)" - create |
+ ** new terms for each component comparison - "a = ?" and "b = ?". The |
+ ** new terms completely replace the original vector comparison, which is |
+ ** no longer used. |
+ ** |
+ ** This is only required if at least one side of the comparison operation |
+ ** is not a sub-select. */ |
+ if( pWC->op==TK_AND |
+ && (pExpr->op==TK_EQ || pExpr->op==TK_IS) |
+ && (nLeft = sqlite3ExprVectorSize(pExpr->pLeft))>1 |
+ && sqlite3ExprVectorSize(pExpr->pRight)==nLeft |
+ && ( (pExpr->pLeft->flags & EP_xIsSelect)==0 |
+ || (pExpr->pRight->flags & EP_xIsSelect)==0) |
+ ){ |
+ int i; |
+ for(i=0; i<nLeft; i++){ |
+ int idxNew; |
+ Expr *pNew; |
+ Expr *pLeft = sqlite3ExprForVectorField(pParse, pExpr->pLeft, i); |
+ Expr *pRight = sqlite3ExprForVectorField(pParse, pExpr->pRight, i); |
+ |
+ pNew = sqlite3PExpr(pParse, pExpr->op, pLeft, pRight); |
+ transferJoinMarkings(pNew, pExpr); |
+ idxNew = whereClauseInsert(pWC, pNew, TERM_DYNAMIC); |
+ exprAnalyze(pSrc, pWC, idxNew); |
+ } |
+ pTerm = &pWC->a[idxTerm]; |
+ pTerm->wtFlags = TERM_CODED|TERM_VIRTUAL; /* Disable the original */ |
+ pTerm->eOperator = 0; |
+ } |
+ |
+ /* If there is a vector IN term - e.g. "(a, b) IN (SELECT ...)" - create |
+ ** a virtual term for each vector component. The expression object |
+ ** used by each such virtual term is pExpr (the full vector IN(...) |
+ ** expression). The WhereTerm.iField variable identifies the index within |
+ ** the vector on the LHS that the virtual term represents. |
+ ** |
+ ** This only works if the RHS is a simple SELECT, not a compound |
+ */ |
+ if( pWC->op==TK_AND && pExpr->op==TK_IN && pTerm->iField==0 |
+ && pExpr->pLeft->op==TK_VECTOR |
+ && pExpr->x.pSelect->pPrior==0 |
+ ){ |
+ int i; |
+ for(i=0; i<sqlite3ExprVectorSize(pExpr->pLeft); i++){ |
+ int idxNew; |
+ idxNew = whereClauseInsert(pWC, pExpr, TERM_VIRTUAL); |
+ pWC->a[idxNew].iField = i+1; |
+ exprAnalyze(pSrc, pWC, idxNew); |
+ markTermAsChild(pWC, idxNew, idxTerm); |
+ } |
+ } |
+ |
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 |
/* When sqlite_stat3 histogram data is available an operator of the |
** form "x IS NOT NULL" can sometimes be evaluated more efficiently |
@@ -1169,7 +1253,7 @@ static void exprAnalyze( |
pNewExpr = sqlite3PExpr(pParse, TK_GT, |
sqlite3ExprDup(db, pLeft, 0), |
- sqlite3PExpr(pParse, TK_NULL, 0, 0, 0), 0); |
+ sqlite3ExprAlloc(db, TK_NULL, 0, 0)); |
idxNew = whereClauseInsert(pWC, pNewExpr, |
TERM_VIRTUAL|TERM_DYNAMIC|TERM_VNULL); |
@@ -1190,6 +1274,8 @@ static void exprAnalyze( |
/* Prevent ON clause terms of a LEFT JOIN from being used to drive |
** an index for tables to the left of the join. |
*/ |
+ testcase( pTerm!=&pWC->a[idxTerm] ); |
+ pTerm = &pWC->a[idxTerm]; |
pTerm->prereqRight |= extraRight; |
} |
@@ -1272,17 +1358,18 @@ void sqlite3WhereClauseClear(WhereClause *pWC){ |
** tree. |
*/ |
Bitmask sqlite3WhereExprUsage(WhereMaskSet *pMaskSet, Expr *p){ |
- Bitmask mask = 0; |
+ Bitmask mask; |
if( p==0 ) return 0; |
if( p->op==TK_COLUMN ){ |
mask = sqlite3WhereGetMask(pMaskSet, p->iTable); |
return mask; |
} |
- mask = sqlite3WhereExprUsage(pMaskSet, p->pRight); |
- mask |= sqlite3WhereExprUsage(pMaskSet, p->pLeft); |
+ assert( !ExprHasProperty(p, EP_TokenOnly) ); |
+ mask = p->pRight ? sqlite3WhereExprUsage(pMaskSet, p->pRight) : 0; |
+ if( p->pLeft ) mask |= sqlite3WhereExprUsage(pMaskSet, p->pLeft); |
if( ExprHasProperty(p, EP_xIsSelect) ){ |
mask |= exprSelectUsage(pMaskSet, p->x.pSelect); |
- }else{ |
+ }else if( p->x.pList ){ |
mask |= sqlite3WhereExprListUsage(pMaskSet, p->x.pList); |
} |
return mask; |
@@ -1346,13 +1433,13 @@ void sqlite3WhereTabFuncArgs( |
pTab->zName, j); |
return; |
} |
- pColRef = sqlite3PExpr(pParse, TK_COLUMN, 0, 0, 0); |
+ pColRef = sqlite3ExprAlloc(pParse->db, TK_COLUMN, 0, 0); |
if( pColRef==0 ) return; |
pColRef->iTable = pItem->iCursor; |
pColRef->iColumn = k++; |
pColRef->pTab = pTab; |
pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef, |
- sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0), 0); |
+ sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0)); |
whereClauseInsert(pWC, pTerm, TERM_DYNAMIC); |
} |
} |