aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordan <dan@noemail.net>2014-01-15 18:12:00 +0000
committerdan <dan@noemail.net>2014-01-15 18:12:00 +0000
commitf43fe6e9f6e8e7e7c2ab43234f46c5767f63b27c (patch)
treeabed19fa9b97c3725d24960c02a0abaf45f70a69 /src
parent60e7068d75acc643cfd045a7cb90d635079f3457 (diff)
downloadsqlite-f43fe6e9f6e8e7e7c2ab43234f46c5767f63b27c.tar.gz
sqlite-f43fe6e9f6e8e7e7c2ab43234f46c5767f63b27c.zip
When resolving names, consider a reference to a recursive CTE column as equivalent to a reference to the outermost name-context. This ensures that correlated sub-queries are correctly identified as such.
FossilOrigin-Name: 61be2da0ae623c1572819481508b044e9d32f294
Diffstat (limited to 'src')
-rw-r--r--src/expr.c1
-rw-r--r--src/resolve.c8
-rw-r--r--src/select.c2
-rw-r--r--src/sqliteInt.h1
4 files changed, 12 insertions, 0 deletions
diff --git a/src/expr.c b/src/expr.c
index fca03a8d9..9a288b73b 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -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;
diff --git a/src/resolve.c b/src/resolve.c
index b0adb8629..d54442e79 100644
--- a/src/resolve.c
+++ b/src/resolve.c
@@ -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(;;){
diff --git a/src/select.c b/src/select.c
index 34a2297c9..3f9f2de55 100644
--- a/src/select.c
+++ b/src/select.c
@@ -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;
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index c7f0609ba..c52013f87 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -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