From: dan Date: Fri, 17 Jan 2014 17:40:46 +0000 (+0000) Subject: Resolve table names within CTEs in the context in which the CTE is declared, not... X-Git-Tag: version-3.8.3~42 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=98f45e53a74e4522f129c11d03993b3d17785559;p=thirdparty%2Fsqlite.git 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 --- diff --git a/manifest b/manifest index 984a0a27fe..7dbf068c5b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\stests\sthat\sverify\sthat\skeywords\sWITH,\sWITHOUT,\sand\sRECURSIVE\scan\sstill\nbe\sused\sas\stable\sand\scolumn\snames. -D 2014-01-17T16:19:01.842 +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-17T17:40:46.168 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -219,7 +219,7 @@ F src/printf.c 85d07756e45d7496d19439dcae3e6e9e0090f269 F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece F src/resolve.c 7eda9097b29fcf3d2b42fdc17d1de672134e09b6 F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0 -F src/select.c b17dd5c3ef4647190bd80f51b56e366c7b12f6e5 +F src/select.c a13cf4a450534bcbdf1cc840d695e259cd4a1409 F src/shell.c 9f3bc02a658b8f61d2cbe60cfc482f660c1c6c48 F src/sqlite.h.in eed7f7d66a60daaa7b4a597dcd9bad87aad9611b F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e @@ -1092,7 +1092,7 @@ F test/win32heap.test ea19770974795cff26e11575e12d422dbd16893c F test/win32lock.test 7a6bd73a5dcdee39b5bb93e92395e1773a194361 F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d F test/with1.test 90490c75e98e1914d84b7cef9e636b48917a020f -F test/with2.test 790c4b7ab3f4eb6984a3bbdae8d4ab429ebe9259 +F test/with2.test 21057990b59eb652a0a30c6a421fac9daad4412d F test/withM.test 52448ce23e1c2ecba79d10e130ee49ce9f9a2a7a F test/without_rowid1.test aaa26da19d543cd8d3d2d0e686dfa255556c15c8 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.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P c8eb11635a356182611ce2ccb8f358b6c453486e -R c791b577950f1652718e7fda0d0264df -U drh -Z 3da1c453f8a3e6f09e0b3d8bdad77daa +P 9ca18a0191db6a9b0763e2f0b3b35d23099fb71b +R b5a3302763f84d4efb48b14faba25e2d +U dan +Z c42b677f74f4986c260cd54897199c85 diff --git a/manifest.uuid b/manifest.uuid index 4cfd423b13..6be4f2395e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9ca18a0191db6a9b0763e2f0b3b35d23099fb71b \ No newline at end of file +a7323838bbd354a1c2f339e5e0f164f0eada47b3 \ No newline at end of file diff --git a/src/select.c b/src/select.c index 956015840c..b3f16e6113 100644 --- a/src/select.c +++ b/src/select.c @@ -3507,8 +3507,15 @@ static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){ ** FROM clause element pItem is really a common-table-expression (CTE) ** then return a pointer to the CTE definition for that table. Otherwise ** 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; if( pItem->zDatabase==0 && (zName = pItem->zName)!=0 ){ With *p; @@ -3516,6 +3523,7 @@ static struct Cte *searchWith(With *pWith, struct SrcList_item *pItem){ int i; for(i=0; inCte; i++){ if( sqlite3StrICmp(zName, p->a[i].zName)==0 ){ + *ppContext = p; return &p->a[i]; } } @@ -3562,19 +3570,21 @@ static int withExpand( Walker *pWalker, struct SrcList_item *pFrom ){ - Table *pTab; Parse *pParse = pWalker->pParse; 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 ); - pCte = searchWith(pParse->pWith, pFrom); + pCte = searchWith(pParse->pWith, pFrom, &pWith); if( pCte ){ + Table *pTab; ExprList *pEList; Select *pSel; Select *pLeft; /* Left-most SELECT statement */ 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 ** recursive reference to CTE pCte. Leave an error in pParse and return @@ -3582,7 +3592,7 @@ static int withExpand( ** In this case, proceed. */ if( pCte->zErr ){ sqlite3ErrorMsg(pParse, pCte->zErr, pCte->zName); - return WRC_Abort; + return SQLITE_ERROR; } pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table)); @@ -3621,11 +3631,13 @@ static int withExpand( sqlite3ErrorMsg( 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 )); pCte->zErr = "circular reference: %s"; + pSavedWith = pParse->pWith; + pParse->pWith = pWith; sqlite3WalkSelect(pWalker, bMayRecursive ? pSel->pPrior : pSel); 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", pCte->zName, pEList->nExpr, pCte->pCols->nExpr ); - return WRC_Abort; + pParse->pWith = pSavedWith; + return SQLITE_ERROR; } pEList = pCte->pCols; } - selectColumnsFromExprList(pParse, pEList, &pTab->nCol, &pTab->aCol); + selectColumnsFromExprList(pParse, pEList, &pTab->nCol, &pTab->aCol); if( bMayRecursive ){ if( pSel->selFlags & SF_Recursive ){ pCte->zErr = "multiple recursive references: %s"; @@ -3650,6 +3663,7 @@ static int withExpand( sqlite3WalkSelect(pWalker, pSel); } pCte->zErr = 0; + pParse->pWith = pSavedWith; } return SQLITE_OK; diff --git a/test/with2.test b/test/with2.test index 83b3b73646..08ef7bf6f7 100644 --- a/test/with2.test +++ b/test/with2.test @@ -50,7 +50,24 @@ do_execsql_test 1.4 { SELECT a FROM i WHERE a NOT IN x1 } {1 4 6 7 8 9 10} -finish_test +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