]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Code refactoring to try to shift FROM-clause subquery manifesting until after
authordrh <drh@noemail.net>
Mon, 8 Jun 2015 22:59:36 +0000 (22:59 +0000)
committerdrh <drh@noemail.net>
Mon, 8 Jun 2015 22:59:36 +0000 (22:59 +0000)
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.

FossilOrigin-Name: cabf218716e3ba584dc27781ba5e2f9f00eab74c

manifest
manifest.uuid
src/delete.c
src/fkey.c
src/select.c
src/sqliteInt.h
src/update.c
src/where.c
src/wherecode.c

index 2ac088fd87c377f44fc846346d759c829e2abbaa..0a7d0cc0a263c75985b45a723a0f7f40bceaf530 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Factor\sout\sthe\sTreeView\sparse\stree\sprinting\smodule\sinto\sa\sseparate\sfile.
-D 2015-06-08T15:08:15.270
+C Code\srefactoring\sto\stry\sto\sshift\sFROM-clause\ssubquery\smanifesting\suntil\safter\nthe\squery\splanner\sruns.\s\sExcept\sthis\sdoes\snot\scurrently\swork\sbecause\sthe\nquery\splanner\sneeds\san\sestimated\sof\sthe\snumber\sof\srows\sin\sthe\smanifested\stable.\nWork\sin\sprogress.
+D 2015-06-08T22:59:36.625
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in a7b384855b72378fd860425b128ea5f75296e9d6
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -201,10 +201,10 @@ F src/complete.c a5cf5b4b56390cfb7b8636e8f7ddef90258dd575
 F src/ctime.c 5a0b735dc95604766f5dac73973658eef782ee8b
 F src/date.c e4d50b3283696836ec1036b695ead9a19e37a5ac
 F src/dbstat.c f402e77e25089c6003d0c60b3233b9b3947d599a
-F src/delete.c 37964e6c1d73ff49cbea9ff690c9605fb15f600e
+F src/delete.c 5cfc68ff81ad92d8bf22ba92f7a9398c7f1d5eb9
 F src/expr.c 0550baeca8dd7472e298d9e881e5e3484f7666f8
 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
-F src/fkey.c c9b63a217d86582c22121699a47f22f524608869
+F src/fkey.c 6c5a2dbf8333303b033a2219e18ce8a9f99981c2
 F src/func.c 5b8b8e77a0fb644eaf8947d413804622e32692b6
 F src/global.c 4f77cadbc5427d00139ba43d0f3979804cbb700e
 F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5
@@ -250,12 +250,12 @@ F src/printf.c 9889e8826f8e2bd8c2718d7d3faa761bef8eac79
 F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
 F src/resolve.c 84c571794e3ee5806274d95158a4c0177c6c4708
 F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
-F src/select.c 45a814a755f90c1a6345164d2da4a8ef293da53d
+F src/select.c 8fd2ea1047ded30900e1aa9d4001c523f4e9c2d0
 F src/shell.c 07dda7cd692911d2f22269953418d049f2e2c0ee
 F src/sqlite.h.in d165beeceb6b40af60f352a4d4e37e02d9af7df0
 F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
 F src/sqlite3ext.h 2ebeb634e751a61a6f0eebfa0f4669f46a42f6cd
-F src/sqliteInt.h 4c6731ce49b90582ea7d77c67b8792a4df8da237
+F src/sqliteInt.h 4cc3db36afb302a29017c44017287c44555245e5
 F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46
 F src/status.c f266ad8a2892d659b74f0f50cb6a88b6e7c12179
 F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e
@@ -309,7 +309,7 @@ F src/threads.c 6bbcc9fe50c917864d48287b4792d46d6e873481
 F src/tokenize.c baa0e550dfa76a8d781732a7bfb1f0aa094942f2
 F src/treeview.c 84aa2d2ed26627ccc8dd3a2becfa18dc86ee4607
 F src/trigger.c 322f23aad694e8f31d384dcfa386d52a48d3c52f
