]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
When resolving names, consider a reference to a recursive CTE column as equivalent...
authordan <dan@noemail.net>
Wed, 15 Jan 2014 18:12:00 +0000 (18:12 +0000)
committerdan <dan@noemail.net>
Wed, 15 Jan 2014 18:12:00 +0000 (18:12 +0000)
FossilOrigin-Name: 61be2da0ae623c1572819481508b044e9d32f294

manifest
manifest.uuid
src/expr.c
src/resolve.c
src/select.c
src/sqliteInt.h
test/with1.test

index d31455438074f6a0cc5fccde9931250c8cdd1680..7847f8e6915e96ac19f905f16f9975d0402582a6 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Return\san\serror\sif\sa\sCTE\sspecifies\sa\sdifferent\snumber\sof\scolumns\sthan\sits\sSELECT\sstatement\sreturns.
-D 2014-01-15T15:27:51.337
+C When\sresolving\snames,\sconsider\sa\sreference\sto\sa\srecursive\sCTE\scolumn\sas\sequivalent\sto\sa\sreference\sto\sthe\soutermost\sname-context.\sThis\sensures\sthat\scorrelated\ssub-queries\sare\scorrectly\sidentified\sas\ssuch.
+D 2014-01-15T18:12:00.359
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -175,7 +175,7 @@ F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
 F src/ctime.c 77779efbe78dd678d84bfb4fc2e87b6b6ad8dccd
 F src/date.c 593c744b2623971e45affd0bde347631bdfa4625
 F src/delete.c 91e1321021db5dc266360531b8b6550009d771ff
-F src/expr.c 46ad3b4161aeaf299130305efd0259bc5643bfd6
+F src/expr.c fccff6c8cd170dc1df244fdd4befb2ec783b72b1
 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
 F src/fkey.c 2ab0f5384b70594468ef3ac5c7ed8ca24bfd17d5
 F src/func.c 6325ac2ec10833ccf4d5c36d323709221d37ea19
@@ -217,14 +217,14 @@ F src/pragma.c ed409ce4104cf4d9de6ead40ace70974f124853b
 F src/prepare.c 677521ab7132615a8a26107a1d1c3132f44ae337
 F src/printf.c 85d07756e45d7496d19439dcae3e6e9e0090f269
 F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece
-F src/resolve.c 7eda9097b29fcf3d2b42fdc17d1de672134e09b6
+F src/resolve.c 41d0cf644aa98131204e6243e108829797f038ab
 F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0
-F src/select.c 7d0d85f5d0a0f35be49230a3b6609fa534980015
+F src/select.c c6ba9c34f5092aeada10928b93c798a5a262c85a
 F src/shell.c a3541193d5fce37e91dad8ef46a9505aa7c9b344
 F src/sqlite.h.in d94a8b89522f526ba711182ee161e06f8669bcc9
 F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
 F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
-F src/sqliteInt.h fc7b2516260c4e14bd4342cd9ed47f3d0ca27cc5
+F src/sqliteInt.h 31bcde5190ca666e4873188a9039ac6ff017a0a8
 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
 F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
@@ -1091,7 +1091,7 @@ F test/wild001.test bca33f499866f04c24510d74baf1e578d4e44b1c
 F test/win32heap.test ea19770974795cff26e11575e12d422dbd16893c
 F test/win32lock.test 7a6bd73a5dcdee39b5bb93e92395e1773a194361
 F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d
-F test/with1.test babb3d9c4007596d2d74468e001b1dc02d1ada91
+F test/with1.test 951807f7246215ec26cf5e9946f1b355ba892f89
 F test/withM.test ac3ec7ee0b33a02d0fa15da91214d97ddea64e34
 F test/without_rowid1.test aaa26da19d543cd8d3d2d0e686dfa255556c15c8
 F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99
@@ -1150,7 +1150,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 860aa936634a60d68e3954fc408a96a9260394e0
-R 0c042289cd11db254af8c2a3a3653738
+P 9a514b50e4b01f109fbdb0aabcbfe1ddab129b44
+R 7a326e6d7d898da8a108f7b49c21709d
 U dan
