1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-14 00:22:38 +03:00

Resolve table names within CTEs in the context in which the CTE is declared, not the context in which it is used.

FossilOrigin-Name: a7323838bbd354a1c2f339e5e0f164f0eada47b3
This commit is contained in:
dan
2014-01-17 17:40:46 +00:00
parent a026b98500
commit 98f45e53a7
4 changed files with 50 additions and 19 deletions

View File

@@ -1,5 +1,5 @@
C Add\stests\sthat\sverify\sthat\skeywords\sWITH,\sWITHOUT,\sand\sRECURSIVE\scan\sstill\nbe\sused\sas\stable\sand\scolumn\snames. C Resolve\stable\snames\swithin\sCTEs\sin\sthe\scontext\sin\swhich\sthe\sCTE\sis\sdeclared,\snot\sthe\scontext\sin\swhich\sit\sis\sused.
D 2014-01-17T16:19:01.842 D 2014-01-17T17:40:46.168
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
@@ -219,7 +219,7 @@ 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 b17dd5c3ef4647190bd80f51b56e366c7b12f6e5 F src/select.c a13cf4a450534bcbdf1cc840d695e259cd4a1409
F src/shell.c 9f3bc02a658b8f61d2cbe60cfc482f660c1c6c48 F src/shell.c 9f3bc02a658b8f61d2cbe60cfc482f660c1c6c48
F src/sqlite.h.in eed7f7d66a60daaa7b4a597dcd9bad87aad9611b F src/sqlite.h.in eed7f7d66a60daaa7b4a597dcd9bad87aad9611b
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
@@ -1092,7 +1092,7 @@ 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 90490c75e98e1914d84b7cef9e636b48917a020f F test/with1.test 90490c75e98e1914d84b7cef9e636b48917a020f
F test/with2.test 790c4b7ab3f4eb6984a3bbdae8d4ab429ebe9259 F test/with2.test 21057990b59eb652a0a30c6a421fac9daad4412d
F test/withM.test 52448ce23e1c2ecba79d10e130ee49ce9f9a2a7a F test/withM.test 52448ce23e1c2ecba79d10e130ee49ce9f9a2a7a
F test/without_rowid1.test aaa26da19d543cd8d3d2d0e686dfa255556c15c8 F test/without_rowid1.test aaa26da19d543cd8d3d2d0e686dfa255556c15c8
F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99 F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99
@@ -1151,7 +1151,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 c8eb11635a356182611ce2ccb8f358b6c453486e P 9ca18a0191db6a9b0763e2f0b3b35d23099fb71b
R c791b577950f1652718e7fda0d0264df R b5a3302763f84d4efb48b14faba25e2d
U drh U dan
Z 3da1c453f8a3e6f09e0b3d8bdad77daa Z c42b677f74f4986c260cd54897199c85

View File

@@ -1 +1 @@
9ca18a0191db6a9b0763e2f0b3b35d23099fb71b a7323838bbd354a1c2f339e5e0f164f0eada47b3

View File