-F src/update.c 487747b328b7216bb7f6af0695d6937d5c9e605f
+F src/update.c 831a657bcfffcb44b25f3551909efcf4977e57c5
 F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c
 F src/util.c a6431c92803b975b7322724a7b433e538d243539
 F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701
@@ -327,9 +327,9 @@ F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb
 F src/wal.c ce2cb2d06faab54d1bce3e739bec79e063dd9113
 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
 F src/walker.c c253b95b4ee44b21c406e2a1052636c31ea27804
-F src/where.c a328fcc3342044992644b6a11bf301593b8dafb4
+F src/where.c fbd93e7654f9a30ca90a469aefa03f844c590cbf
 F src/whereInt.h 5f87e3c4b0551747d119730dfebddd3c54f04047
-F src/wherecode.c 0669481cabaf5caf934b6bb825df15bc57f60d40
+F src/wherecode.c 3f3152ecf4224413bd0491ea4210883b85fe95d1
 F src/whereexpr.c 9ce1c9cfedbf80c93c7d899497025ec8256ce652
 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
 F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
@@ -1285,7 +1285,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P 46ef95c108ad8961f2bf3d2dc839d4fb1fddd770
-R b8b4fb0f1a8beaad9f2b2c3f4237ea7b
+P c32ce54ca46a4be4373983be6fd44b1f3a0250d1
+R 70ebd883d8f71adfaf92b60144faee89
 U drh