-Z d4b370476cdc85ae036fb519ef522aac
+Z a1fae4bd21e81652e55bd538f546aecf
index 2aac3c13b11f03b687af692236a6c08f266a2b8b..7d2b8e9f8ad89cdc1c2e9733225f5d8d02393aec 100644 (file)
@@ -1 +1 @@
-9a514b50e4b01f109fbdb0aabcbfe1ddab129b44
\ No newline at end of file
+61be2da0ae623c1572819481508b044e9d32f294
\ No newline at end of file
index fca03a8d99bb1396630d20cd7561f2a37b86a9d8..9a288b73b2d4b9084439e146ebff5981b1db080d 100644 (file)
@@ -998,6 +998,7 @@ SrcList *sqlite3SrcListDup(sqlite3 *db, SrcList *p, int flags){
     pNewItem->regReturn = pOldItem->regReturn;
     pNewItem->isCorrelated = pOldItem->isCorrelated;
     pNewItem->viaCoroutine = pOldItem->viaCoroutine;
+    pNewItem->isRecursive = pOldItem->isRecursive;
     pNewItem->zIndex = sqlite3DbStrDup(db, pOldItem->zIndex);
     pNewItem->notIndexed = pOldItem->notIndexed;
     pNewItem->pIndex = pOldItem->pIndex;
index b0adb86295dfe97292f582c3d69000995b241ad2..d54442e79c9694252f47ea12b40877580ab0f05d 100644 (file)
@@ -502,6 +502,14 @@ lookupname_end:
     if( pExpr->op!=TK_AS ){
       sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList);
     }
+
+    /* If this expression reads a column value from a recursive CTE 
+    ** reference, then this is equivalent to reading from the outermost
+    ** available name-context.  */
+    if( pMatch && pMatch->isRecursive ){
+      while( pNC->pNext ) pNC = pNC->pNext;
+    }
+
     /* Increment the nRef value on all name contexts from TopNC up to
     ** the point where the name matched. */
     for(;;){
index 34a2297c96c9c93d8554dcdb0c1fe56d8d041f30..3f9f2de55158b2364e9782ab6394a207cc810b0f 100644 (file)
@@ -3551,7 +3551,9 @@ static int withExpand(
 
   if( pCte==pParse->pCte && (pTab = pCte->pTab) ){
     /* This is the recursive part of a recursive CTE */
+    assert( pFrom->pTab==0 && pFrom->isRecursive==0 );
     pFrom->pTab = pTab;
+    pFrom->isRecursive = 1;
     pTab->nRef++;
   }else{
     ExprList *pEList;
index c7f0609ba1a022f0c5866c11f876172d71f06db7..c52013f87f1192be063c91b895497fbb9525e8de 100644 (file)
@@ -2019,6 +2019,7 @@ struct SrcList {
     unsigned notIndexed :1;    /* True if there is a NOT INDEXED clause */
     unsigned isCorrelated :1;  /* True if sub-query is correlated */
     unsigned viaCoroutine :1;  /* Implemented as a co-routine */
+    unsigned isRecursive :1;   /* True for recursive reference in WITH */
 #ifndef SQLITE_OMIT_EXPLAIN
     u8 iSelectId;     /* If pSelect!=0, the id of the sub-select in EQP */
 #endif
index dd1d5c0ab052b879e5ae1af8481ec60566c21693..1f227e81651daa1504cf6512b5b64cae4eb55a9d 100644 (file)
@@ -244,6 +244,25 @@ do_execsql_test 6.2 {
   /home/dan/public_html/index.html/logo.gif
 }
 
+do_execsql_test 6.3 {
+  WITH flat(fid, fpath) AS (
+    SELECT id, '' FROM f WHERE parentid IS NULL
+    UNION ALL
+    SELECT id, fpath || '/' || name FROM f, flat WHERE parentid=+fid
+  )
+  SELECT count(*) FROM flat;
+} {15}
+
+do_execsql_test 6.4 {
+  WITH x(i) AS (
+    SELECT 1
+    UNION ALL
+    SELECT i+1 FROM x WHERE i<10
+  )
+  SELECT count(*) FROM x
+} {10}
+
+
 finish_test