]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Resolve table names within CTEs in the context in which the CTE is declared, not...
authordan <dan@noemail.net>
Fri, 17 Jan 2014 17:40:46 +0000 (17:40 +0000)
committerdan <dan@noemail.net>
Fri, 17 Jan 2014 17:40:46 +0000 (17:40 +0000)
FossilOrigin-Name: a7323838bbd354a1c2f339e5e0f164f0eada47b3

manifest
manifest.uuid
src/select.c
test/with2.test

index 984a0a27fe44a03b2577624ff4ef9b8e9e8cdbe9..7dbf068c5b442b36275c822ef3674127ce9110df 100644 (file)
--- 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
index 4cfd423b138f2c9aad9ef08cc9dea366460599ed..6be4f2395e6d7ccebea5cd6d193c255c25e01e06 100644 (file)
@@ -1 +1 @@
-9ca18a0191db6a9b0763e2f0b3b35d23099fb71b
\ No newline at end of file
+a7323838bbd354a1c2f339e5e0f164f0eada47b3
\ No newline at end of file
index 956015840cad254e395b6f7e8875d1197b6593bb..b3f16e6113ad96a890a9c5ed0ef8bad9e9a023dc 100644 (file)
@@ -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; i<p->nCte; 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;
index 83b3b7364619bb111f01d0acaf38dd2c4c7dd069..08ef7bf6f72f965ded9fcbc25b3cb8f94036c446 100644 (file)
@@ -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