diff options
author | dan <dan@noemail.net> | 2020-06-09 17:45:48 +0000 |
---|---|---|
committer | dan <dan@noemail.net> | 2020-06-09 17:45:48 +0000 |
commit | ed41a96bc1e3a6eb011330b0a109ae4fc703a14c (patch) | |
tree | 42785e67f3f092e33289b83b2eb768c1af9784b0 /src/expr.c | |
parent | cfb8bf6a501ccc5f67b9ae84ad1b6aa40bc1a374 (diff) | |
download | sqlite-ed41a96bc1e3a6eb011330b0a109ae4fc703a14c.tar.gz sqlite-ed41a96bc1e3a6eb011330b0a109ae4fc703a14c.zip |
Ensure that aggregate functions that (a) are part of SELECT statements with no FROM clause and (b) have one or more scalar sub-selects as arguments are assigned to the correct aggregate context.
FossilOrigin-Name: 16a41fa8c4c74bba4e908a9c19e6cf5a927cac140e2070c9abf303158be7257b
Diffstat (limited to 'src/expr.c')
-rw-r--r-- | src/expr.c | 20 |
1 files changed, 18 insertions, 2 deletions
diff --git a/src/expr.c b/src/expr.c index 555b2a8d8..87dbe617a 100644 --- a/src/expr.c +++ b/src/expr.c @@ -5654,11 +5654,26 @@ int sqlite3ExprCoveredByIndex( */ struct SrcCount { SrcList *pSrc; /* One particular FROM clause in a nested query */ + int iSrcInner; /* Smallest cursor number in this context */ int nThis; /* Number of references to columns in pSrcList */ int nOther; /* Number of references to columns in other FROM clauses */ }; /* +** xSelect callback for sqlite3FunctionUsesThisSrc(). If this is the first +** SELECT with a FROM clause encountered during this iteration, set +** SrcCount.iSrcInner to the cursor number of the leftmost object in +** the FROM cause. +*/ +static int selectSrcCount(Walker *pWalker, Select *pSel){ + struct SrcCount *p = pWalker->u.pSrcCount; + if( p->iSrcInner==0x7FFFFFFF && pSel->pSrc && pSel->pSrc->nSrc ){ + pWalker->u.pSrcCount->iSrcInner = pSel->pSrc->a[0].iCursor; + } + return WRC_Continue; +} + +/* ** Count the number of references to columns. */ static int exprSrcCount(Walker *pWalker, Expr *pExpr){ @@ -5678,7 +5693,7 @@ static int exprSrcCount(Walker *pWalker, Expr *pExpr){ } if( i<nSrc ){ p->nThis++; - }else if( nSrc==0 || pExpr->iTable<pSrc->a[0].iCursor ){ + }else if( pExpr->iTable<p->iSrcInner ){ /* In a well-formed parse tree (no name resolution errors), ** TK_COLUMN nodes with smaller Expr.iTable values are in an ** outer context. Those are the only ones to count as "other" */ @@ -5700,9 +5715,10 @@ int sqlite3FunctionUsesThisSrc(Expr *pExpr, SrcList *pSrcList){ assert( pExpr->op==TK_AGG_FUNCTION ); memset(&w, 0, sizeof(w)); w.xExprCallback = exprSrcCount; - w.xSelectCallback = sqlite3SelectWalkNoop; + w.xSelectCallback = selectSrcCount; w.u.pSrcCount = &cnt; cnt.pSrc = pSrcList; + cnt.iSrcInner = (pSrcList&&pSrcList->nSrc)?pSrcList->a[0].iCursor:0x7FFFFFFF; cnt.nThis = 0; cnt.nOther = 0; sqlite3WalkExprList(&w, pExpr->x.pList); |