diff options
author | drh <drh@noemail.net> | 2002-08-25 19:20:40 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2002-08-25 19:20:40 +0000 |
commit | 8c74a8ca5b056f61879f0e44c0d96551fc99706d (patch) | |
tree | 9985f1910dee55acea874e07664133c9a4d75f60 /src/select.c | |
parent | d94a66989474da2fb8c3d848b68a941d0876f9ff (diff) | |
download | sqlite-8c74a8ca5b056f61879f0e44c0d96551fc99706d.tar.gz sqlite-8c74a8ca5b056f61879f0e44c0d96551fc99706d.zip |
Fix for ticket #136: Added the OP_RenameCursor VDBE instruction and used it
to make cursor numbers right on nested subqueries. Also added OP_Gosub and
OP_Return but have not actually used them for anything yet. (CVS 727)
FossilOrigin-Name: c602603e7cd8dc5c8bb9db2748eacab650de5bf0
Diffstat (limited to 'src/select.c')
-rw-r--r-- | src/select.c | 27 |
1 files changed, 24 insertions, 3 deletions
diff --git a/src/select.c b/src/select.c index 73d766227..cc9a7b554 100644 --- a/src/select.c +++ b/src/select.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** -** $Id: select.c,v 1.109 2002/08/25 18:29:12 drh Exp $ +** $Id: select.c,v 1.110 2002/08/25 19:20:40 drh Exp $ */ #include "sqliteInt.h" @@ -1403,7 +1403,13 @@ substExprList(ExprList *pList, int iTable, ExprList *pEList, int iSub){ ** All of the expression analysis must occur on both the outer query and ** the subquery before this routine runs. */ -int flattenSubquery(Select *p, int iFrom, int isAgg, int subqueryIsAgg){ +static int flattenSubquery( + Parse *pParse, /* The parsing context */ + Select *p, /* The parent or outer SELECT statement */ + int iFrom, /* Index in p->pSrc->a[] of the inner subquery */ + int isAgg, /* True if outer SELECT uses aggregate functions */ + int subqueryIsAgg /* True if the subquery uses aggregate functions */ +){ Select *pSub; /* The inner query or "subquery" */ SrcList *pSrc; /* The FROM clause of the outer query */ SrcList *pSubSrc; /* The FROM clause of the subquery */ @@ -1486,6 +1492,7 @@ int flattenSubquery(Select *p, int iFrom, int isAgg, int subqueryIsAgg){ } } p->isDistinct = p->isDistinct || pSub->isDistinct; + if( pSub->nLimit>=0 ){ if( p->nLimit<0 ){ p->nLimit = pSub->nLimit; @@ -1494,6 +1501,20 @@ int flattenSubquery(Select *p, int iFrom, int isAgg, int subqueryIsAgg){ } } p->nOffset += pSub->nOffset; + + /* If the subquery contains subqueries of its own, that were not + ** flattened, then code will have already been generated to put + ** the results of those sub-subqueries into VDBE cursors relative + ** to the subquery. We must translate the cursor number into values + ** suitable for use by the outer query. + */ + for(i=0; i<pSubSrc->nSrc; i++){ + Vdbe *v; + if( pSubSrc->a[i].pSelect==0 ) continue; + v = sqliteGetVdbe(pParse); + sqliteVdbeAddOp(v, OP_RenameCursor, pSub->base+i, p->base+i); + } + if( pSrc->a[iFrom].pTab && pSrc->a[iFrom].pTab->isTransient ){ sqliteDeleteTable(0, pSrc->a[iFrom].pTab); } @@ -1883,7 +1904,7 @@ int sqliteSelect( ** If flattening is a possiblity, do so and return immediately. */ if( pParent && pParentAgg && - flattenSubquery(pParent, parentTab, *pParentAgg, isAgg) ){ + flattenSubquery(pParse, pParent, parentTab, *pParentAgg, isAgg) ){ if( isAgg ) *pParentAgg = 1; return rc; } |