-Z 10e8e7d0fa9ce8baee6c4a1498d642ba
+Z 866fe9a880b0b7241026d0fd41ef95df
index 28f125a126d986ad8bd5d4d67e38586daa99546d..963e9dd99528c195a9d2a1bf16d5c577913ef254 100644 (file)
@@ -1 +1 @@
-c32ce54ca46a4be4373983be6fd44b1f3a0250d1
\ No newline at end of file
+cabf218716e3ba584dc27781ba5e2f9f00eab74c
\ No newline at end of file
index ef6aace1c822b3a890dbb057bf98ff24c50430d6..4377b73110bd297475f3b07ca0920f0e4d226f0f 100644 (file)
@@ -397,7 +397,7 @@ void sqlite3DeleteFrom(
     /* Construct a query to find the rowid or primary key for every row
     ** to be deleted, based on the WHERE clause.
     */
-    pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, 
+    pWInfo = sqlite3WhereBegin(pParse, 0, pTabList, pWhere, 0, 0, 
                                WHERE_ONEPASS_DESIRED|WHERE_DUPLICATES_OK,
                                iTabCur+1);
     if( pWInfo==0 ) goto delete_from_cleanup;
index 09513e4620b8f89f8b2f7da0c716620f7e36eb27..5f00b4457cc7f0b4822e94add3ae6637525f1c25 100644 (file)
@@ -631,7 +631,7 @@ static void fkScanChildren(
   /* Create VDBE to loop through the entries in pSrc that match the WHERE
   ** clause. For each row found, increment either the deferred or immediate
   ** foreign key constraint counter. */
-  pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0);
+  pWInfo = sqlite3WhereBegin(pParse, 0, pSrc, pWhere, 0, 0, 0, 0);
   sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr);
   if( pWInfo ){
     sqlite3WhereEnd(pWInfo);
index f030d2f4a441d911e2f6ff8a153ac367737ee5bd..03d4161e766ee84799748fb5ea7ebb9e65977ea6 100644 (file)
@@ -3788,6 +3788,121 @@ static int pushDownWhereTerms(
 }
 #endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
 
+/*
+** Generate code for all sub-queries in the FROM clause
+*/
+#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
+void sqlite3ManifestSubqueries(
+  Parse *pParse,         /* Parsing context */
+  Select *p,             /* SELECT statement being generated */
+  SrcList *pTabList      /* The FROM clause */
+){
+  int i;
+  sqlite3 *db = pParse->db;
+  Vdbe *v = pParse->pVdbe;
+  for(i=0; i<pTabList->nSrc; i++){
+    struct SrcList_item *pItem = &pTabList->a[i];
+    SelectDest dest;
+    Select *pSub = pItem->pSelect;
+    if( pSub==0 ) continue;
+
+    /* Sometimes the code for a subquery will be generated more than
+    ** once, if the subquery is part of the WHERE clause in a LEFT JOIN,
+    ** for example.  In that case, do not regenerate the code to manifest
+    ** a view or the co-routine to implement a view.  The first instance
+    ** is sufficient, though the subroutine to manifest the view does need
+    ** to be invoked again. */
+    if( pItem->addrFillSub ){
+      if( pItem->viaCoroutine==0 ){
+        sqlite3VdbeAddOp2(v, OP_Gosub, pItem->regReturn, pItem->addrFillSub);
+      }
+      continue;
+    }
+
+    /* Increment Parse.nHeight by the height of the largest expression
+    ** tree referred to by this, the parent select. The child select
+    ** may contain expression trees of at most
+    ** (SQLITE_MAX_EXPR_DEPTH-Parse.nHeight) height. This is a bit
+    ** more conservative than necessary, but much easier than enforcing
+    ** an exact limit.
+    */
+    pParse->nHeight += sqlite3SelectExprHeight(p);
+
+    /* Make copies of constant WHERE-clause terms in the outer query down
+    ** inside the subquery.  This can help the subquery to run more efficiently.
+    */
+    if( (pItem->jointype & JT_OUTER)==0
+     && pushDownWhereTerms(db, pSub, p->pWhere, pItem->iCursor)
+    ){
+#if SELECTTRACE_ENABLED
+      if( sqlite3SelectTrace & 0x100 ){
+        SELECTTRACE(0x100,pParse,p,("After WHERE-clause push-down:\n"));
+        sqlite3TreeViewSelect(0, p, 0);
+      }
+#endif
+    }
+
+    /* Generate code to implement the subquery
+    */
+    if( pTabList->nSrc==1
+     && (p->selFlags & SF_All)==0
+     && OptimizationEnabled(db, SQLITE_SubqCoroutine)
+    ){
+      /* Implement a co-routine that will return a single row of the result
+      ** set on each invocation.
+      */
+      int addrTop = sqlite3VdbeCurrentAddr(v)+1;
+      pItem->regReturn = ++pParse->nMem;
+      sqlite3VdbeAddOp3(v, OP_InitCoroutine, pItem->regReturn, 0, addrTop);
+      VdbeComment((v, "%s", pItem->pTab->zName));
+      pItem->addrFillSub = addrTop;
+      sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn);
+      explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
+      sqlite3Select(pParse, pSub, &dest);
+      pItem->pTab->nRowLogEst = sqlite3LogEst(pSub->nSelectRow);
+      pItem->viaCoroutine = 1;
+      pItem->regResult = dest.iSdst;
+      sqlite3VdbeAddOp1(v, OP_EndCoroutine, pItem->regReturn);
+      sqlite3VdbeJumpHere(v, addrTop-1);
+      sqlite3ClearTempRegCache(pParse);
+    }else{
+      /* Generate a subroutine that will fill an ephemeral table with
+      ** the content of this subquery.  pItem->addrFillSub will point
+      ** to the address of the generated subroutine.  pItem->regReturn
+      ** is a register allocated to hold the subroutine return address
+      */
+      int topAddr;
+      int onceAddr = 0;
+      int retAddr;
+      assert( pItem->addrFillSub==0 );
+      pItem->regReturn = ++pParse->nMem;
+      topAddr = sqlite3VdbeAddOp2(v, OP_Integer, 0, pItem->regReturn);
+      pItem->addrFillSub = topAddr+1;
+      if( pItem->isCorrelated==0 ){
+        /* If the subquery is not correlated and if we are not inside of
+        ** a trigger, then we only need to compute the value of the subquery
+        ** once. */
+        onceAddr = sqlite3CodeOnce(pParse); VdbeCoverage(v);
+        VdbeComment((v, "materialize \"%s\"", pItem->pTab->zName));
+      }else{
+        VdbeNoopComment((v, "materialize \"%s\"", pItem->pTab->zName));
+      }
+      sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
+      explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
+      sqlite3Select(pParse, pSub, &dest);
+      pItem->pTab->nRowLogEst = sqlite3LogEst(pSub->nSelectRow);
+      if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr);
+      retAddr = sqlite3VdbeAddOp1(v, OP_Return, pItem->regReturn);
+      VdbeComment((v, "end %s", pItem->pTab->zName));
+      sqlite3VdbeChangeP1(v, topAddr, retAddr);
+      sqlite3ClearTempRegCache(pParse);
+    }
+    if( db->mallocFailed ) break;
+    pParse->nHeight -= sqlite3SelectExprHeight(p);
+  }
+}
+#endif
+
 /*
 ** Based on the contents of the AggInfo structure indicated by the first
 ** argument, this function checks if the following are true:
@@ -4884,109 +4999,12 @@ int sqlite3Select(
   }
 #endif
 
-  /* Generate code for all sub-queries in the FROM clause
-  */
-#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
-  for(i=0; i<pTabList->nSrc; i++){
-    struct SrcList_item *pItem = &pTabList->a[i];
-    SelectDest dest;
-    Select *pSub = pItem->pSelect;
-    if( pSub==0 ) continue;
-
-    /* Sometimes the code for a subquery will be generated more than
-    ** once, if the subquery is part of the WHERE clause in a LEFT JOIN,
-    ** for example.  In that case, do not regenerate the code to manifest
-    ** a view or the co-routine to implement a view.  The first instance
-    ** is sufficient, though the subroutine to manifest the view does need
-    ** to be invoked again. */
-    if( pItem->addrFillSub ){
-      if( pItem->viaCoroutine==0 ){
-        sqlite3VdbeAddOp2(v, OP_Gosub, pItem->regReturn, pItem->addrFillSub);
-      }
-      continue;
-    }
-
-    /* Increment Parse.nHeight by the height of the largest expression
-    ** tree referred to by this, the parent select. The child select
-    ** may contain expression trees of at most
-    ** (SQLITE_MAX_EXPR_DEPTH-Parse.nHeight) height. This is a bit
-    ** more conservative than necessary, but much easier than enforcing
-    ** an exact limit.
-    */
-    pParse->nHeight += sqlite3SelectExprHeight(p);
-
-    /* Make copies of constant WHERE-clause terms in the outer query down
-    ** inside the subquery.  This can help the subquery to run more efficiently.
-    */
-    if( (pItem->jointype & JT_OUTER)==0
-     && pushDownWhereTerms(db, pSub, p->pWhere, pItem->iCursor)
-    ){
-#if SELECTTRACE_ENABLED
-      if( sqlite3SelectTrace & 0x100 ){
-        SELECTTRACE(0x100,pParse,p,("After WHERE-clause push-down:\n"));
-        sqlite3TreeViewSelect(0, p, 0);
-      }
-#endif
-    }
-
-    /* Generate code to implement the subquery
-    */
-    if( pTabList->nSrc==1
-     && (p->selFlags & SF_All)==0
-     && OptimizationEnabled(db, SQLITE_SubqCoroutine)
-    ){
-      /* Implement a co-routine that will return a single row of the result
-      ** set on each invocation.
-      */
-      int addrTop = sqlite3VdbeCurrentAddr(v)+1;
-      pItem->regReturn = ++pParse->nMem;
-      sqlite3VdbeAddOp3(v, OP_InitCoroutine, pItem->regReturn, 0, addrTop);
-      VdbeComment((v, "%s", pItem->pTab->zName));
-      pItem->addrFillSub = addrTop;
-      sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn);
-      explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
-      sqlite3Select(pParse, pSub, &dest);
-      pItem->pTab->nRowLogEst = sqlite3LogEst(pSub->nSelectRow);
-      pItem->viaCoroutine = 1;
-      pItem->regResult = dest.iSdst;
-      sqlite3VdbeAddOp1(v, OP_EndCoroutine, pItem->regReturn);
-      sqlite3VdbeJumpHere(v, addrTop-1);
-      sqlite3ClearTempRegCache(pParse);
-    }else{
-      /* Generate a subroutine that will fill an ephemeral table with
-      ** the content of this subquery.  pItem->addrFillSub will point
-      ** to the address of the generated subroutine.  pItem->regReturn
-      ** is a register allocated to hold the subroutine return address
-      */
-      int topAddr;
-      int onceAddr = 0;
-      int retAddr;
-      assert( pItem->addrFillSub==0 );
-      pItem->regReturn = ++pParse->nMem;
-      topAddr = sqlite3VdbeAddOp2(v, OP_Integer, 0, pItem->regReturn);
-      pItem->addrFillSub = topAddr+1;
-      if( pItem->isCorrelated==0 ){
-        /* If the subquery is not correlated and if we are not inside of
-        ** a trigger, then we only need to compute the value of the subquery
-        ** once. */
-        onceAddr = sqlite3CodeOnce(pParse); VdbeCoverage(v);
-        VdbeComment((v, "materialize \"%s\"", pItem->pTab->zName));
-      }else{
-        VdbeNoopComment((v, "materialize \"%s\"", pItem->pTab->zName));
-      }
-      sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
-      explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
-      sqlite3Select(pParse, pSub, &dest);
-      pItem->pTab->nRowLogEst = sqlite3LogEst(pSub->nSelectRow);
-      if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr);
-      retAddr = sqlite3VdbeAddOp1(v, OP_Return, pItem->regReturn);
-      VdbeComment((v, "end %s", pItem->pTab->zName));
-      sqlite3VdbeChangeP1(v, topAddr, retAddr);
-      sqlite3ClearTempRegCache(pParse);
-    }
-    if( db->mallocFailed ) goto select_end;
-    pParse->nHeight -= sqlite3SelectExprHeight(p);
-  }
+#if 1
+  /* Manifest the subqueries.  This needs to be done before calling
+  ** sqlite3WhereBegin() so that the Table.nRowLogEst value can be set
+  ** correctly for the subqueries. */
+  sqlite3ManifestSubqueries(pParse, p, pTabList);
+  if( db->mallocFailed ) goto select_end;
 #endif
 
   /* Various elements of the SELECT copied into local variables for
@@ -5086,7 +5104,7 @@ int sqlite3Select(
     u16 wctrlFlags = (sDistinct.isTnct ? WHERE_WANT_DISTINCT : 0);
 
     /* Begin the database scan. */
