-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
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
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
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
-62dfc51a495be017605cf315d72e2db91bfa28f7
\ No newline at end of file
+4b8357ee3c4ccdbd34e0cd077efd84cca677f496
\ No newline at end of file
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;
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
*/
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;
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 */