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:
parent
fa46bfbbc5
commit
d227a291b2
20
manifest
20
manifest
@ -1,5 +1,5 @@
|
|||||||
C Add\sthe\sMandelbrot\sSet\stestcase\sto\sthe\s"cte"\stestset\sof\sspeedtest1.
|
C Use\sthe\sWITH\sclause\sto\shelp\sresolve\snames\sfor\sSELECT\sstatements\son\sthe\sleft\nof\sa\scompound\squery.\s\sProposed\sfix\sfor\sticket\s[31a19d11b97088296a].
|
||||||
D 2014-02-09T00:52:53.682
|
D 2014-02-09T18:02:09.253
|
||||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||||
F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81
|
F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81
|
||||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||||
@ -175,7 +175,7 @@ F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
|
|||||||
F src/ctime.c 77779efbe78dd678d84bfb4fc2e87b6b6ad8dccd
|
F src/ctime.c 77779efbe78dd678d84bfb4fc2e87b6b6ad8dccd
|
||||||
F src/date.c 593c744b2623971e45affd0bde347631bdfa4625
|
F src/date.c 593c744b2623971e45affd0bde347631bdfa4625
|
||||||
F src/delete.c 6765a421f08adbedc5d52d21760ec6dbe5123fd3
|
F src/delete.c 6765a421f08adbedc5d52d21760ec6dbe5123fd3
|
||||||
F src/expr.c fabda9e9320e3284c2a35cdc558313d9e80ce92a
|
F src/expr.c 9bea427f95665c1aa8fdc87b7678546eef50c296
|
||||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||||
F src/fkey.c 2ab0f5384b70594468ef3ac5c7ed8ca24bfd17d5
|
F src/fkey.c 2ab0f5384b70594468ef3ac5c7ed8ca24bfd17d5
|
||||||
F src/func.c f4499b39d66b71825514334ce67b32ff14bd19f5
|
F src/func.c f4499b39d66b71825514334ce67b32ff14bd19f5
|
||||||
@ -209,7 +209,7 @@ F src/os_unix.c 18f7f95dc6bcb9cf4d4a238d8e2de96611bc2ae5
|
|||||||
F src/os_win.c d4284f003445054a26689f1264b1b9bf7261bd1b
|
F src/os_win.c d4284f003445054a26689f1264b1b9bf7261bd1b
|
||||||
F src/pager.c 0ffa313a30ed6d061d9c6601b7b175cc50a1cab7
|
F src/pager.c 0ffa313a30ed6d061d9c6601b7b175cc50a1cab7
|
||||||
F src/pager.h ffd5607f7b3e4590b415b007a4382f693334d428
|
F src/pager.h ffd5607f7b3e4590b415b007a4382f693334d428
|
||||||
F src/parse.y bd51bc17cbfe7549adb4ca3747b1c3d384645065
|
F src/parse.y cce844ccb80b5f969b04c25100c8d94338488efb
|
||||||
F src/pcache.c d8eafac28290d4bb80332005435db44991d07fc2
|
F src/pcache.c d8eafac28290d4bb80332005435db44991d07fc2
|
||||||
F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222
|
F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222
|
||||||
F src/pcache1.c 102e6f5a2fbc646154463eb856d1fd716867b64c
|
F src/pcache1.c 102e6f5a2fbc646154463eb856d1fd716867b64c
|
||||||
@ -219,12 +219,12 @@ F src/printf.c 85d07756e45d7496d19439dcae3e6e9e0090f269
|
|||||||
F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece
|
F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece
|
||||||
F src/resolve.c 7eda9097b29fcf3d2b42fdc17d1de672134e09b6
|
F src/resolve.c 7eda9097b29fcf3d2b42fdc17d1de672134e09b6
|
||||||
F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0
|
F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0
|
||||||
F src/select.c de28cd6d49e0334a3c693fbcce7cd8dfe5fc3979
|
F src/select.c c055a9fa25a4e7fc8c1652c44a31d6382dbb1e8a
|
||||||
F src/shell.c 7dedf7367ee49050b0366bf8dbc8ec2bd15b42c7
|
F src/shell.c 7dedf7367ee49050b0366bf8dbc8ec2bd15b42c7
|
||||||
F src/sqlite.h.in eed7f7d66a60daaa7b4a597dcd9bad87aad9611b
|
F src/sqlite.h.in eed7f7d66a60daaa7b4a597dcd9bad87aad9611b
|
||||||
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
|
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
|
||||||
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
|
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
|
||||||
F src/sqliteInt.h edee30d57dd287aea523406f53123583ca7f0089
|
F src/sqliteInt.h 5b1f4e30c8332270e4c14254ef1fbcbd92a4a4c7
|
||||||
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
|
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
|
||||||
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
|
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
|
||||||
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
||||||
@ -1092,7 +1092,7 @@ F test/wild001.test bca33f499866f04c24510d74baf1e578d4e44b1c
|
|||||||
F test/win32heap.test ea19770974795cff26e11575e12d422dbd16893c
|
F test/win32heap.test ea19770974795cff26e11575e12d422dbd16893c
|
||||||
F test/win32lock.test 7a6bd73a5dcdee39b5bb93e92395e1773a194361
|
F test/win32lock.test 7a6bd73a5dcdee39b5bb93e92395e1773a194361
|
||||||
F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d
|
F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d
|
||||||
F test/with1.test ce15d69d34a2576b0e47d78c244d1ba2a31679d1
|
F test/with1.test 268081a6b14817a262ced4d0ee34d4d2a1dd2068
|
||||||
F test/with2.test 2fe78fcd8deef2a0f9cfc49bfc755911d0b3fd64
|
F test/with2.test 2fe78fcd8deef2a0f9cfc49bfc755911d0b3fd64
|
||||||
F test/withM.test e97f2a8c506ab3ea9eab94e6f6072f6cc924c991
|
F test/withM.test e97f2a8c506ab3ea9eab94e6f6072f6cc924c991
|
||||||
F test/without_rowid1.test aaa26da19d543cd8d3d2d0e686dfa255556c15c8
|
F test/without_rowid1.test aaa26da19d543cd8d3d2d0e686dfa255556c15c8
|
||||||
@ -1152,7 +1152,7 @@ F tool/vdbe-compress.tcl 0cf56e9263a152b84da86e75a5c0cdcdb7a47891
|
|||||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||||
F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
|
F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
|
||||||
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
|
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
|
||||||
P 4677ef2f8a726573c48ee2e532c00a68308dd7e1
|
P 56febbeb575a298ae8839b3a59711150ceb9999d
|
||||||
R 439cd23f35fb63451d5f47c7c9c57942
|
R c206aab6ac6bc2f14c7db43625790fe8
|
||||||
U drh
|
U drh
|
||||||
Z 01b4847ed4d0397261d6befa79512d70
|
Z c763a50ce107ca4b3399be4e022f486e
|
||||||
|
@ -1 +1 @@
|
|||||||
56febbeb575a298ae8839b3a59711150ceb9999d
|
67bfd59d9087a987f15f6148efa1ff104983e1fb
|
@ -1060,7 +1060,6 @@ Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){
|
|||||||
pNew->iLimit = 0;
|
pNew->iLimit = 0;
|
||||||
pNew->iOffset = 0;
|
pNew->iOffset = 0;
|
||||||
pNew->selFlags = p->selFlags & ~SF_UsesEphemeral;
|
pNew->selFlags = p->selFlags & ~SF_UsesEphemeral;
|
||||||
pNew->pRightmost = 0;
|
|
||||||
pNew->addrOpenEphm[0] = -1;
|
pNew->addrOpenEphm[0] = -1;
|
||||||
pNew->addrOpenEphm[1] = -1;
|
pNew->addrOpenEphm[1] = -1;
|
||||||
pNew->addrOpenEphm[2] = -1;
|
pNew->addrOpenEphm[2] = -1;
|
||||||
|
21
src/parse.y
21
src/parse.y
@ -412,13 +412,26 @@ cmd ::= select(X). {
|
|||||||
%type oneselect {Select*}
|
%type oneselect {Select*}
|
||||||
%destructor oneselect {sqlite3SelectDelete(pParse->db, $$);}
|
%destructor oneselect {sqlite3SelectDelete(pParse->db, $$);}
|
||||||
|
|
||||||
select(A) ::= with(W) selectnowith(X). {
|
select(A) ::= with(W) selectnowith(X). {
|
||||||
if( X ){
|
Select *p = X, *pNext, *pLoop;
|
||||||
X->pWith = W;
|
if( p ){
|
||||||
|
int cnt = 0, mxSelect;
|
||||||
|
p->pWith = W;
|
||||||
|
if( p->pPrior ){
|
||||||
|
pNext = 0;
|
||||||
|
for(pLoop=p; pLoop; pNext=pLoop, pLoop=pLoop->pPrior, cnt++){
|
||||||
|
pLoop->pNext = pNext;
|
||||||
|
pLoop->selFlags |= SF_Compound;
|
||||||
|
}
|
||||||
|
mxSelect = pParse->db->aLimit[SQLITE_LIMIT_COMPOUND_SELECT];
|
||||||
|
if( mxSelect && cnt>mxSelect ){
|
||||||
|
sqlite3ErrorMsg(pParse, "too many terms in compound SELECT");
|
||||||
|
}
|
||||||
|
}
|
||||||
}else{
|
}else{
|
||||||
sqlite3WithDelete(pParse->db, W);
|
sqlite3WithDelete(pParse->db, W);
|
||||||
}
|
}
|
||||||
A = X;
|
A = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
selectnowith(A) ::= oneselect(X). {A = X;}
|
selectnowith(A) ::= oneselect(X). {A = X;}
|
||||||
|
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
|
** Given 1 to 3 identifiers preceding the JOIN keyword, determine the
|
||||||
** type of join. Return an integer constant that expresses that type
|
** type of join. Return an integer constant that expresses that type
|
||||||
@ -1877,7 +1885,9 @@ static void generateWithRecursiveQuery(
|
|||||||
p->pOrderBy = 0;
|
p->pOrderBy = 0;
|
||||||
|
|
||||||
/* Store the results of the setup-query in Queue. */
|
/* Store the results of the setup-query in Queue. */
|
||||||
|
pSetup->pNext = 0;
|
||||||
rc = sqlite3Select(pParse, pSetup, &destQueue);
|
rc = sqlite3Select(pParse, pSetup, &destQueue);
|
||||||
|
pSetup->pNext = p;
|
||||||
if( rc ) goto end_of_recursive_query;
|
if( rc ) goto end_of_recursive_query;
|
||||||
|
|
||||||
/* Find the next row in the Queue and output that row */
|
/* 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 );
|
assert( (p->selFlags & SF_Recursive)==0 || p->op==TK_ALL || p->op==TK_UNION );
|
||||||
db = pParse->db;
|
db = pParse->db;
|
||||||
pPrior = p->pPrior;
|
pPrior = p->pPrior;
|
||||||
assert( pPrior->pRightmost!=pPrior );
|
|
||||||
assert( pPrior->pRightmost==p->pRightmost );
|
|
||||||
dest = *pDest;
|
dest = *pDest;
|
||||||
if( pPrior->pOrderBy ){
|
if( pPrior->pOrderBy ){
|
||||||
sqlite3ErrorMsg(pParse,"ORDER BY clause should come after %s not before",
|
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_EXCEPT );
|
||||||
testcase( p->op==TK_UNION );
|
testcase( p->op==TK_UNION );
|
||||||
priorOp = SRT_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
|
/* We can reuse a temporary table generated by a SELECT to our
|
||||||
** right.
|
** 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->pLimit==0 ); /* Not allowed on leftward elements */
|
||||||
assert( p->pOffset==0 ); /* Not allowed on leftward elements */
|
assert( p->pOffset==0 ); /* Not allowed on leftward elements */
|
||||||
unionTab = dest.iSDParm;
|
unionTab = dest.iSDParm;
|
||||||
@ -2109,7 +2115,7 @@ static int multiSelect(
|
|||||||
addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, unionTab, 0);
|
addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, unionTab, 0);
|
||||||
assert( p->addrOpenEphm[0] == -1 );
|
assert( p->addrOpenEphm[0] == -1 );
|
||||||
p->addrOpenEphm[0] = addr;
|
p->addrOpenEphm[0] = addr;
|
||||||
p->pRightmost->selFlags |= SF_UsesEphemeral;
|
findRightmost(p)->selFlags |= SF_UsesEphemeral;
|
||||||
assert( p->pEList );
|
assert( p->pEList );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2198,7 +2204,7 @@ static int multiSelect(
|
|||||||
addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab1, 0);
|
addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab1, 0);
|
||||||
assert( p->addrOpenEphm[0] == -1 );
|
assert( p->addrOpenEphm[0] == -1 );
|
||||||
p->addrOpenEphm[0] = addr;
|
p->addrOpenEphm[0] = addr;
|
||||||
p->pRightmost->selFlags |= SF_UsesEphemeral;
|
findRightmost(p)->selFlags |= SF_UsesEphemeral;
|
||||||
assert( p->pEList );
|
assert( p->pEList );
|
||||||
|
|
||||||
/* Code the SELECTs to our left into temporary table "tab1".
|
/* Code the SELECTs to our left into temporary table "tab1".
|
||||||
@ -2277,7 +2283,7 @@ static int multiSelect(
|
|||||||
CollSeq **apColl; /* For looping through pKeyInfo->aColl[] */
|
CollSeq **apColl; /* For looping through pKeyInfo->aColl[] */
|
||||||
int nCol; /* Number of columns in result set */
|
int nCol; /* Number of columns in result set */
|
||||||
|
|
||||||
assert( p->pRightmost==p );
|
assert( p->pNext==0 );
|
||||||
nCol = p->pEList->nExpr;
|
nCol = p->pEList->nExpr;
|
||||||
pKeyInfo = sqlite3KeyInfoAlloc(db, nCol, 1);
|
pKeyInfo = sqlite3KeyInfoAlloc(db, nCol, 1);
|
||||||
if( !pKeyInfo ){
|
if( !pKeyInfo ){
|
||||||
@ -2693,6 +2699,7 @@ static int multiSelectOrderBy(
|
|||||||
/* Separate the left and the right query from one another
|
/* Separate the left and the right query from one another
|
||||||
*/
|
*/
|
||||||
p->pPrior = 0;
|
p->pPrior = 0;
|
||||||
|
pPrior->pNext = 0;
|
||||||
sqlite3ResolveOrderGroupBy(pParse, p, p->pOrderBy, "ORDER");
|
sqlite3ResolveOrderGroupBy(pParse, p, p->pOrderBy, "ORDER");
|
||||||
if( pPrior->pPrior==0 ){
|
if( pPrior->pPrior==0 ){
|
||||||
sqlite3ResolveOrderGroupBy(pParse, pPrior, pPrior->pOrderBy, "ORDER");
|
sqlite3ResolveOrderGroupBy(pParse, pPrior, pPrior->pOrderBy, "ORDER");
|
||||||
@ -2858,6 +2865,7 @@ static int multiSelectOrderBy(
|
|||||||
sqlite3SelectDelete(db, p->pPrior);
|
sqlite3SelectDelete(db, p->pPrior);
|
||||||
}
|
}
|
||||||
p->pPrior = pPrior;
|
p->pPrior = pPrior;
|
||||||
|
pPrior->pNext = p;
|
||||||
|
|
||||||
/*** TBD: Insert subroutine calls to close cursors on incomplete
|
/*** TBD: Insert subroutine calls to close cursors on incomplete
|
||||||
**** subqueries ****/
|
**** subqueries ****/
|
||||||
@ -3123,7 +3131,7 @@ static int flattenSubquery(
|
|||||||
** and (14). */
|
** and (14). */
|
||||||
if( pSub->pLimit && p->pLimit ) return 0; /* Restriction (13) */
|
if( pSub->pLimit && p->pLimit ) return 0; /* Restriction (13) */
|
||||||
if( pSub->pOffset ) return 0; /* Restriction (14) */
|
if( pSub->pOffset ) return 0; /* Restriction (14) */
|
||||||
if( p->pRightmost && pSub->pLimit ){
|
if( (p->selFlags & SF_Compound)!=0 && pSub->pLimit ){
|
||||||
return 0; /* Restriction (15) */
|
return 0; /* Restriction (15) */
|
||||||
}
|
}
|
||||||
if( pSubSrc->nSrc==0 ) return 0; /* Restriction (7) */
|
if( pSubSrc->nSrc==0 ) return 0; /* Restriction (7) */
|
||||||
@ -3274,14 +3282,14 @@ static int flattenSubquery(
|
|||||||
p->pOrderBy = pOrderBy;
|
p->pOrderBy = pOrderBy;
|
||||||
p->pSrc = pSrc;
|
p->pSrc = pSrc;
|
||||||
p->op = TK_ALL;
|
p->op = TK_ALL;
|
||||||
p->pRightmost = 0;
|
|
||||||
if( pNew==0 ){
|
if( pNew==0 ){
|
||||||
pNew = pPrior;
|
p->pPrior = pPrior;
|
||||||
}else{
|
}else{
|
||||||
pNew->pPrior = pPrior;
|
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;
|
if( db->mallocFailed ) return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3807,9 +3815,10 @@ static int withExpand(
|
|||||||
*/
|
*/
|
||||||
static void selectPopWith(Walker *pWalker, Select *p){
|
static void selectPopWith(Walker *pWalker, Select *p){
|
||||||
Parse *pParse = pWalker->pParse;
|
Parse *pParse = pWalker->pParse;
|
||||||
if( p->pWith ){
|
With *pWith = findRightmost(p)->pWith;
|
||||||
assert( pParse->pWith==p->pWith );
|
if( pWith!=0 ){
|
||||||
pParse->pWith = p->pWith->pOuter;
|
assert( pParse->pWith==pWith );
|
||||||
|
pParse->pWith = pWith->pOuter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
@ -3859,7 +3868,7 @@ static int selectExpander(Walker *pWalker, Select *p){
|
|||||||
}
|
}
|
||||||
pTabList = p->pSrc;
|
pTabList = p->pSrc;
|
||||||
pEList = p->pEList;
|
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
|
/* Make sure cursor numbers have been assigned to all entries in
|
||||||
** the FROM clause of the SELECT statement.
|
** 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 there is are a sequence of queries, do the earlier ones first.
|
||||||
*/
|
*/
|
||||||
if( p->pPrior ){
|
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);
|
rc = multiSelect(pParse, p, pDest);
|
||||||
explainSetInteger(pParse->iSelectId, iRestoreSelectId);
|
explainSetInteger(pParse->iSelectId, iRestoreSelectId);
|
||||||
return rc;
|
return rc;
|
||||||
@ -5279,10 +5273,6 @@ void sqlite3ExplainSelect(Vdbe *pVdbe, Select *p){
|
|||||||
sqlite3ExplainPrintf(pVdbe, "(null-select)");
|
sqlite3ExplainPrintf(pVdbe, "(null-select)");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
while( p->pPrior ){
|
|
||||||
p->pPrior->pNext = p;
|
|
||||||
p = p->pPrior;
|
|
||||||
}
|
|
||||||
sqlite3ExplainPush(pVdbe);
|
sqlite3ExplainPush(pVdbe);
|
||||||
while( p ){
|
while( p ){
|
||||||
explainOneSelect(pVdbe, p);
|
explainOneSelect(pVdbe, p);
|
||||||
|
@ -2148,7 +2148,6 @@ struct Select {
|
|||||||
ExprList *pOrderBy; /* The ORDER BY clause */
|
ExprList *pOrderBy; /* The ORDER BY clause */
|
||||||
Select *pPrior; /* Prior select in a compound select statement */
|
Select *pPrior; /* Prior select in a compound select statement */
|
||||||
Select *pNext; /* Next select to the left in a compound */
|
Select *pNext; /* Next select to the left in a compound */
|
||||||
Select *pRightmost; /* Right-most select in a compound select statement */
|
|
||||||
Expr *pLimit; /* LIMIT expression. NULL means not used. */
|
Expr *pLimit; /* LIMIT expression. NULL means not used. */
|
||||||
Expr *pOffset; /* OFFSET expression. NULL means not used. */
|
Expr *pOffset; /* OFFSET expression. NULL means not used. */
|
||||||
With *pWith; /* WITH clause attached to this select. Or NULL. */
|
With *pWith; /* WITH clause attached to this select. Or NULL. */
|
||||||
@ -2170,6 +2169,7 @@ struct Select {
|
|||||||
#define SF_NestedFrom 0x0200 /* Part of a parenthesized FROM clause */
|
#define SF_NestedFrom 0x0200 /* Part of a parenthesized FROM clause */
|
||||||
#define SF_MaybeConvert 0x0400 /* Need convertCompoundSelectToSubquery() */
|
#define SF_MaybeConvert 0x0400 /* Need convertCompoundSelectToSubquery() */
|
||||||
#define SF_Recursive 0x0800 /* The recursive part of a recursive CTE */
|
#define SF_Recursive 0x0800 /* The recursive part of a recursive CTE */
|
||||||
|
#define SF_Compound 0x1000 /* Part of a compound query */
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -816,5 +816,16 @@ do_execsql_test 11.3 {
|
|||||||
.........Noland
|
.........Noland
|
||||||
.........Olivia}}
|
.........Olivia}}
|
||||||
|
|
||||||
finish_test
|
#--------------------------------------------------------------------------
|
||||||
|
# Ticket [31a19d11b97088296ac104aaff113a9790394927] (2014-02-09)
|
||||||
|
# Name resolution issue with compound SELECTs and Common Table Expressions
|
||||||
|
#
|
||||||
|
do_execsql_test 12.1 {
|
||||||
|
WITH RECURSIVE
|
||||||
|
t1(x) AS (VALUES(2) UNION ALL SELECT x+2 FROM t1 WHERE x<20),
|
||||||
|
t2(y) AS (VALUES(3) UNION ALL SELECT y+3 FROM t2 WHERE y<20)
|
||||||
|
SELECT x FROM t1 EXCEPT SELECT y FROM t2 ORDER BY 1;
|
||||||
|
} {2 4 8 10 14 16 20}
|
||||||
|
|
||||||
|
|
||||||
|
finish_test
|
||||||
|
Loading…
Reference in New Issue
Block a user