/ Check-in [cabf2187]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Code refactoring to try to shift FROM-clause subquery manifesting until after the query planner runs. Except this does not currently work because the query planner needs an estimated of the number of rows in the manifested table. Work in progress.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | view-optimization
Files: files | file ages | folders
SHA1:cabf218716e3ba584dc27781ba5e2f9f00eab74c
User & Date: drh 2015-06-08 22:59:36
Context
2015-06-10
17:20
Resolve FROM-clause subqueries after query planning instead of before. Greatly reduce the estimated cost of automatic indexes for VIEWs and ephemeral tables since performance problems there cannot be mitigated via a CREATE INDEX. check-in: a1eaf171 user: drh tags: view-optimization
2015-06-08
22:59
Code refactoring to try to shift FROM-clause subquery manifesting until after the query planner runs. Except this does not currently work because the query planner needs an estimated of the number of rows in the manifested table. Work in progress. check-in: cabf2187 user: drh tags: view-optimization
15:08
Factor out the TreeView parse tree printing module into a separate file. check-in: c32ce54c user: drh tags: view-optimization
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/delete.c.

   393    393         addrEphOpen = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iEphCur, nPk);
   394    394         sqlite3VdbeSetP4KeyInfo(pParse, pPk);
   395    395       }
   396    396     
   397    397       /* Construct a query to find the rowid or primary key for every row
   398    398       ** to be deleted, based on the WHERE clause.
   399    399       */
   400         -    pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, 
          400  +    pWInfo = sqlite3WhereBegin(pParse, 0, pTabList, pWhere, 0, 0, 
   401    401                                  WHERE_ONEPASS_DESIRED|WHERE_DUPLICATES_OK,
   402    402                                  iTabCur+1);
   403    403       if( pWInfo==0 ) goto delete_from_cleanup;
   404    404       okOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass);
   405    405     
   406    406       /* Keep track of the number of rows to be deleted */
   407    407       if( db->flags & SQLITE_CountRows ){

Changes to src/fkey.c.

   627    627     sNameContext.pSrcList = pSrc;
   628    628     sNameContext.pParse = pParse;
   629    629     sqlite3ResolveExprNames(&sNameContext, pWhere);
   630    630   
   631    631     /* Create VDBE to loop through the entries in pSrc that match the WHERE
   632    632     ** clause. For each row found, increment either the deferred or immediate
   633    633     ** foreign key constraint counter. */
   634         -  pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0);
          634  +  pWInfo = sqlite3WhereBegin(pParse, 0, pSrc, pWhere, 0, 0, 0, 0);
   635    635     sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr);
   636    636     if( pWInfo ){
   637    637       sqlite3WhereEnd(pWInfo);
   638    638     }
   639    639   
   640    640     /* Clean up the WHERE clause constructed above. */
   641    641     sqlite3ExprDelete(db, pWhere);

