| 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 e86e26ef1ae8c5805e51a88a7495eb29115538d4..80dfa20ed15c57509eff45ef6839184c6ac6024e 100644
 | 
| --- a/third_party/sqlite/src/src/where.c
 | 
| +++ b/third_party/sqlite/src/src/where.c
 | 
| @@ -31,8 +31,8 @@ static int whereLoopResize(sqlite3*, WhereLoop*, int);
 | 
|  /*
 | 
|  ** Return the estimated number of output rows from a WHERE clause
 | 
|  */
 | 
| -u64 sqlite3WhereOutputRowCount(WhereInfo *pWInfo){
 | 
| -  return sqlite3LogEstToInt(pWInfo->nRowOut);
 | 
| +LogEst sqlite3WhereOutputRowCount(WhereInfo *pWInfo){
 | 
| +  return pWInfo->nRowOut;
 | 
|  }
 | 
|  
 | 
|  /*
 | 
| @@ -52,6 +52,18 @@ int sqlite3WhereIsOrdered(WhereInfo *pWInfo){
 | 
|  }
 | 
|  
 | 
|  /*
 | 
| +** Return TRUE if the innermost loop of the WHERE clause implementation
 | 
| +** returns rows in ORDER BY order for complete run of the inner loop.
 | 
| +**
 | 
| +** Across multiple iterations of outer loops, the output rows need not be
 | 
| +** sorted.  As long as rows are sorted for just the innermost loop, this
 | 
| +** routine can return TRUE.
 | 
| +*/
 | 
| +int sqlite3WhereOrderedInnerLoop(WhereInfo *pWInfo){
 | 
| +  return pWInfo->bOrderedInnerLoop;
 | 
| +}
 | 
| +
 | 
| +/*
 | 
|  ** Return the VDBE address or label to jump to in order to continue
 | 
|  ** immediately with the next row of a WHERE clause.
 | 
|  */
 | 
| @@ -186,11 +198,13 @@ static WhereTerm *whereScanNext(WhereScan *pScan){
 | 
|    WhereTerm *pTerm;    /* The term being tested */
 | 
|    int k = pScan->k;    /* Where to start scanning */
 | 
|  
 | 
| -  while( pScan->iEquiv<=pScan->nEquiv ){
 | 
| -    iCur = pScan->aiCur[pScan->iEquiv-1];
 | 
| +  assert( pScan->iEquiv<=pScan->nEquiv );
 | 
| +  pWC = pScan->pWC;
 | 
| +  while(1){
 | 
|      iColumn = pScan->aiColumn[pScan->iEquiv-1];
 | 
| -    if( iColumn==XN_EXPR && pScan->pIdxExpr==0 ) return 0;
 | 
| -    while( (pWC = pScan->pWC)!=0 ){
 | 
| +    iCur = pScan->aiCur[pScan->iEquiv-1];
 | 
| +    assert( pWC!=0 );
 | 
| +    do{
 | 
|        for(pTerm=pWC->a+k; k<pWC->nTerm; k++, pTerm++){
 | 
|          if( pTerm->leftCursor==iCur
 | 
|           && pTerm->u.leftColumn==iColumn
 | 
| @@ -240,15 +254,17 @@ static WhereTerm *whereScanNext(WhereScan *pScan){
 | 
|                testcase( pTerm->eOperator & WO_IS );
 | 
|                continue;
 | 
|              }
 | 
| +            pScan->pWC = pWC;
 | 
|              pScan->k = k+1;
 | 
|              return pTerm;
 | 
|            }
 | 
|          }
 | 
|        }
 | 
| -      pScan->pWC = pScan->pWC->pOuter;
 | 
| +      pWC = pWC->pOuter;
 | 
|        k = 0;
 | 
| -    }
 | 
| -    pScan->pWC = pScan->pOrigWC;
 | 
| +    }while( pWC!=0 );
 | 
| +    if( pScan->iEquiv>=pScan->nEquiv ) break;
 | 
| +    pWC = pScan->pOrigWC;
 | 
|      k = 0;
 | 
|      pScan->iEquiv++;
 | 
|    }
 | 
| @@ -261,7 +277,10 @@ static WhereTerm *whereScanNext(WhereScan *pScan){
 | 
|  **
 | 
|  ** The scanner will be searching the WHERE clause pWC.  It will look
 | 
|  ** for terms of the form "X <op> <expr>" where X is column iColumn of table
 | 
| -** iCur.  The <op> must be one of the operators described by opMask.
 | 
| +** iCur.   Or if pIdx!=0 then X is column iColumn of index pIdx.  pIdx
 | 
| +** must be one of the indexes of table iCur.
 | 
| +**
 | 
| +** The <op> must be one of the operators described by opMask.
 | 
|  **
 | 
|  ** If the search is for X and the WHERE clause contains terms of the
 | 
|  ** form X=Y then this routine might also return terms of the form
 | 
| @@ -279,23 +298,25 @@ static WhereTerm *whereScanInit(
 | 
|    u32 opMask,             /* Operator(s) to scan for */
 | 
|    Index *pIdx             /* Must be compatible with this index */
 | 
|  ){
 | 
| -  int j = 0;
 | 
| -
 | 
| -  /* memset(pScan, 0, sizeof(*pScan)); */
 | 
|    pScan->pOrigWC = pWC;
 | 
|    pScan->pWC = pWC;
 | 
|    pScan->pIdxExpr = 0;
 | 
| +  pScan->idxaff = 0;
 | 
| +  pScan->zCollName = 0;
 | 
|    if( pIdx ){
 | 
| -    j = iColumn;
 | 
| +    int j = iColumn;
 | 
|      iColumn = pIdx->aiColumn[j];
 | 
| -    if( iColumn==XN_EXPR ) pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr;
 | 
| -  }
 | 
| -  if( pIdx && iColumn>=0 ){
 | 
| -    pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity;
 | 
| -    pScan->zCollName = pIdx->azColl[j];
 | 
| -  }else{
 | 
| -    pScan->idxaff = 0;
 | 
| -    pScan->zCollName = 0;
 | 
| +    if( iColumn==XN_EXPR ){
 | 
| +      pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr;
 | 
| +      pScan->zCollName = pIdx->azColl[j];
 | 
| +    }else if( iColumn==pIdx->pTable->iPKey ){
 | 
| +      iColumn = XN_ROWID;
 | 
| +    }else if( iColumn>=0 ){
 | 
| +      pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity;
 | 
| +      pScan->zCollName = pIdx->azColl[j];
 | 
| +    }
 | 
| +  }else if( iColumn==XN_EXPR ){
 | 
| +    return 0;
 | 
|    }
 | 
|    pScan->opMask = opMask;
 | 
|    pScan->k = 0;
 | 
| @@ -308,11 +329,12 @@ static WhereTerm *whereScanInit(
 | 
|  
 | 
|  /*
 | 
|  ** Search for a term in the WHERE clause that is of the form "X <op> <expr>"
 | 
| -** where X is a reference to the iColumn of table iCur and <op> is one of
 | 
| -** the WO_xx operator codes specified by the op parameter.
 | 
| -** Return a pointer to the term.  Return 0 if not found.
 | 
| +** where X is a reference to the iColumn of table iCur or of index pIdx
 | 
| +** if pIdx!=0 and <op> is one of the WO_xx operator codes specified by
 | 
| +** the op parameter.  Return a pointer to the term.  Return 0 if not found.
 | 
|  **
 | 
| -** If pIdx!=0 then search for terms matching the iColumn-th column of pIdx
 | 
| +** If pIdx!=0 then it must be one of the indexes of table iCur.  
 | 
| +** Search for terms matching the iColumn-th column of pIdx
 | 
|  ** rather than the iColumn-th column of table iCur.
 | 
|  **
 | 
|  ** The term returned might by Y=<expr> if there is another constraint in
 | 
| @@ -634,7 +656,7 @@ static void constructAutomaticIndex(
 | 
|    ** transient index on 2nd and subsequent iterations of the loop. */
 | 
|    v = pParse->pVdbe;
 | 
|    assert( v!=0 );
 | 
| -  addrInit = sqlite3CodeOnce(pParse); VdbeCoverage(v);
 | 
| +  addrInit = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
 | 
|  
 | 
|    /* Count the number of columns that will be added to the index
 | 
|    ** and used to match WHERE clause constraints */
 | 
| @@ -809,7 +831,8 @@ static sqlite3_index_info *allocateIndexInfo(
 | 
|    WhereClause *pWC,
 | 
|    Bitmask mUnusable,              /* Ignore terms with these prereqs */
 | 
|    struct SrcList_item *pSrc,
 | 
| -  ExprList *pOrderBy
 | 
| +  ExprList *pOrderBy,
 | 
| +  u16 *pmNoOmit                   /* Mask of terms not to omit */
 | 
|  ){
 | 
|    int i, j;
 | 
|    int nTerm;
 | 
| @@ -819,6 +842,7 @@ static sqlite3_index_info *allocateIndexInfo(
 | 
|    WhereTerm *pTerm;
 | 
|    int nOrderBy;
 | 
|    sqlite3_index_info *pIdxInfo;
 | 
| +  u16 mNoOmit = 0;
 | 
|  
 | 
|    /* Count the number of possible WHERE clause constraints referring
 | 
|    ** to this virtual table */
 | 
| @@ -907,6 +931,15 @@ static sqlite3_index_info *allocateIndexInfo(
 | 
|      assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE );
 | 
|      assert( WO_MATCH==SQLITE_INDEX_CONSTRAINT_MATCH );
 | 
|      assert( pTerm->eOperator & (WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_MATCH) );
 | 
| +
 | 
| +    if( op & (WO_LT|WO_LE|WO_GT|WO_GE)
 | 
| +     && sqlite3ExprIsVector(pTerm->pExpr->pRight) 
 | 
| +    ){
 | 
| +      if( i<16 ) mNoOmit |= (1 << i);
 | 
| +      if( op==WO_LT ) pIdxCons[j].op = WO_LE;
 | 
| +      if( op==WO_GT ) pIdxCons[j].op = WO_GE;
 | 
| +    }
 | 
| +
 | 
|      j++;
 | 
|    }
 | 
|    for(i=0; i<nOrderBy; i++){
 | 
| @@ -915,6 +948,7 @@ static sqlite3_index_info *allocateIndexInfo(
 | 
|      pIdxOrderBy[i].desc = pOrderBy->a[i].sortOrder;
 | 
|    }
 | 
|  
 | 
| +  *pmNoOmit = mNoOmit;
 | 
|    return pIdxInfo;
 | 
|  }
 | 
|  
 | 
| @@ -934,7 +968,6 @@ static sqlite3_index_info *allocateIndexInfo(
 | 
|  */
 | 
|  static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
 | 
|    sqlite3_vtab *pVtab = sqlite3GetVTable(pParse->db, pTab)->pVtab;
 | 
| -  int i;
 | 
|    int rc;
 | 
|  
 | 
|    TRACE_IDX_INPUTS(p);
 | 
| @@ -943,7 +976,7 @@ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
 | 
|  
 | 
|    if( rc!=SQLITE_OK ){
 | 
|      if( rc==SQLITE_NOMEM ){
 | 
| -      pParse->db->mallocFailed = 1;
 | 
| +      sqlite3OomFault(pParse->db);
 | 
|      }else if( !pVtab->zErrMsg ){
 | 
|        sqlite3ErrorMsg(pParse, "%s", sqlite3ErrStr(rc));
 | 
|      }else{
 | 
| @@ -953,12 +986,16 @@ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
 | 
|    sqlite3_free(pVtab->zErrMsg);
 | 
|    pVtab->zErrMsg = 0;
 | 
|  
 | 
| +#if 0
 | 
| +  /* This error is now caught by the caller.
 | 
| +  ** Search for "xBestIndex malfunction" below */
 | 
|    for(i=0; i<p->nConstraint; i++){
 | 
|      if( !p->aConstraint[i].usable && p->aConstraintUsage[i].argvIndex>0 ){
 | 
|        sqlite3ErrorMsg(pParse, 
 | 
|            "table %s: xBestIndex returned an invalid plan", pTab->zName);
 | 
|      }
 | 
|    }
 | 
| +#endif
 | 
|  
 | 
|    return pParse->nErr;
 | 
|  }
 | 
| @@ -1187,7 +1224,7 @@ static LogEst whereRangeAdjust(WhereTerm *pTerm, LogEst nNew){
 | 
|  /*
 | 
|  ** Return the affinity for a single column of an index.
 | 
|  */
 | 
| -static char sqlite3IndexColumnAffinity(sqlite3 *db, Index *pIdx, int iCol){
 | 
| +char sqlite3IndexColumnAffinity(sqlite3 *db, Index *pIdx, int iCol){
 | 
|    assert( iCol>=0 && iCol<pIdx->nColumn );
 | 
|    if( !pIdx->zColAff ){
 | 
|      if( sqlite3IndexAffinityStr(db, pIdx)==0 ) return SQLITE_AFF_BLOB;
 | 
| @@ -1364,7 +1401,8 @@ static int whereRangeScanEst(
 | 
|      if( nEq==pBuilder->nRecValid ){
 | 
|        UnpackedRecord *pRec = pBuilder->pRec;
 | 
|        tRowcnt a[2];
 | 
| -      u8 aff;
 | 
| +      int nBtm = pLoop->u.btree.nBtm;
 | 
| +      int nTop = pLoop->u.btree.nTop;
 | 
|  
 | 
|        /* Variable iLower will be set to the estimate of the number of rows in 
 | 
|        ** the index that are less than the lower bound of the range query. The
 | 
| @@ -1394,8 +1432,6 @@ static int whereRangeScanEst(
 | 
|          testcase( pRec->nField!=pBuilder->nRecValid );
 | 
|          pRec->nField = pBuilder->nRecValid;
 | 
|        }
 | 
| -      aff = sqlite3IndexColumnAffinity(pParse->db, p, nEq);
 | 
| -      assert( nEq!=p->nKeyCol || aff==SQLITE_AFF_INTEGER );
 | 
|        /* Determine iLower and iUpper using ($P) only. */
 | 
|        if( nEq==0 ){
 | 
|          iLower = 0;
 | 
| @@ -1414,17 +1450,20 @@ static int whereRangeScanEst(
 | 
|        if( p->aSortOrder[nEq] ){
 | 
|          /* The roles of pLower and pUpper are swapped for a DESC index */
 | 
|          SWAP(WhereTerm*, pLower, pUpper);
 | 
| +        SWAP(int, nBtm, nTop);
 | 
|        }
 | 
|  
 | 
|        /* If possible, improve on the iLower estimate using ($P:$L). */
 | 
|        if( pLower ){
 | 
| -        int bOk;                    /* True if value is extracted from pExpr */
 | 
| +        int n;                    /* Values extracted from pExpr */
 | 
|          Expr *pExpr = pLower->pExpr->pRight;
 | 
| -        rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq, &bOk);
 | 
| -        if( rc==SQLITE_OK && bOk ){
 | 
| +        rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, nBtm, nEq, &n);
 | 
| +        if( rc==SQLITE_OK && n ){
 | 
|            tRowcnt iNew;
 | 
| +          u16 mask = WO_GT|WO_LE;
 | 
| +          if( sqlite3ExprVectorSize(pExpr)>n ) mask = (WO_LE|WO_LT);
 | 
|            iLwrIdx = whereKeyStats(pParse, p, pRec, 0, a);
 | 
| -          iNew = a[0] + ((pLower->eOperator & (WO_GT|WO_LE)) ? a[1] : 0);
 | 
| +          iNew = a[0] + ((pLower->eOperator & mask) ? a[1] : 0);
 | 
|            if( iNew>iLower ) iLower = iNew;
 | 
|            nOut--;
 | 
|            pLower = 0;
 | 
| @@ -1433,13 +1472,15 @@ static int whereRangeScanEst(
 | 
|  
 | 
|        /* If possible, improve on the iUpper estimate using ($P:$U). */
 | 
|        if( pUpper ){
 | 
| -        int bOk;                    /* True if value is extracted from pExpr */
 | 
| +        int n;                    /* Values extracted from pExpr */
 | 
|          Expr *pExpr = pUpper->pExpr->pRight;
 | 
| -        rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq, &bOk);
 | 
| -        if( rc==SQLITE_OK && bOk ){
 | 
| +        rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, nTop, nEq, &n);
 | 
| +        if( rc==SQLITE_OK && n ){
 | 
|            tRowcnt iNew;
 | 
| +          u16 mask = WO_GT|WO_LE;
 | 
| +          if( sqlite3ExprVectorSize(pExpr)>n ) mask = (WO_LE|WO_LT);
 | 
|            iUprIdx = whereKeyStats(pParse, p, pRec, 1, a);
 | 
| -          iNew = a[0] + ((pUpper->eOperator & (WO_GT|WO_LE)) ? a[1] : 0);
 | 
| +          iNew = a[0] + ((pUpper->eOperator & mask) ? a[1] : 0);
 | 
|            if( iNew<iUpper ) iUpper = iNew;
 | 
|            nOut--;
 | 
|            pUpper = 0;
 | 
| @@ -1529,7 +1570,6 @@ static int whereEqualScanEst(
 | 
|    Index *p = pBuilder->pNew->u.btree.pIndex;
 | 
|    int nEq = pBuilder->pNew->u.btree.nEq;
 | 
|    UnpackedRecord *pRec = pBuilder->pRec;
 | 
| -  u8 aff;                   /* Column affinity */
 | 
|    int rc;                   /* Subfunction return code */
 | 
|    tRowcnt a[2];             /* Statistics */
 | 
|    int bOk;
 | 
| @@ -1553,15 +1593,15 @@ static int whereEqualScanEst(
 | 
|      return SQLITE_OK;
 | 
|    }
 | 
|  
 | 
| -  aff = sqlite3IndexColumnAffinity(pParse->db, p, nEq-1);
 | 
| -  rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq-1, &bOk);
 | 
| +  rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, 1, nEq-1, &bOk);
 | 
|    pBuilder->pRec = pRec;
 | 
|    if( rc!=SQLITE_OK ) return rc;
 | 
|    if( bOk==0 ) return SQLITE_NOTFOUND;
 | 
|    pBuilder->nRecValid = nEq;
 | 
|  
 | 
|    whereKeyStats(pParse, p, pRec, 0, a);
 | 
| -  WHERETRACE(0x10,("equality scan regions: %d\n", (int)a[1]));
 | 
| +  WHERETRACE(0x10,("equality scan regions %s(%d): %d\n",
 | 
| +                   p->zName, nEq-1, (int)a[1]));
 | 
|    *pnRow = a[1];
 | 
|    
 | 
|    return rc;
 | 
| @@ -1627,14 +1667,29 @@ static void whereTermPrint(WhereTerm *pTerm, int iTerm){
 | 
|      sqlite3DebugPrintf("TERM-%-3d NULL\n", iTerm);
 | 
|    }else{
 | 
|      char zType[4];
 | 
| +    char zLeft[50];
 | 
|      memcpy(zType, "...", 4);
 | 
|      if( pTerm->wtFlags & TERM_VIRTUAL ) zType[0] = 'V';
 | 
|      if( pTerm->eOperator & WO_EQUIV  ) zType[1] = 'E';
 | 
|      if( ExprHasProperty(pTerm->pExpr, EP_FromJoin) ) zType[2] = 'L';
 | 
| +    if( pTerm->eOperator & WO_SINGLE ){
 | 
| +      sqlite3_snprintf(sizeof(zLeft),zLeft,"left={%d:%d}",
 | 
| +                       pTerm->leftCursor, pTerm->u.leftColumn);
 | 
| +    }else if( (pTerm->eOperator & WO_OR)!=0 && pTerm->u.pOrInfo!=0 ){
 | 
| +      sqlite3_snprintf(sizeof(zLeft),zLeft,"indexable=0x%lld", 
 | 
| +                       pTerm->u.pOrInfo->indexable);
 | 
| +    }else{
 | 
| +      sqlite3_snprintf(sizeof(zLeft),zLeft,"left=%d", pTerm->leftCursor);
 | 
| +    }
 | 
|      sqlite3DebugPrintf(
 | 
| -       "TERM-%-3d %p %s cursor=%-3d prob=%-3d op=0x%03x wtFlags=0x%04x\n",
 | 
| -       iTerm, pTerm, zType, pTerm->leftCursor, pTerm->truthProb,
 | 
| +       "TERM-%-3d %p %s %-12s prob=%-3d op=0x%03x wtFlags=0x%04x",
 | 
| +       iTerm, pTerm, zType, zLeft, pTerm->truthProb,
 | 
|         pTerm->eOperator, pTerm->wtFlags);
 | 
| +    if( pTerm->iField ){
 | 
| +      sqlite3DebugPrintf(" iField=%d\n", pTerm->iField);
 | 
| +    }else{
 | 
| +      sqlite3DebugPrintf("\n");
 | 
| +    }
 | 
|      sqlite3TreeViewExpr(0, pTerm->pExpr, 0);
 | 
|    }
 | 
|  }
 | 
| @@ -1642,15 +1697,28 @@ static void whereTermPrint(WhereTerm *pTerm, int iTerm){
 | 
|  
 | 
|  #ifdef WHERETRACE_ENABLED
 | 
|  /*
 | 
| +** Show the complete content of a WhereClause
 | 
| +*/
 | 
| +void sqlite3WhereClausePrint(WhereClause *pWC){
 | 
| +  int i;
 | 
| +  for(i=0; i<pWC->nTerm; i++){
 | 
| +    whereTermPrint(&pWC->a[i], i);
 | 
| +  }
 | 
| +}
 | 
| +#endif
 | 
| +
 | 
| +#ifdef WHERETRACE_ENABLED
 | 
| +/*
 | 
|  ** Print a WhereLoop object for debugging purposes
 | 
|  */
 | 
|  static void whereLoopPrint(WhereLoop *p, WhereClause *pWC){
 | 
|    WhereInfo *pWInfo = pWC->pWInfo;
 | 
| -  int nb = 1+(pWInfo->pTabList->nSrc+7)/8;
 | 
| +  int nb = 1+(pWInfo->pTabList->nSrc+3)/4;
 | 
|    struct SrcList_item *pItem = pWInfo->pTabList->a + p->iTab;
 | 
|    Table *pTab = pItem->pTab;
 | 
| +  Bitmask mAll = (((Bitmask)1)<<(nb*4)) - 1;
 | 
|    sqlite3DebugPrintf("%c%2d.%0*llx.%0*llx", p->cId,
 | 
| -                     p->iTab, nb, p->maskSelf, nb, p->prereq);
 | 
| +                     p->iTab, nb, p->maskSelf, nb, p->prereq & mAll);
 | 
|    sqlite3DebugPrintf(" %12s",
 | 
|                       pItem->zAlias ? pItem->zAlias : pTab->zName);
 | 
|    if( (p->wsFlags & WHERE_VIRTUALTABLE)==0 ){
 | 
| @@ -1735,8 +1803,8 @@ static int whereLoopResize(sqlite3 *db, WhereLoop *p, int n){
 | 
|    WhereTerm **paNew;
 | 
|    if( p->nLSlot>=n ) return SQLITE_OK;
 | 
|    n = (n+7)&~7;
 | 
| -  paNew = sqlite3DbMallocRaw(db, sizeof(p->aLTerm[0])*n);
 | 
| -  if( paNew==0 ) return SQLITE_NOMEM;
 | 
| +  paNew = sqlite3DbMallocRawNN(db, sizeof(p->aLTerm[0])*n);
 | 
| +  if( paNew==0 ) return SQLITE_NOMEM_BKPT;
 | 
|    memcpy(paNew, p->aLTerm, sizeof(p->aLTerm[0])*p->nLSlot);
 | 
|    if( p->aLTerm!=p->aLTermSpace ) sqlite3DbFree(db, p->aLTerm);
 | 
|    p->aLTerm = paNew;
 | 
| @@ -1751,7 +1819,7 @@ static int whereLoopXfer(sqlite3 *db, WhereLoop *pTo, WhereLoop *pFrom){
 | 
|    whereLoopClearUnion(db, pTo);
 | 
|    if( whereLoopResize(db, pTo, pFrom->nLTerm) ){
 | 
|      memset(&pTo->u, 0, sizeof(pTo->u));
 | 
| -    return SQLITE_NOMEM;
 | 
| +    return SQLITE_NOMEM_BKPT;
 | 
|    }
 | 
|    memcpy(pTo, pFrom, WHERE_LOOP_XFER_SZ);
 | 
|    memcpy(pTo->aLTerm, pFrom->aLTerm, pTo->nLTerm*sizeof(pTo->aLTerm[0]));
 | 
| @@ -1975,6 +2043,7 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
 | 
|    WhereLoop **ppPrev, *p;
 | 
|    WhereInfo *pWInfo = pBuilder->pWInfo;
 | 
|    sqlite3 *db = pWInfo->pParse->db;
 | 
| +  int rc;
 | 
|  
 | 
|    /* If pBuilder->pOrSet is defined, then only keep track of the costs
 | 
|    ** and prereqs.
 | 
| @@ -2032,8 +2101,8 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
 | 
|  #endif
 | 
|    if( p==0 ){
 | 
|      /* Allocate a new WhereLoop to add to the end of the list */
 | 
| -    *ppPrev = p = sqlite3DbMallocRaw(db, sizeof(WhereLoop));
 | 
| -    if( p==0 ) return SQLITE_NOMEM;
 | 
| +    *ppPrev = p = sqlite3DbMallocRawNN(db, sizeof(WhereLoop));
 | 
| +    if( p==0 ) return SQLITE_NOMEM_BKPT;
 | 
|      whereLoopInit(p);
 | 
|      p->pNextLoop = 0;
 | 
|    }else{
 | 
| @@ -2057,14 +2126,14 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
 | 
|        whereLoopDelete(db, pToDel);
 | 
|      }
 | 
|    }
 | 
| -  whereLoopXfer(db, p, pTemplate);
 | 
| +  rc = whereLoopXfer(db, p, pTemplate);
 | 
|    if( (p->wsFlags & WHERE_VIRTUALTABLE)==0 ){
 | 
|      Index *pIndex = p->u.btree.pIndex;
 | 
|      if( pIndex && pIndex->tnum==0 ){
 | 
|        p->u.btree.pIndex = 0;
 | 
|      }
 | 
|    }
 | 
| -  return SQLITE_OK;
 | 
| +  return rc;
 | 
|  }
 | 
|  
 | 
|  /*
 | 
| @@ -2142,6 +2211,72 @@ static void whereLoopOutputAdjust(
 | 
|    if( pLoop->nOut > nRow-iReduce )  pLoop->nOut = nRow - iReduce;
 | 
|  }
 | 
|  
 | 
| +/* 
 | 
| +** Term pTerm is a vector range comparison operation. The first comparison
 | 
| +** in the vector can be optimized using column nEq of the index. This
 | 
| +** function returns the total number of vector elements that can be used
 | 
| +** as part of the range comparison.
 | 
| +**
 | 
| +** For example, if the query is:
 | 
| +**
 | 
| +**   WHERE a = ? AND (b, c, d) > (?, ?, ?)
 | 
| +**
 | 
| +** and the index:
 | 
| +**
 | 
| +**   CREATE INDEX ... ON (a, b, c, d, e)
 | 
| +**
 | 
| +** then this function would be invoked with nEq=1. The value returned in
 | 
| +** this case is 3.
 | 
| +*/
 | 
| +static int whereRangeVectorLen(
 | 
| +  Parse *pParse,       /* Parsing context */
 | 
| +  int iCur,            /* Cursor open on pIdx */
 | 
| +  Index *pIdx,         /* The index to be used for a inequality constraint */
 | 
| +  int nEq,             /* Number of prior equality constraints on same index */
 | 
| +  WhereTerm *pTerm     /* The vector inequality constraint */
 | 
| +){
 | 
| +  int nCmp = sqlite3ExprVectorSize(pTerm->pExpr->pLeft);
 | 
| +  int i;
 | 
| +
 | 
| +  nCmp = MIN(nCmp, (pIdx->nColumn - nEq));
 | 
| +  for(i=1; i<nCmp; i++){
 | 
| +    /* Test if comparison i of pTerm is compatible with column (i+nEq) 
 | 
| +    ** of the index. If not, exit the loop.  */
 | 
| +    char aff;                     /* Comparison affinity */
 | 
| +    char idxaff = 0;              /* Indexed columns affinity */
 | 
| +    CollSeq *pColl;               /* Comparison collation sequence */
 | 
| +    Expr *pLhs = pTerm->pExpr->pLeft->x.pList->a[i].pExpr;
 | 
| +    Expr *pRhs = pTerm->pExpr->pRight;
 | 
| +    if( pRhs->flags & EP_xIsSelect ){
 | 
| +      pRhs = pRhs->x.pSelect->pEList->a[i].pExpr;
 | 
| +    }else{
 | 
| +      pRhs = pRhs->x.pList->a[i].pExpr;
 | 
| +    }
 | 
| +
 | 
| +    /* Check that the LHS of the comparison is a column reference to
 | 
| +    ** the right column of the right source table. And that the sort
 | 
| +    ** order of the index column is the same as the sort order of the
 | 
| +    ** leftmost index column.  */
 | 
| +    if( pLhs->op!=TK_COLUMN 
 | 
| +     || pLhs->iTable!=iCur 
 | 
| +     || pLhs->iColumn!=pIdx->aiColumn[i+nEq] 
 | 
| +     || pIdx->aSortOrder[i+nEq]!=pIdx->aSortOrder[nEq]
 | 
| +    ){
 | 
| +      break;
 | 
| +    }
 | 
| +
 | 
| +    testcase( pLhs->iColumn==XN_ROWID );
 | 
| +    aff = sqlite3CompareAffinity(pRhs, sqlite3ExprAffinity(pLhs));
 | 
| +    idxaff = sqlite3TableColumnAffinity(pIdx->pTable, pLhs->iColumn);
 | 
| +    if( aff!=idxaff ) break;
 | 
| +
 | 
| +    pColl = sqlite3BinaryCompareCollSeq(pParse, pLhs, pRhs);
 | 
| +    if( pColl==0 ) break;
 | 
| +    if( sqlite3StrICmp(pColl->zName, pIdx->azColl[i+nEq]) ) break;
 | 
| +  }
 | 
| +  return i;
 | 
| +}
 | 
| +
 | 
|  /*
 | 
|  ** Adjust the cost C by the costMult facter T.  This only occurs if
 | 
|  ** compiled with -DSQLITE_ENABLE_COSTMULT
 | 
| @@ -2180,6 +2315,8 @@ static int whereLoopAddBtreeIndex(
 | 
|    Bitmask saved_prereq;           /* Original value of pNew->prereq */
 | 
|    u16 saved_nLTerm;               /* Original value of pNew->nLTerm */
 | 
|    u16 saved_nEq;                  /* Original value of pNew->u.btree.nEq */
 | 
| +  u16 saved_nBtm;                 /* Original value of pNew->u.btree.nBtm */
 | 
| +  u16 saved_nTop;                 /* Original value of pNew->u.btree.nTop */
 | 
|    u16 saved_nSkip;                /* Original value of pNew->nSkip */
 | 
|    u32 saved_wsFlags;              /* Original value of pNew->wsFlags */
 | 
|    LogEst saved_nOut;              /* Original value of pNew->nOut */
 | 
| @@ -2189,15 +2326,16 @@ static int whereLoopAddBtreeIndex(
 | 
|    WhereTerm *pTop = 0, *pBtm = 0; /* Top and bottom range constraints */
 | 
|  
 | 
|    pNew = pBuilder->pNew;
 | 
| -  if( db->mallocFailed ) return SQLITE_NOMEM;
 | 
| +  if( db->mallocFailed ) return SQLITE_NOMEM_BKPT;
 | 
| +  WHERETRACE(0x800, ("BEGIN addBtreeIdx(%s), nEq=%d\n",
 | 
| +                     pProbe->zName, pNew->u.btree.nEq));
 | 
|  
 | 
|    assert( (pNew->wsFlags & WHERE_VIRTUALTABLE)==0 );
 | 
|    assert( (pNew->wsFlags & WHERE_TOP_LIMIT)==0 );
 | 
|    if( pNew->wsFlags & WHERE_BTM_LIMIT ){
 | 
|      opMask = WO_LT|WO_LE;
 | 
| -  }else if( /*pProbe->tnum<=0 ||*/ (pSrc->fg.jointype & JT_LEFT)!=0 ){
 | 
| -    opMask = WO_EQ|WO_IN|WO_GT|WO_GE|WO_LT|WO_LE;
 | 
|    }else{
 | 
| +    assert( pNew->u.btree.nBtm==0 );
 | 
|      opMask = WO_EQ|WO_IN|WO_GT|WO_GE|WO_LT|WO_LE|WO_ISNULL|WO_IS;
 | 
|    }
 | 
|    if( pProbe->bUnordered ) opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE);
 | 
| @@ -2205,6 +2343,8 @@ static int whereLoopAddBtreeIndex(
 | 
|    assert( pNew->u.btree.nEq<pProbe->nColumn );
 | 
|  
 | 
|    saved_nEq = pNew->u.btree.nEq;
 | 
| +  saved_nBtm = pNew->u.btree.nBtm;
 | 
| +  saved_nTop = pNew->u.btree.nTop;
 | 
|    saved_nSkip = pNew->nSkip;
 | 
|    saved_nLTerm = pNew->nLTerm;
 | 
|    saved_wsFlags = pNew->wsFlags;
 | 
| @@ -2234,8 +2374,22 @@ static int whereLoopAddBtreeIndex(
 | 
|      ** to mix with a lower range bound from some other source */
 | 
|      if( pTerm->wtFlags & TERM_LIKEOPT && pTerm->eOperator==WO_LT ) continue;
 | 
|  
 | 
| +    /* Do not allow IS constraints from the WHERE clause to be used by the
 | 
| +    ** right table of a LEFT JOIN.  Only constraints in the ON clause are
 | 
| +    ** allowed */
 | 
| +    if( (pSrc->fg.jointype & JT_LEFT)!=0
 | 
| +     && !ExprHasProperty(pTerm->pExpr, EP_FromJoin)
 | 
| +     && (eOp & (WO_IS|WO_ISNULL))!=0
 | 
| +    ){
 | 
| +      testcase( eOp & WO_IS );
 | 
| +      testcase( eOp & WO_ISNULL );
 | 
| +      continue;
 | 
| +    }
 | 
| +
 | 
|      pNew->wsFlags = saved_wsFlags;
 | 
|      pNew->u.btree.nEq = saved_nEq;
 | 
| +    pNew->u.btree.nBtm = saved_nBtm;
 | 
| +    pNew->u.btree.nTop = saved_nTop;
 | 
|      pNew->nLTerm = saved_nLTerm;
 | 
|      if( whereLoopResize(db, pNew, pNew->nLTerm+1) ) break; /* OOM */
 | 
|      pNew->aLTerm[pNew->nLTerm++] = pTerm;
 | 
| @@ -2252,14 +2406,23 @@ static int whereLoopAddBtreeIndex(
 | 
|        pNew->wsFlags |= WHERE_COLUMN_IN;
 | 
|        if( ExprHasProperty(pExpr, EP_xIsSelect) ){
 | 
|          /* "x IN (SELECT ...)":  TUNING: the SELECT returns 25 rows */
 | 
| +        int i;
 | 
|          nIn = 46;  assert( 46==sqlite3LogEst(25) );
 | 
| +
 | 
| +        /* The expression may actually be of the form (x, y) IN (SELECT...).
 | 
| +        ** In this case there is a separate term for each of (x) and (y).
 | 
| +        ** However, the nIn multiplier should only be applied once, not once
 | 
| +        ** for each such term. The following loop checks that pTerm is the
 | 
| +        ** first such term in use, and sets nIn back to 0 if it is not. */
 | 
| +        for(i=0; i<pNew->nLTerm-1; i++){
 | 
| +          if( pNew->aLTerm[i] && pNew->aLTerm[i]->pExpr==pExpr ) nIn = 0;
 | 
| +        }
 | 
|        }else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){
 | 
|          /* "x IN (value, value, ...)" */
 | 
|          nIn = sqlite3LogEst(pExpr->x.pList->nExpr);
 | 
| +        assert( nIn>0 );  /* RHS always has 2 or more terms...  The parser
 | 
| +                          ** changes "x IN (?)" into "x=?". */
 | 
|        }
 | 
| -      assert( nIn>0 );  /* RHS always has 2 or more terms...  The parser
 | 
| -                        ** changes "x IN (?)" into "x=?". */
 | 
| -
 | 
|      }else if( eOp & (WO_EQ|WO_IS) ){
 | 
|        int iCol = pProbe->aiColumn[saved_nEq];
 | 
|        pNew->wsFlags |= WHERE_COLUMN_EQ;
 | 
| @@ -2279,6 +2442,9 @@ static int whereLoopAddBtreeIndex(
 | 
|        testcase( eOp & WO_GT );
 | 
|        testcase( eOp & WO_GE );
 | 
|        pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_BTM_LIMIT;
 | 
| +      pNew->u.btree.nBtm = whereRangeVectorLen(
 | 
| +          pParse, pSrc->iCursor, pProbe, saved_nEq, pTerm
 | 
| +      );
 | 
|        pBtm = pTerm;
 | 
|        pTop = 0;
 | 
|        if( pTerm->wtFlags & TERM_LIKEOPT ){
 | 
| @@ -2291,12 +2457,16 @@ static int whereLoopAddBtreeIndex(
 | 
|          if( whereLoopResize(db, pNew, pNew->nLTerm+1) ) break; /* OOM */
 | 
|          pNew->aLTerm[pNew->nLTerm++] = pTop;
 | 
|          pNew->wsFlags |= WHERE_TOP_LIMIT;
 | 
| +        pNew->u.btree.nTop = 1;
 | 
|        }
 | 
|      }else{
 | 
|        assert( eOp & (WO_LT|WO_LE) );
 | 
|        testcase( eOp & WO_LT );
 | 
|        testcase( eOp & WO_LE );
 | 
|        pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_TOP_LIMIT;
 | 
| +      pNew->u.btree.nTop = whereRangeVectorLen(
 | 
| +          pParse, pSrc->iCursor, pProbe, saved_nEq, pTerm
 | 
| +      );
 | 
|        pTop = pTerm;
 | 
|        pBtm = (pNew->wsFlags & WHERE_BTM_LIMIT)!=0 ?
 | 
|                       pNew->aLTerm[pNew->nLTerm-2] : 0;
 | 
| @@ -2396,6 +2566,8 @@ static int whereLoopAddBtreeIndex(
 | 
|    }
 | 
|    pNew->prereq = saved_prereq;
 | 
|    pNew->u.btree.nEq = saved_nEq;
 | 
| +  pNew->u.btree.nBtm = saved_nBtm;
 | 
| +  pNew->u.btree.nTop = saved_nTop;
 | 
|    pNew->nSkip = saved_nSkip;
 | 
|    pNew->wsFlags = saved_wsFlags;
 | 
|    pNew->nOut = saved_nOut;
 | 
| @@ -2435,6 +2607,8 @@ static int whereLoopAddBtreeIndex(
 | 
|      pNew->wsFlags = saved_wsFlags;
 | 
|    }
 | 
|  
 | 
| +  WHERETRACE(0x800, ("END addBtreeIdx(%s), nEq=%d, rc=%d\n",
 | 
| +                      pProbe->zName, saved_nEq, rc));
 | 
|    return rc;
 | 
|  }
 | 
|  
 | 
| @@ -2517,7 +2691,7 @@ static int whereUsablePartialIndex(int iTab, WhereClause *pWC, Expr *pWhere){
 | 
|  
 | 
|  /*
 | 
|  ** Add all WhereLoop objects for a single table of the join where the table
 | 
| -** is idenfied by pBuilder->pNew->iTab.  That table is guaranteed to be
 | 
| +** is identified by pBuilder->pNew->iTab.  That table is guaranteed to be
 | 
|  ** a b-tree table, not a virtual table.
 | 
|  **
 | 
|  ** The costs (WhereLoop.rRun) of the b-tree loops added by this function
 | 
| @@ -2553,7 +2727,7 @@ static int whereUsablePartialIndex(int iTab, WhereClause *pWC, Expr *pWhere){
 | 
|  */
 | 
|  static int whereLoopAddBtree(
 | 
|    WhereLoopBuilder *pBuilder, /* WHERE clause information */
 | 
| -  Bitmask mExtra              /* Extra prerequesites for using this table */
 | 
| +  Bitmask mPrereq             /* Extra prerequesites for using this table */
 | 
|  ){
 | 
|    WhereInfo *pWInfo;          /* WHERE analysis context */
 | 
|    Index *pProbe;              /* An index we are evaluating */
 | 
| @@ -2614,7 +2788,7 @@ static int whereLoopAddBtree(
 | 
|  #ifndef SQLITE_OMIT_AUTOMATIC_INDEX
 | 
|    /* Automatic indexes */
 | 
|    if( !pBuilder->pOrSet      /* Not part of an OR optimization */
 | 
| -   && (pWInfo->wctrlFlags & WHERE_NO_AUTOINDEX)==0
 | 
| +   && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0
 | 
|     && (pWInfo->pParse->db->flags & SQLITE_AutoIndex)!=0
 | 
|     && pSrc->pIBIndex==0      /* Has no INDEXED BY clause */
 | 
|     && !pSrc->fg.notIndexed   /* Has no NOT INDEXED clause */
 | 
| @@ -2646,6 +2820,7 @@ static int whereLoopAddBtree(
 | 
|            pNew->rSetup += 24;
 | 
|          }
 | 
|          ApplyCostMultiplier(pNew->rSetup, pTab->costMult);
 | 
| +        if( pNew->rSetup<0 ) pNew->rSetup = 0;
 | 
|          /* TUNING: Each index lookup yields 20 rows in the table.  This
 | 
|          ** is more than the usual guess of 10 rows, since we have no way
 | 
|          ** of knowing how selective the index will ultimately be.  It would
 | 
| @@ -2653,7 +2828,7 @@ static int whereLoopAddBtree(
 | 
|          pNew->nOut = 43;  assert( 43==sqlite3LogEst(20) );
 | 
|          pNew->rRun = sqlite3LogEstAdd(rLogSize,pNew->nOut);
 | 
|          pNew->wsFlags = WHERE_AUTO_INDEX;
 | 
| -        pNew->prereq = mExtra | pTerm->prereqRight;
 | 
| +        pNew->prereq = mPrereq | pTerm->prereqRight;
 | 
|          rc = whereLoopInsert(pBuilder, pNew);
 | 
|        }
 | 
|      }
 | 
| @@ -2670,11 +2845,13 @@ static int whereLoopAddBtree(
 | 
|      }
 | 
|      rSize = pProbe->aiRowLogEst[0];
 | 
|      pNew->u.btree.nEq = 0;
 | 
| +    pNew->u.btree.nBtm = 0;
 | 
| +    pNew->u.btree.nTop = 0;
 | 
|      pNew->nSkip = 0;
 | 
|      pNew->nLTerm = 0;
 | 
|      pNew->iSortIdx = 0;
 | 
|      pNew->rSetup = 0;
 | 
| -    pNew->prereq = mExtra;
 | 
| +    pNew->prereq = mPrereq;
 | 
|      pNew->nOut = rSize;
 | 
|      pNew->u.btree.pIndex = pProbe;
 | 
|      b = indexMightHelpWithOrderBy(pBuilder, pProbe, pSrc->iCursor);
 | 
| @@ -2706,6 +2883,7 @@ static int whereLoopAddBtree(
 | 
|        /* Full scan via index */
 | 
|        if( b
 | 
|         || !HasRowid(pTab)
 | 
| +       || pProbe->pPartIdxWhere!=0
 | 
|         || ( m==0
 | 
|           && pProbe->bUnordered==0
 | 
|           && (pProbe->szIdxRow<pTab->szTabRow)
 | 
| @@ -2718,11 +2896,34 @@ static int whereLoopAddBtree(
 | 
|  
 | 
|          /* The cost of visiting the index rows is N*K, where K is
 | 
|          ** between 1.1 and 3.0, depending on the relative sizes of the
 | 
| -        ** index and table rows. If this is a non-covering index scan,
 | 
| -        ** also add the cost of visiting table rows (N*3.0).  */
 | 
| +        ** index and table rows. */
 | 
|          pNew->rRun = rSize + 1 + (15*pProbe->szIdxRow)/pTab->szTabRow;
 | 
|          if( m!=0 ){
 | 
| -          pNew->rRun = sqlite3LogEstAdd(pNew->rRun, rSize+16);
 | 
| +          /* If this is a non-covering index scan, add in the cost of
 | 
| +          ** doing table lookups.  The cost will be 3x the number of
 | 
| +          ** lookups.  Take into account WHERE clause terms that can be
 | 
| +          ** satisfied using just the index, and that do not require a
 | 
| +          ** table lookup. */
 | 
| +          LogEst nLookup = rSize + 16;  /* Base cost:  N*3 */
 | 
| +          int ii;
 | 
| +          int iCur = pSrc->iCursor;
 | 
| +          WhereClause *pWC2 = &pWInfo->sWC;
 | 
| +          for(ii=0; ii<pWC2->nTerm; ii++){
 | 
| +            WhereTerm *pTerm = &pWC2->a[ii];
 | 
| +            if( !sqlite3ExprCoveredByIndex(pTerm->pExpr, iCur, pProbe) ){
 | 
| +              break;
 | 
| +            }
 | 
| +            /* pTerm can be evaluated using just the index.  So reduce
 | 
| +            ** the expected number of table lookups accordingly */
 | 
| +            if( pTerm->truthProb<=0 ){
 | 
| +              nLookup += pTerm->truthProb;
 | 
| +            }else{
 | 
| +              nLookup--;
 | 
| +              if( pTerm->eOperator & (WO_EQ|WO_IS) ) nLookup -= 19;
 | 
| +            }
 | 
| +          }
 | 
| +          
 | 
| +          pNew->rRun = sqlite3LogEstAdd(pNew->rRun, nLookup);
 | 
|          }
 | 
|          ApplyCostMultiplier(pNew->rRun, pTab->costMult);
 | 
|          whereLoopOutputAdjust(pWC, pNew, rSize);
 | 
| @@ -2747,12 +2948,162 @@ static int whereLoopAddBtree(
 | 
|  }
 | 
|  
 | 
|  #ifndef SQLITE_OMIT_VIRTUALTABLE
 | 
| +
 | 
| +/*
 | 
| +** Argument pIdxInfo is already populated with all constraints that may
 | 
| +** be used by the virtual table identified by pBuilder->pNew->iTab. This
 | 
| +** function marks a subset of those constraints usable, invokes the
 | 
| +** xBestIndex method and adds the returned plan to pBuilder.
 | 
| +**
 | 
| +** A constraint is marked usable if:
 | 
| +**
 | 
| +**   * Argument mUsable indicates that its prerequisites are available, and
 | 
| +**
 | 
| +**   * It is not one of the operators specified in the mExclude mask passed
 | 
| +**     as the fourth argument (which in practice is either WO_IN or 0).
 | 
| +**
 | 
| +** Argument mPrereq is a mask of tables that must be scanned before the
 | 
| +** virtual table in question. These are added to the plans prerequisites
 | 
| +** before it is added to pBuilder.
 | 
| +**
 | 
| +** Output parameter *pbIn is set to true if the plan added to pBuilder
 | 
| +** uses one or more WO_IN terms, or false otherwise.
 | 
| +*/
 | 
| +static int whereLoopAddVirtualOne(
 | 
| +  WhereLoopBuilder *pBuilder,
 | 
| +  Bitmask mPrereq,                /* Mask of tables that must be used. */
 | 
| +  Bitmask mUsable,                /* Mask of usable tables */
 | 
| +  u16 mExclude,                   /* Exclude terms using these operators */
 | 
| +  sqlite3_index_info *pIdxInfo,   /* Populated object for xBestIndex */
 | 
| +  u16 mNoOmit,                    /* Do not omit these constraints */
 | 
| +  int *pbIn                       /* OUT: True if plan uses an IN(...) op */
 | 
| +){
 | 
| +  WhereClause *pWC = pBuilder->pWC;
 | 
| +  struct sqlite3_index_constraint *pIdxCons;
 | 
| +  struct sqlite3_index_constraint_usage *pUsage = pIdxInfo->aConstraintUsage;
 | 
| +  int i;
 | 
| +  int mxTerm;
 | 
| +  int rc = SQLITE_OK;
 | 
| +  WhereLoop *pNew = pBuilder->pNew;
 | 
| +  Parse *pParse = pBuilder->pWInfo->pParse;
 | 
| +  struct SrcList_item *pSrc = &pBuilder->pWInfo->pTabList->a[pNew->iTab];
 | 
| +  int nConstraint = pIdxInfo->nConstraint;
 | 
| +
 | 
| +  assert( (mUsable & mPrereq)==mPrereq );
 | 
| +  *pbIn = 0;
 | 
| +  pNew->prereq = mPrereq;
 | 
| +
 | 
| +  /* Set the usable flag on the subset of constraints identified by 
 | 
| +  ** arguments mUsable and mExclude. */
 | 
| +  pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
 | 
| +  for(i=0; i<nConstraint; i++, pIdxCons++){
 | 
| +    WhereTerm *pTerm = &pWC->a[pIdxCons->iTermOffset];
 | 
| +    pIdxCons->usable = 0;
 | 
| +    if( (pTerm->prereqRight & mUsable)==pTerm->prereqRight 
 | 
| +     && (pTerm->eOperator & mExclude)==0
 | 
| +    ){
 | 
| +      pIdxCons->usable = 1;
 | 
| +    }
 | 
| +  }
 | 
| +
 | 
| +  /* Initialize the output fields of the sqlite3_index_info structure */
 | 
| +  memset(pUsage, 0, sizeof(pUsage[0])*nConstraint);
 | 
| +  assert( pIdxInfo->needToFreeIdxStr==0 );
 | 
| +  pIdxInfo->idxStr = 0;
 | 
| +  pIdxInfo->idxNum = 0;
 | 
| +  pIdxInfo->orderByConsumed = 0;
 | 
| +  pIdxInfo->estimatedCost = SQLITE_BIG_DBL / (double)2;
 | 
| +  pIdxInfo->estimatedRows = 25;
 | 
| +  pIdxInfo->idxFlags = 0;
 | 
| +  pIdxInfo->colUsed = (sqlite3_int64)pSrc->colUsed;
 | 
| +
 | 
| +  /* Invoke the virtual table xBestIndex() method */
 | 
| +  rc = vtabBestIndex(pParse, pSrc->pTab, pIdxInfo);
 | 
| +  if( rc ) return rc;
 | 
| +
 | 
| +  mxTerm = -1;
 | 
| +  assert( pNew->nLSlot>=nConstraint );
 | 
| +  for(i=0; i<nConstraint; i++) pNew->aLTerm[i] = 0;
 | 
| +  pNew->u.vtab.omitMask = 0;
 | 
| +  pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
 | 
| +  for(i=0; i<nConstraint; i++, pIdxCons++){
 | 
| +    int iTerm;
 | 
| +    if( (iTerm = pUsage[i].argvIndex - 1)>=0 ){
 | 
| +      WhereTerm *pTerm;
 | 
| +      int j = pIdxCons->iTermOffset;
 | 
| +      if( iTerm>=nConstraint
 | 
| +       || j<0
 | 
| +       || j>=pWC->nTerm
 | 
| +       || pNew->aLTerm[iTerm]!=0
 | 
| +       || pIdxCons->usable==0
 | 
| +      ){
 | 
| +        rc = SQLITE_ERROR;
 | 
| +        sqlite3ErrorMsg(pParse,"%s.xBestIndex malfunction",pSrc->pTab->zName);
 | 
| +        return rc;
 | 
| +      }
 | 
| +      testcase( iTerm==nConstraint-1 );
 | 
| +      testcase( j==0 );
 | 
| +      testcase( j==pWC->nTerm-1 );
 | 
| +      pTerm = &pWC->a[j];
 | 
| +      pNew->prereq |= pTerm->prereqRight;
 | 
| +      assert( iTerm<pNew->nLSlot );
 | 
| +      pNew->aLTerm[iTerm] = pTerm;
 | 
| +      if( iTerm>mxTerm ) mxTerm = iTerm;
 | 
| +      testcase( iTerm==15 );
 | 
| +      testcase( iTerm==16 );
 | 
| +      if( iTerm<16 && pUsage[i].omit ) pNew->u.vtab.omitMask |= 1<<iTerm;
 | 
| +      if( (pTerm->eOperator & WO_IN)!=0 ){
 | 
| +        /* A virtual table that is constrained by an IN clause may not
 | 
| +        ** consume the ORDER BY clause because (1) the order of IN terms
 | 
| +        ** is not necessarily related to the order of output terms and
 | 
| +        ** (2) Multiple outputs from a single IN value will not merge
 | 
| +        ** together.  */
 | 
| +        pIdxInfo->orderByConsumed = 0;
 | 
| +        pIdxInfo->idxFlags &= ~SQLITE_INDEX_SCAN_UNIQUE;
 | 
| +        *pbIn = 1; assert( (mExclude & WO_IN)==0 );
 | 
| +      }
 | 
| +    }
 | 
| +  }
 | 
| +  pNew->u.vtab.omitMask &= ~mNoOmit;
 | 
| +
 | 
| +  pNew->nLTerm = mxTerm+1;
 | 
| +  assert( pNew->nLTerm<=pNew->nLSlot );
 | 
| +  pNew->u.vtab.idxNum = pIdxInfo->idxNum;
 | 
| +  pNew->u.vtab.needFree = pIdxInfo->needToFreeIdxStr;
 | 
| +  pIdxInfo->needToFreeIdxStr = 0;
 | 
| +  pNew->u.vtab.idxStr = pIdxInfo->idxStr;
 | 
| +  pNew->u.vtab.isOrdered = (i8)(pIdxInfo->orderByConsumed ?
 | 
| +      pIdxInfo->nOrderBy : 0);
 | 
| +  pNew->rSetup = 0;
 | 
| +  pNew->rRun = sqlite3LogEstFromDouble(pIdxInfo->estimatedCost);
 | 
| +  pNew->nOut = sqlite3LogEst(pIdxInfo->estimatedRows);
 | 
| +
 | 
| +  /* Set the WHERE_ONEROW flag if the xBestIndex() method indicated
 | 
| +  ** that the scan will visit at most one row. Clear it otherwise. */
 | 
| +  if( pIdxInfo->idxFlags & SQLITE_INDEX_SCAN_UNIQUE ){
 | 
| +    pNew->wsFlags |= WHERE_ONEROW;
 | 
| +  }else{
 | 
| +    pNew->wsFlags &= ~WHERE_ONEROW;
 | 
| +  }
 | 
| +  rc = whereLoopInsert(pBuilder, pNew);
 | 
| +  if( pNew->u.vtab.needFree ){
 | 
| +    sqlite3_free(pNew->u.vtab.idxStr);
 | 
| +    pNew->u.vtab.needFree = 0;
 | 
| +  }
 | 
| +  WHERETRACE(0xffff, ("  bIn=%d prereqIn=%04llx prereqOut=%04llx\n",
 | 
| +                      *pbIn, (sqlite3_uint64)mPrereq,
 | 
| +                      (sqlite3_uint64)(pNew->prereq & ~mPrereq)));
 | 
| +
 | 
| +  return rc;
 | 
| +}
 | 
| +
 | 
| +
 | 
|  /*
 | 
|  ** Add all WhereLoop objects for a table of the join identified by
 | 
|  ** pBuilder->pNew->iTab.  That table is guaranteed to be a virtual table.
 | 
|  **
 | 
| -** If there are no LEFT or CROSS JOIN joins in the query, both mExtra and
 | 
| -** mUnusable are set to 0. Otherwise, mExtra is a mask of all FROM clause
 | 
| +** If there are no LEFT or CROSS JOIN joins in the query, both mPrereq and
 | 
| +** mUnusable are set to 0. Otherwise, mPrereq is a mask of all FROM clause
 | 
|  ** entries that occur before the virtual table in the FROM clause and are
 | 
|  ** separated from it by at least one LEFT or CROSS JOIN. Similarly, the
 | 
|  ** mUnusable mask contains all FROM clause entries that occur after the
 | 
| @@ -2763,188 +3114,128 @@ static int whereLoopAddBtree(
 | 
|  **
 | 
|  **   ... FROM t1, t2 LEFT JOIN t3, t4, vt CROSS JOIN t5, t6;
 | 
|  **
 | 
| -** then mExtra corresponds to (t1, t2) and mUnusable to (t5, t6).
 | 
| +** then mPrereq corresponds to (t1, t2) and mUnusable to (t5, t6).
 | 
|  **
 | 
| -** All the tables in mExtra must be scanned before the current virtual 
 | 
| +** All the tables in mPrereq must be scanned before the current virtual 
 | 
|  ** table. So any terms for which all prerequisites are satisfied by 
 | 
| -** mExtra may be specified as "usable" in all calls to xBestIndex. 
 | 
| +** mPrereq may be specified as "usable" in all calls to xBestIndex. 
 | 
|  ** Conversely, all tables in mUnusable must be scanned after the current
 | 
|  ** virtual table, so any terms for which the prerequisites overlap with
 | 
|  ** mUnusable should always be configured as "not-usable" for xBestIndex.
 | 
|  */
 | 
|  static int whereLoopAddVirtual(
 | 
|    WhereLoopBuilder *pBuilder,  /* WHERE clause information */
 | 
| -  Bitmask mExtra,              /* Tables that must be scanned before this one */
 | 
| +  Bitmask mPrereq,             /* Tables that must be scanned before this one */
 | 
|    Bitmask mUnusable            /* Tables that must be scanned after this one */
 | 
|  ){
 | 
| +  int rc = SQLITE_OK;          /* Return code */
 | 
|    WhereInfo *pWInfo;           /* WHERE analysis context */
 | 
|    Parse *pParse;               /* The parsing context */
 | 
|    WhereClause *pWC;            /* The WHERE clause */
 | 
|    struct SrcList_item *pSrc;   /* The FROM clause term to search */
 | 
| -  Table *pTab;
 | 
| -  sqlite3 *db;
 | 
| -  sqlite3_index_info *pIdxInfo;
 | 
| -  struct sqlite3_index_constraint *pIdxCons;
 | 
| -  struct sqlite3_index_constraint_usage *pUsage;
 | 
| -  WhereTerm *pTerm;
 | 
| -  int i, j;
 | 
| -  int iTerm, mxTerm;
 | 
| -  int nConstraint;
 | 
| -  int seenIn = 0;              /* True if an IN operator is seen */
 | 
| -  int seenVar = 0;             /* True if a non-constant constraint is seen */
 | 
| -  int iPhase;                  /* 0: const w/o IN, 1: const, 2: no IN,  2: IN */
 | 
| +  sqlite3_index_info *p;       /* Object to pass to xBestIndex() */
 | 
| +  int nConstraint;             /* Number of constraints in p */
 | 
| +  int bIn;                     /* True if plan uses IN(...) operator */
 | 
|    WhereLoop *pNew;
 | 
| -  int rc = SQLITE_OK;
 | 
| +  Bitmask mBest;               /* Tables used by best possible plan */
 | 
| +  u16 mNoOmit;
 | 
|  
 | 
| -  assert( (mExtra & mUnusable)==0 );
 | 
| +  assert( (mPrereq & mUnusable)==0 );
 | 
|    pWInfo = pBuilder->pWInfo;
 | 
|    pParse = pWInfo->pParse;
 | 
| -  db = pParse->db;
 | 
|    pWC = pBuilder->pWC;
 | 
|    pNew = pBuilder->pNew;
 | 
|    pSrc = &pWInfo->pTabList->a[pNew->iTab];
 | 
| -  pTab = pSrc->pTab;
 | 
| -  assert( IsVirtual(pTab) );
 | 
| -  pIdxInfo = allocateIndexInfo(pParse, pWC, mUnusable, pSrc,pBuilder->pOrderBy);
 | 
| -  if( pIdxInfo==0 ) return SQLITE_NOMEM;
 | 
| -  pNew->prereq = 0;
 | 
| +  assert( IsVirtual(pSrc->pTab) );
 | 
| +  p = allocateIndexInfo(pParse, pWC, mUnusable, pSrc, pBuilder->pOrderBy, 
 | 
| +      &mNoOmit);
 | 
| +  if( p==0 ) return SQLITE_NOMEM_BKPT;
 | 
|    pNew->rSetup = 0;
 | 
|    pNew->wsFlags = WHERE_VIRTUALTABLE;
 | 
|    pNew->nLTerm = 0;
 | 
|    pNew->u.vtab.needFree = 0;
 | 
| -  pUsage = pIdxInfo->aConstraintUsage;
 | 
| -  nConstraint = pIdxInfo->nConstraint;
 | 
| -  if( whereLoopResize(db, pNew, nConstraint) ){
 | 
| -    sqlite3DbFree(db, pIdxInfo);
 | 
| -    return SQLITE_NOMEM;
 | 
| +  nConstraint = p->nConstraint;
 | 
| +  if( whereLoopResize(pParse->db, pNew, nConstraint) ){
 | 
| +    sqlite3DbFree(pParse->db, p);
 | 
| +    return SQLITE_NOMEM_BKPT;
 | 
|    }
 | 
|  
 | 
| -  for(iPhase=0; iPhase<=3; iPhase++){
 | 
| -    if( !seenIn && (iPhase&1)!=0 ){
 | 
| -      iPhase++;
 | 
| -      if( iPhase>3 ) break;
 | 
| -    }
 | 
| -    if( !seenVar && iPhase>1 ) break;
 | 
| -    pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
 | 
| -    for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){
 | 
| -      j = pIdxCons->iTermOffset;
 | 
| -      pTerm = &pWC->a[j];
 | 
| -      switch( iPhase ){
 | 
| -        case 0:    /* Constants without IN operator */
 | 
| -          pIdxCons->usable = 0;
 | 
| -          if( (pTerm->eOperator & WO_IN)!=0 ){
 | 
| -            seenIn = 1;
 | 
| -          }
 | 
| -          if( (pTerm->prereqRight & ~mExtra)!=0 ){
 | 
| -            seenVar = 1;
 | 
| -          }else if( (pTerm->eOperator & WO_IN)==0 ){
 | 
| -            pIdxCons->usable = 1;
 | 
| -          }
 | 
| -          break;
 | 
| -        case 1:    /* Constants with IN operators */
 | 
| -          assert( seenIn );
 | 
| -          pIdxCons->usable = (pTerm->prereqRight & ~mExtra)==0;
 | 
| -          break;
 | 
| -        case 2:    /* Variables without IN */
 | 
| -          assert( seenVar );
 | 
| -          pIdxCons->usable = (pTerm->eOperator & WO_IN)==0;
 | 
| -          break;
 | 
| -        default:   /* Variables with IN */
 | 
| -          assert( seenVar && seenIn );
 | 
| -          pIdxCons->usable = 1;
 | 
| -          break;
 | 
| -      }
 | 
| -    }
 | 
| -    memset(pUsage, 0, sizeof(pUsage[0])*pIdxInfo->nConstraint);
 | 
| -    if( pIdxInfo->needToFreeIdxStr ) sqlite3_free(pIdxInfo->idxStr);
 | 
| -    pIdxInfo->idxStr = 0;
 | 
| -    pIdxInfo->idxNum = 0;
 | 
| -    pIdxInfo->needToFreeIdxStr = 0;
 | 
| -    pIdxInfo->orderByConsumed = 0;
 | 
| -    pIdxInfo->estimatedCost = SQLITE_BIG_DBL / (double)2;
 | 
| -    pIdxInfo->estimatedRows = 25;
 | 
| -    pIdxInfo->idxFlags = 0;
 | 
| -    pIdxInfo->colUsed = (sqlite3_int64)pSrc->colUsed;
 | 
| -    rc = vtabBestIndex(pParse, pTab, pIdxInfo);
 | 
| -    if( rc ) goto whereLoopAddVtab_exit;
 | 
| -    pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
 | 
| -    pNew->prereq = mExtra;
 | 
| -    mxTerm = -1;
 | 
| -    assert( pNew->nLSlot>=nConstraint );
 | 
| -    for(i=0; i<nConstraint; i++) pNew->aLTerm[i] = 0;
 | 
| -    pNew->u.vtab.omitMask = 0;
 | 
| -    for(i=0; i<nConstraint; i++, pIdxCons++){
 | 
| -      if( (iTerm = pUsage[i].argvIndex - 1)>=0 ){
 | 
| -        j = pIdxCons->iTermOffset;
 | 
| -        if( iTerm>=nConstraint
 | 
| -         || j<0
 | 
| -         || j>=pWC->nTerm
 | 
| -         || pNew->aLTerm[iTerm]!=0
 | 
| -        ){
 | 
| -          rc = SQLITE_ERROR;
 | 
| -          sqlite3ErrorMsg(pParse, "%s.xBestIndex() malfunction", pTab->zName);
 | 
| -          goto whereLoopAddVtab_exit;
 | 
| -        }
 | 
| -        testcase( iTerm==nConstraint-1 );
 | 
| -        testcase( j==0 );
 | 
| -        testcase( j==pWC->nTerm-1 );
 | 
| -        pTerm = &pWC->a[j];
 | 
| -        pNew->prereq |= pTerm->prereqRight;
 | 
| -        assert( iTerm<pNew->nLSlot );
 | 
| -        pNew->aLTerm[iTerm] = pTerm;
 | 
| -        if( iTerm>mxTerm ) mxTerm = iTerm;
 | 
| -        testcase( iTerm==15 );
 | 
| -        testcase( iTerm==16 );
 | 
| -        if( iTerm<16 && pUsage[i].omit ) pNew->u.vtab.omitMask |= 1<<iTerm;
 | 
| -        if( (pTerm->eOperator & WO_IN)!=0 ){
 | 
| -          if( pUsage[i].omit==0 ){
 | 
| -            /* Do not attempt to use an IN constraint if the virtual table
 | 
| -            ** says that the equivalent EQ constraint cannot be safely omitted.
 | 
| -            ** If we do attempt to use such a constraint, some rows might be
 | 
| -            ** repeated in the output. */
 | 
| -            break;
 | 
| -          }
 | 
| -          /* A virtual table that is constrained by an IN clause may not
 | 
| -          ** consume the ORDER BY clause because (1) the order of IN terms
 | 
| -          ** is not necessarily related to the order of output terms and
 | 
| -          ** (2) Multiple outputs from a single IN value will not merge
 | 
| -          ** together.  */
 | 
| -          pIdxInfo->orderByConsumed = 0;
 | 
| -          pIdxInfo->idxFlags &= ~SQLITE_INDEX_SCAN_UNIQUE;
 | 
| -        }
 | 
| +  /* First call xBestIndex() with all constraints usable. */
 | 
| +  WHERETRACE(0x40, ("  VirtualOne: all usable\n"));
 | 
| +  rc = whereLoopAddVirtualOne(pBuilder, mPrereq, ALLBITS, 0, p, mNoOmit, &bIn);
 | 
| +
 | 
| +  /* If the call to xBestIndex() with all terms enabled produced a plan
 | 
| +  ** that does not require any source tables (IOW: a plan with mBest==0),
 | 
| +  ** then there is no point in making any further calls to xBestIndex() 
 | 
| +  ** since they will all return the same result (if the xBestIndex()
 | 
| +  ** implementation is sane). */
 | 
| +  if( rc==SQLITE_OK && (mBest = (pNew->prereq & ~mPrereq))!=0 ){
 | 
| +    int seenZero = 0;             /* True if a plan with no prereqs seen */
 | 
| +    int seenZeroNoIN = 0;         /* Plan with no prereqs and no IN(...) seen */
 | 
| +    Bitmask mPrev = 0;
 | 
| +    Bitmask mBestNoIn = 0;
 | 
| +
 | 
| +    /* If the plan produced by the earlier call uses an IN(...) term, call
 | 
| +    ** xBestIndex again, this time with IN(...) terms disabled. */
 | 
| +    if( bIn ){
 | 
| +      WHERETRACE(0x40, ("  VirtualOne: all usable w/o IN\n"));
 | 
| +      rc = whereLoopAddVirtualOne(
 | 
| +          pBuilder, mPrereq, ALLBITS, WO_IN, p, mNoOmit, &bIn);
 | 
| +      assert( bIn==0 );
 | 
| +      mBestNoIn = pNew->prereq & ~mPrereq;
 | 
| +      if( mBestNoIn==0 ){
 | 
| +        seenZero = 1;
 | 
| +        seenZeroNoIN = 1;
 | 
|        }
 | 
|      }
 | 
| -    if( i>=nConstraint ){
 | 
| -      pNew->nLTerm = mxTerm+1;
 | 
| -      assert( pNew->nLTerm<=pNew->nLSlot );
 | 
| -      pNew->u.vtab.idxNum = pIdxInfo->idxNum;
 | 
| -      pNew->u.vtab.needFree = pIdxInfo->needToFreeIdxStr;
 | 
| -      pIdxInfo->needToFreeIdxStr = 0;
 | 
| -      pNew->u.vtab.idxStr = pIdxInfo->idxStr;
 | 
| -      pNew->u.vtab.isOrdered = (i8)(pIdxInfo->orderByConsumed ?
 | 
| -                                      pIdxInfo->nOrderBy : 0);
 | 
| -      pNew->rSetup = 0;
 | 
| -      pNew->rRun = sqlite3LogEstFromDouble(pIdxInfo->estimatedCost);
 | 
| -      pNew->nOut = sqlite3LogEst(pIdxInfo->estimatedRows);
 | 
|  
 | 
| -      /* Set the WHERE_ONEROW flag if the xBestIndex() method indicated
 | 
| -      ** that the scan will visit at most one row. Clear it otherwise. */
 | 
| -      if( pIdxInfo->idxFlags & SQLITE_INDEX_SCAN_UNIQUE ){
 | 
| -        pNew->wsFlags |= WHERE_ONEROW;
 | 
| -      }else{
 | 
| -        pNew->wsFlags &= ~WHERE_ONEROW;
 | 
| +    /* Call xBestIndex once for each distinct value of (prereqRight & ~mPrereq) 
 | 
| +    ** in the set of terms that apply to the current virtual table.  */
 | 
| +    while( rc==SQLITE_OK ){
 | 
| +      int i;
 | 
| +      Bitmask mNext = ALLBITS;
 | 
| +      assert( mNext>0 );
 | 
| +      for(i=0; i<nConstraint; i++){
 | 
| +        Bitmask mThis = (
 | 
| +            pWC->a[p->aConstraint[i].iTermOffset].prereqRight & ~mPrereq
 | 
| +        );
 | 
| +        if( mThis>mPrev && mThis<mNext ) mNext = mThis;
 | 
|        }
 | 
| -      whereLoopInsert(pBuilder, pNew);
 | 
| -      if( pNew->u.vtab.needFree ){
 | 
| -        sqlite3_free(pNew->u.vtab.idxStr);
 | 
| -        pNew->u.vtab.needFree = 0;
 | 
| +      mPrev = mNext;
 | 
| +      if( mNext==ALLBITS ) break;
 | 
| +      if( mNext==mBest || mNext==mBestNoIn ) continue;
 | 
| +      WHERETRACE(0x40, ("  VirtualOne: mPrev=%04llx mNext=%04llx\n",
 | 
| +                       (sqlite3_uint64)mPrev, (sqlite3_uint64)mNext));
 | 
| +      rc = whereLoopAddVirtualOne(
 | 
| +          pBuilder, mPrereq, mNext|mPrereq, 0, p, mNoOmit, &bIn);
 | 
| +      if( pNew->prereq==mPrereq ){
 | 
| +        seenZero = 1;
 | 
| +        if( bIn==0 ) seenZeroNoIN = 1;
 | 
|        }
 | 
|      }
 | 
| -  }  
 | 
|  
 | 
| -whereLoopAddVtab_exit:
 | 
| -  if( pIdxInfo->needToFreeIdxStr ) sqlite3_free(pIdxInfo->idxStr);
 | 
| -  sqlite3DbFree(db, pIdxInfo);
 | 
| +    /* If the calls to xBestIndex() in the above loop did not find a plan
 | 
| +    ** that requires no source tables at all (i.e. one guaranteed to be
 | 
| +    ** usable), make a call here with all source tables disabled */
 | 
| +    if( rc==SQLITE_OK && seenZero==0 ){
 | 
| +      WHERETRACE(0x40, ("  VirtualOne: all disabled\n"));
 | 
| +      rc = whereLoopAddVirtualOne(
 | 
| +          pBuilder, mPrereq, mPrereq, 0, p, mNoOmit, &bIn);
 | 
| +      if( bIn==0 ) seenZeroNoIN = 1;
 | 
| +    }
 | 
| +
 | 
| +    /* If the calls to xBestIndex() have so far failed to find a plan
 | 
| +    ** that requires no source tables at all and does not use an IN(...)
 | 
| +    ** operator, make a final call to obtain one here.  */
 | 
| +    if( rc==SQLITE_OK && seenZeroNoIN==0 ){
 | 
| +      WHERETRACE(0x40, ("  VirtualOne: all disabled and w/o IN\n"));
 | 
| +      rc = whereLoopAddVirtualOne(
 | 
| +          pBuilder, mPrereq, mPrereq, WO_IN, p, mNoOmit, &bIn);
 | 
| +    }
 | 
| +  }
 | 
| +
 | 
| +  if( p->needToFreeIdxStr ) sqlite3_free(p->idxStr);
 | 
| +  sqlite3DbFree(pParse->db, p);
 | 
|    return rc;
 | 
|  }
 | 
|  #endif /* SQLITE_OMIT_VIRTUALTABLE */
 | 
| @@ -2955,7 +3246,7 @@ whereLoopAddVtab_exit:
 | 
|  */
 | 
|  static int whereLoopAddOr(
 | 
|    WhereLoopBuilder *pBuilder, 
 | 
| -  Bitmask mExtra, 
 | 
| +  Bitmask mPrereq, 
 | 
|    Bitmask mUnusable
 | 
|  ){
 | 
|    WhereInfo *pWInfo = pBuilder->pWInfo;
 | 
| @@ -3009,21 +3300,19 @@ static int whereLoopAddOr(
 | 
|          WHERETRACE(0x200, ("OR-term %d of %p has %d subterms:\n", 
 | 
|                     (int)(pOrTerm-pOrWC->a), pTerm, sSubBuild.pWC->nTerm));
 | 
|          if( sqlite3WhereTrace & 0x400 ){
 | 
| -          for(i=0; i<sSubBuild.pWC->nTerm; i++){
 | 
| -            whereTermPrint(&sSubBuild.pWC->a[i], i);
 | 
| -          }
 | 
| +          sqlite3WhereClausePrint(sSubBuild.pWC);
 | 
|          }
 | 
|  #endif
 | 
|  #ifndef SQLITE_OMIT_VIRTUALTABLE
 | 
|          if( IsVirtual(pItem->pTab) ){
 | 
| -          rc = whereLoopAddVirtual(&sSubBuild, mExtra, mUnusable);
 | 
| +          rc = whereLoopAddVirtual(&sSubBuild, mPrereq, mUnusable);
 | 
|          }else
 | 
|  #endif
 | 
|          {
 | 
| -          rc = whereLoopAddBtree(&sSubBuild, mExtra);
 | 
| +          rc = whereLoopAddBtree(&sSubBuild, mPrereq);
 | 
|          }
 | 
|          if( rc==SQLITE_OK ){
 | 
| -          rc = whereLoopAddOr(&sSubBuild, mExtra, mUnusable);
 | 
| +          rc = whereLoopAddOr(&sSubBuild, mPrereq, mUnusable);
 | 
|          }
 | 
|          assert( rc==SQLITE_OK || sCur.n==0 );
 | 
|          if( sCur.n==0 ){
 | 
| @@ -3080,7 +3369,7 @@ static int whereLoopAddOr(
 | 
|  */
 | 
|  static int whereLoopAddAll(WhereLoopBuilder *pBuilder){
 | 
|    WhereInfo *pWInfo = pBuilder->pWInfo;
 | 
| -  Bitmask mExtra = 0;
 | 
| +  Bitmask mPrereq = 0;
 | 
|    Bitmask mPrior = 0;
 | 
|    int iTab;
 | 
|    SrcList *pTabList = pWInfo->pTabList;
 | 
| @@ -3101,9 +3390,10 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){
 | 
|      if( ((pItem->fg.jointype|priorJointype) & (JT_LEFT|JT_CROSS))!=0 ){
 | 
|        /* This condition is true when pItem is the FROM clause term on the
 | 
|        ** right-hand-side of a LEFT or CROSS JOIN.  */
 | 
| -      mExtra = mPrior;
 | 
| +      mPrereq = mPrior;
 | 
|      }
 | 
|      priorJointype = pItem->fg.jointype;
 | 
| +#ifndef SQLITE_OMIT_VIRTUALTABLE
 | 
|      if( IsVirtual(pItem->pTab) ){
 | 
|        struct SrcList_item *p;
 | 
|        for(p=&pItem[1]; p<pEnd; p++){
 | 
| @@ -3111,12 +3401,14 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){
 | 
|            mUnusable |= sqlite3WhereGetMask(&pWInfo->sMaskSet, p->iCursor);
 | 
|          }
 | 
|        }
 | 
| -      rc = whereLoopAddVirtual(pBuilder, mExtra, mUnusable);
 | 
| -    }else{
 | 
| -      rc = whereLoopAddBtree(pBuilder, mExtra);
 | 
| +      rc = whereLoopAddVirtual(pBuilder, mPrereq, mUnusable);
 | 
| +    }else
 | 
| +#endif /* SQLITE_OMIT_VIRTUALTABLE */
 | 
| +    {
 | 
| +      rc = whereLoopAddBtree(pBuilder, mPrereq);
 | 
|      }
 | 
|      if( rc==SQLITE_OK ){
 | 
| -      rc = whereLoopAddOr(pBuilder, mExtra, mUnusable);
 | 
| +      rc = whereLoopAddOr(pBuilder, mPrereq, mUnusable);
 | 
|      }
 | 
|      mPrior |= pNew->maskSelf;
 | 
|      if( rc || db->mallocFailed ) break;
 | 
| @@ -3147,7 +3439,7 @@ static i8 wherePathSatisfiesOrderBy(
 | 
|    WhereInfo *pWInfo,    /* The WHERE clause */
 | 
|    ExprList *pOrderBy,   /* ORDER BY or GROUP BY or DISTINCT clause to check */
 | 
|    WherePath *pPath,     /* The WherePath to check */
 | 
| -  u16 wctrlFlags,       /* Might contain WHERE_GROUPBY or WHERE_DISTINCTBY */
 | 
| +  u16 wctrlFlags,       /* WHERE_GROUPBY or _DISTINCTBY or _ORDERBY_LIMIT */
 | 
|    u16 nLoop,            /* Number of entries in pPath->aLoop[] */
 | 
|    WhereLoop *pLast,     /* Add this WhereLoop to the end of pPath->aLoop[] */
 | 
|    Bitmask *pRevMask     /* OUT: Mask of WhereLoops to run in reverse order */
 | 
| @@ -3158,6 +3450,7 @@ static i8 wherePathSatisfiesOrderBy(
 | 
|    u8 isOrderDistinct;   /* All prior WhereLoops are order-distinct */
 | 
|    u8 distinctColumns;   /* True if the loop has UNIQUE NOT NULL columns */
 | 
|    u8 isMatch;           /* iColumn matches a term of the ORDER BY clause */
 | 
| +  u16 eqOpMask;         /* Allowed equality operators */
 | 
|    u16 nKeyCol;          /* Number of key columns in pIndex */
 | 
|    u16 nColumn;          /* Total number of ordered columns in the index */
 | 
|    u16 nOrderBy;         /* Number terms in the ORDER BY clause */
 | 
| @@ -3208,9 +3501,16 @@ static i8 wherePathSatisfiesOrderBy(
 | 
|    obDone = MASKBIT(nOrderBy)-1;
 | 
|    orderDistinctMask = 0;
 | 
|    ready = 0;
 | 
| +  eqOpMask = WO_EQ | WO_IS | WO_ISNULL;
 | 
| +  if( wctrlFlags & WHERE_ORDERBY_LIMIT ) eqOpMask |= WO_IN;
 | 
|    for(iLoop=0; isOrderDistinct && obSat<obDone && iLoop<=nLoop; iLoop++){
 | 
|      if( iLoop>0 ) ready |= pLoop->maskSelf;
 | 
| -    pLoop = iLoop<nLoop ? pPath->aLoop[iLoop] : pLast;
 | 
| +    if( iLoop<nLoop ){
 | 
| +      pLoop = pPath->aLoop[iLoop];
 | 
| +      if( wctrlFlags & WHERE_ORDERBY_LIMIT ) continue;
 | 
| +    }else{
 | 
| +      pLoop = pLast;
 | 
| +    }
 | 
|      if( pLoop->wsFlags & WHERE_VIRTUALTABLE ){
 | 
|        if( pLoop->u.vtab.isOrdered ) obSat = obDone;
 | 
|        break;
 | 
| @@ -3228,8 +3528,16 @@ static i8 wherePathSatisfiesOrderBy(
 | 
|        if( pOBExpr->op!=TK_COLUMN ) continue;
 | 
|        if( pOBExpr->iTable!=iCur ) continue;
 | 
|        pTerm = sqlite3WhereFindTerm(&pWInfo->sWC, iCur, pOBExpr->iColumn,
 | 
| -                       ~ready, WO_EQ|WO_ISNULL|WO_IS, 0);
 | 
| +                       ~ready, eqOpMask, 0);
 | 
|        if( pTerm==0 ) continue;
 | 
| +      if( pTerm->eOperator==WO_IN ){
 | 
| +        /* IN terms are only valid for sorting in the ORDER BY LIMIT 
 | 
| +        ** optimization, and then only if they are actually used
 | 
| +        ** by the query plan */
 | 
| +        assert( wctrlFlags & WHERE_ORDERBY_LIMIT );
 | 
| +        for(j=0; j<pLoop->nLTerm && pTerm!=pLoop->aLTerm[j]; j++){}
 | 
| +        if( j>=pLoop->nLTerm ) continue;
 | 
| +      }
 | 
|        if( (pTerm->eOperator&(WO_EQ|WO_IS))!=0 && pOBExpr->iColumn>=0 ){
 | 
|          const char *z1, *z2;
 | 
|          pColl = sqlite3ExprCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr);
 | 
| @@ -3266,18 +3574,42 @@ static i8 wherePathSatisfiesOrderBy(
 | 
|        rev = revSet = 0;
 | 
|        distinctColumns = 0;
 | 
|        for(j=0; j<nColumn; j++){
 | 
| -        u8 bOnce;   /* True to run the ORDER BY search loop */
 | 
| -
 | 
| -        /* Skip over == and IS NULL terms */
 | 
| -        if( j<pLoop->u.btree.nEq
 | 
| -         && pLoop->nSkip==0
 | 
| -         && ((i = pLoop->aLTerm[j]->eOperator) & (WO_EQ|WO_ISNULL|WO_IS))!=0
 | 
| -        ){
 | 
| -          if( i & WO_ISNULL ){
 | 
| -            testcase( isOrderDistinct );
 | 
| -            isOrderDistinct = 0;
 | 
| +        u8 bOnce = 1; /* True to run the ORDER BY search loop */
 | 
| +
 | 
| +        assert( j>=pLoop->u.btree.nEq 
 | 
| +            || (pLoop->aLTerm[j]==0)==(j<pLoop->nSkip)
 | 
| +        );
 | 
| +        if( j<pLoop->u.btree.nEq && j>=pLoop->nSkip ){
 | 
| +          u16 eOp = pLoop->aLTerm[j]->eOperator;
 | 
| +
 | 
| +          /* Skip over == and IS and ISNULL terms.  (Also skip IN terms when
 | 
| +          ** doing WHERE_ORDERBY_LIMIT processing). 
 | 
| +          **
 | 
| +          ** If the current term is a column of an ((?,?) IN (SELECT...)) 
 | 
| +          ** expression for which the SELECT returns more than one column,
 | 
| +          ** check that it is the only column used by this loop. Otherwise,
 | 
| +          ** if it is one of two or more, none of the columns can be
 | 
| +          ** considered to match an ORDER BY term.  */
 | 
| +          if( (eOp & eqOpMask)!=0 ){
 | 
| +            if( eOp & WO_ISNULL ){
 | 
| +              testcase( isOrderDistinct );
 | 
| +              isOrderDistinct = 0;
 | 
| +            }
 | 
| +            continue;  
 | 
| +          }else if( ALWAYS(eOp & WO_IN) ){
 | 
| +            /* ALWAYS() justification: eOp is an equality operator due to the
 | 
| +            ** j<pLoop->u.btree.nEq constraint above.  Any equality other
 | 
| +            ** than WO_IN is captured by the previous "if".  So this one
 | 
| +            ** always has to be WO_IN. */
 | 
| +            Expr *pX = pLoop->aLTerm[j]->pExpr;
 | 
| +            for(i=j+1; i<pLoop->u.btree.nEq; i++){
 | 
| +              if( pLoop->aLTerm[i]->pExpr==pX ){
 | 
| +                assert( (pLoop->aLTerm[i]->eOperator & WO_IN) );
 | 
| +                bOnce = 0;
 | 
| +                break;
 | 
| +              }
 | 
| +            }
 | 
|            }
 | 
| -          continue;  
 | 
|          }
 | 
|  
 | 
|          /* Get the column number in the table (iColumn) and sort order
 | 
| @@ -3306,7 +3638,6 @@ static i8 wherePathSatisfiesOrderBy(
 | 
|          /* Find the ORDER BY term that corresponds to the j-th column
 | 
|          ** of the index and mark that ORDER BY term off 
 | 
|          */
 | 
| -        bOnce = 1;
 | 
|          isMatch = 0;
 | 
|          for(i=0; bOnce && i<nOrderBy; i++){
 | 
|            if( MASKBIT(i) & obSat ) continue;
 | 
| @@ -3343,7 +3674,7 @@ static i8 wherePathSatisfiesOrderBy(
 | 
|            }
 | 
|          }
 | 
|          if( isMatch ){
 | 
| -          if( iColumn<0 ){
 | 
| +          if( iColumn==XN_ROWID ){
 | 
|              testcase( distinctColumns==0 );
 | 
|              distinctColumns = 1;
 | 
|            }
 | 
| @@ -3459,15 +3790,14 @@ static LogEst whereSortingCost(
 | 
|    LogEst rScale, rSortCost;
 | 
|    assert( nOrderBy>0 && 66==sqlite3LogEst(100) );
 | 
|    rScale = sqlite3LogEst((nOrderBy-nSorted)*100/nOrderBy) - 66;
 | 
| -  rSortCost = nRow + estLog(nRow) + rScale + 16;
 | 
| +  rSortCost = nRow + rScale + 16;
 | 
|  
 | 
| -  /* TUNING: The cost of implementing DISTINCT using a B-TREE is
 | 
| -  ** similar but with a larger constant of proportionality. 
 | 
| -  ** Multiply by an additional factor of 3.0.  */
 | 
| -  if( pWInfo->wctrlFlags & WHERE_WANT_DISTINCT ){
 | 
| -    rSortCost += 16;
 | 
| +  /* Multiple by log(M) where M is the number of output rows.
 | 
| +  ** Use the LIMIT for M if it is smaller */
 | 
| +  if( (pWInfo->wctrlFlags & WHERE_USE_LIMIT)!=0 && pWInfo->iLimit<nRow ){
 | 
| +    nRow = pWInfo->iLimit;
 | 
|    }
 | 
| -
 | 
| +  rSortCost += estLog(nRow);
 | 
|    return rSortCost;
 | 
|  }
 | 
|  
 | 
| @@ -3529,8 +3859,8 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
 | 
|    /* Allocate and initialize space for aTo, aFrom and aSortCost[] */
 | 
|    nSpace = (sizeof(WherePath)+sizeof(WhereLoop*)*nLoop)*mxChoice*2;
 | 
|    nSpace += sizeof(LogEst) * nOrderBy;
 | 
| -  pSpace = sqlite3DbMallocRaw(db, nSpace);
 | 
| -  if( pSpace==0 ) return SQLITE_NOMEM;
 | 
| +  pSpace = sqlite3DbMallocRawNN(db, nSpace);
 | 
| +  if( pSpace==0 ) return SQLITE_NOMEM_BKPT;
 | 
|    aTo = (WherePath*)pSpace;
 | 
|    aFrom = aTo+mxChoice;
 | 
|    memset(aFrom, 0, sizeof(aFrom[0]));
 | 
| @@ -3585,6 +3915,12 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
 | 
|  
 | 
|          if( (pWLoop->prereq & ~pFrom->maskLoop)!=0 ) continue;
 | 
|          if( (pWLoop->maskSelf & pFrom->maskLoop)!=0 ) continue;
 | 
| +        if( (pWLoop->wsFlags & WHERE_AUTO_INDEX)!=0 && pFrom->nRow<10 ){
 | 
| +          /* Do not use an automatic index if the this loop is expected
 | 
| +          ** to run less than 2 times. */
 | 
| +          assert( 10==sqlite3LogEst(2) );
 | 
| +          continue;
 | 
| +        }
 | 
|          /* At this point, pWLoop is a candidate to be the next loop. 
 | 
|          ** Compute its cost */
 | 
|          rUnsorted = sqlite3LogEstAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow);
 | 
| @@ -3777,9 +4113,9 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
 | 
|     && nRowEst
 | 
|    ){
 | 
|      Bitmask notUsed;
 | 
| -    int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pResultSet, pFrom,
 | 
| +    int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pDistinctSet, pFrom,
 | 
|                   WHERE_DISTINCTBY, nLoop-1, pFrom->aLoop[nLoop-1], ¬Used);
 | 
| -    if( rc==pWInfo->pResultSet->nExpr ){
 | 
| +    if( rc==pWInfo->pDistinctSet->nExpr ){
 | 
|        pWInfo->eDistinct = WHERE_DISTINCT_ORDERED;
 | 
|      }
 | 
|    }
 | 
| @@ -3790,8 +4126,26 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
 | 
|        }
 | 
|      }else{
 | 
|        pWInfo->nOBSat = pFrom->isOrdered;
 | 
| -      if( pWInfo->nOBSat<0 ) pWInfo->nOBSat = 0;
 | 
|        pWInfo->revMask = pFrom->revLoop;
 | 
| +      if( pWInfo->nOBSat<=0 ){
 | 
| +        pWInfo->nOBSat = 0;
 | 
| +        if( nLoop>0 ){
 | 
| +          u32 wsFlags = pFrom->aLoop[nLoop-1]->wsFlags;
 | 
| +          if( (wsFlags & WHERE_ONEROW)==0 
 | 
| +           && (wsFlags&(WHERE_IPK|WHERE_COLUMN_IN))!=(WHERE_IPK|WHERE_COLUMN_IN)
 | 
| +          ){
 | 
| +            Bitmask m = 0;
 | 
| +            int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pOrderBy, pFrom,
 | 
| +                      WHERE_ORDERBY_LIMIT, nLoop-1, pFrom->aLoop[nLoop-1], &m);
 | 
| +            testcase( wsFlags & WHERE_IPK );
 | 
| +            testcase( wsFlags & WHERE_COLUMN_IN );
 | 
| +            if( rc==pWInfo->pOrderBy->nExpr ){
 | 
| +              pWInfo->bOrderedInnerLoop = 1;
 | 
| +              pWInfo->revMask = m;
 | 
| +            }
 | 
| +          }
 | 
| +        }
 | 
| +      }
 | 
|      }
 | 
|      if( (pWInfo->wctrlFlags & WHERE_SORTBYGROUP)
 | 
|          && pWInfo->nOBSat==pWInfo->pOrderBy->nExpr && nLoop>0
 | 
| @@ -3837,9 +4191,9 @@ static int whereShortCut(WhereLoopBuilder *pBuilder){
 | 
|    int j;
 | 
|    Table *pTab;
 | 
|    Index *pIdx;
 | 
| -  
 | 
| +
 | 
|    pWInfo = pBuilder->pWInfo;
 | 
| -  if( pWInfo->wctrlFlags & WHERE_FORCE_TABLE ) return 0;
 | 
| +  if( pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE ) return 0;
 | 
|    assert( pWInfo->pTabList->nSrc>=1 );
 | 
|    pItem = pWInfo->pTabList->a;
 | 
|    pTab = pItem->pTab;
 | 
| @@ -3986,7 +4340,7 @@ static int whereShortCut(WhereLoopBuilder *pBuilder){
 | 
|  ** is called from an UPDATE or DELETE statement, then pOrderBy is NULL.
 | 
|  **
 | 
|  ** The iIdxCur parameter is the cursor number of an index.  If 
 | 
| -** WHERE_ONETABLE_ONLY is set, iIdxCur is the cursor number of an index
 | 
| +** WHERE_OR_SUBCLAUSE is set, iIdxCur is the cursor number of an index
 | 
|  ** to use for OR clause processing.  The WHERE clause should use this
 | 
|  ** specific cursor.  If WHERE_ONEPASS_DESIRED is set, then iIdxCur is
 | 
|  ** the first cursor in an array of cursors for all indices.  iIdxCur should
 | 
| @@ -3994,13 +4348,14 @@ static int whereShortCut(WhereLoopBuilder *pBuilder){
 | 
|  ** used.
 | 
|  */
 | 
|  WhereInfo *sqlite3WhereBegin(
 | 
| -  Parse *pParse,        /* The parser context */
 | 
| -  SrcList *pTabList,    /* FROM clause: A list of all tables to be scanned */
 | 
| -  Expr *pWhere,         /* The WHERE clause */
 | 
| -  ExprList *pOrderBy,   /* An ORDER BY (or GROUP BY) clause, or NULL */
 | 
| -  ExprList *pResultSet, /* Result set of the query */
 | 
| -  u16 wctrlFlags,       /* One of the WHERE_* flags defined in sqliteInt.h */
 | 
| -  int iIdxCur           /* If WHERE_ONETABLE_ONLY is set, index cursor number */
 | 
| +  Parse *pParse,          /* The parser context */
 | 
| +  SrcList *pTabList,      /* FROM clause: A list of all tables to be scanned */
 | 
| +  Expr *pWhere,           /* The WHERE clause */
 | 
| +  ExprList *pOrderBy,     /* An ORDER BY (or GROUP BY) clause, or NULL */
 | 
| +  ExprList *pDistinctSet, /* Try not to output two rows that duplicate these */
 | 
| +  u16 wctrlFlags,         /* The WHERE_* flags defined in sqliteInt.h */
 | 
| +  int iAuxArg             /* If WHERE_OR_SUBCLAUSE is set, index cursor number
 | 
| +                          ** If WHERE_USE_LIMIT, then the limit amount */
 | 
|  ){
 | 
|    int nByteWInfo;            /* Num. bytes allocated for WhereInfo struct */
 | 
|    int nTabList;              /* Number of elements in pTabList */
 | 
| @@ -4014,13 +4369,17 @@ WhereInfo *sqlite3WhereBegin(
 | 
|    int ii;                    /* Loop counter */
 | 
|    sqlite3 *db;               /* Database connection */
 | 
|    int rc;                    /* Return code */
 | 
| -  u8 bFordelete = 0;
 | 
| +  u8 bFordelete = 0;         /* OPFLAG_FORDELETE or zero, as appropriate */
 | 
|  
 | 
|    assert( (wctrlFlags & WHERE_ONEPASS_MULTIROW)==0 || (
 | 
|          (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0 
 | 
| -     && (wctrlFlags & WHERE_OMIT_OPEN_CLOSE)==0 
 | 
| +     && (wctrlFlags & WHERE_OR_SUBCLAUSE)==0 
 | 
|    ));
 | 
|  
 | 
| +  /* Only one of WHERE_OR_SUBCLAUSE or WHERE_USE_LIMIT */
 | 
| +  assert( (wctrlFlags & WHERE_OR_SUBCLAUSE)==0
 | 
| +            || (wctrlFlags & WHERE_USE_LIMIT)==0 );
 | 
| +
 | 
|    /* Variable initialization */
 | 
|    db = pParse->db;
 | 
|    memset(&sWLB, 0, sizeof(sWLB));
 | 
| @@ -4046,11 +4405,11 @@ WhereInfo *sqlite3WhereBegin(
 | 
|    }
 | 
|  
 | 
|    /* This function normally generates a nested loop for all tables in 
 | 
| -  ** pTabList.  But if the WHERE_ONETABLE_ONLY flag is set, then we should
 | 
| +  ** pTabList.  But if the WHERE_OR_SUBCLAUSE 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;
 | 
| +  nTabList = (wctrlFlags & WHERE_OR_SUBCLAUSE) ? 1 : pTabList->nSrc;
 | 
|  
 | 
|    /* Allocate and initialize the WhereInfo structure that will become the
 | 
|    ** return value. A single allocation is used to store the WhereInfo
 | 
| @@ -4060,21 +4419,25 @@ WhereInfo *sqlite3WhereBegin(
 | 
|    ** some architectures. Hence the ROUND8() below.
 | 
|    */
 | 
|    nByteWInfo = ROUND8(sizeof(WhereInfo)+(nTabList-1)*sizeof(WhereLevel));
 | 
| -  pWInfo = sqlite3DbMallocZero(db, nByteWInfo + sizeof(WhereLoop));
 | 
| +  pWInfo = sqlite3DbMallocRawNN(db, nByteWInfo + sizeof(WhereLoop));
 | 
|    if( db->mallocFailed ){
 | 
|      sqlite3DbFree(db, pWInfo);
 | 
|      pWInfo = 0;
 | 
|      goto whereBeginError;
 | 
|    }
 | 
| -  pWInfo->aiCurOnePass[0] = pWInfo->aiCurOnePass[1] = -1;
 | 
| -  pWInfo->nLevel = nTabList;
 | 
|    pWInfo->pParse = pParse;
 | 
|    pWInfo->pTabList = pTabList;
 | 
|    pWInfo->pOrderBy = pOrderBy;
 | 
| -  pWInfo->pResultSet = pResultSet;
 | 
| +  pWInfo->pDistinctSet = pDistinctSet;
 | 
| +  pWInfo->aiCurOnePass[0] = pWInfo->aiCurOnePass[1] = -1;
 | 
| +  pWInfo->nLevel = nTabList;
 | 
|    pWInfo->iBreak = pWInfo->iContinue = sqlite3VdbeMakeLabel(v);
 | 
|    pWInfo->wctrlFlags = wctrlFlags;
 | 
| +  pWInfo->iLimit = iAuxArg;
 | 
|    pWInfo->savedNQueryLoop = pParse->nQueryLoop;
 | 
| +  memset(&pWInfo->nOBSat, 0, 
 | 
| +         offsetof(WhereInfo,sWC) - offsetof(WhereInfo,nOBSat));
 | 
| +  memset(&pWInfo->a[0], 0, sizeof(WhereLoop)+nTabList*sizeof(WhereLevel));
 | 
|    assert( pWInfo->eOnePass==ONEPASS_OFF );  /* ONEPASS defaults to OFF */
 | 
|    pMaskSet = &pWInfo->sMaskSet;
 | 
|    sWLB.pWInfo = pWInfo;
 | 
| @@ -4125,7 +4488,7 @@ WhereInfo *sqlite3WhereBegin(
 | 
|    ** 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.
 | 
| +  ** WHERE_OR_SUBCLAUSE flag is set.
 | 
|    */
 | 
|    for(ii=0; ii<pTabList->nSrc; ii++){
 | 
|      createMask(pMaskSet, pTabList->a[ii].iCursor);
 | 
| @@ -4143,25 +4506,27 @@ WhereInfo *sqlite3WhereBegin(
 | 
|    if( db->mallocFailed ) goto whereBeginError;
 | 
|  
 | 
|    if( wctrlFlags & WHERE_WANT_DISTINCT ){
 | 
| -    if( isDistinctRedundant(pParse, pTabList, &pWInfo->sWC, pResultSet) ){
 | 
| +    if( isDistinctRedundant(pParse, pTabList, &pWInfo->sWC, pDistinctSet) ){
 | 
|        /* The DISTINCT marking is pointless.  Ignore it. */
 | 
|        pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
 | 
|      }else if( pOrderBy==0 ){
 | 
|        /* Try to ORDER BY the result set to make distinct processing easier */
 | 
|        pWInfo->wctrlFlags |= WHERE_DISTINCTBY;
 | 
| -      pWInfo->pOrderBy = pResultSet;
 | 
| +      pWInfo->pOrderBy = pDistinctSet;
 | 
|      }
 | 
|    }
 | 
|  
 | 
|    /* Construct the WhereLoop objects */
 | 
| -  WHERETRACE(0xffff,("*** Optimizer Start *** (wctrlFlags: 0x%x)\n",
 | 
| -             wctrlFlags));
 | 
|  #if defined(WHERETRACE_ENABLED)
 | 
| -  if( sqlite3WhereTrace & 0x100 ){ /* Display all terms of the WHERE clause */
 | 
| -    int i;
 | 
| -    for(i=0; i<sWLB.pWC->nTerm; i++){
 | 
| -      whereTermPrint(&sWLB.pWC->a[i], i);
 | 
| +  if( sqlite3WhereTrace & 0xffff ){
 | 
| +    sqlite3DebugPrintf("*** Optimizer Start *** (wctrlFlags: 0x%x",wctrlFlags);
 | 
| +    if( wctrlFlags & WHERE_USE_LIMIT ){
 | 
| +      sqlite3DebugPrintf(", limit: %d", iAuxArg);
 | 
|      }
 | 
| +    sqlite3DebugPrintf(")\n");
 | 
| +  }
 | 
| +  if( sqlite3WhereTrace & 0x100 ){ /* Display all terms of the WHERE clause */
 | 
| +    sqlite3WhereClausePrint(sWLB.pWC);
 | 
|    }
 | 
|  #endif
 | 
|  
 | 
| @@ -4190,7 +4555,7 @@ WhereInfo *sqlite3WhereBegin(
 | 
|      }
 | 
|    }
 | 
|    if( pWInfo->pOrderBy==0 && (db->flags & SQLITE_ReverseOrder)!=0 ){
 | 
| -     pWInfo->revMask = (Bitmask)(-1);
 | 
| +     pWInfo->revMask = ALLBITS;
 | 
|    }
 | 
|    if( pParse->nErr || NEVER(db->mallocFailed) ){
 | 
|      goto whereBeginError;
 | 
| @@ -4223,10 +4588,10 @@ WhereInfo *sqlite3WhereBegin(
 | 
|  #endif
 | 
|    /* Attempt to omit tables from the join that do not effect the result */
 | 
|    if( pWInfo->nLevel>=2
 | 
| -   && pResultSet!=0
 | 
| +   && pDistinctSet!=0
 | 
|     && OptimizationEnabled(db, SQLITE_OmitNoopJoin)
 | 
|    ){
 | 
| -    Bitmask tabUsed = sqlite3WhereExprListUsage(pMaskSet, pResultSet);
 | 
| +    Bitmask tabUsed = sqlite3WhereExprListUsage(pMaskSet, pDistinctSet);
 | 
|      if( sWLB.pOrderBy ){
 | 
|        tabUsed |= sqlite3WhereExprListUsage(pMaskSet, sWLB.pOrderBy);
 | 
|      }
 | 
| @@ -4259,16 +4624,15 @@ WhereInfo *sqlite3WhereBegin(
 | 
|  
 | 
|    /* If the caller is an UPDATE or DELETE statement that is requesting
 | 
|    ** to use a one-pass algorithm, determine if this is appropriate.
 | 
| -  ** The one-pass algorithm only works if the WHERE clause constrains
 | 
| -  ** the statement to update or delete a single row.
 | 
|    */
 | 
|    assert( (wctrlFlags & WHERE_ONEPASS_DESIRED)==0 || pWInfo->nLevel==1 );
 | 
|    if( (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0 ){
 | 
|      int wsFlags = pWInfo->a[0].pWLoop->wsFlags;
 | 
|      int bOnerow = (wsFlags & WHERE_ONEROW)!=0;
 | 
| -    if( bOnerow || ( (wctrlFlags & WHERE_ONEPASS_MULTIROW)
 | 
| -       && 0==(wsFlags & WHERE_VIRTUALTABLE)
 | 
| -    )){
 | 
| +    if( bOnerow
 | 
| +     || ((wctrlFlags & WHERE_ONEPASS_MULTIROW)!=0
 | 
| +           && 0==(wsFlags & WHERE_VIRTUALTABLE))
 | 
| +    ){
 | 
|        pWInfo->eOnePass = bOnerow ? ONEPASS_SINGLE : ONEPASS_MULTI;
 | 
|        if( HasRowid(pTabList->a[0].pTab) && (wsFlags & WHERE_IDX_ONLY) ){
 | 
|          if( wctrlFlags & WHERE_ONEPASS_MULTIROW ){
 | 
| @@ -4304,7 +4668,7 @@ WhereInfo *sqlite3WhereBegin(
 | 
|      }else
 | 
|  #endif
 | 
|      if( (pLoop->wsFlags & WHERE_IDX_ONLY)==0
 | 
| -         && (wctrlFlags & WHERE_OMIT_OPEN_CLOSE)==0 ){
 | 
| +         && (wctrlFlags & WHERE_OR_SUBCLAUSE)==0 ){
 | 
|        int op = OP_OpenRead;
 | 
|        if( pWInfo->eOnePass!=ONEPASS_OFF ){
 | 
|          op = OP_OpenWrite;
 | 
| @@ -4318,8 +4682,7 @@ WhereInfo *sqlite3WhereBegin(
 | 
|          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, -1, SQLITE_INT_TO_PTR(n), P4_INT32);
 | 
|          assert( n<=pTab->nCol );
 | 
|        }
 | 
|  #ifdef SQLITE_ENABLE_CURSOR_HINTS
 | 
| @@ -4341,10 +4704,10 @@ WhereInfo *sqlite3WhereBegin(
 | 
|        Index *pIx = pLoop->u.btree.pIndex;
 | 
|        int iIndexCur;
 | 
|        int op = OP_OpenRead;
 | 
| -      /* iIdxCur is always set if to a positive value if ONEPASS is possible */
 | 
| -      assert( iIdxCur!=0 || (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0 );
 | 
| +      /* iAuxArg is always set if to a positive value if ONEPASS is possible */
 | 
| +      assert( iAuxArg!=0 || (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0 );
 | 
|        if( !HasRowid(pTab) && IsPrimaryKeyIndex(pIx)
 | 
| -       && (wctrlFlags & WHERE_ONETABLE_ONLY)!=0
 | 
| +       && (wctrlFlags & WHERE_OR_SUBCLAUSE)!=0
 | 
|        ){
 | 
|          /* This is one term of an OR-optimization using the PRIMARY KEY of a
 | 
|          ** WITHOUT ROWID table.  No need for a separate index */
 | 
| @@ -4352,7 +4715,7 @@ WhereInfo *sqlite3WhereBegin(
 | 
|          op = 0;
 | 
|        }else if( pWInfo->eOnePass!=ONEPASS_OFF ){
 | 
|          Index *pJ = pTabItem->pTab->pIndex;
 | 
| -        iIndexCur = iIdxCur;
 | 
| +        iIndexCur = iAuxArg;
 | 
|          assert( wctrlFlags & WHERE_ONEPASS_DESIRED );
 | 
|          while( ALWAYS(pJ) && pJ!=pIx ){
 | 
|            iIndexCur++;
 | 
| @@ -4360,9 +4723,9 @@ WhereInfo *sqlite3WhereBegin(
 | 
|          }
 | 
|          op = OP_OpenWrite;
 | 
|          pWInfo->aiCurOnePass[1] = iIndexCur;
 | 
| -      }else if( iIdxCur && (wctrlFlags & WHERE_ONETABLE_ONLY)!=0 ){
 | 
| -        iIndexCur = iIdxCur;
 | 
| -        if( wctrlFlags & WHERE_REOPEN_IDX ) op = OP_ReopenIdx;
 | 
| +      }else if( iAuxArg && (wctrlFlags & WHERE_OR_SUBCLAUSE)!=0 ){
 | 
| +        iIndexCur = iAuxArg;
 | 
| +        op = OP_ReopenIdx;
 | 
|        }else{
 | 
|          iIndexCur = pParse->nTab++;
 | 
|        }
 | 
| @@ -4424,7 +4787,7 @@ WhereInfo *sqlite3WhereBegin(
 | 
|      pLevel->addrBody = sqlite3VdbeCurrentAddr(v);
 | 
|      notReady = sqlite3WhereCodeOneLoopStart(pWInfo, ii, notReady);
 | 
|      pWInfo->iContinue = pLevel->addrCont;
 | 
| -    if( (wsFlags&WHERE_MULTI_OR)==0 && (wctrlFlags&WHERE_ONETABLE_ONLY)==0 ){
 | 
| +    if( (wsFlags&WHERE_MULTI_OR)==0 && (wctrlFlags&WHERE_OR_SUBCLAUSE)==0 ){
 | 
|        sqlite3WhereAddScanStatus(v, pTabList, pLevel, addrExplain);
 | 
|      }
 | 
|    }
 | 
| @@ -4478,10 +4841,12 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
 | 
|        sqlite3VdbeResolveLabel(v, pLevel->addrNxt);
 | 
|        for(j=pLevel->u.in.nIn, pIn=&pLevel->u.in.aInLoop[j-1]; j>0; j--, pIn--){
 | 
|          sqlite3VdbeJumpHere(v, pIn->addrInTop+1);
 | 
| -        sqlite3VdbeAddOp2(v, pIn->eEndLoopOp, pIn->iCur, pIn->addrInTop);
 | 
| -        VdbeCoverage(v);
 | 
| -        VdbeCoverageIf(v, pIn->eEndLoopOp==OP_PrevIfOpen);
 | 
| -        VdbeCoverageIf(v, pIn->eEndLoopOp==OP_NextIfOpen);
 | 
| +        if( pIn->eEndLoopOp!=OP_Noop ){
 | 
| +          sqlite3VdbeAddOp2(v, pIn->eEndLoopOp, pIn->iCur, pIn->addrInTop);
 | 
| +          VdbeCoverage(v);
 | 
| +          VdbeCoverageIf(v, pIn->eEndLoopOp==OP_PrevIfOpen);
 | 
| +          VdbeCoverageIf(v, pIn->eEndLoopOp==OP_NextIfOpen);
 | 
| +        }
 | 
|          sqlite3VdbeJumpHere(v, pIn->addrInTop-1);
 | 
|        }
 | 
|      }
 | 
| @@ -4494,24 +4859,21 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
 | 
|      }
 | 
|  #ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS
 | 
|      if( pLevel->addrLikeRep ){
 | 
| -      int op;
 | 
| -      if( sqlite3VdbeGetOp(v, pLevel->addrLikeRep-1)->p1 ){
 | 
| -        op = OP_DecrJumpZero;
 | 
| -      }else{
 | 
| -        op = OP_JumpZeroIncr;
 | 
| -      }
 | 
| -      sqlite3VdbeAddOp2(v, op, pLevel->iLikeRepCntr, pLevel->addrLikeRep);
 | 
| +      sqlite3VdbeAddOp2(v, OP_DecrJumpZero, (int)(pLevel->iLikeRepCntr>>1),
 | 
| +                        pLevel->addrLikeRep);
 | 
|        VdbeCoverage(v);
 | 
|      }
 | 
|  #endif
 | 
|      if( pLevel->iLeftJoin ){
 | 
| +      int ws = pLoop->wsFlags;
 | 
|        addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); VdbeCoverage(v);
 | 
| -      assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0
 | 
| -           || (pLoop->wsFlags & WHERE_INDEXED)!=0 );
 | 
| -      if( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 ){
 | 
| +      assert( (ws & WHERE_IDX_ONLY)==0 || (ws & WHERE_INDEXED)!=0 );
 | 
| +      if( (ws & WHERE_IDX_ONLY)==0 ){
 | 
|          sqlite3VdbeAddOp1(v, OP_NullRow, pTabList->a[i].iCursor);
 | 
|        }
 | 
| -      if( pLoop->wsFlags & WHERE_INDEXED ){
 | 
| +      if( (ws & WHERE_INDEXED) 
 | 
| +       || ((ws & WHERE_MULTI_OR) && pLevel->u.pCovidx) 
 | 
| +      ){
 | 
|          sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iIdxCur);
 | 
|        }
 | 
|        if( pLevel->op==OP_Return ){
 | 
| @@ -4550,27 +4912,6 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
 | 
|        continue;
 | 
|      }
 | 
|  
 | 
| -    /* Close all of the cursors that were opened by sqlite3WhereBegin.
 | 
| -    ** Except, do not close cursors that will be reused by the OR optimization
 | 
| -    ** (WHERE_OMIT_OPEN_CLOSE).  And do not close the OP_OpenWrite cursors
 | 
| -    ** created for the ONEPASS optimization.
 | 
| -    */
 | 
| -    if( (pTab->tabFlags & TF_Ephemeral)==0
 | 
| -     && pTab->pSelect==0
 | 
| -     && (pWInfo->wctrlFlags & WHERE_OMIT_OPEN_CLOSE)==0
 | 
| -    ){
 | 
| -      int ws = pLoop->wsFlags;
 | 
| -      if( pWInfo->eOnePass==ONEPASS_OFF && (ws & WHERE_IDX_ONLY)==0 ){
 | 
| -        sqlite3VdbeAddOp1(v, OP_Close, pTabItem->iCursor);
 | 
| -      }
 | 
| -      if( (ws & WHERE_INDEXED)!=0
 | 
| -       && (ws & (WHERE_IPK|WHERE_AUTO_INDEX))==0 
 | 
| -       && pLevel->iIdxCur!=pWInfo->aiCurOnePass[1]
 | 
| -      ){
 | 
| -        sqlite3VdbeAddOp1(v, OP_Close, pLevel->iIdxCur);
 | 
| -      }
 | 
| -    }
 | 
| -
 | 
|      /* If this scan uses an index, make VDBE code substitutions to read data
 | 
|      ** from the index instead of from the table where possible.  In some cases
 | 
|      ** this optimization prevents the table from ever being read, which can
 | 
| @@ -4609,7 +4950,8 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
 | 
|              pOp->p2 = x;
 | 
|              pOp->p1 = pLevel->iIdxCur;
 | 
|            }
 | 
| -          assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 || x>=0 );
 | 
| +          assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 || x>=0 
 | 
| +              || pWInfo->eOnePass );
 | 
|          }else if( pOp->opcode==OP_Rowid ){
 | 
|            pOp->p1 = pLevel->iIdxCur;
 | 
|            pOp->opcode = OP_IdxRowid;
 | 
| 
 |