From b560ec1b0d7b910ce13edc51ffaafaca72136e3b Mon Sep 17 00:00:00 2001 From: Noah Misch Date: Tue, 16 Jul 2013 20:15:36 -0400 Subject: Implement the FILTER clause for aggregate function calls. This is SQL-standard with a few extensions, namely support for subqueries and outer references in clause expressions. catversion bump due to change in Aggref and WindowFunc. David Fetter, reviewed by Dean Rasheed. --- src/backend/parser/parse_expr.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) (limited to 'src/backend/parser/parse_expr.c') diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index 06f6512c4e4..68b711dfd9a 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -22,6 +22,7 @@ #include "nodes/nodeFuncs.h" #include "optimizer/var.h" #include "parser/analyze.h" +#include "parser/parse_clause.h" #include "parser/parse_coerce.h" #include "parser/parse_collate.h" #include "parser/parse_expr.h" @@ -462,7 +463,7 @@ transformIndirection(ParseState *pstate, Node *basenode, List *indirection) newresult = ParseFuncOrColumn(pstate, list_make1(n), list_make1(result), - NIL, false, false, false, + NIL, NULL, false, false, false, NULL, true, location); if (newresult == NULL) unknown_attribute(pstate, result, strVal(n), location); @@ -630,7 +631,7 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref) node = ParseFuncOrColumn(pstate, list_make1(makeString(colname)), list_make1(node), - NIL, false, false, false, + NIL, NULL, false, false, false, NULL, true, cref->location); } break; @@ -675,7 +676,7 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref) node = ParseFuncOrColumn(pstate, list_make1(makeString(colname)), list_make1(node), - NIL, false, false, false, + NIL, NULL, false, false, false, NULL, true, cref->location); } break; @@ -733,7 +734,7 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref) node = ParseFuncOrColumn(pstate, list_make1(makeString(colname)), list_make1(node), - NIL, false, false, false, + NIL, NULL, false, false, false, NULL, true, cref->location); } break; @@ -1241,6 +1242,7 @@ transformFuncCall(ParseState *pstate, FuncCall *fn) { List *targs; ListCell *args; + Expr *tagg_filter; /* Transform the list of arguments ... */ targs = NIL; @@ -1250,11 +1252,22 @@ transformFuncCall(ParseState *pstate, FuncCall *fn) (Node *) lfirst(args))); } + /* + * Transform the aggregate filter using transformWhereClause(), to which + * FILTER is virtually identical... + */ + tagg_filter = NULL; + if (fn->agg_filter != NULL) + tagg_filter = (Expr *) + transformWhereClause(pstate, (Node *) fn->agg_filter, + EXPR_KIND_FILTER, "FILTER"); + /* ... and hand off to ParseFuncOrColumn */ return ParseFuncOrColumn(pstate, fn->funcname, targs, fn->agg_order, + tagg_filter, fn->agg_star, fn->agg_distinct, fn->func_variadic, @@ -1430,6 +1443,7 @@ transformSubLink(ParseState *pstate, SubLink *sublink) case EXPR_KIND_FROM_FUNCTION: case EXPR_KIND_WHERE: case EXPR_KIND_HAVING: + case EXPR_KIND_FILTER: case EXPR_KIND_WINDOW_PARTITION: case EXPR_KIND_WINDOW_ORDER: case EXPR_KIND_WINDOW_FRAME_RANGE: @@ -2579,6 +2593,8 @@ ParseExprKindName(ParseExprKind exprKind) return "WHERE"; case EXPR_KIND_HAVING: return "HAVING"; + case EXPR_KIND_FILTER: + return "FILTER"; case EXPR_KIND_WINDOW_PARTITION: return "window PARTITION BY"; case EXPR_KIND_WINDOW_ORDER: -- cgit v1.2.3