| Index: third_party/sqlite/src/src/where.c
|
| diff --git a/third_party/sqlite/src/src/where.c b/third_party/sqlite/src/src/where.c
|
| index 702bdaf0355c14315d42036587b768b869fede6f..226055b47265e2a15ad687f3288b5058e57f127b 100644
|
| --- a/third_party/sqlite/src/src/where.c
|
| +++ b/third_party/sqlite/src/src/where.c
|
| @@ -15,8 +15,6 @@
|
| ** rows. Indices are selected and used to speed the search when doing
|
| ** so is applicable. Because this module is responsible for selecting
|
| ** indices, you might also think of this module as the "query optimizer".
|
| -**
|
| -** $Id: where.c,v 1.411 2009/07/31 06:14:52 danielk1977 Exp $
|
| */
|
| #include "sqliteInt.h"
|
|
|
| @@ -237,6 +235,7 @@ struct WhereCost {
|
| #define WHERE_COLUMN_IN 0x00040000 /* x IN (...) */
|
| #define WHERE_COLUMN_NULL 0x00080000 /* x IS NULL */
|
| #define WHERE_INDEXED 0x000f0000 /* Anything that uses an index */
|
| +#define WHERE_NOT_FULLSCAN 0x000f3000 /* Does not do a full table scan */
|
| #define WHERE_IN_ABLE 0x000f1000 /* Able to support an IN operator */
|
| #define WHERE_TOP_LIMIT 0x00100000 /* x<EXPR or x<=EXPR constraint */
|
| #define WHERE_BTM_LIMIT 0x00200000 /* x>EXPR or x>=EXPR constraint */
|
| @@ -246,6 +245,7 @@ struct WhereCost {
|
| #define WHERE_UNIQUE 0x04000000 /* Selects no more than one row */
|
| #define WHERE_VIRTUALTABLE 0x08000000 /* Use virtual-table processing */
|
| #define WHERE_MULTI_OR 0x10000000 /* OR using multiple indices */
|
| +#define WHERE_TEMP_INDEX 0x20000000 /* Uses an ephemeral index */
|
|
|
| /*
|
| ** Initialize a preallocated WhereClause structure.
|
| @@ -327,6 +327,7 @@ static void whereClauseClear(WhereClause *pWC){
|
| static int whereClauseInsert(WhereClause *pWC, Expr *p, u8 wtFlags){
|
| WhereTerm *pTerm;
|
| int idx;
|
| + testcase( wtFlags & TERM_VIRTUAL ); /* EV: R-00211-15100 */
|
| if( pWC->nTerm>=pWC->nSlot ){
|
| WhereTerm *pOld = pWC->a;
|
| sqlite3 *db = pWC->pParse->db;
|
| @@ -472,6 +473,13 @@ static Bitmask exprSelectTableUsage(WhereMaskSet *pMaskSet, Select *pS){
|
| ** Return TRUE if the given operator is one of the operators that is
|
| ** allowed for an indexable WHERE clause term. The allowed operators are
|
| ** "=", "<", ">", "<=", ">=", and "IN".
|
| +**
|
| +** IMPLEMENTATION-OF: R-59926-26393 To be usable by an index a term must be
|
| +** of one of the following forms: column = expression column > expression
|
| +** column >= expression column < expression column <= expression
|
| +** expression = column expression > column expression >= column
|
| +** expression < column expression <= column column IN
|
| +** (expression-list) column IN (subquery) column IS NULL
|
| */
|
| static int allowedOp(int op){
|
| assert( TK_GT>TK_EQ && TK_GT<TK_GE );
|
| @@ -625,18 +633,19 @@ static void exprAnalyzeAll(
|
| static int isLikeOrGlob(
|
| Parse *pParse, /* Parsing and code generating context */
|
| Expr *pExpr, /* Test this expression */
|
| - int *pnPattern, /* Number of non-wildcard prefix characters */
|
| + Expr **ppPrefix, /* Pointer to TK_STRING expression with pattern prefix */
|
| int *pisComplete, /* True if the only wildcard is % in the last character */
|
| int *pnoCase /* True if uppercase is equivalent to lowercase */
|
| ){
|
| - const char *z; /* String on RHS of LIKE operator */
|
| + const char *z = 0; /* String on RHS of LIKE operator */
|
| Expr *pRight, *pLeft; /* Right and left size of LIKE operator */
|
| ExprList *pList; /* List of operands to the LIKE operator */
|
| int c; /* One character in z[] */
|
| int cnt; /* Number of non-wildcard prefix characters */
|
| char wc[3]; /* Wildcard characters */
|
| - CollSeq *pColl; /* Collating sequence for LHS */
|
| sqlite3 *db = pParse->db; /* Database connection */
|
| + sqlite3_value *pVal = 0;
|
| + int op; /* Opcode of pRight */
|
|
|
| if( !sqlite3IsLikeFunction(db, pExpr, pnoCase, wc) ){
|
| return 0;
|
| @@ -645,35 +654,65 @@ static int isLikeOrGlob(
|
| if( *pnoCase ) return 0;
|
| #endif
|
| pList = pExpr->x.pList;
|
| - pRight = pList->a[0].pExpr;
|
| - if( pRight->op!=TK_STRING ){
|
| - return 0;
|
| - }
|
| pLeft = pList->a[1].pExpr;
|
| - if( pLeft->op!=TK_COLUMN ){
|
| + if( pLeft->op!=TK_COLUMN || sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT ){
|
| + /* IMP: R-02065-49465 The left-hand side of the LIKE or GLOB operator must
|
| + ** be the name of an indexed column with TEXT affinity. */
|
| return 0;
|
| }
|
| - pColl = sqlite3ExprCollSeq(pParse, pLeft);
|
| - assert( pColl!=0 || pLeft->iColumn==-1 );
|
| - if( pColl==0 ) return 0;
|
| - if( (pColl->type!=SQLITE_COLL_BINARY || *pnoCase) &&
|
| - (pColl->type!=SQLITE_COLL_NOCASE || !*pnoCase) ){
|
| - return 0;
|
| + assert( pLeft->iColumn!=(-1) ); /* Because IPK never has AFF_TEXT */
|
| +
|
| + pRight = pList->a[0].pExpr;
|
| + op = pRight->op;
|
| + if( op==TK_REGISTER ){
|
| + op = pRight->op2;
|
| + }
|
| + if( op==TK_VARIABLE ){
|
| + Vdbe *pReprepare = pParse->pReprepare;
|
| + int iCol = pRight->iColumn;
|
| + pVal = sqlite3VdbeGetValue(pReprepare, iCol, SQLITE_AFF_NONE);
|
| + if( pVal && sqlite3_value_type(pVal)==SQLITE_TEXT ){
|
| + z = (char *)sqlite3_value_text(pVal);
|
| + }
|
| + sqlite3VdbeSetVarmask(pParse->pVdbe, iCol); /* IMP: R-23257-02778 */
|
| + assert( pRight->op==TK_VARIABLE || pRight->op==TK_REGISTER );
|
| + }else if( op==TK_STRING ){
|
| + z = pRight->u.zToken;
|
| }
|
| - if( sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT ) return 0;
|
| - z = pRight->u.zToken;
|
| - if( ALWAYS(z) ){
|
| + if( z ){
|
| cnt = 0;
|
| while( (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2] ){
|
| cnt++;
|
| }
|
| - if( cnt!=0 && c!=0 && 255!=(u8)z[cnt-1] ){
|
| - *pisComplete = z[cnt]==wc[0] && z[cnt+1]==0;
|
| - *pnPattern = cnt;
|
| - return 1;
|
| + if( cnt!=0 && 255!=(u8)z[cnt-1] ){
|
| + Expr *pPrefix;
|
| + *pisComplete = c==wc[0] && z[cnt+1]==0;
|
| + pPrefix = sqlite3Expr(db, TK_STRING, z);
|
| + if( pPrefix ) pPrefix->u.zToken[cnt] = 0;
|
| + *ppPrefix = pPrefix;
|
| + if( op==TK_VARIABLE ){
|
| + Vdbe *v = pParse->pVdbe;
|
| + sqlite3VdbeSetVarmask(v, pRight->iColumn); /* IMP: R-23257-02778 */
|
| + if( *pisComplete && pRight->u.zToken[1] ){
|
| + /* If the rhs of the LIKE expression is a variable, and the current
|
| + ** value of the variable means there is no need to invoke the LIKE
|
| + ** function, then no OP_Variable will be added to the program.
|
| + ** This causes problems for the sqlite3_bind_parameter_name()
|
| + ** API. To workaround them, add a dummy OP_Variable here.
|
| + */
|
| + int r1 = sqlite3GetTempReg(pParse);
|
| + sqlite3ExprCodeTarget(pParse, pRight, r1);
|
| + sqlite3VdbeChangeP3(v, sqlite3VdbeCurrentAddr(v)-1, 0);
|
| + sqlite3ReleaseTempReg(pParse, r1);
|
| + }
|
| + }
|
| + }else{
|
| + z = 0;
|
| }
|
| }
|
| - return 0;
|
| +
|
| + sqlite3ValueFree(pVal);
|
| + return (z!=0);
|
| }
|
| #endif /* SQLITE_OMIT_LIKE_OPTIMIZATION */
|
|
|
| @@ -986,6 +1025,8 @@ static void exprAnalyzeOrTerm(
|
| /* At this point, okToChngToIN is true if original pTerm satisfies
|
| ** case 1. In that case, construct a new virtual term that is
|
| ** pTerm converted into an IN operator.
|
| + **
|
| + ** EV: R-00211-15100
|
| */
|
| if( okToChngToIN ){
|
| Expr *pDup; /* A transient duplicate expression */
|
| @@ -1054,10 +1095,10 @@ static void exprAnalyze(
|
| Expr *pExpr; /* The expression to be analyzed */
|
| Bitmask prereqLeft; /* Prerequesites of the pExpr->pLeft */
|
| Bitmask prereqAll; /* Prerequesites of pExpr */
|
| - Bitmask extraRight = 0;
|
| - int nPattern;
|
| - int isComplete;
|
| - int noCase;
|
| + Bitmask extraRight = 0; /* Extra dependencies on LEFT JOIN */
|
| + Expr *pStr1 = 0; /* RHS of LIKE/GLOB operator */
|
| + int isComplete = 0; /* RHS of LIKE/GLOB ends with wildcard */
|
| + int noCase = 0; /* LIKE/GLOB distinguishes case */
|
| int op; /* Top-level operator. pExpr->op */
|
| Parse *pParse = pWC->pParse; /* Parsing context */
|
| sqlite3 *db = pParse->db; /* Database connection */
|
| @@ -1126,7 +1167,8 @@ static void exprAnalyze(
|
| pLeft = pDup->pLeft;
|
| pNew->leftCursor = pLeft->iTable;
|
| pNew->u.leftColumn = pLeft->iColumn;
|
| - pNew->prereqRight = prereqLeft;
|
| + testcase( (prereqLeft | extraRight) != prereqLeft );
|
| + pNew->prereqRight = prereqLeft | extraRight;
|
| pNew->prereqAll = prereqAll;
|
| pNew->eOperator = operatorMask(pDup->op);
|
| }
|
| @@ -1192,21 +1234,22 @@ static void exprAnalyze(
|
| ** The last character of the prefix "abc" is incremented to form the
|
| ** termination condition "abd".
|
| */
|
| - if( isLikeOrGlob(pParse, pExpr, &nPattern, &isComplete, &noCase)
|
| - && pWC->op==TK_AND ){
|
| - Expr *pLeft, *pRight;
|
| - Expr *pStr1, *pStr2;
|
| - Expr *pNewExpr1, *pNewExpr2;
|
| - int idxNew1, idxNew2;
|
| + if( pWC->op==TK_AND
|
| + && isLikeOrGlob(pParse, pExpr, &pStr1, &isComplete, &noCase)
|
| + ){
|
| + Expr *pLeft; /* LHS of LIKE/GLOB operator */
|
| + Expr *pStr2; /* Copy of pStr1 - RHS of LIKE/GLOB operator */
|
| + Expr *pNewExpr1;
|
| + Expr *pNewExpr2;
|
| + int idxNew1;
|
| + int idxNew2;
|
| + CollSeq *pColl; /* Collating sequence to use */
|
|
|
| pLeft = pExpr->x.pList->a[1].pExpr;
|
| - pRight = pExpr->x.pList->a[0].pExpr;
|
| - pStr1 = sqlite3Expr(db, TK_STRING, pRight->u.zToken);
|
| - if( pStr1 ) pStr1->u.zToken[nPattern] = 0;
|
| pStr2 = sqlite3ExprDup(db, pStr1, 0);
|
| if( !db->mallocFailed ){
|
| u8 c, *pC; /* Last character before the first wildcard */
|
| - pC = (u8*)&pStr2->u.zToken[nPattern-1];
|
| + pC = (u8*)&pStr2->u.zToken[sqlite3Strlen30(pStr2->u.zToken)-1];
|
| c = *pC;
|
| if( noCase ){
|
| /* The point is to increment the last character before the first
|
| @@ -1215,17 +1258,23 @@ static void exprAnalyze(
|
| ** inequality. To avoid this, make sure to also run the full
|
| ** LIKE on all candidate expressions by clearing the isComplete flag
|
| */
|
| - if( c=='A'-1 ) isComplete = 0;
|
| + if( c=='A'-1 ) isComplete = 0; /* EV: R-64339-08207 */
|
| +
|
|
|
| c = sqlite3UpperToLower[c];
|
| }
|
| *pC = c + 1;
|
| }
|
| - pNewExpr1 = sqlite3PExpr(pParse, TK_GE, sqlite3ExprDup(db,pLeft,0),pStr1,0);
|
| + pColl = sqlite3FindCollSeq(db, SQLITE_UTF8, noCase ? "NOCASE" : "BINARY",0);
|
| + pNewExpr1 = sqlite3PExpr(pParse, TK_GE,
|
| + sqlite3ExprSetColl(sqlite3ExprDup(db,pLeft,0), pColl),
|
| + pStr1, 0);
|
| idxNew1 = whereClauseInsert(pWC, pNewExpr1, TERM_VIRTUAL|TERM_DYNAMIC);
|
| testcase( idxNew1==0 );
|
| exprAnalyze(pSrc, pWC, idxNew1);
|
| - pNewExpr2 = sqlite3PExpr(pParse, TK_LT, sqlite3ExprDup(db,pLeft,0),pStr2,0);
|
| + pNewExpr2 = sqlite3PExpr(pParse, TK_LT,
|
| + sqlite3ExprSetColl(sqlite3ExprDup(db,pLeft,0), pColl),
|
| + pStr2, 0);
|
| idxNew2 = whereClauseInsert(pWC, pNewExpr2, TERM_VIRTUAL|TERM_DYNAMIC);
|
| testcase( idxNew2==0 );
|
| exprAnalyze(pSrc, pWC, idxNew2);
|
| @@ -1507,7 +1556,8 @@ static void TRACE_IDX_OUTPUTS(sqlite3_index_info *p){
|
| ** Required because bestIndex() is called by bestOrClauseIndex()
|
| */
|
| static void bestIndex(
|
| - Parse*, WhereClause*, struct SrcList_item*, Bitmask, ExprList*, WhereCost*);
|
| + Parse*, WhereClause*, struct SrcList_item*,
|
| + Bitmask, Bitmask, ExprList*, WhereCost*);
|
|
|
| /*
|
| ** This routine attempts to find an scanning strategy that can be used
|
| @@ -1520,7 +1570,8 @@ static void bestOrClauseIndex(
|
| Parse *pParse, /* The parsing context */
|
| WhereClause *pWC, /* The WHERE clause */
|
| struct SrcList_item *pSrc, /* The FROM clause term to search */
|
| - Bitmask notReady, /* Mask of cursors that are not available */
|
| + Bitmask notReady, /* Mask of cursors not available for indexing */
|
| + Bitmask notValid, /* Cursors not available for any purpose */
|
| ExprList *pOrderBy, /* The ORDER BY clause */
|
| WhereCost *pCost /* Lowest cost query plan */
|
| ){
|
| @@ -1530,6 +1581,11 @@ static void bestOrClauseIndex(
|
| WhereTerm * const pWCEnd = &pWC->a[pWC->nTerm]; /* End of pWC->a[] */
|
| WhereTerm *pTerm; /* A single term of the WHERE clause */
|
|
|
| + /* No OR-clause optimization allowed if the NOT INDEXED clause is used */
|
| + if( pSrc->notIndexed ){
|
| + return;
|
| + }
|
| +
|
| /* Search the WHERE clause terms for a usable WO_OR term. */
|
| for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
|
| if( pTerm->eOperator==WO_OR
|
| @@ -1551,7 +1607,7 @@ static void bestOrClauseIndex(
|
| ));
|
| if( pOrTerm->eOperator==WO_AND ){
|
| WhereClause *pAndWC = &pOrTerm->u.pAndInfo->wc;
|
| - bestIndex(pParse, pAndWC, pSrc, notReady, 0, &sTermCost);
|
| + bestIndex(pParse, pAndWC, pSrc, notReady, notValid, 0, &sTermCost);
|
| }else if( pOrTerm->leftCursor==iCur ){
|
| WhereClause tempWC;
|
| tempWC.pParse = pWC->pParse;
|
| @@ -1559,7 +1615,7 @@ static void bestOrClauseIndex(
|
| tempWC.op = TK_AND;
|
| tempWC.a = pOrTerm;
|
| tempWC.nTerm = 1;
|
| - bestIndex(pParse, &tempWC, pSrc, notReady, 0, &sTermCost);
|
| + bestIndex(pParse, &tempWC, pSrc, notReady, notValid, 0, &sTermCost);
|
| }else{
|
| continue;
|
| }
|
| @@ -1572,8 +1628,9 @@ static void bestOrClauseIndex(
|
| /* If there is an ORDER BY clause, increase the scan cost to account
|
| ** for the cost of the sort. */
|
| if( pOrderBy!=0 ){
|
| + WHERETRACE(("... sorting increases OR cost %.9g to %.9g\n",
|
| + rTotal, rTotal+nRow*estLog(nRow)));
|
| rTotal += nRow*estLog(nRow);
|
| - WHERETRACE(("... sorting increases OR cost to %.9g\n", rTotal));
|
| }
|
|
|
| /* If the cost of scanning using this OR term for optimization is
|
| @@ -1592,6 +1649,247 @@ static void bestOrClauseIndex(
|
| #endif /* SQLITE_OMIT_OR_OPTIMIZATION */
|
| }
|
|
|
| +#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
|
| +/*
|
| +** Return TRUE if the WHERE clause term pTerm is of a form where it
|
| +** could be used with an index to access pSrc, assuming an appropriate
|
| +** index existed.
|
| +*/
|
| +static int termCanDriveIndex(
|
| + WhereTerm *pTerm, /* WHERE clause term to check */
|
| + struct SrcList_item *pSrc, /* Table we are trying to access */
|
| + Bitmask notReady /* Tables in outer loops of the join */
|
| +){
|
| + char aff;
|
| + if( pTerm->leftCursor!=pSrc->iCursor ) return 0;
|
| + if( pTerm->eOperator!=WO_EQ ) return 0;
|
| + if( (pTerm->prereqRight & notReady)!=0 ) return 0;
|
| + aff = pSrc->pTab->aCol[pTerm->u.leftColumn].affinity;
|
| + if( !sqlite3IndexAffinityOk(pTerm->pExpr, aff) ) return 0;
|
| + return 1;
|
| +}
|
| +#endif
|
| +
|
| +#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
|
| +/*
|
| +** If the query plan for pSrc specified in pCost is a full table scan
|
| +** and indexing is allows (if there is no NOT INDEXED clause) and it
|
| +** possible to construct a transient index that would perform better
|
| +** than a full table scan even when the cost of constructing the index
|
| +** is taken into account, then alter the query plan to use the
|
| +** transient index.
|
| +*/
|
| +static void bestAutomaticIndex(
|
| + Parse *pParse, /* The parsing context */
|
| + WhereClause *pWC, /* The WHERE clause */
|
| + struct SrcList_item *pSrc, /* The FROM clause term to search */
|
| + Bitmask notReady, /* Mask of cursors that are not available */
|
| + WhereCost *pCost /* Lowest cost query plan */
|
| +){
|
| + double nTableRow; /* Rows in the input table */
|
| + double logN; /* log(nTableRow) */
|
| + double costTempIdx; /* per-query cost of the transient index */
|
| + WhereTerm *pTerm; /* A single term of the WHERE clause */
|
| + WhereTerm *pWCEnd; /* End of pWC->a[] */
|
| + Table *pTable; /* Table tht might be indexed */
|
| +
|
| + if( (pParse->db->flags & SQLITE_AutoIndex)==0 ){
|
| + /* Automatic indices are disabled at run-time */
|
| + return;
|
| + }
|
| + if( (pCost->plan.wsFlags & WHERE_NOT_FULLSCAN)!=0 ){
|
| + /* We already have some kind of index in use for this query. */
|
| + return;
|
| + }
|
| + if( pSrc->notIndexed ){
|
| + /* The NOT INDEXED clause appears in the SQL. */
|
| + return;
|
| + }
|
| +
|
| + assert( pParse->nQueryLoop >= (double)1 );
|
| + pTable = pSrc->pTab;
|
| + nTableRow = pTable->nRowEst;
|
| + logN = estLog(nTableRow);
|
| + costTempIdx = 2*logN*(nTableRow/pParse->nQueryLoop + 1);
|
| + if( costTempIdx>=pCost->rCost ){
|
| + /* The cost of creating the transient table would be greater than
|
| + ** doing the full table scan */
|
| + return;
|
| + }
|
| +
|
| + /* Search for any equality comparison term */
|
| + pWCEnd = &pWC->a[pWC->nTerm];
|
| + for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
|
| + if( termCanDriveIndex(pTerm, pSrc, notReady) ){
|
| + WHERETRACE(("auto-index reduces cost from %.2f to %.2f\n",
|
| + pCost->rCost, costTempIdx));
|
| + pCost->rCost = costTempIdx;
|
| + pCost->nRow = logN + 1;
|
| + pCost->plan.wsFlags = WHERE_TEMP_INDEX;
|
| + pCost->used = pTerm->prereqRight;
|
| + break;
|
| + }
|
| + }
|
| +}
|
| +#else
|
| +# define bestAutomaticIndex(A,B,C,D,E) /* no-op */
|
| +#endif /* SQLITE_OMIT_AUTOMATIC_INDEX */
|
| +
|
| +
|
| +#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
|
| +/*
|
| +** Generate code to construct the Index object for an automatic index
|
| +** and to set up the WhereLevel object pLevel so that the code generator
|
| +** makes use of the automatic index.
|
| +*/
|
| +static void constructAutomaticIndex(
|
| + Parse *pParse, /* The parsing context */
|
| + WhereClause *pWC, /* The WHERE clause */
|
| + struct SrcList_item *pSrc, /* The FROM clause term to get the next index */
|
| + Bitmask notReady, /* Mask of cursors that are not available */
|
| + WhereLevel *pLevel /* Write new index here */
|
| +){
|
| + int nColumn; /* Number of columns in the constructed index */
|
| + WhereTerm *pTerm; /* A single term of the WHERE clause */
|
| + WhereTerm *pWCEnd; /* End of pWC->a[] */
|
| + int nByte; /* Byte of memory needed for pIdx */
|
| + Index *pIdx; /* Object describing the transient index */
|
| + Vdbe *v; /* Prepared statement under construction */
|
| + int regIsInit; /* Register set by initialization */
|
| + int addrInit; /* Address of the initialization bypass jump */
|
| + Table *pTable; /* The table being indexed */
|
| + KeyInfo *pKeyinfo; /* Key information for the index */
|
| + int addrTop; /* Top of the index fill loop */
|
| + int regRecord; /* Register holding an index record */
|
| + int n; /* Column counter */
|
| + int i; /* Loop counter */
|
| + int mxBitCol; /* Maximum column in pSrc->colUsed */
|
| + CollSeq *pColl; /* Collating sequence to on a column */
|
| + Bitmask idxCols; /* Bitmap of columns used for indexing */
|
| + Bitmask extraCols; /* Bitmap of additional columns */
|
| +
|
| + /* Generate code to skip over the creation and initialization of the
|
| + ** transient index on 2nd and subsequent iterations of the loop. */
|
| + v = pParse->pVdbe;
|
| + assert( v!=0 );
|
| + regIsInit = ++pParse->nMem;
|
| + addrInit = sqlite3VdbeAddOp1(v, OP_If, regIsInit);
|
| + sqlite3VdbeAddOp2(v, OP_Integer, 1, regIsInit);
|
| +
|
| + /* Count the number of columns that will be added to the index
|
| + ** and used to match WHERE clause constraints */
|
| + nColumn = 0;
|
| + pTable = pSrc->pTab;
|
| + pWCEnd = &pWC->a[pWC->nTerm];
|
| + idxCols = 0;
|
| + for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
|
| + if( termCanDriveIndex(pTerm, pSrc, notReady) ){
|
| + int iCol = pTerm->u.leftColumn;
|
| + Bitmask cMask = iCol>=BMS ? ((Bitmask)1)<<(BMS-1) : ((Bitmask)1)<<iCol;
|
| + testcase( iCol==BMS );
|
| + testcase( iCol==BMS-1 );
|
| + if( (idxCols & cMask)==0 ){
|
| + nColumn++;
|
| + idxCols |= cMask;
|
| + }
|
| + }
|
| + }
|
| + assert( nColumn>0 );
|
| + pLevel->plan.nEq = nColumn;
|
| +
|
| + /* Count the number of additional columns needed to create a
|
| + ** covering index. A "covering index" is an index that contains all
|
| + ** columns that are needed by the query. With a covering index, the
|
| + ** original table never needs to be accessed. Automatic indices must
|
| + ** be a covering index because the index will not be updated if the
|
| + ** original table changes and the index and table cannot both be used
|
| + ** if they go out of sync.
|
| + */
|
| + extraCols = pSrc->colUsed & (~idxCols | (((Bitmask)1)<<(BMS-1)));
|
| + mxBitCol = (pTable->nCol >= BMS-1) ? BMS-1 : pTable->nCol;
|
| + testcase( pTable->nCol==BMS-1 );
|
| + testcase( pTable->nCol==BMS-2 );
|
| + for(i=0; i<mxBitCol; i++){
|
| + if( extraCols & (((Bitmask)1)<<i) ) nColumn++;
|
| + }
|
| + if( pSrc->colUsed & (((Bitmask)1)<<(BMS-1)) ){
|
| + nColumn += pTable->nCol - BMS + 1;
|
| + }
|
| + pLevel->plan.wsFlags |= WHERE_COLUMN_EQ | WHERE_IDX_ONLY | WO_EQ;
|
| +
|
| + /* Construct the Index object to describe this index */
|
| + nByte = sizeof(Index);
|
| + nByte += nColumn*sizeof(int); /* Index.aiColumn */
|
| + nByte += nColumn*sizeof(char*); /* Index.azColl */
|
| + nByte += nColumn; /* Index.aSortOrder */
|
| + pIdx = sqlite3DbMallocZero(pParse->db, nByte);
|
| + if( pIdx==0 ) return;
|
| + pLevel->plan.u.pIdx = pIdx;
|
| + pIdx->azColl = (char**)&pIdx[1];
|
| + pIdx->aiColumn = (int*)&pIdx->azColl[nColumn];
|
| + pIdx->aSortOrder = (u8*)&pIdx->aiColumn[nColumn];
|
| + pIdx->zName = "auto-index";
|
| + pIdx->nColumn = nColumn;
|
| + pIdx->pTable = pTable;
|
| + n = 0;
|
| + idxCols = 0;
|
| + for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
|
| + if( termCanDriveIndex(pTerm, pSrc, notReady) ){
|
| + int iCol = pTerm->u.leftColumn;
|
| + Bitmask cMask = iCol>=BMS ? ((Bitmask)1)<<(BMS-1) : ((Bitmask)1)<<iCol;
|
| + if( (idxCols & cMask)==0 ){
|
| + Expr *pX = pTerm->pExpr;
|
| + idxCols |= cMask;
|
| + pIdx->aiColumn[n] = pTerm->u.leftColumn;
|
| + pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
|
| + pIdx->azColl[n] = pColl->zName;
|
| + n++;
|
| + }
|
| + }
|
| + }
|
| + assert( (u32)n==pLevel->plan.nEq );
|
| +
|
| + /* Add additional columns needed to make the automatic index into
|
| + ** a covering index */
|
| + for(i=0; i<mxBitCol; i++){
|
| + if( extraCols & (((Bitmask)1)<<i) ){
|
| + pIdx->aiColumn[n] = i;
|
| + pIdx->azColl[n] = "BINARY";
|
| + n++;
|
| + }
|
| + }
|
| + if( pSrc->colUsed & (((Bitmask)1)<<(BMS-1)) ){
|
| + for(i=BMS-1; i<pTable->nCol; i++){
|
| + pIdx->aiColumn[n] = i;
|
| + pIdx->azColl[n] = "BINARY";
|
| + n++;
|
| + }
|
| + }
|
| + assert( n==nColumn );
|
| +
|
| + /* Create the automatic index */
|
| + pKeyinfo = sqlite3IndexKeyinfo(pParse, pIdx);
|
| + assert( pLevel->iIdxCur>=0 );
|
| + sqlite3VdbeAddOp4(v, OP_OpenAutoindex, pLevel->iIdxCur, nColumn+1, 0,
|
| + (char*)pKeyinfo, P4_KEYINFO_HANDOFF);
|
| + VdbeComment((v, "for %s", pTable->zName));
|
| +
|
| + /* Fill the automatic index with content */
|
| + addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, pLevel->iTabCur);
|
| + regRecord = sqlite3GetTempReg(pParse);
|
| + sqlite3GenerateIndexKey(pParse, pIdx, pLevel->iTabCur, regRecord, 1);
|
| + sqlite3VdbeAddOp2(v, OP_IdxInsert, pLevel->iIdxCur, regRecord);
|
| + sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
|
| + sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1);
|
| + sqlite3VdbeChangeP5(v, SQLITE_STMTSTATUS_AUTOINDEX);
|
| + sqlite3VdbeJumpHere(v, addrTop);
|
| + sqlite3ReleaseTempReg(pParse, regRecord);
|
| +
|
| + /* Jump here when skipping the initialization */
|
| + sqlite3VdbeJumpHere(v, addrInit);
|
| +}
|
| +#endif /* SQLITE_OMIT_AUTOMATIC_INDEX */
|
| +
|
| #ifndef SQLITE_OMIT_VIRTUALTABLE
|
| /*
|
| ** Allocate and populate an sqlite3_index_info structure. It is the
|
| @@ -1716,12 +2014,10 @@ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
|
| int i;
|
| int rc;
|
|
|
| - (void)sqlite3SafetyOff(pParse->db);
|
| WHERETRACE(("xBestIndex for %s\n", pTab->zName));
|
| TRACE_IDX_INPUTS(p);
|
| rc = pVtab->pModule->xBestIndex(pVtab, p);
|
| TRACE_IDX_OUTPUTS(p);
|
| - (void)sqlite3SafetyOn(pParse->db);
|
|
|
| if( rc!=SQLITE_OK ){
|
| if( rc==SQLITE_NOMEM ){
|
| @@ -1732,7 +2028,7 @@ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
|
| sqlite3ErrorMsg(pParse, "%s", pVtab->zErrMsg);
|
| }
|
| }
|
| - sqlite3DbFree(pParse->db, pVtab->zErrMsg);
|
| + sqlite3_free(pVtab->zErrMsg);
|
| pVtab->zErrMsg = 0;
|
|
|
| for(i=0; i<p->nConstraint; i++){
|
| @@ -1766,7 +2062,8 @@ static void bestVirtualIndex(
|
| Parse *pParse, /* The parsing context */
|
| WhereClause *pWC, /* The WHERE clause */
|
| struct SrcList_item *pSrc, /* The FROM clause term to search */
|
| - Bitmask notReady, /* Mask of cursors that are not available */
|
| + Bitmask notReady, /* Mask of cursors not available for index */
|
| + Bitmask notValid, /* Cursors not valid for any purpose */
|
| ExprList *pOrderBy, /* The order by clause */
|
| WhereCost *pCost, /* Lowest cost query plan */
|
| sqlite3_index_info **ppIdxInfo /* Index information passed to xBestIndex */
|
| @@ -1778,6 +2075,7 @@ static void bestVirtualIndex(
|
| WhereTerm *pTerm;
|
| int i, j;
|
| int nOrderBy;
|
| + double rCost;
|
|
|
| /* Make sure wsFlags is initialized to some sane value. Otherwise, if the
|
| ** malloc in allocateIndexInfo() fails and this function returns leaving
|
| @@ -1864,6 +2162,15 @@ static void bestVirtualIndex(
|
| }
|
| }
|
|
|
| + /* If there is an ORDER BY clause, and the selected virtual table index
|
| + ** does not satisfy it, increase the cost of the scan accordingly. This
|
| + ** matches the processing for non-virtual tables in bestBtreeIndex().
|
| + */
|
| + rCost = pIdxInfo->estimatedCost;
|
| + if( pOrderBy && pIdxInfo->orderByConsumed==0 ){
|
| + rCost += estLog(rCost)*rCost;
|
| + }
|
| +
|
| /* The cost is not allowed to be larger than SQLITE_BIG_DBL (the
|
| ** inital value of lowestCost in this loop. If it is, then the
|
| ** (cost<lowestCost) test below will never be true.
|
| @@ -1871,10 +2178,10 @@ static void bestVirtualIndex(
|
| ** Use "(double)2" instead of "2.0" in case OMIT_FLOATING_POINT
|
| ** is defined.
|
| */
|
| - if( (SQLITE_BIG_DBL/((double)2))<pIdxInfo->estimatedCost ){
|
| + if( (SQLITE_BIG_DBL/((double)2))<rCost ){
|
| pCost->rCost = (SQLITE_BIG_DBL/((double)2));
|
| }else{
|
| - pCost->rCost = pIdxInfo->estimatedCost;
|
| + pCost->rCost = rCost;
|
| }
|
| pCost->plan.u.pVtabIdx = pIdxInfo;
|
| if( pIdxInfo->orderByConsumed ){
|
| @@ -1886,7 +2193,7 @@ static void bestVirtualIndex(
|
| /* Try to find a more efficient access pattern by using multiple indexes
|
| ** to optimize an OR expression within the WHERE clause.
|
| */
|
| - bestOrClauseIndex(pParse, pWC, pSrc, notReady, pOrderBy, pCost);
|
| + bestOrClauseIndex(pParse, pWC, pSrc, notReady, notValid, pOrderBy, pCost);
|
| }
|
| #endif /* SQLITE_OMIT_VIRTUALTABLE */
|
|
|
| @@ -1956,9 +2263,8 @@ static int whereRangeRegion(
|
| int eSampletype = aSample[i].eType;
|
| if( eSampletype==SQLITE_NULL || eSampletype<eType ) continue;
|
| if( (eSampletype!=eType) ) break;
|
| - if( pColl->enc==SQLITE_UTF8 ){
|
| - r = pColl->xCmp(pColl->pUser, aSample[i].nByte, aSample[i].u.z, n, z);
|
| - }else{
|
| +#ifndef SQLITE_OMIT_UTF16
|
| + if( pColl->enc!=SQLITE_UTF8 ){
|
| int nSample;
|
| char *zSample = sqlite3Utf8to16(
|
| db, pColl->enc, aSample[i].u.z, aSample[i].nByte, &nSample
|
| @@ -1969,6 +2275,10 @@ static int whereRangeRegion(
|
| }
|
| r = pColl->xCmp(pColl->pUser, nSample, zSample, n, z);
|
| sqlite3DbFree(db, zSample);
|
| + }else
|
| +#endif
|
| + {
|
| + r = pColl->xCmp(pColl->pUser, aSample[i].nByte, aSample[i].u.z, n, z);
|
| }
|
| if( r>0 ) break;
|
| }
|
| @@ -1982,6 +2292,42 @@ static int whereRangeRegion(
|
| #endif /* #ifdef SQLITE_ENABLE_STAT2 */
|
|
|
| /*
|
| +** If expression pExpr represents a literal value, set *pp to point to
|
| +** an sqlite3_value structure containing the same value, with affinity
|
| +** aff applied to it, before returning. It is the responsibility of the
|
| +** caller to eventually release this structure by passing it to
|
| +** sqlite3ValueFree().
|
| +**
|
| +** If the current parse is a recompile (sqlite3Reprepare()) and pExpr
|
| +** is an SQL variable that currently has a non-NULL value bound to it,
|
| +** create an sqlite3_value structure containing this value, again with
|
| +** affinity aff applied to it, instead.
|
| +**
|
| +** If neither of the above apply, set *pp to NULL.
|
| +**
|
| +** If an error occurs, return an error code. Otherwise, SQLITE_OK.
|
| +*/
|
| +#ifdef SQLITE_ENABLE_STAT2
|
| +static int valueFromExpr(
|
| + Parse *pParse,
|
| + Expr *pExpr,
|
| + u8 aff,
|
| + sqlite3_value **pp
|
| +){
|
| + /* The evalConstExpr() function will have already converted any TK_VARIABLE
|
| + ** expression involved in an comparison into a TK_REGISTER. */
|
| + assert( pExpr->op!=TK_VARIABLE );
|
| + if( pExpr->op==TK_REGISTER && pExpr->op2==TK_VARIABLE ){
|
| + int iVar = pExpr->iColumn;
|
| + sqlite3VdbeSetVarmask(pParse->pVdbe, iVar); /* IMP: R-23257-02778 */
|
| + *pp = sqlite3VdbeGetValue(pParse->pReprepare, iVar, aff);
|
| + return SQLITE_OK;
|
| + }
|
| + return sqlite3ValueFromExpr(pParse->db, pExpr, SQLITE_UTF8, aff, pp);
|
| +}
|
| +#endif
|
| +
|
| +/*
|
| ** This function is used to estimate the number of rows that will be visited
|
| ** by scanning an index for a range of values. The range may have an upper
|
| ** bound, a lower bound, or both. The WHERE clause terms that set the upper
|
| @@ -2033,23 +2379,22 @@ static int whereRangeScanEst(
|
| int rc = SQLITE_OK;
|
|
|
| #ifdef SQLITE_ENABLE_STAT2
|
| - sqlite3 *db = pParse->db;
|
| - sqlite3_value *pLowerVal = 0;
|
| - sqlite3_value *pUpperVal = 0;
|
|
|
| if( nEq==0 && p->aSample ){
|
| + sqlite3_value *pLowerVal = 0;
|
| + sqlite3_value *pUpperVal = 0;
|
| int iEst;
|
| int iLower = 0;
|
| int iUpper = SQLITE_INDEX_SAMPLES;
|
| - u8 aff = p->pTable->aCol[0].affinity;
|
| + u8 aff = p->pTable->aCol[p->aiColumn[0]].affinity;
|
|
|
| if( pLower ){
|
| Expr *pExpr = pLower->pExpr->pRight;
|
| - rc = sqlite3ValueFromExpr(db, pExpr, SQLITE_UTF8, aff, &pLowerVal);
|
| + rc = valueFromExpr(pParse, pExpr, aff, &pLowerVal);
|
| }
|
| if( rc==SQLITE_OK && pUpper ){
|
| Expr *pExpr = pUpper->pExpr->pRight;
|
| - rc = sqlite3ValueFromExpr(db, pExpr, SQLITE_UTF8, aff, &pUpperVal);
|
| + rc = valueFromExpr(pParse, pExpr, aff, &pUpperVal);
|
| }
|
|
|
| if( rc!=SQLITE_OK || (pLowerVal==0 && pUpperVal==0) ){
|
| @@ -2129,7 +2474,8 @@ static void bestBtreeIndex(
|
| Parse *pParse, /* The parsing context */
|
| WhereClause *pWC, /* The WHERE clause */
|
| struct SrcList_item *pSrc, /* The FROM clause term to search */
|
| - Bitmask notReady, /* Mask of cursors that are not available */
|
| + Bitmask notReady, /* Mask of cursors not available for indexing */
|
| + Bitmask notValid, /* Cursors not available for any purpose */
|
| ExprList *pOrderBy, /* The ORDER BY clause */
|
| WhereCost *pCost /* Lowest cost query plan */
|
| ){
|
| @@ -2171,23 +2517,14 @@ static void bestBtreeIndex(
|
| sPk.nColumn = 1;
|
| sPk.aiColumn = &aiColumnPk;
|
| sPk.aiRowEst = aiRowEstPk;
|
| - aiRowEstPk[1] = 1;
|
| sPk.onError = OE_Replace;
|
| sPk.pTable = pSrc->pTab;
|
| + aiRowEstPk[0] = pSrc->pTab->nRowEst;
|
| + aiRowEstPk[1] = 1;
|
| pFirst = pSrc->pTab->pIndex;
|
| if( pSrc->notIndexed==0 ){
|
| sPk.pNext = pFirst;
|
| }
|
| - /* The aiRowEstPk[0] is an estimate of the total number of rows in the
|
| - ** table. Get this information from the ANALYZE information if it is
|
| - ** available. If not available, assume the table 1 million rows in size.
|
| - */
|
| - if( pFirst ){
|
| - assert( pFirst->aiRowEst!=0 ); /* Allocated together with pFirst */
|
| - aiRowEstPk[0] = pFirst->aiRowEst[0];
|
| - }else{
|
| - aiRowEstPk[0] = 1000000;
|
| - }
|
| pProbe = &sPk;
|
| wsFlagMask = ~(
|
| WHERE_COLUMN_IN|WHERE_COLUMN_EQ|WHERE_COLUMN_NULL|WHERE_COLUMN_RANGE
|
| @@ -2237,14 +2574,14 @@ static void bestBtreeIndex(
|
| ** Set to true if there was at least one "x IN (SELECT ...)" term used
|
| ** in determining the value of nInMul.
|
| **
|
| - ** nBound:
|
| + ** estBound:
|
| ** An estimate on the amount of the table that must be searched. A
|
| ** value of 100 means the entire table is searched. Range constraints
|
| ** might reduce this to a value less than 100 to indicate that only
|
| ** a fraction of the table needs searching. In the absence of
|
| ** sqlite_stat2 ANALYZE data, a single inequality reduces the search
|
| ** space to 1/3rd its original size. So an x>? constraint reduces
|
| - ** nBound to 33. Two constraints (x>? AND x<?) reduce nBound to 11.
|
| + ** estBound to 33. Two constraints (x>? AND x<?) reduce estBound to 11.
|
| **
|
| ** bSort:
|
| ** Boolean. True if there is an ORDER BY clause that will require an
|
| @@ -2266,13 +2603,14 @@ static void bestBtreeIndex(
|
| int nEq;
|
| int bInEst = 0;
|
| int nInMul = 1;
|
| - int nBound = 100;
|
| + int estBound = 100;
|
| + int nBound = 0; /* Number of range constraints seen */
|
| int bSort = 0;
|
| int bLookup = 0;
|
| + WhereTerm *pTerm; /* A single term of the WHERE clause */
|
|
|
| /* Determine the values of nEq and nInMul */
|
| for(nEq=0; nEq<pProbe->nColumn; nEq++){
|
| - WhereTerm *pTerm; /* A single term of the WHERE clause */
|
| int j = pProbe->aiColumn[nEq];
|
| pTerm = findTerm(pWC, iCur, j, notReady, eqTermMask, pIdx);
|
| if( pTerm==0 ) break;
|
| @@ -2283,7 +2621,7 @@ static void bestBtreeIndex(
|
| if( ExprHasProperty(pExpr, EP_xIsSelect) ){
|
| nInMul *= 25;
|
| bInEst = 1;
|
| - }else if( pExpr->x.pList ){
|
| + }else if( ALWAYS(pExpr->x.pList) ){
|
| nInMul *= pExpr->x.pList->nExpr + 1;
|
| }
|
| }else if( pTerm->eOperator & WO_ISNULL ){
|
| @@ -2292,18 +2630,20 @@ static void bestBtreeIndex(
|
| used |= pTerm->prereqRight;
|
| }
|
|
|
| - /* Determine the value of nBound. */
|
| + /* Determine the value of estBound. */
|
| if( nEq<pProbe->nColumn ){
|
| int j = pProbe->aiColumn[nEq];
|
| if( findTerm(pWC, iCur, j, notReady, WO_LT|WO_LE|WO_GT|WO_GE, pIdx) ){
|
| WhereTerm *pTop = findTerm(pWC, iCur, j, notReady, WO_LT|WO_LE, pIdx);
|
| WhereTerm *pBtm = findTerm(pWC, iCur, j, notReady, WO_GT|WO_GE, pIdx);
|
| - whereRangeScanEst(pParse, pProbe, nEq, pBtm, pTop, &nBound);
|
| + whereRangeScanEst(pParse, pProbe, nEq, pBtm, pTop, &estBound);
|
| if( pTop ){
|
| + nBound = 1;
|
| wsFlags |= WHERE_TOP_LIMIT;
|
| used |= pTop->prereqRight;
|
| }
|
| if( pBtm ){
|
| + nBound++;
|
| wsFlags |= WHERE_BTM_LIMIT;
|
| used |= pBtm->prereqRight;
|
| }
|
| @@ -2334,7 +2674,7 @@ static void bestBtreeIndex(
|
|
|
| /* If currently calculating the cost of using an index (not the IPK
|
| ** index), determine if all required column data may be obtained without
|
| - ** seeking to entries in the main table (i.e. if the index is a covering
|
| + ** using the main table (i.e. if the index is a covering
|
| ** index for this query). If it is, set the WHERE_IDX_ONLY flag in
|
| ** wsFlags. Otherwise, set the bLookup variable to true. */
|
| if( pIdx && wsFlags ){
|
| @@ -2353,8 +2693,7 @@ static void bestBtreeIndex(
|
| }
|
| }
|
|
|
| - /**** Begin adding up the cost of using this index (Needs improvements)
|
| - **
|
| + /*
|
| ** Estimate the number of rows of output. For an IN operator,
|
| ** do not let the estimate exceed half the rows in the table.
|
| */
|
| @@ -2373,8 +2712,8 @@ static void bestBtreeIndex(
|
| /* Adjust the number of rows and the cost downward to reflect rows
|
| ** that are excluded by range constraints.
|
| */
|
| - nRow = (nRow * (double)nBound) / (double)100;
|
| - cost = (cost * (double)nBound) / (double)100;
|
| + nRow = (nRow * (double)estBound) / (double)100;
|
| + cost = (cost * (double)estBound) / (double)100;
|
|
|
| /* Add in the estimated cost of sorting the result
|
| */
|
| @@ -2391,17 +2730,75 @@ static void bestBtreeIndex(
|
| }
|
| /**** Cost of using this index has now been computed ****/
|
|
|
| + /* If there are additional constraints on this table that cannot
|
| + ** be used with the current index, but which might lower the number
|
| + ** of output rows, adjust the nRow value accordingly. This only
|
| + ** matters if the current index is the least costly, so do not bother
|
| + ** with this step if we already know this index will not be chosen.
|
| + ** Also, never reduce the output row count below 2 using this step.
|
| + **
|
| + ** It is critical that the notValid mask be used here instead of
|
| + ** the notReady mask. When computing an "optimal" index, the notReady
|
| + ** mask will only have one bit set - the bit for the current table.
|
| + ** The notValid mask, on the other hand, always has all bits set for
|
| + ** tables that are not in outer loops. If notReady is used here instead
|
| + ** of notValid, then a optimal index that depends on inner joins loops
|
| + ** might be selected even when there exists an optimal index that has
|
| + ** no such dependency.
|
| + */
|
| + if( nRow>2 && cost<=pCost->rCost ){
|
| + int k; /* Loop counter */
|
| + int nSkipEq = nEq; /* Number of == constraints to skip */
|
| + int nSkipRange = nBound; /* Number of < constraints to skip */
|
| + Bitmask thisTab; /* Bitmap for pSrc */
|
| +
|
| + thisTab = getMask(pWC->pMaskSet, iCur);
|
| + for(pTerm=pWC->a, k=pWC->nTerm; nRow>2 && k; k--, pTerm++){
|
| + if( pTerm->wtFlags & TERM_VIRTUAL ) continue;
|
| + if( (pTerm->prereqAll & notValid)!=thisTab ) continue;
|
| + if( pTerm->eOperator & (WO_EQ|WO_IN|WO_ISNULL) ){
|
| + if( nSkipEq ){
|
| + /* Ignore the first nEq equality matches since the index
|
| + ** has already accounted for these */
|
| + nSkipEq--;
|
| + }else{
|
| + /* Assume each additional equality match reduces the result
|
| + ** set size by a factor of 10 */
|
| + nRow /= 10;
|
| + }
|
| + }else if( pTerm->eOperator & (WO_LT|WO_LE|WO_GT|WO_GE) ){
|
| + if( nSkipRange ){
|
| + /* Ignore the first nBound range constraints since the index
|
| + ** has already accounted for these */
|
| + nSkipRange--;
|
| + }else{
|
| + /* Assume each additional range constraint reduces the result
|
| + ** set size by a factor of 3 */
|
| + nRow /= 3;
|
| + }
|
| + }else{
|
| + /* Any other expression lowers the output row count by half */
|
| + nRow /= 2;
|
| + }
|
| + }
|
| + if( nRow<2 ) nRow = 2;
|
| + }
|
| +
|
| +
|
| WHERETRACE((
|
| - "tbl=%s idx=%s nEq=%d nInMul=%d nBound=%d bSort=%d bLookup=%d"
|
| - " wsFlags=%d (nRow=%.2f cost=%.2f)\n",
|
| + "%s(%s): nEq=%d nInMul=%d estBound=%d bSort=%d bLookup=%d wsFlags=0x%x\n"
|
| + " notReady=0x%llx nRow=%.2f cost=%.2f used=0x%llx\n",
|
| pSrc->pTab->zName, (pIdx ? pIdx->zName : "ipk"),
|
| - nEq, nInMul, nBound, bSort, bLookup, wsFlags, nRow, cost
|
| + nEq, nInMul, estBound, bSort, bLookup, wsFlags,
|
| + notReady, nRow, cost, used
|
| ));
|
|
|
| /* If this index is the best we have seen so far, then record this
|
| ** index and its cost in the pCost structure.
|
| */
|
| - if( (!pIdx || wsFlags) && cost<pCost->rCost ){
|
| + if( (!pIdx || wsFlags)
|
| + && (cost<pCost->rCost || (cost<=pCost->rCost && nRow<pCost->nRow))
|
| + ){
|
| pCost->rCost = cost;
|
| pCost->nRow = nRow;
|
| pCost->used = used;
|
| @@ -2436,10 +2833,12 @@ static void bestBtreeIndex(
|
| );
|
|
|
| WHERETRACE(("best index is: %s\n",
|
| - (pCost->plan.u.pIdx ? pCost->plan.u.pIdx->zName : "ipk")
|
| + ((pCost->plan.wsFlags & WHERE_NOT_FULLSCAN)==0 ? "none" :
|
| + pCost->plan.u.pIdx ? pCost->plan.u.pIdx->zName : "ipk")
|
| ));
|
|
|
| - bestOrClauseIndex(pParse, pWC, pSrc, notReady, pOrderBy, pCost);
|
| + bestOrClauseIndex(pParse, pWC, pSrc, notReady, notValid, pOrderBy, pCost);
|
| + bestAutomaticIndex(pParse, pWC, pSrc, notReady, pCost);
|
| pCost->plan.wsFlags |= eqTermMask;
|
| }
|
|
|
| @@ -2453,14 +2852,15 @@ static void bestIndex(
|
| Parse *pParse, /* The parsing context */
|
| WhereClause *pWC, /* The WHERE clause */
|
| struct SrcList_item *pSrc, /* The FROM clause term to search */
|
| - Bitmask notReady, /* Mask of cursors that are not available */
|
| + Bitmask notReady, /* Mask of cursors not available for indexing */
|
| + Bitmask notValid, /* Cursors not available for any purpose */
|
| ExprList *pOrderBy, /* The ORDER BY clause */
|
| WhereCost *pCost /* Lowest cost query plan */
|
| ){
|
| #ifndef SQLITE_OMIT_VIRTUALTABLE
|
| if( IsVirtual(pSrc->pTab) ){
|
| sqlite3_index_info *p = 0;
|
| - bestVirtualIndex(pParse, pWC, pSrc, notReady, pOrderBy, pCost, &p);
|
| + bestVirtualIndex(pParse, pWC, pSrc, notReady, notValid, pOrderBy, pCost,&p);
|
| if( p->needToFreeIdxStr ){
|
| sqlite3_free(p->idxStr);
|
| }
|
| @@ -2468,7 +2868,7 @@ static void bestIndex(
|
| }else
|
| #endif
|
| {
|
| - bestBtreeIndex(pParse, pWC, pSrc, notReady, pOrderBy, pCost);
|
| + bestBtreeIndex(pParse, pWC, pSrc, notReady, notValid, pOrderBy, pCost);
|
| }
|
| }
|
|
|
| @@ -2487,6 +2887,9 @@ static void bestIndex(
|
| ** in the ON clause. The term is disabled in (3) because it is not part
|
| ** of a LEFT OUTER JOIN. In (1), the term is not disabled.
|
| **
|
| +** IMPLEMENTATION-OF: R-24597-58655 No tests are done for terms that are
|
| +** completely satisfied by indices.
|
| +**
|
| ** Disabling a term causes that term to not be tested in the inner loop
|
| ** of the join. Disabling is an optimization. When terms are satisfied
|
| ** by indices, we disable them to prevent redundant tests in the inner
|
| @@ -2497,7 +2900,7 @@ static void bestIndex(
|
| */
|
| static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){
|
| if( pTerm
|
| - && ALWAYS((pTerm->wtFlags & TERM_CODED)==0)
|
| + && (pTerm->wtFlags & TERM_CODED)==0
|
| && (pLevel->iLeftJoin==0 || ExprHasProperty(pTerm->pExpr, EP_FromJoin))
|
| ){
|
| pTerm->wtFlags |= TERM_CODED;
|
| @@ -2514,16 +2917,39 @@ static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){
|
| ** Code an OP_Affinity opcode to apply the column affinity string zAff
|
| ** to the n registers starting at base.
|
| **
|
| -** Buffer zAff was allocated using sqlite3DbMalloc(). It is the
|
| -** responsibility of this function to arrange for it to be eventually
|
| -** freed using sqlite3DbFree().
|
| +** As an optimization, SQLITE_AFF_NONE entries (which are no-ops) at the
|
| +** beginning and end of zAff are ignored. If all entries in zAff are
|
| +** SQLITE_AFF_NONE, then no code gets generated.
|
| +**
|
| +** This routine makes its own copy of zAff so that the caller is free
|
| +** to modify zAff after this routine returns.
|
| */
|
| static void codeApplyAffinity(Parse *pParse, int base, int n, char *zAff){
|
| Vdbe *v = pParse->pVdbe;
|
| + if( zAff==0 ){
|
| + assert( pParse->db->mallocFailed );
|
| + return;
|
| + }
|
| assert( v!=0 );
|
| - sqlite3VdbeAddOp2(v, OP_Affinity, base, n);
|
| - sqlite3VdbeChangeP4(v, -1, zAff, P4_DYNAMIC);
|
| - sqlite3ExprCacheAffinityChange(pParse, base, n);
|
| +
|
| + /* Adjust base and n to skip over SQLITE_AFF_NONE entries at the beginning
|
| + ** and end of the affinity string.
|
| + */
|
| + while( n>0 && zAff[0]==SQLITE_AFF_NONE ){
|
| + n--;
|
| + base++;
|
| + zAff++;
|
| + }
|
| + while( n>1 && zAff[n-1]==SQLITE_AFF_NONE ){
|
| + n--;
|
| + }
|
| +
|
| + /* Code the OP_Affinity opcode if there is anything left to do. */
|
| + if( n>0 ){
|
| + sqlite3VdbeAddOp2(v, OP_Affinity, base, n);
|
| + sqlite3VdbeChangeP4(v, -1, zAff, n);
|
| + sqlite3ExprCacheAffinityChange(pParse, base, n);
|
| + }
|
| }
|
|
|
|
|
| @@ -2594,7 +3020,7 @@ static int codeEqualityTerm(
|
|
|
| /*
|
| ** Generate code that will evaluate all == and IN constraints for an
|
| -** index. The values for all constraints are left on the stack.
|
| +** index.
|
| **
|
| ** For example, consider table t1(a,b,c,d,e,f) with index i1(a,b,c).
|
| ** Suppose the WHERE clause is this: a==5 AND b IN (1,2,3) AND c>5 AND c<10
|
| @@ -2606,7 +3032,8 @@ static int codeEqualityTerm(
|
| **
|
| ** In the example above nEq==2. But this subroutine works for any value
|
| ** of nEq including 0. If nEq==0, this routine is nearly a no-op.
|
| -** The only thing it does is allocate the pLevel->iMem memory cell.
|
| +** The only thing it does is allocate the pLevel->iMem memory cell and
|
| +** compute the affinity string.
|
| **
|
| ** This routine always allocates at least one memory cell and returns
|
| ** the index of that memory cell. The code that
|
| @@ -2671,7 +3098,10 @@ static int codeAllEqualityTerms(
|
| int k = pIdx->aiColumn[j];
|
| pTerm = findTerm(pWC, iCur, k, notReady, pLevel->plan.wsFlags, pIdx);
|
| if( NEVER(pTerm==0) ) break;
|
| - assert( (pTerm->wtFlags & TERM_CODED)==0 );
|
| + /* The following true for indices with redundant columns.
|
| + ** Ex: CREATE INDEX i1 ON t1(a,b,a); SELECT * FROM t1 WHERE a=0 AND b=0; */
|
| + testcase( (pTerm->wtFlags & TERM_CODED)!=0 );
|
| + testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
|
| r1 = codeEqualityTerm(pParse, pTerm, pLevel, regBase+j);
|
| if( r1!=regBase+j ){
|
| if( nReg==1 ){
|
| @@ -2684,11 +3114,15 @@ static int codeAllEqualityTerms(
|
| testcase( pTerm->eOperator & WO_ISNULL );
|
| testcase( pTerm->eOperator & WO_IN );
|
| if( (pTerm->eOperator & (WO_ISNULL|WO_IN))==0 ){
|
| - sqlite3VdbeAddOp2(v, OP_IsNull, regBase+j, pLevel->addrBrk);
|
| - if( zAff
|
| - && sqlite3CompareAffinity(pTerm->pExpr->pRight, zAff[j])==SQLITE_AFF_NONE
|
| - ){
|
| - zAff[j] = SQLITE_AFF_NONE;
|
| + Expr *pRight = pTerm->pExpr->pRight;
|
| + sqlite3ExprCodeIsNullJump(v, pRight, regBase+j, pLevel->addrBrk);
|
| + if( zAff ){
|
| + if( sqlite3CompareAffinity(pRight, zAff[j])==SQLITE_AFF_NONE ){
|
| + zAff[j] = SQLITE_AFF_NONE;
|
| + }
|
| + if( sqlite3ExprNeedsNoAffinityChange(pRight, zAff[j]) ){
|
| + zAff[j] = SQLITE_AFF_NONE;
|
| + }
|
| }
|
| }
|
| }
|
| @@ -2768,6 +3202,7 @@ static Bitmask codeOneLoopStart(
|
| const struct sqlite3_index_constraint *aConstraint =
|
| pVtabIdx->aConstraint;
|
|
|
| + sqlite3ExprCachePush(pParse);
|
| iReg = sqlite3GetTempRange(pParse, nConstraint+2);
|
| for(j=1; j<=nConstraint; j++){
|
| for(k=0; k<nConstraint; k++){
|
| @@ -2794,6 +3229,7 @@ static Bitmask codeOneLoopStart(
|
| pLevel->p1 = iCur;
|
| pLevel->p2 = sqlite3VdbeCurrentAddr(v);
|
| sqlite3ReleaseTempRange(pParse, iReg, nConstraint+2);
|
| + sqlite3ExprCachePop(pParse, 1);
|
| }else
|
| #endif /* SQLITE_OMIT_VIRTUALTABLE */
|
|
|
| @@ -2809,6 +3245,7 @@ static Bitmask codeOneLoopStart(
|
| assert( pTerm->pExpr!=0 );
|
| assert( pTerm->leftCursor==iCur );
|
| assert( omitTable==0 );
|
| + testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
|
| iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, iReleaseReg);
|
| addrNxt = pLevel->addrNxt;
|
| sqlite3VdbeAddOp2(v, OP_MustBeInt, iRowidReg, addrNxt);
|
| @@ -2849,6 +3286,7 @@ static Bitmask codeOneLoopStart(
|
| assert( TK_LT==TK_GT+2 ); /* ... of the TK_xx values... */
|
| assert( TK_GE==TK_GT+3 ); /* ... is correcct. */
|
|
|
| + testcase( pStart->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
|
| pX = pStart->pExpr;
|
| assert( pX!=0 );
|
| assert( pStart->leftCursor==iCur );
|
| @@ -2866,6 +3304,7 @@ static Bitmask codeOneLoopStart(
|
| pX = pEnd->pExpr;
|
| assert( pX!=0 );
|
| assert( pEnd->leftCursor==iCur );
|
| + testcase( pEnd->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
|
| memEndValue = ++pParse->nMem;
|
| sqlite3ExprCode(pParse, pX->pRight, memEndValue);
|
| if( pX->op==TK_LT || pX->op==TK_GT ){
|
| @@ -2879,7 +3318,11 @@ static Bitmask codeOneLoopStart(
|
| pLevel->op = bRev ? OP_Prev : OP_Next;
|
| pLevel->p1 = iCur;
|
| pLevel->p2 = start;
|
| - pLevel->p5 = (pStart==0 && pEnd==0) ?1:0;
|
| + if( pStart==0 && pEnd==0 ){
|
| + pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP;
|
| + }else{
|
| + assert( pLevel->p5==0 );
|
| + }
|
| if( testOp!=OP_Noop ){
|
| iRowidReg = iReleaseReg = sqlite3GetTempReg(pParse);
|
| sqlite3VdbeAddOp2(v, OP_Rowid, iCur, iRowidReg);
|
| @@ -2919,7 +3362,7 @@ static Bitmask codeOneLoopStart(
|
| ** constraints but an index is selected anyway, in order
|
| ** to force the output order to conform to an ORDER BY.
|
| */
|
| - int aStartOp[] = {
|
| + static const u8 aStartOp[] = {
|
| 0,
|
| 0,
|
| OP_Rewind, /* 2: (!start_constraints && startEq && !bRev) */
|
| @@ -2929,12 +3372,12 @@ static Bitmask codeOneLoopStart(
|
| OP_SeekGe, /* 6: (start_constraints && startEq && !bRev) */
|
| OP_SeekLe /* 7: (start_constraints && startEq && bRev) */
|
| };
|
| - int aEndOp[] = {
|
| + static const u8 aEndOp[] = {
|
| OP_Noop, /* 0: (!end_constraints) */
|
| OP_IdxGE, /* 1: (end_constraints && !bRev) */
|
| OP_IdxLT /* 2: (end_constraints && bRev) */
|
| };
|
| - int nEq = pLevel->plan.nEq;
|
| + int nEq = pLevel->plan.nEq; /* Number of == or IN terms */
|
| int isMinQuery = 0; /* If this is an optimized SELECT min(x).. */
|
| int regBase; /* Base register holding constraint values */
|
| int r1; /* Temp register */
|
| @@ -2944,11 +3387,12 @@ static Bitmask codeOneLoopStart(
|
| 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 */
|
| - char *zAff;
|
| + 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 */
|
| + char *zStartAff; /* Affinity for start of range constraint */
|
| + char *zEndAff; /* Affinity for end of range constraint */
|
|
|
| pIdx = pLevel->plan.u.pIdx;
|
| iIdxCur = pLevel->iIdxCur;
|
| @@ -2989,15 +3433,16 @@ static Bitmask codeOneLoopStart(
|
| ** starting at regBase.
|
| */
|
| regBase = codeAllEqualityTerms(
|
| - pParse, pLevel, pWC, notReady, nExtraReg, &zAff
|
| + pParse, pLevel, pWC, notReady, nExtraReg, &zStartAff
|
| );
|
| + zEndAff = sqlite3DbStrDup(pParse->db, zStartAff);
|
| addrNxt = pLevel->addrNxt;
|
|
|
| /* If we are doing a reverse order scan on an ascending index, or
|
| ** a forward order scan on a descending index, interchange the
|
| ** start and end terms (pRangeStart and pRangeEnd).
|
| */
|
| - if( bRev==(pIdx->aSortOrder[nEq]==SQLITE_SO_ASC) ){
|
| + if( nEq<pIdx->nColumn && bRev==(pIdx->aSortOrder[nEq]==SQLITE_SO_ASC) ){
|
| SWAP(WhereTerm *, pRangeEnd, pRangeStart);
|
| }
|
|
|
| @@ -3014,23 +3459,27 @@ static Bitmask codeOneLoopStart(
|
| if( pRangeStart ){
|
| Expr *pRight = pRangeStart->pExpr->pRight;
|
| sqlite3ExprCode(pParse, pRight, regBase+nEq);
|
| - sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt);
|
| - if( zAff
|
| - && sqlite3CompareAffinity(pRight, zAff[nConstraint])==SQLITE_AFF_NONE
|
| - ){
|
| - /* Since the comparison is to be performed with no conversions applied
|
| - ** to the operands, set the affinity to apply to pRight to
|
| - ** SQLITE_AFF_NONE. */
|
| - zAff[nConstraint] = SQLITE_AFF_NONE;
|
| - }
|
| + sqlite3ExprCodeIsNullJump(v, pRight, regBase+nEq, addrNxt);
|
| + if( zStartAff ){
|
| + if( sqlite3CompareAffinity(pRight, zStartAff[nEq])==SQLITE_AFF_NONE){
|
| + /* Since the comparison is to be performed with no conversions
|
| + ** applied to the operands, set the affinity to apply to pRight to
|
| + ** SQLITE_AFF_NONE. */
|
| + zStartAff[nEq] = SQLITE_AFF_NONE;
|
| + }
|
| + if( sqlite3ExprNeedsNoAffinityChange(pRight, zStartAff[nEq]) ){
|
| + zStartAff[nEq] = SQLITE_AFF_NONE;
|
| + }
|
| + }
|
| nConstraint++;
|
| + testcase( pRangeStart->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
|
| }else if( isMinQuery ){
|
| sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq);
|
| nConstraint++;
|
| startEq = 0;
|
| start_constraints = 1;
|
| }
|
| - codeApplyAffinity(pParse, regBase, nConstraint, zAff);
|
| + codeApplyAffinity(pParse, regBase, nConstraint, zStartAff);
|
| op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev];
|
| assert( op!=0 );
|
| testcase( op==OP_Rewind );
|
| @@ -3039,8 +3488,7 @@ static Bitmask codeOneLoopStart(
|
| testcase( op==OP_SeekGe );
|
| testcase( op==OP_SeekLe );
|
| testcase( op==OP_SeekLt );
|
| - sqlite3VdbeAddOp4(v, op, iIdxCur, addrNxt, regBase,
|
| - SQLITE_INT_TO_PTR(nConstraint), P4_INT32);
|
| + sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);
|
|
|
| /* Load the value for the inequality constraint at the end of the
|
| ** range (if any).
|
| @@ -3048,21 +3496,26 @@ static Bitmask codeOneLoopStart(
|
| nConstraint = nEq;
|
| if( pRangeEnd ){
|
| Expr *pRight = pRangeEnd->pExpr->pRight;
|
| - sqlite3ExprCacheRemove(pParse, regBase+nEq);
|
| + sqlite3ExprCacheRemove(pParse, regBase+nEq, 1);
|
| sqlite3ExprCode(pParse, pRight, regBase+nEq);
|
| - sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt);
|
| - zAff = sqlite3DbStrDup(pParse->db, zAff);
|
| - if( zAff
|
| - && sqlite3CompareAffinity(pRight, zAff[nConstraint])==SQLITE_AFF_NONE
|
| - ){
|
| - /* Since the comparison is to be performed with no conversions applied
|
| - ** to the operands, set the affinity to apply to pRight to
|
| - ** SQLITE_AFF_NONE. */
|
| - zAff[nConstraint] = SQLITE_AFF_NONE;
|
| - }
|
| - codeApplyAffinity(pParse, regBase, nEq+1, zAff);
|
| + sqlite3ExprCodeIsNullJump(v, pRight, regBase+nEq, addrNxt);
|
| + if( zEndAff ){
|
| + if( sqlite3CompareAffinity(pRight, zEndAff[nEq])==SQLITE_AFF_NONE){
|
| + /* Since the comparison is to be performed with no conversions
|
| + ** applied to the operands, set the affinity to apply to pRight to
|
| + ** SQLITE_AFF_NONE. */
|
| + zEndAff[nEq] = SQLITE_AFF_NONE;
|
| + }
|
| + if( sqlite3ExprNeedsNoAffinityChange(pRight, zEndAff[nEq]) ){
|
| + zEndAff[nEq] = SQLITE_AFF_NONE;
|
| + }
|
| + }
|
| + codeApplyAffinity(pParse, regBase, nEq+1, zEndAff);
|
| nConstraint++;
|
| + testcase( pRangeEnd->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
|
| }
|
| + sqlite3DbFree(pParse->db, zStartAff);
|
| + sqlite3DbFree(pParse->db, zEndAff);
|
|
|
| /* Top of the loop body */
|
| pLevel->p2 = sqlite3VdbeCurrentAddr(v);
|
| @@ -3073,8 +3526,7 @@ static Bitmask codeOneLoopStart(
|
| testcase( op==OP_IdxGE );
|
| testcase( op==OP_IdxLT );
|
| if( op!=OP_Noop ){
|
| - sqlite3VdbeAddOp4(v, op, iIdxCur, addrNxt, regBase,
|
| - SQLITE_INT_TO_PTR(nConstraint), P4_INT32);
|
| + sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);
|
| sqlite3VdbeChangeP5(v, endEq!=bRev ?1:0);
|
| }
|
|
|
| @@ -3151,13 +3603,14 @@ static Bitmask codeOneLoopStart(
|
| */
|
| WhereClause *pOrWc; /* The OR-clause broken out into subterms */
|
| WhereTerm *pFinal; /* Final subterm within the OR-clause. */
|
| - SrcList oneTab; /* Shortened table list */
|
| + SrcList *pOrTab; /* Shortened table list or OR-clause generation */
|
|
|
| int regReturn = ++pParse->nMem; /* Register used with OP_Gosub */
|
| int regRowset = 0; /* Register for RowSet object */
|
| int regRowid = 0; /* Register holding rowid */
|
| int iLoopBody = sqlite3VdbeMakeLabel(v); /* Start of loop body */
|
| int iRetInit; /* Address of regReturn init */
|
| + int untestedTerms = 0; /* Some terms not completely tested */
|
| int ii;
|
|
|
| pTerm = pLevel->plan.u.pTerm;
|
| @@ -3166,11 +3619,30 @@ static Bitmask codeOneLoopStart(
|
| assert( (pTerm->wtFlags & TERM_ORINFO)!=0 );
|
| pOrWc = &pTerm->u.pOrInfo->wc;
|
| pFinal = &pOrWc->a[pOrWc->nTerm-1];
|
| + pLevel->op = OP_Return;
|
| + pLevel->p1 = regReturn;
|
|
|
| - /* Set up a SrcList containing just the table being scanned by this loop. */
|
| - oneTab.nSrc = 1;
|
| - oneTab.nAlloc = 1;
|
| - oneTab.a[0] = *pTabItem;
|
| + /* Set up a new SrcList ni pOrTab containing the table being scanned
|
| + ** by this loop in the a[0] slot and all notReady tables in a[1..] slots.
|
| + ** This becomes the SrcList in the recursive call to sqlite3WhereBegin().
|
| + */
|
| + if( pWInfo->nLevel>1 ){
|
| + int nNotReady; /* The number of notReady tables */
|
| + struct SrcList_item *origSrc; /* Original list of tables */
|
| + nNotReady = pWInfo->nLevel - iLevel - 1;
|
| + pOrTab = sqlite3StackAllocRaw(pParse->db,
|
| + sizeof(*pOrTab)+ nNotReady*sizeof(pOrTab->a[0]));
|
| + if( pOrTab==0 ) return notReady;
|
| + pOrTab->nAlloc = (i16)(nNotReady + 1);
|
| + pOrTab->nSrc = pOrTab->nAlloc;
|
| + memcpy(pOrTab->a, pTabItem, sizeof(*pTabItem));
|
| + origSrc = pWInfo->pTabList->a;
|
| + for(k=1; k<=nNotReady; k++){
|
| + memcpy(&pOrTab->a[k], &origSrc[pLevel[k].iFrom], sizeof(pOrTab->a[k]));
|
| + }
|
| + }else{
|
| + pOrTab = pWInfo->pTabList;
|
| + }
|
|
|
| /* Initialize the rowset register to contain NULL. An SQL NULL is
|
| ** equivalent to an empty rowset.
|
| @@ -3195,33 +3667,38 @@ static Bitmask codeOneLoopStart(
|
| if( pOrTerm->leftCursor==iCur || pOrTerm->eOperator==WO_AND ){
|
| WhereInfo *pSubWInfo; /* Info for single OR-term scan */
|
| /* Loop through table entries that match term pOrTerm. */
|
| - pSubWInfo = sqlite3WhereBegin(pParse, &oneTab, pOrTerm->pExpr, 0,
|
| - WHERE_OMIT_OPEN | WHERE_OMIT_CLOSE | WHERE_FORCE_TABLE);
|
| + pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrTerm->pExpr, 0,
|
| + WHERE_OMIT_OPEN | WHERE_OMIT_CLOSE |
|
| + WHERE_FORCE_TABLE | WHERE_ONETABLE_ONLY);
|
| if( pSubWInfo ){
|
| if( (wctrlFlags & WHERE_DUPLICATES_OK)==0 ){
|
| int iSet = ((ii==pOrWc->nTerm-1)?-1:ii);
|
| int r;
|
| r = sqlite3ExprCodeGetColumn(pParse, pTabItem->pTab, -1, iCur,
|
| - regRowid, 0);
|
| - sqlite3VdbeAddOp4(v, OP_RowSetTest, regRowset,
|
| - sqlite3VdbeCurrentAddr(v)+2,
|
| - r, SQLITE_INT_TO_PTR(iSet), P4_INT32);
|
| + regRowid);
|
| + sqlite3VdbeAddOp4Int(v, OP_RowSetTest, regRowset,
|
| + sqlite3VdbeCurrentAddr(v)+2, r, iSet);
|
| }
|
| sqlite3VdbeAddOp2(v, OP_Gosub, regReturn, iLoopBody);
|
|
|
| + /* The pSubWInfo->untestedTerms flag means that this OR term
|
| + ** contained one or more AND term from a notReady table. The
|
| + ** terms from the notReady table could not be tested and will
|
| + ** need to be tested later.
|
| + */
|
| + if( pSubWInfo->untestedTerms ) untestedTerms = 1;
|
| +
|
| /* Finish the loop through table entries that match term pOrTerm. */
|
| sqlite3WhereEnd(pSubWInfo);
|
| }
|
| }
|
| }
|
| sqlite3VdbeChangeP1(v, iRetInit, sqlite3VdbeCurrentAddr(v));
|
| - /* sqlite3VdbeAddOp2(v, OP_Null, 0, regRowset); */
|
| sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrBrk);
|
| sqlite3VdbeResolveLabel(v, iLoopBody);
|
|
|
| - pLevel->op = OP_Return;
|
| - pLevel->p1 = regReturn;
|
| - disableTerm(pLevel, pTerm);
|
| + if( pWInfo->nLevel>1 ) sqlite3StackFree(pParse->db, pOrTab);
|
| + if( !untestedTerms ) disableTerm(pLevel, pTerm);
|
| }else
|
| #endif /* SQLITE_OMIT_OR_OPTIMIZATION */
|
|
|
| @@ -3242,14 +3719,23 @@ static Bitmask codeOneLoopStart(
|
|
|
| /* Insert code to test every subexpression that can be completely
|
| ** computed using the current set of tables.
|
| + **
|
| + ** IMPLEMENTATION-OF: R-49525-50935 Terms that cannot be satisfied through
|
| + ** the use of indices become tests that are evaluated against each row of
|
| + ** the relevant input tables.
|
| */
|
| k = 0;
|
| for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){
|
| Expr *pE;
|
| - testcase( pTerm->wtFlags & TERM_VIRTUAL );
|
| + testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* IMP: R-30575-11662 */
|
| testcase( pTerm->wtFlags & TERM_CODED );
|
| if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
|
| - if( (pTerm->prereqAll & notReady)!=0 ) continue;
|
| + if( (pTerm->prereqAll & notReady)!=0 ){
|
| + testcase( pWInfo->untestedTerms==0
|
| + && (pWInfo->wctrlFlags & WHERE_ONETABLE_ONLY)!=0 );
|
| + pWInfo->untestedTerms = 1;
|
| + continue;
|
| + }
|
| pE = pTerm->pExpr;
|
| assert( pE!=0 );
|
| if( pLevel->iLeftJoin && !ExprHasProperty(pE, EP_FromJoin) ){
|
| @@ -3269,10 +3755,13 @@ static Bitmask codeOneLoopStart(
|
| VdbeComment((v, "record LEFT JOIN hit"));
|
| sqlite3ExprCacheClear(pParse);
|
| for(pTerm=pWC->a, j=0; j<pWC->nTerm; j++, pTerm++){
|
| - testcase( pTerm->wtFlags & TERM_VIRTUAL );
|
| + testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* IMP: R-30575-11662 */
|
| testcase( pTerm->wtFlags & TERM_CODED );
|
| if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
|
| - if( (pTerm->prereqAll & notReady)!=0 ) continue;
|
| + if( (pTerm->prereqAll & notReady)!=0 ){
|
| + assert( pWInfo->untestedTerms );
|
| + continue;
|
| + }
|
| assert( pTerm->pExpr );
|
| sqlite3ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE_JUMPIFNULL);
|
| pTerm->wtFlags |= TERM_CODED;
|
| @@ -3300,7 +3789,7 @@ static int nQPlan = 0; /* Next free slow in _query_plan[] */
|
| ** Free a WhereInfo structure
|
| */
|
| static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
|
| - if( pWInfo ){
|
| + if( ALWAYS(pWInfo) ){
|
| int i;
|
| for(i=0; i<pWInfo->nLevel; i++){
|
| sqlite3_index_info *pInfo = pWInfo->a[i].pIdxInfo;
|
| @@ -3311,6 +3800,13 @@ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
|
| }
|
| sqlite3DbFree(db, pInfo);
|
| }
|
| + if( pWInfo->a[i].plan.wsFlags & WHERE_TEMP_INDEX ){
|
| + Index *pIdx = pWInfo->a[i].plan.u.pIdx;
|
| + if( pIdx ){
|
| + sqlite3DbFree(db, pIdx->zColAff);
|
| + sqlite3DbFree(db, pIdx);
|
| + }
|
| + }
|
| }
|
| whereClauseClear(pWInfo->pWC);
|
| sqlite3DbFree(db, pWInfo);
|
| @@ -3415,6 +3911,7 @@ WhereInfo *sqlite3WhereBegin(
|
| ){
|
| int i; /* Loop counter */
|
| int nByteWInfo; /* Num. bytes allocated for WhereInfo struct */
|
| + int nTabList; /* Number of elements in pTabList */
|
| WhereInfo *pWInfo; /* Will become the return value of this function */
|
| Vdbe *v = pParse->pVdbe; /* The virtual database engine */
|
| Bitmask notReady; /* Cursors that are not yet positioned */
|
| @@ -3429,11 +3926,19 @@ WhereInfo *sqlite3WhereBegin(
|
| /* The number of tables in the FROM clause is limited by the number of
|
| ** bits in a Bitmask
|
| */
|
| + testcase( pTabList->nSrc==BMS );
|
| if( pTabList->nSrc>BMS ){
|
| sqlite3ErrorMsg(pParse, "at most %d tables in a join", BMS);
|
| return 0;
|
| }
|
|
|
| + /* This function normally generates a nested loop for all tables in
|
| + ** pTabList. But if the WHERE_ONETABLE_ONLY flag is set, then we should
|
| + ** only generate code for the first table in pTabList and assume that
|
| + ** any cursors associated with subsequent tables are uninitialized.
|
| + */
|
| + nTabList = (wctrlFlags & WHERE_ONETABLE_ONLY) ? 1 : pTabList->nSrc;
|
| +
|
| /* Allocate and initialize the WhereInfo structure that will become the
|
| ** return value. A single allocation is used to store the WhereInfo
|
| ** struct, the contents of WhereInfo.a[], the WhereClause structure
|
| @@ -3442,21 +3947,24 @@ WhereInfo *sqlite3WhereBegin(
|
| ** some architectures. Hence the ROUND8() below.
|
| */
|
| db = pParse->db;
|
| - nByteWInfo = ROUND8(sizeof(WhereInfo)+(pTabList->nSrc-1)*sizeof(WhereLevel));
|
| + nByteWInfo = ROUND8(sizeof(WhereInfo)+(nTabList-1)*sizeof(WhereLevel));
|
| pWInfo = sqlite3DbMallocZero(db,
|
| nByteWInfo +
|
| sizeof(WhereClause) +
|
| sizeof(WhereMaskSet)
|
| );
|
| if( db->mallocFailed ){
|
| + sqlite3DbFree(db, pWInfo);
|
| + pWInfo = 0;
|
| goto whereBeginError;
|
| }
|
| - pWInfo->nLevel = pTabList->nSrc;
|
| + pWInfo->nLevel = nTabList;
|
| pWInfo->pParse = pParse;
|
| pWInfo->pTabList = pTabList;
|
| pWInfo->iBreak = sqlite3VdbeMakeLabel(v);
|
| pWInfo->pWC = pWC = (WhereClause *)&((u8 *)pWInfo)[nByteWInfo];
|
| pWInfo->wctrlFlags = wctrlFlags;
|
| + pWInfo->savedNQueryLoop = pParse->nQueryLoop;
|
| pMaskSet = (WhereMaskSet*)&pWC[1];
|
|
|
| /* Split the WHERE clause into separate subexpressions where each
|
| @@ -3465,12 +3973,12 @@ WhereInfo *sqlite3WhereBegin(
|
| initMaskSet(pMaskSet);
|
| whereClauseInit(pWC, pParse, pMaskSet);
|
| sqlite3ExprCodeConstants(pParse, pWhere);
|
| - whereSplit(pWC, pWhere, TK_AND);
|
| + whereSplit(pWC, pWhere, TK_AND); /* IMP: R-15842-53296 */
|
|
|
| /* Special case: a WHERE clause that is constant. Evaluate the
|
| ** expression and either jump over all of the code or fall thru.
|
| */
|
| - if( pWhere && (pTabList->nSrc==0 || sqlite3ExprIsConstantNotJoin(pWhere)) ){
|
| + if( pWhere && (nTabList==0 || sqlite3ExprIsConstantNotJoin(pWhere)) ){
|
| sqlite3ExprIfFalse(pParse, pWhere, pWInfo->iBreak, SQLITE_JUMPIFNULL);
|
| pWhere = 0;
|
| }
|
| @@ -3490,6 +3998,11 @@ WhereInfo *sqlite3WhereBegin(
|
| ** to virtual table cursors are set. This is used to selectively disable
|
| ** the OR-to-IN transformation in exprAnalyzeOrTerm(). It is not helpful
|
| ** with virtual tables.
|
| + **
|
| + ** Note that bitmasks are created for all pTabList->nSrc tables in
|
| + ** pTabList, not just the first nTabList tables. nTabList is normally
|
| + ** equal to pTabList->nSrc but might be shortened to 1 if the
|
| + ** WHERE_ONETABLE_ONLY flag is set.
|
| */
|
| assert( pWC->vmask==0 && pMaskSet->n==0 );
|
| for(i=0; i<pTabList->nSrc; i++){
|
| @@ -3541,32 +4054,45 @@ WhereInfo *sqlite3WhereBegin(
|
| pLevel = pWInfo->a;
|
| andFlags = ~0;
|
| WHERETRACE(("*** Optimizer Start ***\n"));
|
| - for(i=iFrom=0, pLevel=pWInfo->a; i<pTabList->nSrc; i++, pLevel++){
|
| + for(i=iFrom=0, pLevel=pWInfo->a; i<nTabList; i++, pLevel++){
|
| WhereCost bestPlan; /* Most efficient plan seen so far */
|
| Index *pIdx; /* Index for FROM table at pTabItem */
|
| int j; /* For looping over FROM tables */
|
| int bestJ = -1; /* The value of j */
|
| Bitmask m; /* Bitmask value for j or bestJ */
|
| int isOptimal; /* Iterator for optimal/non-optimal search */
|
| + int nUnconstrained; /* Number tables without INDEXED BY */
|
| + Bitmask notIndexed; /* Mask of tables that cannot use an index */
|
|
|
| memset(&bestPlan, 0, sizeof(bestPlan));
|
| bestPlan.rCost = SQLITE_BIG_DBL;
|
|
|
| /* Loop through the remaining entries in the FROM clause to find the
|
| - ** next nested loop. The FROM clause entries may be iterated through
|
| + ** next nested loop. The loop tests all FROM clause entries
|
| ** either once or twice.
|
| **
|
| - ** The first iteration, which is always performed, searches for the
|
| - ** FROM clause entry that permits the lowest-cost, "optimal" scan. In
|
| + ** The first test is always performed if there are two or more entries
|
| + ** remaining and never performed if there is only one FROM clause entry
|
| + ** to choose from. The first test looks for an "optimal" scan. In
|
| ** this context an optimal scan is one that uses the same strategy
|
| ** for the given FROM clause entry as would be selected if the entry
|
| ** were used as the innermost nested loop. In other words, a table
|
| ** is chosen such that the cost of running that table cannot be reduced
|
| - ** by waiting for other tables to run first.
|
| + ** by waiting for other tables to run first. This "optimal" test works
|
| + ** by first assuming that the FROM clause is on the inner loop and finding
|
| + ** its query plan, then checking to see if that query plan uses any
|
| + ** other FROM clause terms that are notReady. If no notReady terms are
|
| + ** used then the "optimal" query plan works.
|
| + **
|
| + ** Note that the WhereCost.nRow parameter for an optimal scan might
|
| + ** not be as small as it would be if the table really were the innermost
|
| + ** join. The nRow value can be reduced by WHERE clause constraints
|
| + ** that do not use indices. But this nRow reduction only happens if the
|
| + ** table really is the innermost join.
|
| **
|
| - ** The second iteration is only performed if no optimal scan strategies
|
| - ** were found by the first. This iteration is used to search for the
|
| - ** lowest cost scan overall.
|
| + ** The second loop iteration is only performed if no optimal scan
|
| + ** strategies were found by the first iteration. This second iteration
|
| + ** is used to search for the lowest cost scan overall.
|
| **
|
| ** Previous versions of SQLite performed only the second iteration -
|
| ** the next outermost loop was always that with the lowest overall
|
| @@ -3579,15 +4105,16 @@ WhereInfo *sqlite3WhereBegin(
|
| **
|
| ** The best strategy is to iterate through table t1 first. However it
|
| ** is not possible to determine this with a simple greedy algorithm.
|
| - ** However, since the cost of a linear scan through table t2 is the same
|
| + ** Since the cost of a linear scan through table t2 is the same
|
| ** as the cost of a linear scan through table t1, a simple greedy
|
| ** algorithm may choose to use t2 for the outer loop, which is a much
|
| ** costlier approach.
|
| */
|
| - for(isOptimal=1; isOptimal>=0 && bestJ<0; isOptimal--){
|
| - Bitmask mask = (isOptimal ? 0 : notReady);
|
| - assert( (pTabList->nSrc-iFrom)>1 || isOptimal );
|
| - for(j=iFrom, pTabItem=&pTabList->a[j]; j<pTabList->nSrc; j++, pTabItem++){
|
| + nUnconstrained = 0;
|
| + notIndexed = 0;
|
| + for(isOptimal=(iFrom<nTabList-1); isOptimal>=0 && bestJ<0; isOptimal--){
|
| + Bitmask mask; /* Mask of tables not yet ready */
|
| + for(j=iFrom, pTabItem=&pTabList->a[j]; j<nTabList; j++, pTabItem++){
|
| int doNotReorder; /* True if this table should not be reordered */
|
| WhereCost sCost; /* Cost information from best[Virtual]Index() */
|
| ExprList *pOrderBy; /* ORDER BY clause for index to optimize */
|
| @@ -3599,23 +4126,64 @@ WhereInfo *sqlite3WhereBegin(
|
| if( j==iFrom ) iFrom++;
|
| continue;
|
| }
|
| + mask = (isOptimal ? m : notReady);
|
| pOrderBy = ((i==0 && ppOrderBy )?*ppOrderBy:0);
|
| + if( pTabItem->pIndex==0 ) nUnconstrained++;
|
|
|
| assert( pTabItem->pTab );
|
| #ifndef SQLITE_OMIT_VIRTUALTABLE
|
| if( IsVirtual(pTabItem->pTab) ){
|
| sqlite3_index_info **pp = &pWInfo->a[j].pIdxInfo;
|
| - bestVirtualIndex(pParse, pWC, pTabItem, mask, pOrderBy, &sCost, pp);
|
| + bestVirtualIndex(pParse, pWC, pTabItem, mask, notReady, pOrderBy,
|
| + &sCost, pp);
|
| }else
|
| #endif
|
| {
|
| - bestBtreeIndex(pParse, pWC, pTabItem, mask, pOrderBy, &sCost);
|
| + bestBtreeIndex(pParse, pWC, pTabItem, mask, notReady, pOrderBy,
|
| + &sCost);
|
| }
|
| assert( isOptimal || (sCost.used¬Ready)==0 );
|
|
|
| - if( (sCost.used¬Ready)==0
|
| - && (j==iFrom || sCost.rCost<bestPlan.rCost)
|
| + /* If an INDEXED BY clause is present, then the plan must use that
|
| + ** index if it uses any index at all */
|
| + assert( pTabItem->pIndex==0
|
| + || (sCost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0
|
| + || sCost.plan.u.pIdx==pTabItem->pIndex );
|
| +
|
| + if( isOptimal && (sCost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 ){
|
| + notIndexed |= m;
|
| + }
|
| +
|
| + /* Conditions under which this table becomes the best so far:
|
| + **
|
| + ** (1) The table must not depend on other tables that have not
|
| + ** yet run.
|
| + **
|
| + ** (2) A full-table-scan plan cannot supercede another plan unless
|
| + ** it is an "optimal" plan as defined above.
|
| + **
|
| + ** (3) All tables have an INDEXED BY clause or this table lacks an
|
| + ** INDEXED BY clause or this table uses the specific
|
| + ** index specified by its INDEXED BY clause. This rule ensures
|
| + ** that a best-so-far is always selected even if an impossible
|
| + ** combination of INDEXED BY clauses are given. The error
|
| + ** will be detected and relayed back to the application later.
|
| + ** The NEVER() comes about because rule (2) above prevents
|
| + ** An indexable full-table-scan from reaching rule (3).
|
| + **
|
| + ** (4) The plan cost must be lower than prior plans or else the
|
| + ** cost must be the same and the number of rows must be lower.
|
| + */
|
| + if( (sCost.used¬Ready)==0 /* (1) */
|
| + && (bestJ<0 || (notIndexed&m)!=0 /* (2) */
|
| + || (sCost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0)
|
| + && (nUnconstrained==0 || pTabItem->pIndex==0 /* (3) */
|
| + || NEVER((sCost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0))
|
| + && (bestJ<0 || sCost.rCost<bestPlan.rCost /* (4) */
|
| + || (sCost.rCost<=bestPlan.rCost && sCost.nRow<bestPlan.nRow))
|
| ){
|
| + WHERETRACE(("... best so far with cost=%g and nRow=%g\n",
|
| + sCost.rCost, sCost.nRow));
|
| bestPlan = sCost;
|
| bestJ = j;
|
| }
|
| @@ -3631,13 +4199,16 @@ WhereInfo *sqlite3WhereBegin(
|
| }
|
| andFlags &= bestPlan.plan.wsFlags;
|
| pLevel->plan = bestPlan.plan;
|
| - if( bestPlan.plan.wsFlags & WHERE_INDEXED ){
|
| + testcase( bestPlan.plan.wsFlags & WHERE_INDEXED );
|
| + testcase( bestPlan.plan.wsFlags & WHERE_TEMP_INDEX );
|
| + if( bestPlan.plan.wsFlags & (WHERE_INDEXED|WHERE_TEMP_INDEX) ){
|
| pLevel->iIdxCur = pParse->nTab++;
|
| }else{
|
| pLevel->iIdxCur = -1;
|
| }
|
| notReady &= ~getMask(pMaskSet, pTabList->a[bestJ].iCursor);
|
| pLevel->iFrom = (u8)bestJ;
|
| + if( bestPlan.nRow>=(double)1 ) pParse->nQueryLoop *= bestPlan.nRow;
|
|
|
| /* Check that if the table scanned by this loop iteration had an
|
| ** INDEXED BY clause attached to it, that the named index is being
|
| @@ -3684,7 +4255,8 @@ WhereInfo *sqlite3WhereBegin(
|
| ** searching those tables.
|
| */
|
| sqlite3CodeVerifySchema(pParse, -1); /* Insert the cookie verifier Goto */
|
| - for(i=0, pLevel=pWInfo->a; i<pTabList->nSrc; i++, pLevel++){
|
| + notReady = ~(Bitmask)0;
|
| + for(i=0, pLevel=pWInfo->a; i<nTabList; i++, pLevel++){
|
| Table *pTab; /* Table to open */
|
| int iDb; /* Index of database containing table/index */
|
|
|
| @@ -3696,7 +4268,9 @@ WhereInfo *sqlite3WhereBegin(
|
| if( pItem->zAlias ){
|
| zMsg = sqlite3MAppendf(db, zMsg, "%s AS %s", zMsg, pItem->zAlias);
|
| }
|
| - if( (pLevel->plan.wsFlags & WHERE_INDEXED)!=0 ){
|
| + if( (pLevel->plan.wsFlags & WHERE_TEMP_INDEX)!=0 ){
|
| + zMsg = sqlite3MAppendf(db, zMsg, "%s WITH AUTOMATIC INDEX", zMsg);
|
| + }else if( (pLevel->plan.wsFlags & WHERE_INDEXED)!=0 ){
|
| zMsg = sqlite3MAppendf(db, zMsg, "%s WITH INDEX %s",
|
| zMsg, pLevel->plan.u.pIdx->zName);
|
| }else if( pLevel->plan.wsFlags & WHERE_MULTI_OR ){
|
| @@ -3719,8 +4293,11 @@ WhereInfo *sqlite3WhereBegin(
|
| #endif /* SQLITE_OMIT_EXPLAIN */
|
| pTabItem = &pTabList->a[pLevel->iFrom];
|
| pTab = pTabItem->pTab;
|
| + pLevel->iTabCur = pTabItem->iCursor;
|
| iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
| - if( (pTab->tabFlags & TF_Ephemeral)!=0 || pTab->pSelect ) continue;
|
| + if( (pTab->tabFlags & TF_Ephemeral)!=0 || pTab->pSelect ){
|
| + /* Do nothing */
|
| + }else
|
| #ifndef SQLITE_OMIT_VIRTUALTABLE
|
| if( (pLevel->plan.wsFlags & WHERE_VIRTUALTABLE)!=0 ){
|
| const char *pVTab = (const char *)sqlite3GetVTable(db, pTab);
|
| @@ -3732,17 +4309,24 @@ WhereInfo *sqlite3WhereBegin(
|
| && (wctrlFlags & WHERE_OMIT_OPEN)==0 ){
|
| int op = pWInfo->okOnePass ? OP_OpenWrite : OP_OpenRead;
|
| sqlite3OpenTable(pParse, pTabItem->iCursor, iDb, pTab, op);
|
| + testcase( pTab->nCol==BMS-1 );
|
| + testcase( pTab->nCol==BMS );
|
| if( !pWInfo->okOnePass && pTab->nCol<BMS ){
|
| Bitmask b = pTabItem->colUsed;
|
| int n = 0;
|
| for(; b; b=b>>1, n++){}
|
| - sqlite3VdbeChangeP4(v, sqlite3VdbeCurrentAddr(v)-1, SQLITE_INT_TO_PTR(n), P4_INT32);
|
| + sqlite3VdbeChangeP4(v, sqlite3VdbeCurrentAddr(v)-1,
|
| + SQLITE_INT_TO_PTR(n), P4_INT32);
|
| assert( n<=pTab->nCol );
|
| }
|
| }else{
|
| sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
|
| }
|
| - pLevel->iTabCur = pTabItem->iCursor;
|
| +#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
|
| + if( (pLevel->plan.wsFlags & WHERE_TEMP_INDEX)!=0 ){
|
| + constructAutomaticIndex(pParse, pWC, pTabItem, notReady, pLevel);
|
| + }else
|
| +#endif
|
| if( (pLevel->plan.wsFlags & WHERE_INDEXED)!=0 ){
|
| Index *pIx = pLevel->plan.u.pIdx;
|
| KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIx);
|
| @@ -3754,15 +4338,17 @@ WhereInfo *sqlite3WhereBegin(
|
| VdbeComment((v, "%s", pIx->zName));
|
| }
|
| sqlite3CodeVerifySchema(pParse, iDb);
|
| + notReady &= ~getMask(pWC->pMaskSet, pTabItem->iCursor);
|
| }
|
| pWInfo->iTop = sqlite3VdbeCurrentAddr(v);
|
| + if( db->mallocFailed ) goto whereBeginError;
|
|
|
| /* Generate the code to do the search. Each iteration of the for
|
| ** loop below generates code for a single nested loop of the VM
|
| ** program.
|
| */
|
| notReady = ~(Bitmask)0;
|
| - for(i=0; i<pTabList->nSrc; i++){
|
| + for(i=0; i<nTabList; i++){
|
| notReady = codeOneLoopStart(pWInfo, i, wctrlFlags, notReady);
|
| pWInfo->iContinue = pWInfo->a[i].addrCont;
|
| }
|
| @@ -3774,7 +4360,7 @@ WhereInfo *sqlite3WhereBegin(
|
| ** the index is listed as "{}". If the primary key is used the
|
| ** index name is '*'.
|
| */
|
| - for(i=0; i<pTabList->nSrc; i++){
|
| + for(i=0; i<nTabList; i++){
|
| char *z;
|
| int n;
|
| pLevel = &pWInfo->a[i];
|
| @@ -3823,7 +4409,10 @@ WhereInfo *sqlite3WhereBegin(
|
|
|
| /* Jump here if malloc fails */
|
| whereBeginError:
|
| - whereInfoFree(db, pWInfo);
|
| + if( pWInfo ){
|
| + pParse->nQueryLoop = pWInfo->savedNQueryLoop;
|
| + whereInfoFree(db, pWInfo);
|
| + }
|
| return 0;
|
| }
|
|
|
| @@ -3842,7 +4431,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
|
| /* Generate loop termination code.
|
| */
|
| sqlite3ExprCacheClear(pParse);
|
| - for(i=pTabList->nSrc-1; i>=0; i--){
|
| + for(i=pWInfo->nLevel-1; i>=0; i--){
|
| pLevel = &pWInfo->a[i];
|
| sqlite3VdbeResolveLabel(v, pLevel->addrCont);
|
| if( pLevel->op!=OP_Noop ){
|
| @@ -3864,7 +4453,11 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
|
| if( pLevel->iLeftJoin ){
|
| int addr;
|
| addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin);
|
| - sqlite3VdbeAddOp1(v, OP_NullRow, pTabList->a[i].iCursor);
|
| + assert( (pLevel->plan.wsFlags & WHERE_IDX_ONLY)==0
|
| + || (pLevel->plan.wsFlags & WHERE_INDEXED)!=0 );
|
| + if( (pLevel->plan.wsFlags & WHERE_IDX_ONLY)==0 ){
|
| + sqlite3VdbeAddOp1(v, OP_NullRow, pTabList->a[i].iCursor);
|
| + }
|
| if( pLevel->iIdxCur>=0 ){
|
| sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iIdxCur);
|
| }
|
| @@ -3884,16 +4477,20 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
|
|
|
| /* Close all of the cursors that were opened by sqlite3WhereBegin.
|
| */
|
| - for(i=0, pLevel=pWInfo->a; i<pTabList->nSrc; i++, pLevel++){
|
| + assert( pWInfo->nLevel==1 || pWInfo->nLevel==pTabList->nSrc );
|
| + for(i=0, pLevel=pWInfo->a; i<pWInfo->nLevel; i++, pLevel++){
|
| struct SrcList_item *pTabItem = &pTabList->a[pLevel->iFrom];
|
| Table *pTab = pTabItem->pTab;
|
| assert( pTab!=0 );
|
| - if( (pTab->tabFlags & TF_Ephemeral)!=0 || pTab->pSelect ) continue;
|
| - if( (pWInfo->wctrlFlags & WHERE_OMIT_CLOSE)==0 ){
|
| - if( !pWInfo->okOnePass && (pLevel->plan.wsFlags & WHERE_IDX_ONLY)==0 ){
|
| + if( (pTab->tabFlags & TF_Ephemeral)==0
|
| + && pTab->pSelect==0
|
| + && (pWInfo->wctrlFlags & WHERE_OMIT_CLOSE)==0
|
| + ){
|
| + int ws = pLevel->plan.wsFlags;
|
| + if( !pWInfo->okOnePass && (ws & WHERE_IDX_ONLY)==0 ){
|
| sqlite3VdbeAddOp1(v, OP_Close, pTabItem->iCursor);
|
| }
|
| - if( (pLevel->plan.wsFlags & WHERE_INDEXED)!=0 ){
|
| + if( (ws & WHERE_INDEXED)!=0 && (ws & WHERE_TEMP_INDEX)==0 ){
|
| sqlite3VdbeAddOp1(v, OP_Close, pLevel->iIdxCur);
|
| }
|
| }
|
| @@ -3915,7 +4512,6 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
|
| int k, j, last;
|
| VdbeOp *pOp;
|
| Index *pIdx = pLevel->plan.u.pIdx;
|
| - int useIndexOnly = pLevel->plan.wsFlags & WHERE_IDX_ONLY;
|
|
|
| assert( pIdx!=0 );
|
| pOp = sqlite3VdbeGetOp(v, pWInfo->iTop);
|
| @@ -3930,12 +4526,11 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
|
| break;
|
| }
|
| }
|
| - assert(!useIndexOnly || j<pIdx->nColumn);
|
| + assert( (pLevel->plan.wsFlags & WHERE_IDX_ONLY)==0
|
| + || j<pIdx->nColumn );
|
| }else if( pOp->opcode==OP_Rowid ){
|
| pOp->p1 = pLevel->iIdxCur;
|
| pOp->opcode = OP_IdxRowid;
|
| - }else if( pOp->opcode==OP_NullRow && useIndexOnly ){
|
| - pOp->opcode = OP_Noop;
|
| }
|
| }
|
| }
|
| @@ -3943,6 +4538,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
|
|
|
| /* Final cleanup
|
| */
|
| + pParse->nQueryLoop = pWInfo->savedNQueryLoop;
|
| whereInfoFree(db, pWInfo);
|
| return;
|
| }
|
|
|