Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(359)

Unified Diff: third_party/sqlite/src/src/whereexpr.c

Issue 2751253002: [sql] Import SQLite 3.17.0. (Closed)
Patch Set: also clang on Linux i386 Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « third_party/sqlite/src/src/wherecode.c ('k') | third_party/sqlite/src/test/affinity3.test » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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);
}
}
« no previous file with comments | « third_party/sqlite/src/src/wherecode.c ('k') | third_party/sqlite/src/test/affinity3.test » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698