Merge trunk fixes.
FossilOrigin-Name: 1df8cbbea66f303029737752f37cf2a6db98fcd4
diff --git a/manifest b/manifest
index 53cae3d..dde7861 100644
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Remove\sstray\soutputs\sfrom\sthe\stest\ssuite.
-D 2015-06-11T14:19:05.376
+C Merge\strunk\sfixes.
+D 2015-06-11T17:58:27.864
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 1063c58075b7400d93326b0eb332b48a54f53025
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -201,10 +201,10 @@
F src/ctime.c 5a0b735dc95604766f5dac73973658eef782ee8b
F src/date.c e4d50b3283696836ec1036b695ead9a19e37a5ac
F src/dbstat.c f402e77e25089c6003d0c60b3233b9b3947d599a
-F src/delete.c 8857a6f27560718f65d43bdbec86c967ae1f8dfa
+F src/delete.c 81fc0453b0e95275bef8c2091636fcafc7229e91
F src/expr.c 710c764c1974b15a0e56b004ff9f5e6ceab3a854
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/random.c ba2679f80ec82c4190062d756f22d0c358180696
F src/resolve.c 84c571794e3ee5806274d95158a4c0177c6c4708
F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
-F src/select.c 45a814a755f90c1a6345164d2da4a8ef293da53d
+F src/select.c ecd8562e686b968511abbad6d6810fa30fda2952
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 8f095bfe43ba68c32bac8d5349131ffacc660967
+F src/sqliteInt.h e389c788cd9f0af14528dfcddefc9ccece17d385
F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46
F src/status.c f266ad8a2892d659b74f0f50cb6a88b6e7c12179
F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e
@@ -309,7 +309,7 @@
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/wal.c ce2cb2d06faab54d1bce3e739bec79e063dd9113
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
F src/walker.c c253b95b4ee44b21c406e2a1052636c31ea27804
-F src/where.c 95c0fbfff7aef890b5da7293f6d85cd9a5f99af8
+F src/where.c aa26f4b0a3ad9c586f3315cb499d2dc813e14f01
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
@@ -517,7 +517,7 @@
F test/enc2.test 83437a79ba1545a55fb549309175c683fb334473
F test/enc3.test 90683ad0e6ea587b9d5542ca93568af9a9858c40
F test/enc4.test c8f1ce3618508fd0909945beb8b8831feef2c020
-F test/eqp.test 85873fa5816c48915c82c4e74cb5c35a5b48160f
+F test/eqp.test bd139ceea2ebc6ebb01c50f55f7c6f79473af6e5
F test/errmsg.test f31592a594b44ee121371d25ddd5d63497bb3401
F test/eval.test a64c9105d6ff163df7cf09d6ac29cdad5922078c
F test/exclusive.test c7ebbc756eacf544c108b15eed64d7d4e5f86b75
@@ -1286,8 +1286,7 @@
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P e63d01c69c3e50f49ee3022a519c4f3e91f00520 e64a5681793238fa04fe3636f48d34b2dd36cdfa
-R 169aa55aecdac74f95270959f0b49156
-T +closed e64a5681793238fa04fe3636f48d34b2dd36cdfa
+P 0e23a079bd648f9778c857ec51e39acfd30a4040 afc6db9b105f32110112b877f06091757888a5f2
+R 66f6090af762e2af727925054063787e
U drh
-Z 8e453d8625c4e71ab15cead2df245827
+Z 15f99ba3f20685296cbae74ff03f5eca
diff --git a/manifest.uuid b/manifest.uuid
index 9c8de4c..98f9c75 100644
--- a/manifest.uuid
+++ b/manifest.uuid
@@ -1 +1 @@
-afc6db9b105f32110112b877f06091757888a5f2
\ No newline at end of file
+1df8cbbea66f303029737752f37cf2a6db98fcd4
\ No newline at end of file
diff --git a/src/delete.c b/src/delete.c
index 369cdaf..763c436 100644
--- a/src/delete.c
+++ b/src/delete.c
@@ -397,7 +397,7 @@
/* 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;
diff --git a/src/fkey.c b/src/fkey.c
index 09513e4..5f00b44 100644
--- a/src/fkey.c
+++ b/src/fkey.c
@@ -631,7 +631,7 @@
/* 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);
diff --git a/src/select.c b/src/select.c
index f030d2f..b0f2772 100644
--- a/src/select.c
+++ b/src/select.c
@@ -3789,6 +3789,121 @@
#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,110 +4999,13 @@
}
#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( !OptimizationEnabled(db, SQLITE_LateSubquery) ){
+ /* 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;
- pParse->nHeight -= sqlite3SelectExprHeight(p);
}
-#endif
/* Various elements of the SELECT copied into local variables for
** convenience */
@@ -5086,7 +5104,7 @@
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 @@
** 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 @@
** 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;
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 2378376..205d328 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -1273,6 +1273,7 @@
#define SQLITE_Transitive 0x0200 /* Transitive constraints */
#define SQLITE_OmitNoopJoin 0x0400 /* Omit unused tables in joins */
#define SQLITE_Stat34 0x0800 /* Use STAT3 or STAT4 data */
+#define SQLITE_LateSubquery 0x1000 /* Plan main Q before rendering subQ */
#define SQLITE_AllOpts 0xffff /* All optimizations */
/*
@@ -3285,6 +3286,7 @@
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 +3299,8 @@
#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*);
diff --git a/src/update.c b/src/update.c
index f834744..0b7223b 100644
--- a/src/update.c
+++ b/src/update.c
@@ -347,7 +347,7 @@
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 @@
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);
diff --git a/src/where.c b/src/where.c
index e32d176..4610e96 100644
--- a/src/where.c
+++ b/src/where.c
@@ -2555,15 +2555,16 @@
/* TUNING: One-time cost for computing the automatic index is
** estimated to be X*N*log2(N) where N is the number of rows in
** the table being indexed and where X is 7 (LogEst=28) for normal
- ** tables or 1.375 (LogEst=4) for views and subqueries. The value
+ ** tables or 0.3333 (LogEst=-16) for views and subqueries. The value
** of X is smaller for views and subqueries so that the query planner
** will be more aggressive about generating automatic indexes for
** those objects, since there is no opportunity to add schema
** indexes on subqueries and views. */
- pNew->rSetup = rLogSize + rSize + 4;
+ pNew->rSetup = rLogSize + rSize - 16;
if( pTab->pSelect==0 && (pTab->tabFlags & TF_Ephemeral)==0 ){
- pNew->rSetup += 24;
+ pNew->rSetup += 44;
}
+ if( pNew->rSetup<1 ) pNew->rSetup = 1;
ApplyCostMultiplier(pNew->rSetup, pTab->costMult);
/* 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
@@ -3896,6 +3897,7 @@
*/
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 */
@@ -4170,6 +4172,16 @@
}
}
+ /* 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( OptimizationEnabled(db, SQLITE_LateSubquery) && pSelect!=0 ){
+ sqlite3ManifestSubqueries(pParse, pSelect, pTabList);
+ if( db->mallocFailed ) goto whereBeginError;
+ }
+
/* Open all tables in the pTabList and any indices selected for
** searching those tables.
*/
diff --git a/src/wherecode.c b/src/wherecode.c
index e1f0f86..800ff93 100644
--- a/src/wherecode.c
+++ b/src/wherecode.c
@@ -1265,7 +1265,7 @@
}
/* 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 ){
diff --git a/test/eqp.test b/test/eqp.test
index 046088c..b4124b0 100644
--- a/test/eqp.test
+++ b/test/eqp.test
@@ -81,31 +81,31 @@
do_eqp_test 1.7 {
SELECT * FROM t3 JOIN (SELECT 1)
} {
- 0 0 1 {SCAN SUBQUERY 1}
- 0 1 0 {SCAN TABLE t3}
+ 0 0 0 {SCAN TABLE t3}
+ 0 1 1 {SCAN SUBQUERY 1}
}
do_eqp_test 1.8 {
SELECT * FROM t3 JOIN (SELECT 1 UNION SELECT 2)
} {
1 0 0 {COMPOUND SUBQUERIES 2 AND 3 USING TEMP B-TREE (UNION)}
- 0 0 1 {SCAN SUBQUERY 1}
- 0 1 0 {SCAN TABLE t3}
+ 0 0 0 {SCAN TABLE t3}
+ 0 1 1 {SCAN SUBQUERY 1}
}
do_eqp_test 1.9 {
SELECT * FROM t3 JOIN (SELECT 1 EXCEPT SELECT a FROM t3 LIMIT 17)
} {
3 0 0 {SCAN TABLE t3}
1 0 0 {COMPOUND SUBQUERIES 2 AND 3 USING TEMP B-TREE (EXCEPT)}
- 0 0 1 {SCAN SUBQUERY 1}
- 0 1 0 {SCAN TABLE t3}
+ 0 0 0 {SCAN TABLE t3}
+ 0 1 1 {SCAN SUBQUERY 1}
}
do_eqp_test 1.10 {
SELECT * FROM t3 JOIN (SELECT 1 INTERSECT SELECT a FROM t3 LIMIT 17)
} {
3 0 0 {SCAN TABLE t3}
1 0 0 {COMPOUND SUBQUERIES 2 AND 3 USING TEMP B-TREE (INTERSECT)}
- 0 0 1 {SCAN SUBQUERY 1}
- 0 1 0 {SCAN TABLE t3}
+ 0 0 0 {SCAN TABLE t3}
+ 0 1 1 {SCAN SUBQUERY 1}
}
do_eqp_test 1.11 {
@@ -113,8 +113,8 @@
} {
3 0 0 {SCAN TABLE t3}
1 0 0 {COMPOUND SUBQUERIES 2 AND 3 (UNION ALL)}
- 0 0 1 {SCAN SUBQUERY 1}
- 0 1 0 {SCAN TABLE t3}
+ 0 0 0 {SCAN TABLE t3}
+ 0 1 1 {SCAN SUBQUERY 1}
}
#-------------------------------------------------------------------------