diff options
author | drh <drh@noemail.net> | 2012-08-23 16:18:10 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2012-08-23 16:18:10 +0000 |
commit | 030796df8d36a781ce062fad3fcb7312b8ac6a47 (patch) | |
tree | be229e02e99b56c9d35e6d418921865d66cdcee7 /src/expr.c | |
parent | 2f7d5d83946b7ccb14dff3b82375d9a25b34d76d (diff) | |
download | sqlite-030796df8d36a781ce062fad3fcb7312b8ac6a47.tar.gz sqlite-030796df8d36a781ce062fad3fcb7312b8ac6a47.zip |
Further improvements to the processing of nested aggregate queries.
FossilOrigin-Name: 3c3ffa901f5ce8a523028ff15563ce3e0f55a641
Diffstat (limited to 'src/expr.c')
-rw-r--r-- | src/expr.c | 65 |
1 files changed, 51 insertions, 14 deletions
diff --git a/src/expr.c b/src/expr.c index 790aa45f3..e2f8b4578 100644 --- a/src/expr.c +++ b/src/expr.c @@ -3816,22 +3816,35 @@ int sqlite3ExprListCompare(ExprList *pA, ExprList *pB){ } /* -** This is the expression callback for sqlite3FunctionUsesOtherSrc(). -** -** Determine if an expression references any table other than one of the -** tables in pWalker->u.pSrcList and abort if it does. +** An instance of the following structure is used by the tree walker +** to count references to table columns in the arguments of an +** aggregate function, in order to implement the sqlite3FunctionUsesOtherSrc() +** and sqlite3FunctionThisSrc() routines. */ -static int exprUsesOtherSrc(Walker *pWalker, Expr *pExpr){ +struct SrcCount { + SrcList *pSrc; /* One particular FROM clause in a nested query */ + int nThis; /* Number of references to columns in pSrcList */ + int nOther; /* Number of references to columns in other FROM clauses */ +}; + +/* +** Count the number of references to columns. +*/ +static int exprSrcCount(Walker *pWalker, Expr *pExpr){ if( pExpr->op==TK_COLUMN || pExpr->op==TK_AGG_COLUMN ){ int i; - SrcList *pSrc = pWalker->u.pSrcList; + struct SrcCount *p = pWalker->u.pSrcCount; + SrcList *pSrc = p->pSrc; for(i=0; i<pSrc->nSrc; i++){ - if( pExpr->iTable==pSrc->a[i].iCursor ) return WRC_Continue; + if( pExpr->iTable==pSrc->a[i].iCursor ) break; + } + if( i<pSrc->nSrc ){ + p->nThis++; + }else{ + p->nOther++; } - return WRC_Abort; - }else{ - return WRC_Continue; } + return WRC_Continue; } /* @@ -3842,12 +3855,36 @@ static int exprUsesOtherSrc(Walker *pWalker, Expr *pExpr){ */ static int sqlite3FunctionUsesOtherSrc(Expr *pExpr, SrcList *pSrcList){ Walker w; + struct SrcCount cnt; assert( pExpr->op==TK_AGG_FUNCTION ); memset(&w, 0, sizeof(w)); - w.xExprCallback = exprUsesOtherSrc; - w.u.pSrcList = pSrcList; - if( sqlite3WalkExprList(&w, pExpr->x.pList)!=WRC_Continue ) return 1; - return 0; + w.xExprCallback = exprSrcCount; + w.u.pSrcCount = &cnt; + cnt.pSrc = pSrcList; + cnt.nThis = 0; + cnt.nOther = 0; + sqlite3WalkExprList(&w, pExpr->x.pList); + return cnt.nOther>0; +} + +/* +** Determine if any of the arguments to the pExpr Function reference +** pSrcList. Return true if they do. Also return true if the function +** has no arguments or has only constant arguments. Return false if pExpr +** references columns but not columns of tables found in pSrcList. +*/ +int sqlite3FunctionUsesThisSrc(Expr *pExpr, SrcList *pSrcList){ + Walker w; + struct SrcCount cnt; + assert( pExpr->op==TK_AGG_FUNCTION ); + memset(&w, 0, sizeof(w)); + w.xExprCallback = exprSrcCount; + w.u.pSrcCount = &cnt; + cnt.pSrc = pSrcList; + cnt.nThis = 0; + cnt.nOther = 0; + sqlite3WalkExprList(&w, pExpr->x.pList); + return cnt.nThis>0 || cnt.nOther==0; } /* |