-    pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, sSort.pOrderBy,
+    pWInfo = sqlite3WhereBegin(pParse, p, pTabList, pWhere, sSort.pOrderBy,
                                p->pEList, wctrlFlags, 0);
     if( pWInfo==0 ) goto select_end;
     if( sqlite3WhereOutputRowCount(pWInfo) < p->nSelectRow ){
@@ -5242,7 +5260,7 @@ int sqlite3Select(
       ** in the right order to begin with.
       */
       sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
-      pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pGroupBy, 0,
+      pWInfo = sqlite3WhereBegin(pParse, p, pTabList, pWhere, pGroupBy, 0,
           WHERE_GROUPBY | (orderByGrp ? WHERE_SORTBYGROUP : 0), 0
       );
       if( pWInfo==0 ) goto select_end;
@@ -5537,7 +5555,7 @@ int sqlite3Select(
         ** of output.
         */
         resetAccumulator(pParse, &sAggInfo);
-        pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pMinMax,0,flag,0);
+        pWInfo = sqlite3WhereBegin(pParse,p,pTabList, pWhere, pMinMax,0,flag,0);
         if( pWInfo==0 ){
           sqlite3ExprListDelete(db, pDel);
           goto select_end;
index 43e4b0be9b03799a18dcdaf8d070d634ca2b7eb6..06d859608f92767fcfd9e9dd13d3b648f0839cbe 100644 (file)
@@ -3285,6 +3285,7 @@ Index *sqlite3AllocateIndexObject(sqlite3*,i16,int,char**);
 Index *sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*,
                           Expr*, int, int);
 void sqlite3DropIndex(Parse*, SrcList*, int);
+void sqlite3ManifestSubqueries(Parse*, Select*, SrcList*);
 int sqlite3Select(Parse*, Select*, SelectDest*);
 Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*,
                          Expr*,ExprList*,u16,Expr*,Expr*);
@@ -3297,7 +3298,8 @@ Expr *sqlite3LimitWhere(Parse*,SrcList*,Expr*,ExprList*,Expr*,Expr*,char*);
 #endif
 void sqlite3DeleteFrom(Parse*, SrcList*, Expr*);
 void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
-WhereInfo *sqlite3WhereBegin(Parse*,SrcList*,Expr*,ExprList*,ExprList*,u16,int);
+WhereInfo *sqlite3WhereBegin(Parse*,Select*,SrcList*,Expr*,ExprList*,
+                             ExprList*,u16,int);
 void sqlite3WhereEnd(WhereInfo*);
 u64 sqlite3WhereOutputRowCount(WhereInfo*);
 int sqlite3WhereIsDistinct(WhereInfo*);
index f8347448a17b7b4dffd089cfb07639b619d58264..0b7223b9bbdfbfc991a5835d07e5a8fd049e71f4 100644 (file)
@@ -347,7 +347,7 @@ void sqlite3Update(
   if( HasRowid(pTab) ){
     sqlite3VdbeAddOp3(v, OP_Null, 0, regRowSet, regOldRowid);
     pWInfo = sqlite3WhereBegin(
-        pParse, pTabList, pWhere, 0, 0, WHERE_ONEPASS_DESIRED, iIdxCur
+        pParse, 0, pTabList, pWhere, 0, 0, WHERE_ONEPASS_DESIRED, iIdxCur
     );
     if( pWInfo==0 ) goto update_cleanup;
     okOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass);
@@ -376,7 +376,7 @@ void sqlite3Update(
     sqlite3VdbeAddOp2(v, OP_Null, 0, iPk);
     addrOpen = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iEph, nPk);
     sqlite3VdbeSetP4KeyInfo(pParse, pPk);
-    pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, 
+    pWInfo = sqlite3WhereBegin(pParse, 0, pTabList, pWhere, 0, 0, 
                                WHERE_ONEPASS_DESIRED, iIdxCur);
     if( pWInfo==0 ) goto update_cleanup;
     okOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass);
index 5c5022c9f689878c5e522f1686a6f1ff5372e588..9304e6eef5e426650e703d8fe225ef9053222e95 100644 (file)
@@ -3856,6 +3856,7 @@ static int whereShortCut(WhereLoopBuilder *pBuilder){
 */
 WhereInfo *sqlite3WhereBegin(
   Parse *pParse,        /* The parser context */
+  Select *pSelect,      /* SELECT stmt that owns this WHERE. Might be NULL */
   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 */
@@ -4130,6 +4131,18 @@ WhereInfo *sqlite3WhereBegin(
     }
   }
 
+#if 0
+  /* If this WHERE clause is part of a SELECT statement, then there
+  ** might be subqueries in the FROM clause that need to be manifested.
+  ** This works mostly - except the Table.nRowLogEst value is not set
+  ** correctly for the subquery, resulting in a bad plan in some cases.
+  */
+  if( pSelect!=0 ){
+    sqlite3ManifestSubqueries(pParse, pSelect, pTabList);
+    if( db->mallocFailed ) goto whereBeginError;
+  }
+#endif
+
   /* Open all tables in the pTabList and any indices selected for
   ** searching those tables.
   */
index e1f0f86615f82efdb348e3495eb69c824863991b..800ff937ae39d623becd5d251fa079785bb9c231 100644 (file)
@@ -1265,7 +1265,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
         }
         /* Loop through table entries that match term pOrTerm. */
         WHERETRACE(0xffff, ("Subplan for OR-clause:\n"));
-        pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrExpr, 0, 0,
+        pSubWInfo = sqlite3WhereBegin(pParse, 0, pOrTab, pOrExpr, 0, 0,
                                       wctrlFlags, iCovCur);
         assert( pSubWInfo || pParse->nErr || db->mallocFailed );
         if( pSubWInfo ){