From: drh Date: Thu, 15 Sep 2011 23:58:14 +0000 (+0000) Subject: Materialize subqueries using a subroutine and invoke that subroutine X-Git-Tag: version-3.7.8~11^2~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5b6a9ed49556deac6d48be80b6ef2816102f1951;p=thirdparty%2Fsqlite.git Materialize subqueries using a subroutine and invoke that subroutine prior to each use of the subqueries manifestation. Fix for ticket [002caede898aee4] FossilOrigin-Name: 4b8357ee3c4ccdbd34e0cd077efd84cca677f496 --- diff --git a/manifest b/manifest index ef2b75267c..f94f12be4d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Adding\stest\scase\sfor\sticket\s[002caede898] -D 2011-09-15T19:39:42.113 +C Materialize\ssubqueries\susing\sa\ssubroutine\sand\sinvoke\sthat\ssubroutine\nprior\sto\seach\suse\sof\sthe\ssubqueries\smanifestation.\s\sFix\sfor\nticket\s[002caede898aee4] +D 2011-09-15T23:58:14.314 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in d314143fa6be24828021d3f583ad37d9afdce505 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -133,7 +133,7 @@ F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac F src/ctime.c e3132ec65240b2e2f3d50831021eac387f27584d F src/date.c a3c6842bad7ae632281811de112a8ba63ff08ab3 F src/delete.c ff68e5ef23aee08c0ff528f699a19397ed8bbed8 -F src/expr.c cbcd8c2f1588a9862291a081699854c5e1cb28ab +F src/expr.c 109de1d4a58d25c062a79d7e84bdbb77b348844e F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c 9f00ea98f6b360d477b5a78b5b59a1fbde82431c F src/func.c 59bb046d7e3df1ab512ac339ccb0a6f996a17cb7 @@ -179,11 +179,11 @@ F src/printf.c 585a36b6a963df832cfb69505afa3a34ed5ef8a1 F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50 F src/resolve.c 36368f44569208fa074e61f4dd0b6c4fb60ca2b4 F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697 -F src/select.c bf7b7ea6befb483619da5f597b0864668b828c3c +F src/select.c d85d83c334a3842b47d14e0574acb5f531d5579a F src/shell.c bbe7818ff5bc8614105ceb81ad67b8bdc0b671dd F src/sqlite.h.in 0a6c9c23337fd1352c5c75a613ff9533aa7d91cb F src/sqlite3ext.h 1a1a4f784aa9c3b00edd287940197de52487cd93 -F src/sqliteInt.h c7e37ee49b1a922ddcd18fa98dd750efa4d2db14 +F src/sqliteInt.h feb4f2b212fe36bbd951e44d2490c6aacf02f689 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 7ac64842c86cec2fc1a1d0e5c16d3beb8ad332bf F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -961,10 +961,7 @@ F tool/symbols.sh caaf6ccc7300fd43353318b44524853e222557d5 F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings.sh b7fdb2cc525f5ef4fa43c80e771636dd3690f9d2 -P 3fc566ac5dfce314ee414a3fb79daeeed6d0f179 -R 3df652f1b6c038f8caa8cb1ea6bf4532 -T *branch * tkt-002caede898 -T *sym-tkt-002caede898 * -T -sym-trunk * +P 62dfc51a495be017605cf315d72e2db91bfa28f7 +R 6d5602e8586fba23bb68456f6fac9e14 U drh -Z 9197dd7d4afe8679532f19b1e34148bf +Z 035be646ae967eef8d7d2956eeb67c86 diff --git a/manifest.uuid b/manifest.uuid index 993429f085..adf0713f44 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -62dfc51a495be017605cf315d72e2db91bfa28f7 \ No newline at end of file +4b8357ee3c4ccdbd34e0cd077efd84cca677f496 \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index ab218078db..7bfcf5733a 100644 --- a/src/expr.c +++ b/src/expr.c @@ -901,7 +901,8 @@ SrcList *sqlite3SrcListDup(sqlite3 *db, SrcList *p, int flags){ pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias); pNewItem->jointype = pOldItem->jointype; pNewItem->iCursor = pOldItem->iCursor; - pNewItem->isPopulated = pOldItem->isPopulated; + pNewItem->addrFillSub = pOldItem->addrFillSub; + pNewItem->regReturn = pOldItem->regReturn; pNewItem->isCorrelated = pOldItem->isCorrelated; pNewItem->zIndex = sqlite3DbStrDup(db, pOldItem->zIndex); pNewItem->notIndexed = pOldItem->notIndexed; diff --git a/src/select.c b/src/select.c index a8ea08a781..2ddc751b58 100644 --- a/src/select.c +++ b/src/select.c @@ -3801,7 +3801,11 @@ int sqlite3Select( Select *pSub = pItem->pSelect; int isAggSub; - if( pSub==0 || pItem->isPopulated ) continue; + if( pSub==0 ) continue; + if( pItem->addrFillSub ){ + sqlite3VdbeAddOp2(v, OP_Gosub, pItem->regReturn, pItem->addrFillSub); + continue; + } /* Increment Parse.nHeight by the height of the largest expression ** tree refered to by this, the parent select. The child select @@ -3812,21 +3816,41 @@ int sqlite3Select( */ pParse->nHeight += sqlite3SelectExprHeight(p); - /* Check to see if the subquery can be absorbed into the parent. */ isAggSub = (pSub->selFlags & SF_Aggregate)!=0; if( flattenSubquery(pParse, p, i, isAgg, isAggSub) ){ + /* This subquery can be absorbed into its parent. */ if( isAggSub ){ isAgg = 1; p->selFlags |= SF_Aggregate; } i = -1; }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 = sqlite3VdbeAddOp0(v, OP_Goto); + int regOnce = 0; + assert( pItem->addrFillSub==0 ); + pItem->addrFillSub = topAddr+1; + pItem->regReturn = ++pParse->nMem; + if( pItem->isCorrelated==0 && pParse->pTriggerTab==0 ){ + /* If the subquery is no correlated and if we are not inside of + ** a trigger, then we only need to compute the value of the subquery + ** once. */ + regOnce = ++pParse->nMem; + sqlite3VdbeAddOp1(v, OP_If, regOnce); + sqlite3VdbeAddOp2(v, OP_Integer, 1, regOnce); + } sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor); - assert( pItem->isPopulated==0 ); explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId); sqlite3Select(pParse, pSub, &dest); - pItem->isPopulated = 1; pItem->pTab->nRowEst = (unsigned)pSub->nSelectRow; + if( regOnce ) sqlite3VdbeJumpHere(v, topAddr+1); + sqlite3VdbeAddOp1(v, OP_Return, pItem->regReturn); + sqlite3VdbeJumpHere(v, topAddr); + sqlite3VdbeAddOp2(v, OP_Gosub, pItem->regReturn, topAddr+1); } if( /*pParse->nErr ||*/ db->mallocFailed ){ goto select_end; diff --git a/src/sqliteInt.h b/src/sqliteInt.h index f27fea2b3a..65b0aa1fc6 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1852,7 +1852,8 @@ struct SrcList { char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */ Table *pTab; /* An SQL table corresponding to zName */ Select *pSelect; /* A SELECT statement used in place of a table name */ - u8 isPopulated; /* Temporary table associated with SELECT is populated */ + int addrFillSub; /* Address of subroutine to manifest a subquery */ + int regReturn; /* Register holding return address of addrFillSub */ u8 jointype; /* Type of join between this able and the previous */ u8 notIndexed; /* True if there is a NOT INDEXED clause */ u8 isCorrelated; /* True if sub-query is correlated */