aboutsummaryrefslogtreecommitdiff
path: root/src/expr.c
diff options
context:
space:
mode:
authordan <dan@noemail.net>2017-04-29 20:53:09 +0000
committerdan <dan@noemail.net>2017-04-29 20:53:09 +0000
commitab31a8450b5d4a122c8157d2aaf281b8844b0d6b (patch)
tree76261c52185e7a00a1d081d24a462671d56df448 /src/expr.c
parentbc43995f99d3f15aa3cb056068ee7e6b7ca40029 (diff)
downloadsqlite-ab31a8450b5d4a122c8157d2aaf281b8844b0d6b.tar.gz
sqlite-ab31a8450b5d4a122c8157d2aaf281b8844b0d6b.zip
Automatically transfer terms from the HAVING clause to the WHERE clause of an
aggregate query in cases where the result of evaluating the term depends only one one or more of the GROUP BY expressions (and on no other inputs). FossilOrigin-Name: 5375a3ce56f1d993b13b469fe33ec7679948f53940f62a15ddbaeb8aaa26a22c
Diffstat (limited to 'src/expr.c')
-rw-r--r--src/expr.c45
1 files changed, 45 insertions, 0 deletions
diff --git a/src/expr.c b/src/expr.c
index 873911633..73143c51d 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -1815,6 +1815,51 @@ int sqlite3ExprIsTableConstant(Expr *p, int iCur){
return exprIsConst(p, 3, iCur);
}
+
+/*
+** sqlite3WalkExpr() callback used by sqlite3ExprIsConstantOrGroupBy().
+*/
+static int exprNodeIsConstantOrGroupBy(Walker *pWalker, Expr *pExpr){
+ ExprList *pGroupBy = pWalker->u.pGroupBy;
+ int i;
+
+ /* Check if pExpr is identical to any GROUP BY term. If so, consider
+ ** it constant. */
+ for(i=0; i<pGroupBy->nExpr; i++){
+ Expr *p = pGroupBy->a[i].pExpr;
+ if( sqlite3ExprCompare(pExpr, p, -1)<2 ){
+ CollSeq *pColl = sqlite3ExprCollSeq(pWalker->pParse, p);
+ if( pColl==0 || sqlite3_stricmp("BINARY", pColl->zName)==0 ){
+ return WRC_Prune;
+ }
+ }
+ }
+
+ /* Check if pExpr is a sub-select. If so, consider it variable. */
+ if( ExprHasProperty(pExpr, EP_xIsSelect) ){
+ pWalker->eCode = 0;
+ return WRC_Abort;
+ }
+
+ return exprNodeIsConstant(pWalker, pExpr);
+}
+
+/*
+** Walk the expression tree passed as the first argument. Return non-zero
+** if the expression consists entirely of constants or copies of terms
+** in pGroupBy that sort with the BINARY collation sequence.
+*/
+int sqlite3ExprIsConstantOrGroupBy(Parse *pParse, Expr *p, ExprList *pGroupBy){
+ Walker w;
+ memset(&w, 0, sizeof(w));
+ w.eCode = 1;
+ w.xExprCallback = exprNodeIsConstantOrGroupBy;
+ w.u.pGroupBy = pGroupBy;
+ w.pParse = pParse;
+ sqlite3WalkExpr(&w, p);
+ return w.eCode;
+}
+
/*
** Walk an expression tree. Return non-zero if the expression is constant
** or a function call with constant arguments. Return and 0 if there