Materialize subqueries using a subroutine and invoke that subroutine

prior to each use of the subqueries manifestation.  Fix for
ticket [002caede898aee4]

FossilOrigin-Name: 4b8357ee3c4ccdbd34e0cd077efd84cca677f496
This commit is contained in:
drh 2011-09-15 23:58:14 +00:00
parent 4327aeaafd
commit 5b6a9ed495
5 changed files with 41 additions and 18 deletions

View File

@ -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

View File

@ -1 +1 @@
62dfc51a495be017605cf315d72e2db91bfa28f7
4b8357ee3c4ccdbd34e0cd077efd84cca677f496

View File

@ -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;

View File

@ -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;

View File

@ -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 */