Changes to src/select.c.

  3784   3784         pSubq = pSubq->pPrior;
  3785   3785       }
  3786   3786     }
  3787   3787     return nChng;
  3788   3788   }
  3789   3789   #endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
  3790   3790   
         3791  +/*
         3792  +** Generate code for all sub-queries in the FROM clause
         3793  +*/
         3794  +#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
         3795  +void sqlite3ManifestSubqueries(
         3796  +  Parse *pParse,         /* Parsing context */
         3797  +  Select *p,             /* SELECT statement being generated */
         3798  +  SrcList *pTabList      /* The FROM clause */
         3799  +){
         3800  +  int i;
         3801  +  sqlite3 *db = pParse->db;
         3802  +  Vdbe *v = pParse->pVdbe;
         3803  +  for(i=0; i<pTabList->nSrc; i++){
         3804  +    struct SrcList_item *pItem = &pTabList->a[i];
         3805  +    SelectDest dest;
         3806  +    Select *pSub = pItem->pSelect;
         3807  +    if( pSub==0 ) continue;
         3808  +
         3809  +    /* Sometimes the code for a subquery will be generated more than
         3810  +    ** once, if the subquery is part of the WHERE clause in a LEFT JOIN,
         3811  +    ** for example.  In that case, do not regenerate the code to manifest
         3812  +    ** a view or the co-routine to implement a view.  The first instance
         3813  +    ** is sufficient, though the subroutine to manifest the view does need
         3814  +    ** to be invoked again. */
         3815  +    if( pItem->addrFillSub ){
         3816  +      if( pItem->viaCoroutine==0 ){
         3817  +        sqlite3VdbeAddOp2(v, OP_Gosub, pItem->regReturn, pItem->addrFillSub);
         3818  +      }
         3819  +      continue;
         3820  +    }
         3821  +
         3822  +    /* Increment Parse.nHeight by the height of the largest expression
         3823  +    ** tree referred to by this, the parent select. The child select
         3824  +    ** may contain expression trees of at most
         3825  +    ** (SQLITE_MAX_EXPR_DEPTH-Parse.nHeight) height. This is a bit
         3826  +    ** more conservative than necessary, but much easier than enforcing
         3827  +    ** an exact limit.
         3828  +    */
         3829  +    pParse->nHeight += sqlite3SelectExprHeight(p);
         3830  +
         3831  +    /* Make copies of constant WHERE-clause terms in the outer query down
         3832  +    ** inside the subquery.  This can help the subquery to run more efficiently.
         3833  +    */
         3834  +    if( (pItem->jointype & JT_OUTER)==0
         3835  +     && pushDownWhereTerms(db, pSub, p->pWhere, pItem->iCursor)
         3836  +    ){
         3837  +#if SELECTTRACE_ENABLED
         3838  +      if( sqlite3SelectTrace & 0x100 ){
         3839  +        SELECTTRACE(0x100,pParse,p,("After WHERE-clause push-down:\n"));
         3840  +        sqlite3TreeViewSelect(0, p, 0);
         3841  +      }
         3842  +#endif
         3843  +    }
         3844  +
         3845  +    /* Generate code to implement the subquery
         3846  +    */
         3847  +    if( pTabList->nSrc==1
         3848  +     && (p->selFlags & SF_All)==0
         3849  +     && OptimizationEnabled(db, SQLITE_SubqCoroutine)
         3850  +    ){
         3851  +      /* Implement a co-routine that will return a single row of the result
         3852  +      ** set on each invocation.
         3853  +      */
         3854  +      int addrTop = sqlite3VdbeCurrentAddr(v)+1;
         3855  +      pItem->regReturn = ++pParse->nMem;
         3856  +      sqlite3VdbeAddOp3(v, OP_InitCoroutine, pItem->regReturn, 0, addrTop);
         3857  +      VdbeComment((v, "%s", pItem->pTab->zName));
         3858  +      pItem->addrFillSub = addrTop;
         3859  +      sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn);
         3860  +      explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
         3861  +      sqlite3Select(pParse, pSub, &dest);
         3862  +      pItem->pTab->nRowLogEst = sqlite3LogEst(pSub->nSelectRow);
         3863  +      pItem->viaCoroutine = 1;
         3864  +      pItem->regResult = dest.iSdst;
         3865  +      sqlite3VdbeAddOp1(v, OP_EndCoroutine, pItem->regReturn);
         3866  +      sqlite3VdbeJumpHere(v, addrTop-1);
         3867  +      sqlite3ClearTempRegCache(pParse);
         3868  +    }else{
         3869  +      /* Generate a subroutine that will fill an ephemeral table with
         3870  +      ** the content of this subquery.  pItem->addrFillSub will point
         3871  +      ** to the address of the generated subroutine.  pItem->regReturn
         3872  +      ** is a register allocated to hold the subroutine return address
         3873  +      */
         3874  +      int topAddr;
         3875  +      int onceAddr = 0;
         3876  +      int retAddr;
         3877  +      assert( pItem->addrFillSub==0 );
         3878  +      pItem->regReturn = ++pParse->nMem;
         3879  +      topAddr = sqlite3VdbeAddOp2(v, OP_Integer, 0, pItem->regReturn);
         3880  +      pItem->addrFillSub = topAddr+1;
         3881  +      if( pItem->isCorrelated==0 ){
         3882  +        /* If the subquery is not correlated and if we are not inside of
         3883  +        ** a trigger, then we only need to compute the value of the subquery
         3884  +        ** once. */
         3885  +        onceAddr = sqlite3CodeOnce(pParse); VdbeCoverage(v);
         3886  +        VdbeComment((v, "materialize \"%s\"", pItem->pTab->zName));
         3887  +      }else{
         3888  +        VdbeNoopComment((v, "materialize \"%s\"", pItem->pTab->zName));
         3889  +      }
         3890  +      sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
         3891  +      explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
         3892  +      sqlite3Select(pParse, pSub, &dest);
         3893  +      pItem->pTab->nRowLogEst = sqlite3LogEst(pSub->nSelectRow);
         3894  +      if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr);
         3895  +      retAddr = sqlite3VdbeAddOp1(v, OP_Return, pItem->regReturn);
         3896  +      VdbeComment((v, "end %s", pItem->pTab->zName));
         3897  +      sqlite3VdbeChangeP1(v, topAddr, retAddr);
         3898  +      sqlite3ClearTempRegCache(pParse);
         3899  +    }
         3900  +    if( db->mallocFailed ) break;
         3901  +    pParse->nHeight -= sqlite3SelectExprHeight(p);
         3902  +  }
         3903  +}
         3904  +#endif
         3905  +
  3791   3906   /*
  3792   3907   ** Based on the contents of the AggInfo structure indicated by the first
  3793   3908   ** argument, this function checks if the following are true:
  3794   3909   **
  3795   3910   **    * the query contains just a single aggregate function,
  3796   3911   **    * the aggregate function is either min() or max(), and
  3797   3912   **    * the argument to the aggregate function is a column value.
................................................................................
  4880   4995       SELECTTRACE(1,pParse,p,("end compound-select processing\n"));
  4881   4996       pParse->nSelectIndent--;
  4882   4997   #endif
  4883   4998       return rc;
  4884   4999     }
  4885   5000   #endif
  4886   5001   
  4887         -  /* Generate code for all sub-queries in the FROM clause
  4888         -  */
  4889         -#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
  4890         -  for(i=0; i<pTabList->nSrc; i++){
  4891         -    struct SrcList_item *pItem = &pTabList->a[i];
  4892         -    SelectDest dest;
  4893         -    Select *pSub = pItem->pSelect;
  4894         -    if( pSub==0 ) continue;
  4895         -
  4896         -    /* Sometimes the code for a subquery will be generated more than
  4897         -    ** once, if the subquery is part of the WHERE clause in a LEFT JOIN,
  4898         -    ** for example.  In that case, do not regenerate the code to manifest
  4899         -    ** a view or the co-routine to implement a view.  The first instance
  4900         -    ** is sufficient, though the subroutine to manifest the view does need
  4901         -    ** to be invoked again. */
  4902         -    if( pItem->addrFillSub ){
  4903         -      if( pItem->viaCoroutine==0 ){
  4904         -        sqlite3VdbeAddOp2(v, OP_Gosub, pItem->regReturn, pItem->addrFillSub);
  4905         -      }
  4906         -      continue;
  4907         -    }
  4908         -
  4909         -    /* Increment Parse.nHeight by the height of the largest expression
  4910         -    ** tree referred to by this, the parent select. The child select
  4911         -    ** may contain expression trees of at most
  4912         -    ** (SQLITE_MAX_EXPR_DEPTH-Parse.nHeight) height. This is a bit
  4913         -    ** more conservative than necessary, but much easier than enforcing
  4914         -    ** an exact limit.
  4915         -    */
  4916         -    pParse->nHeight += sqlite3SelectExprHeight(p);
  4917         -
  4918         -    /* Make copies of constant WHERE-clause terms in the outer query down
  4919         -    ** inside the subquery.  This can help the subquery to run more efficiently.
  4920         -    */
  4921         -    if( (pItem->jointype & JT_OUTER)==0
  4922         -     && pushDownWhereTerms(db, pSub, p->pWhere, pItem->iCursor)
  4923         -    ){
  4924         -#if SELECTTRACE_ENABLED
  4925         -      if( sqlite3SelectTrace & 0x100 ){
  4926         -        SELECTTRACE(0x100,pParse,p,("After WHERE-clause push-down:\n"));
  4927         -        sqlite3TreeViewSelect(0, p, 0);
  4928         -      }
  4929         -#endif
  4930         -    }
  4931         -
  4932         -    /* Generate code to implement the subquery
  4933         -    */
  4934         -    if( pTabList->nSrc==1
  4935         -     && (p->selFlags & SF_All)==0
  4936         -     && OptimizationEnabled(db, SQLITE_SubqCoroutine)
  4937         -    ){
  4938         -      /* Implement a co-routine that will return a single row of the result
  4939         -      ** set on each invocation.
  4940         -      */
  4941         -      int addrTop = sqlite3VdbeCurrentAddr(v)+1;
  4942         -      pItem->regReturn = ++pParse->nMem;
  4943         -      sqlite3VdbeAddOp3(v, OP_InitCoroutine, pItem->regReturn, 0, addrTop);
  4944         -      VdbeComment((v, "%s", pItem->pTab->zName));
  4945         -      pItem->addrFillSub = addrTop;
  4946         -      sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn);
  4947         -      explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
  4948         -      sqlite3Select(pParse, pSub, &dest);
  4949         -      pItem->pTab->nRowLogEst = sqlite3LogEst(pSub->nSelectRow);
  4950         -      pItem->viaCoroutine = 1;
  4951         -      pItem->regResult = dest.iSdst;
  4952         -      sqlite3VdbeAddOp1(v, OP_EndCoroutine, pItem->regReturn);
  4953         -      sqlite3VdbeJumpHere(v, addrTop-1);
  4954         -      sqlite3ClearTempRegCache(pParse);
  4955         -    }else{
  4956         -      /* Generate a subroutine that will fill an ephemeral table with
  4957         -      ** the content of this subquery.  pItem->addrFillSub will point
  4958         -      ** to the address of the generated subroutine.  pItem->regReturn
  4959         -      ** is a register allocated to hold the subroutine return address
  4960         -      */
  4961         -      int topAddr;
  4962         -      int onceAddr = 0;
  4963         -      int retAddr;
  4964         -      assert( pItem->addrFillSub==0 );
  4965         -      pItem->regReturn = ++pParse->nMem;
  4966         -      topAddr = sqlite3VdbeAddOp2(v, OP_Integer, 0, pItem->regReturn);
  4967         -      pItem->addrFillSub = topAddr+1;
  4968         -      if( pItem->isCorrelated==0 ){
  4969         -        /* If the subquery is not correlated and if we are not inside of
  4970         -        ** a trigger, then we only need to compute the value of the subquery
  4971         -        ** once. */
  4972         -        onceAddr = sqlite3CodeOnce(pParse); VdbeCoverage(v);
  4973         -        VdbeComment((v, "materialize \"%s\"", pItem->pTab->zName));
  4974         -      }else{
  4975         -        VdbeNoopComment((v, "materialize \"%s\"", pItem->pTab->zName));
  4976         -      }
  4977         -      sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
  4978         -      explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
  4979         -      sqlite3Select(pParse, pSub, &dest);
  4980         -      pItem->pTab->nRowLogEst = sqlite3LogEst(pSub->nSelectRow);
  4981         -      if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr);
  4982         -      retAddr = sqlite3VdbeAddOp1(v, OP_Return, pItem->regReturn);
  4983         -      VdbeComment((v, "end %s", pItem->pTab->zName));
  4984         -      sqlite3VdbeChangeP1(v, topAddr, retAddr);
  4985         -      sqlite3ClearTempRegCache(pParse);
  4986         -    }
  4987         -    if( db->mallocFailed ) goto select_end;
  4988         -    pParse->nHeight -= sqlite3SelectExprHeight(p);
  4989         -  }
         5002  +#if 1
         5003  +  /* Manifest the subqueries.  This needs to be done before calling
         5004  +  ** sqlite3WhereBegin() so that the Table.nRowLogEst value can be set
         5005  +  ** correctly for the subqueries. */
         5006  +  sqlite3ManifestSubqueries(pParse, p, pTabList);
         5007  +  if( db->mallocFailed ) goto select_end;
  4990   5008   #endif
  4991   5009   
  4992   5010     /* Various elements of the SELECT copied into local variables for
  4993   5011     ** convenience */
  4994   5012     pEList = p->pEList;
  4995   5013     pWhere = p->pWhere;
  4996   5014     pGroupBy = p->pGroupBy;