@@ -3507,8 +3507,15 @@ static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){
** FROM clause element pItem is really a common-table-expression (CTE) ** FROM clause element pItem is really a common-table-expression (CTE)
** then return a pointer to the CTE definition for that table. Otherwise ** then return a pointer to the CTE definition for that table. Otherwise
** return NULL. ** return NULL.
**
** If a non-NULL value is returned, set *ppContext to point to the With
** object that the returned CTE belongs to.
*/ */
static struct Cte *searchWith(With *pWith, struct SrcList_item *pItem){ static struct Cte *searchWith(
With *pWith, /* Current outermost WITH clause */
struct SrcList_item *pItem, /* FROM clause element to resolve */
With **ppContext /* OUT: WITH clause return value belongs to */
){
const char *zName; const char *zName;
if( pItem->zDatabase==0 && (zName = pItem->zName)!=0 ){ if( pItem->zDatabase==0 && (zName = pItem->zName)!=0 ){
With *p; With *p;
@@ -3516,6 +3523,7 @@ static struct Cte *searchWith(With *pWith, struct SrcList_item *pItem){
int i; int i;
for(i=0; i<p->nCte; i++){ for(i=0; i<p->nCte; i++){
if( sqlite3StrICmp(zName, p->a[i].zName)==0 ){ if( sqlite3StrICmp(zName, p->a[i].zName)==0 ){
*ppContext = p;
return &p->a[i]; return &p->a[i];
} }
} }
@@ -3562,19 +3570,21 @@ static int withExpand(
Walker *pWalker, Walker *pWalker,
struct SrcList_item *pFrom struct SrcList_item *pFrom
){ ){
Table *pTab;
Parse *pParse = pWalker->pParse; Parse *pParse = pWalker->pParse;
sqlite3 *db = pParse->db; sqlite3 *db = pParse->db;
struct Cte *pCte; struct Cte *pCte; /* Matched CTE (or NULL if no match) */
With *pWith; /* WITH clause that pCte belongs to */
assert( pFrom->pTab==0 ); assert( pFrom->pTab==0 );
pCte = searchWith(pParse->pWith, pFrom); pCte = searchWith(pParse->pWith, pFrom, &pWith);
if( pCte ){ if( pCte ){
Table *pTab;
ExprList *pEList; ExprList *pEList;
Select *pSel; Select *pSel;
Select *pLeft; /* Left-most SELECT statement */ Select *pLeft; /* Left-most SELECT statement */
int bMayRecursive; /* True if compound joined by UNION [ALL] */ int bMayRecursive; /* True if compound joined by UNION [ALL] */
With *pSavedWith; /* Initial value of pParse->pWith */
/* If pCte->zErr is non-NULL at this point, then this is an illegal /* If pCte->zErr is non-NULL at this point, then this is an illegal
** recursive reference to CTE pCte. Leave an error in pParse and return ** recursive reference to CTE pCte. Leave an error in pParse and return
@@ -3582,7 +3592,7 @@ static int withExpand(
** In this case, proceed. */ ** In this case, proceed. */
if( pCte->zErr ){ if( pCte->zErr ){
sqlite3ErrorMsg(pParse, pCte->zErr, pCte->zName); sqlite3ErrorMsg(pParse, pCte->zErr, pCte->zName);
return WRC_Abort; return SQLITE_ERROR;
} }
pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table)); pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table));
@@ -3621,11 +3631,13 @@ static int withExpand(
sqlite3ErrorMsg( sqlite3ErrorMsg(
pParse, "multiple references to recursive table: %s", pCte->zName pParse, "multiple references to recursive table: %s", pCte->zName
); );
return WRC_Abort; return SQLITE_ERROR;
} }
assert( pTab->nRef==1 || ((pSel->selFlags&SF_Recursive) && pTab->nRef==2 )); assert( pTab->nRef==1 || ((pSel->selFlags&SF_Recursive) && pTab->nRef==2 ));
pCte->zErr = "circular reference: %s"; pCte->zErr = "circular reference: %s";
pSavedWith = pParse->pWith;
pParse->pWith = pWith;
sqlite3WalkSelect(pWalker, bMayRecursive ? pSel->pPrior : pSel); sqlite3WalkSelect(pWalker, bMayRecursive ? pSel->pPrior : pSel);
for(pLeft=pSel; pLeft->pPrior; pLeft=pLeft->pPrior); for(pLeft=pSel; pLeft->pPrior; pLeft=pLeft->pPrior);
@@ -3635,12 +3647,13 @@ static int withExpand(
sqlite3ErrorMsg(pParse, "table %s has %d values for %d columns", sqlite3ErrorMsg(pParse, "table %s has %d values for %d columns",
pCte->zName, pEList->nExpr, pCte->pCols->nExpr pCte->zName, pEList->nExpr, pCte->pCols->nExpr
); );
return WRC_Abort; pParse->pWith = pSavedWith;
return SQLITE_ERROR;
} }
pEList = pCte->pCols; pEList = pCte->pCols;
} }
selectColumnsFromExprList(pParse, pEList, &pTab->nCol, &pTab->aCol);
selectColumnsFromExprList(pParse, pEList, &pTab->nCol, &pTab->aCol);
if( bMayRecursive ){ if( bMayRecursive ){
if( pSel->selFlags & SF_Recursive ){ if( pSel->selFlags & SF_Recursive ){
pCte->zErr = "multiple recursive references: %s"; pCte->zErr = "multiple recursive references: %s";
@@ -3650,6 +3663,7 @@ static int withExpand(
sqlite3WalkSelect(pWalker, pSel); sqlite3WalkSelect(pWalker, pSel);
} }
pCte->zErr = 0; pCte->zErr = 0;
pParse->pWith = pSavedWith;
} }
return SQLITE_OK; return SQLITE_OK;

View File

@@ -50,7 +50,24 @@ do_execsql_test 1.4 {
SELECT a FROM i WHERE a NOT IN x1 SELECT a FROM i WHERE a NOT IN x1
} {1 4 6 7 8 9 10} } {1 4 6 7 8 9 10}
do_execsql_test 1.5 {
WITH x1 AS (SELECT a FROM t1),
x2 AS (SELECT i FROM t2),
x3 AS (SELECT * FROM x1, x2 WHERE x1.a IN x2 AND x2.i IN x1)
SELECT * FROM x3
} {2 2}
do_execsql_test 1.6 {
CREATE TABLE t3 AS SELECT 3 AS x;
CREATE TABLE t4 AS SELECT 4 AS x;
WITH x1 AS (SELECT * FROM t3),
x2 AS (
WITH t3 AS (SELECT * FROM t4)
SELECT * FROM x1
)
SELECT * FROM x2;
} {3}
finish_test finish_test