mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-12 13:01:09 +03:00
Use the WITH clause to help resolve names for SELECT statements on the left
of a compound query. Proposed fix for ticket [31a19d11b97088296a]. FossilOrigin-Name: 67bfd59d9087a987f15f6148efa1ff104983e1fb
This commit is contained in:
62
src/select.c
62
src/select.c
@@ -109,6 +109,14 @@ void sqlite3SelectDelete(sqlite3 *db, Select *p){
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Return a pointer to the right-most SELECT statement in a compound.
|
||||
*/
|
||||
static Select *findRightmost(Select *p){
|
||||
while( p->pNext ) p = p->pNext;
|
||||
return p;
|
||||
}
|
||||
|
||||
/*
|
||||
** Given 1 to 3 identifiers preceding the JOIN keyword, determine the
|
||||
** type of join. Return an integer constant that expresses that type
|
||||
@@ -1877,7 +1885,9 @@ static void generateWithRecursiveQuery(
|
||||
p->pOrderBy = 0;
|
||||
|
||||
/* Store the results of the setup-query in Queue. */
|
||||
pSetup->pNext = 0;
|
||||
rc = sqlite3Select(pParse, pSetup, &destQueue);
|
||||
pSetup->pNext = p;
|
||||
if( rc ) goto end_of_recursive_query;
|
||||
|
||||
/* Find the next row in the Queue and output that row */
|
||||
@@ -1982,8 +1992,6 @@ static int multiSelect(
|
||||
assert( (p->selFlags & SF_Recursive)==0 || p->op==TK_ALL || p->op==TK_UNION );
|
||||
db = pParse->db;
|
||||
pPrior = p->pPrior;
|
||||
assert( pPrior->pRightmost!=pPrior );
|
||||
assert( pPrior->pRightmost==p->pRightmost );
|
||||
dest = *pDest;
|
||||
if( pPrior->pOrderBy ){
|
||||
sqlite3ErrorMsg(pParse,"ORDER BY clause should come after %s not before",
|
||||
@@ -2091,12 +2099,10 @@ static int multiSelect(
|
||||
testcase( p->op==TK_EXCEPT );
|
||||
testcase( p->op==TK_UNION );
|
||||
priorOp = SRT_Union;
|
||||
if( dest.eDest==priorOp && ALWAYS(!p->pLimit &&!p->pOffset) ){
|
||||
if( dest.eDest==priorOp ){
|
||||
/* We can reuse a temporary table generated by a SELECT to our
|
||||
** right.
|
||||
*/
|
||||
assert( p->pRightmost!=p ); /* Can only happen for leftward elements
|
||||
** of a 3-way or more compound */
|
||||
assert( p->pLimit==0 ); /* Not allowed on leftward elements */
|
||||
assert( p->pOffset==0 ); /* Not allowed on leftward elements */
|
||||
unionTab = dest.iSDParm;
|
||||
@@ -2109,7 +2115,7 @@ static int multiSelect(
|
||||
addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, unionTab, 0);
|
||||
assert( p->addrOpenEphm[0] == -1 );
|
||||
p->addrOpenEphm[0] = addr;
|
||||
p->pRightmost->selFlags |= SF_UsesEphemeral;
|
||||
findRightmost(p)->selFlags |= SF_UsesEphemeral;
|
||||
assert( p->pEList );
|
||||
}
|
||||
|
||||
@@ -2198,7 +2204,7 @@ static int multiSelect(
|
||||
addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab1, 0);
|
||||
assert( p->addrOpenEphm[0] == -1 );
|
||||
p->addrOpenEphm[0] = addr;
|
||||
p->pRightmost->selFlags |= SF_UsesEphemeral;
|
||||
findRightmost(p)->selFlags |= SF_UsesEphemeral;
|
||||
assert( p->pEList );
|
||||
|
||||
/* Code the SELECTs to our left into temporary table "tab1".
|
||||
@@ -2277,7 +2283,7 @@ static int multiSelect(
|
||||
CollSeq **apColl; /* For looping through pKeyInfo->aColl[] */
|
||||
int nCol; /* Number of columns in result set */
|
||||
|
||||
assert( p->pRightmost==p );
|
||||
assert( p->pNext==0 );
|
||||
nCol = p->pEList->nExpr;
|
||||
pKeyInfo = sqlite3KeyInfoAlloc(db, nCol, 1);
|
||||
if( !pKeyInfo ){
|
||||
@@ -2693,6 +2699,7 @@ static int multiSelectOrderBy(
|
||||
/* Separate the left and the right query from one another
|
||||
*/
|
||||
p->pPrior = 0;
|
||||
pPrior->pNext = 0;
|
||||
sqlite3ResolveOrderGroupBy(pParse, p, p->pOrderBy, "ORDER");
|
||||
if( pPrior->pPrior==0 ){
|
||||
sqlite3ResolveOrderGroupBy(pParse, pPrior, pPrior->pOrderBy, "ORDER");
|
||||
@@ -2858,6 +2865,7 @@ static int multiSelectOrderBy(
|
||||
sqlite3SelectDelete(db, p->pPrior);
|
||||
}
|
||||
p->pPrior = pPrior;
|
||||
pPrior->pNext = p;
|
||||
|
||||
/*** TBD: Insert subroutine calls to close cursors on incomplete
|
||||
**** subqueries ****/
|
||||
@@ -3123,7 +3131,7 @@ static int flattenSubquery(
|
||||
** and (14). */
|
||||
if( pSub->pLimit && p->pLimit ) return 0; /* Restriction (13) */
|
||||
if( pSub->pOffset ) return 0; /* Restriction (14) */
|
||||
if( p->pRightmost && pSub->pLimit ){
|
||||
if( (p->selFlags & SF_Compound)!=0 && pSub->pLimit ){
|
||||
return 0; /* Restriction (15) */
|
||||
}
|
||||
if( pSubSrc->nSrc==0 ) return 0; /* Restriction (7) */
|
||||
@@ -3274,14 +3282,14 @@ static int flattenSubquery(
|
||||
p->pOrderBy = pOrderBy;
|
||||
p->pSrc = pSrc;
|
||||
p->op = TK_ALL;
|
||||
p->pRightmost = 0;
|
||||
if( pNew==0 ){
|
||||
pNew = pPrior;
|
||||
p->pPrior = pPrior;
|
||||
}else{
|
||||
pNew->pPrior = pPrior;
|
||||
pNew->pRightmost = 0;
|
||||
if( pPrior ) pPrior->pNext = pNew;
|
||||
pNew->pNext = p;
|
||||
p->pPrior = pNew;
|
||||
}
|
||||
p->pPrior = pNew;
|
||||
if( db->mallocFailed ) return 1;
|
||||
}
|
||||
|
||||
@@ -3807,9 +3815,10 @@ static int withExpand(
|
||||
*/
|
||||
static void selectPopWith(Walker *pWalker, Select *p){
|
||||
Parse *pParse = pWalker->pParse;
|
||||
if( p->pWith ){
|
||||
assert( pParse->pWith==p->pWith );
|
||||
pParse->pWith = p->pWith->pOuter;
|
||||
With *pWith = findRightmost(p)->pWith;
|
||||
if( pWith!=0 ){
|
||||
assert( pParse->pWith==pWith );
|
||||
pParse->pWith = pWith->pOuter;
|
||||
}
|
||||
}
|
||||
#else
|
||||
@@ -3859,7 +3868,7 @@ static int selectExpander(Walker *pWalker, Select *p){
|
||||
}
|
||||
pTabList = p->pSrc;
|
||||
pEList = p->pEList;
|
||||
sqlite3WithPush(pParse, p->pWith, 0);
|
||||
sqlite3WithPush(pParse, findRightmost(p)->pWith, 0);
|
||||
|
||||
/* Make sure cursor numbers have been assigned to all entries in
|
||||
** the FROM clause of the SELECT statement.
|
||||
@@ -4603,21 +4612,6 @@ int sqlite3Select(
|
||||
/* If there is are a sequence of queries, do the earlier ones first.
|
||||
*/
|
||||
if( p->pPrior ){
|
||||
if( p->pRightmost==0 ){
|
||||
Select *pLoop, *pRight = 0;
|
||||
int cnt = 0;
|
||||
int mxSelect;
|
||||
for(pLoop=p; pLoop; pLoop=pLoop->pPrior, cnt++){
|
||||
pLoop->pRightmost = p;
|
||||
pLoop->pNext = pRight;
|
||||
pRight = pLoop;
|
||||
}
|
||||
mxSelect = db->aLimit[SQLITE_LIMIT_COMPOUND_SELECT];
|
||||
if( mxSelect && cnt>mxSelect ){
|
||||
sqlite3ErrorMsg(pParse, "too many terms in compound SELECT");
|
||||
goto select_end;
|
||||
}
|
||||
}
|
||||
rc = multiSelect(pParse, p, pDest);
|
||||
explainSetInteger(pParse->iSelectId, iRestoreSelectId);
|
||||
return rc;
|
||||
@@ -5279,10 +5273,6 @@ void sqlite3ExplainSelect(Vdbe *pVdbe, Select *p){
|
||||
sqlite3ExplainPrintf(pVdbe, "(null-select)");
|
||||
return;
|
||||
}
|
||||
while( p->pPrior ){
|
||||
p->pPrior->pNext = p;
|
||||
p = p->pPrior;
|
||||
}
|
||||
sqlite3ExplainPush(pVdbe);
|
||||
while( p ){
|
||||
explainOneSelect(pVdbe, p);
|
||||
|
||||
Reference in New Issue
Block a user