................................................................................
  5082   5100     }
  5083   5101   
  5084   5102     if( !isAgg && pGroupBy==0 ){
  5085   5103       /* No aggregate functions and no GROUP BY clause */
  5086   5104       u16 wctrlFlags = (sDistinct.isTnct ? WHERE_WANT_DISTINCT : 0);
  5087   5105   
  5088   5106       /* Begin the database scan. */
  5089         -    pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, sSort.pOrderBy,
         5107  +    pWInfo = sqlite3WhereBegin(pParse, p, pTabList, pWhere, sSort.pOrderBy,
  5090   5108                                  p->pEList, wctrlFlags, 0);
  5091   5109       if( pWInfo==0 ) goto select_end;
  5092   5110       if( sqlite3WhereOutputRowCount(pWInfo) < p->nSelectRow ){
  5093   5111         p->nSelectRow = sqlite3WhereOutputRowCount(pWInfo);
  5094   5112       }
  5095   5113       if( sDistinct.isTnct && sqlite3WhereIsDistinct(pWInfo) ){
  5096   5114         sDistinct.eTnctType = sqlite3WhereIsDistinct(pWInfo);
................................................................................
  5238   5256   
  5239   5257         /* Begin a loop that will extract all source rows in GROUP BY order.
  5240   5258         ** This might involve two separate loops with an OP_Sort in between, or
  5241   5259         ** it might be a single loop that uses an index to extract information
  5242   5260         ** in the right order to begin with.
  5243   5261         */
  5244   5262         sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
  5245         -      pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pGroupBy, 0,
         5263  +      pWInfo = sqlite3WhereBegin(pParse, p, pTabList, pWhere, pGroupBy, 0,
  5246   5264             WHERE_GROUPBY | (orderByGrp ? WHERE_SORTBYGROUP : 0), 0
  5247   5265         );
  5248   5266         if( pWInfo==0 ) goto select_end;
  5249   5267         if( sqlite3WhereIsOrdered(pWInfo)==pGroupBy->nExpr ){
  5250   5268           /* The optimizer is able to deliver rows in group by order so
  5251   5269           ** we do not have to sort.  The OP_OpenEphemeral table will be
  5252   5270           ** cancelled later because we still need to use the pKeyInfo
................................................................................
  5533   5551           }
  5534   5552     
  5535   5553           /* This case runs if the aggregate has no GROUP BY clause.  The
  5536   5554           ** processing is much simpler since there is only a single row
  5537   5555           ** of output.
  5538   5556           */
  5539   5557           resetAccumulator(pParse, &sAggInfo);
  5540         -        pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pMinMax,0,flag,0);
         5558  +        pWInfo = sqlite3WhereBegin(pParse,p,pTabList, pWhere, pMinMax,0,flag,0);
  5541   5559           if( pWInfo==0 ){
  5542   5560             sqlite3ExprListDelete(db, pDel);
  5543   5561             goto select_end;
  5544   5562           }
  5545   5563           updateAccumulator(pParse, &sAggInfo);
  5546   5564           assert( pMinMax==0 || pMinMax->nExpr==1 );
  5547   5565           if( sqlite3WhereIsOrdered(pWInfo)>0 ){

Changes to src/sqliteInt.h.

  3281   3281   void sqlite3SrcListAssignCursors(Parse*, SrcList*);
  3282   3282   void sqlite3IdListDelete(sqlite3*, IdList*);
  3283   3283   void sqlite3SrcListDelete(sqlite3*, SrcList*);
  3284   3284   Index *sqlite3AllocateIndexObject(sqlite3*,i16,int,char**);
  3285   3285   Index *sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*,
  3286   3286                             Expr*, int, int);
  3287   3287   void sqlite3DropIndex(Parse*, SrcList*, int);
         3288  +void sqlite3ManifestSubqueries(Parse*, Select*, SrcList*);
  3288   3289   int sqlite3Select(Parse*, Select*, SelectDest*);
  3289   3290   Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*,
  3290   3291                            Expr*,ExprList*,u16,Expr*,Expr*);
  3291   3292   void sqlite3SelectDelete(sqlite3*, Select*);
  3292   3293   Table *sqlite3SrcListLookup(Parse*, SrcList*);
  3293   3294   int sqlite3IsReadOnly(Parse*, Table*, int);
  3294   3295   void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int);
  3295   3296   #if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
  3296   3297   Expr *sqlite3LimitWhere(Parse*,SrcList*,Expr*,ExprList*,Expr*,Expr*,char*);
  3297   3298   #endif
  3298   3299   void sqlite3DeleteFrom(Parse*, SrcList*, Expr*);
  3299   3300   void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
  3300         -WhereInfo *sqlite3WhereBegin(Parse*,SrcList*,Expr*,ExprList*,ExprList*,u16,int);
         3301  +WhereInfo *sqlite3WhereBegin(Parse*,Select*,SrcList*,Expr*,ExprList*,
         3302  +                             ExprList*,u16,int);
  3301   3303   void sqlite3WhereEnd(WhereInfo*);
  3302   3304   u64 sqlite3WhereOutputRowCount(WhereInfo*);
  3303   3305   int sqlite3WhereIsDistinct(WhereInfo*);
  3304   3306   int sqlite3WhereIsOrdered(WhereInfo*);
  3305   3307   int sqlite3WhereIsSorted(WhereInfo*);
  3306   3308   int sqlite3WhereContinueLabel(WhereInfo*);
  3307   3309   int sqlite3WhereBreakLabel(WhereInfo*);

Changes to src/update.c.

   343    343     }
   344    344   
   345    345     /* Begin the database scan
   346    346     */
   347    347     if( HasRowid(pTab) ){
   348    348       sqlite3VdbeAddOp3(v, OP_Null, 0, regRowSet, regOldRowid);
   349    349       pWInfo = sqlite3WhereBegin(
   350         -        pParse, pTabList, pWhere, 0, 0, WHERE_ONEPASS_DESIRED, iIdxCur
          350  +        pParse, 0, pTabList, pWhere, 0, 0, WHERE_ONEPASS_DESIRED, iIdxCur
   351    351       );
   352    352       if( pWInfo==0 ) goto update_cleanup;
   353    353       okOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass);
   354    354     
   355    355       /* Remember the rowid of every item to be updated.
   356    356       */
   357    357       sqlite3VdbeAddOp2(v, OP_Rowid, iDataCur, regOldRowid);
................................................................................
   372    372       iPk = pParse->nMem+1;
   373    373       pParse->nMem += nPk;
   374    374       regKey = ++pParse->nMem;
   375    375       iEph = pParse->nTab++;
   376    376       sqlite3VdbeAddOp2(v, OP_Null, 0, iPk);
   377    377       addrOpen = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iEph, nPk);
   378    378       sqlite3VdbeSetP4KeyInfo(pParse, pPk);
   379         -    pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, 
          379  +    pWInfo = sqlite3WhereBegin(pParse, 0, pTabList, pWhere, 0, 0, 
   380    380                                  WHERE_ONEPASS_DESIRED, iIdxCur);
   381    381       if( pWInfo==0 ) goto update_cleanup;
   382    382       okOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass);
   383    383       for(i=0; i<nPk; i++){
   384    384         sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, pPk->aiColumn[i],
   385    385                                         iPk+i);
   386    386       }

Changes to src/where.c.

  3852   3852   ** specific cursor.  If WHERE_ONEPASS_DESIRED is set, then iIdxCur is
  3853   3853   ** the first cursor in an array of cursors for all indices.  iIdxCur should
  3854   3854   ** be used to compute the appropriate cursor depending on which index is
  3855   3855   ** used.
  3856   3856   */
  3857   3857   WhereInfo *sqlite3WhereBegin(
  3858   3858     Parse *pParse,        /* The parser context */
         3859  +  Select *pSelect,      /* SELECT stmt that owns this WHERE. Might be NULL */
  3859   3860     SrcList *pTabList,    /* FROM clause: A list of all tables to be scanned */
  3860   3861     Expr *pWhere,         /* The WHERE clause */
  3861   3862     ExprList *pOrderBy,   /* An ORDER BY (or GROUP BY) clause, or NULL */
  3862   3863     ExprList *pResultSet, /* Result set of the query */
  3863   3864     u16 wctrlFlags,       /* One of the WHERE_* flags defined in sqliteInt.h */
  3864   3865     int iIdxCur           /* If WHERE_ONETABLE_ONLY is set, index cursor number */
  3865   3866   ){
................................................................................
  4126   4127      && (pWInfo->a[0].pWLoop->wsFlags & WHERE_ONEROW)!=0 ){
  4127   4128       pWInfo->okOnePass = 1;
  4128   4129       if( HasRowid(pTabList->a[0].pTab) ){
  4129   4130         pWInfo->a[0].pWLoop->wsFlags &= ~WHERE_IDX_ONLY;
  4130   4131       }
  4131   4132     }
  4132   4133   
         4134  +#if 0
         4135  +  /* If this WHERE clause is part of a SELECT statement, then there
         4136  +  ** might be subqueries in the FROM clause that need to be manifested.
         4137  +  ** This works mostly - except the Table.nRowLogEst value is not set
         4138  +  ** correctly for the subquery, resulting in a bad plan in some cases.
         4139  +  */
         4140  +  if( pSelect!=0 ){
         4141  +    sqlite3ManifestSubqueries(pParse, pSelect, pTabList);
         4142  +    if( db->mallocFailed ) goto whereBeginError;
         4143  +  }
         4144  +#endif
         4145  +
  4133   4146     /* Open all tables in the pTabList and any indices selected for
  4134   4147     ** searching those tables.
  4135   4148     */
  4136   4149     for(ii=0, pLevel=pWInfo->a; ii<nTabList; ii++, pLevel++){
  4137   4150       Table *pTab;     /* Table to open */
  4138   4151       int iDb;         /* Index of database containing table/index */
  4139   4152       struct SrcList_item *pTabItem;

Changes to src/wherecode.c.

  1261   1261           int j1 = 0;                     /* Address of jump operation */
  1262   1262           if( pAndExpr && !ExprHasProperty(pOrExpr, EP_FromJoin) ){
  1263   1263             pAndExpr->pLeft = pOrExpr;
  1264   1264             pOrExpr = pAndExpr;
  1265   1265           }
  1266   1266           /* Loop through table entries that match term pOrTerm. */
  1267   1267           WHERETRACE(0xffff, ("Subplan for OR-clause:\n"));
  1268         -        pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrExpr, 0, 0,
         1268  +        pSubWInfo = sqlite3WhereBegin(pParse, 0, pOrTab, pOrExpr, 0, 0,
  1269   1269                                         wctrlFlags, iCovCur);
  1270   1270           assert( pSubWInfo || pParse->nErr || db->mallocFailed );
  1271   1271           if( pSubWInfo ){
  1272   1272             WhereLoop *pSubLoop;
  1273   1273             int addrExplain = sqlite3WhereExplainOneScan(
  1274   1274                 pParse, pOrTab, &pSubWInfo->a[0], iLevel, pLevel->iFrom, 0
  1275   1275             );