diff options
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/optimizer/util/clauses.c | 50 | ||||
-rw-r--r-- | src/backend/parser/parse_func.c | 11 | ||||
-rw-r--r-- | src/backend/utils/adt/ruleutils.c | 7 |
3 files changed, 55 insertions, 13 deletions
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index 76c032c5698..4fa73a9d223 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -2251,6 +2251,56 @@ eval_const_expressions_mutator(Node *node, */ return (Node *) copyObject(param); } + case T_WindowFunc: + { + WindowFunc *expr = (WindowFunc *) node; + Oid funcid = expr->winfnoid; + List *args; + Expr *aggfilter; + HeapTuple func_tuple; + WindowFunc *newexpr; + + /* + * We can't really simplify a WindowFunc node, but we mustn't + * just fall through to the default processing, because we + * have to apply expand_function_arguments to its argument + * list. That takes care of inserting default arguments and + * expanding named-argument notation. + */ + func_tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid)); + if (!HeapTupleIsValid(func_tuple)) + elog(ERROR, "cache lookup failed for function %u", funcid); + + args = expand_function_arguments(expr->args, expr->wintype, + func_tuple); + + ReleaseSysCache(func_tuple); + + /* Now, recursively simplify the args (which are a List) */ + args = (List *) + expression_tree_mutator((Node *) args, + eval_const_expressions_mutator, + (void *) context); + /* ... and the filter expression, which isn't */ + aggfilter = (Expr *) + eval_const_expressions_mutator((Node *) expr->aggfilter, + context); + + /* And build the replacement WindowFunc node */ + newexpr = makeNode(WindowFunc); + newexpr->winfnoid = expr->winfnoid; + newexpr->wintype = expr->wintype; + newexpr->wincollid = expr->wincollid; + newexpr->inputcollid = expr->inputcollid; + newexpr->args = args; + newexpr->aggfilter = aggfilter; + newexpr->winref = expr->winref; + newexpr->winstar = expr->winstar; + newexpr->winagg = expr->winagg; + newexpr->location = expr->location; + + return (Node *) newexpr; + } case T_FuncExpr: { FuncExpr *expr = (FuncExpr *) node; diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c index 2bd24c89c87..ede36d159a3 100644 --- a/src/backend/parser/parse_func.c +++ b/src/backend/parser/parse_func.c @@ -537,17 +537,6 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, errmsg("window functions cannot return sets"), parser_errposition(pstate, location))); - /* - * We might want to support this later, but for now reject it because - * the planner and executor wouldn't cope with NamedArgExprs in a - * WindowFunc node. - */ - if (argnames != NIL) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("window functions cannot use named arguments"), - parser_errposition(pstate, location))); - /* parse_agg.c does additional window-func-specific processing */ transformWindowFuncCall(pstate, wfunc, over); diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 04b1c4f8956..915fb7a6689 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -7461,6 +7461,7 @@ get_windowfunc_expr(WindowFunc *wfunc, deparse_context *context) StringInfo buf = context->buf; Oid argtypes[FUNC_MAX_ARGS]; int nargs; + List *argnames; ListCell *l; if (list_length(wfunc->args) > FUNC_MAX_ARGS) @@ -7468,18 +7469,20 @@ get_windowfunc_expr(WindowFunc *wfunc, deparse_context *context) (errcode(ERRCODE_TOO_MANY_ARGUMENTS), errmsg("too many arguments"))); nargs = 0; + argnames = NIL; foreach(l, wfunc->args) { Node *arg = (Node *) lfirst(l); - Assert(!IsA(arg, NamedArgExpr)); + if (IsA(arg, NamedArgExpr)) + argnames = lappend(argnames, ((NamedArgExpr *) arg)->name); argtypes[nargs] = exprType(arg); nargs++; } appendStringInfo(buf, "%s(", generate_function_name(wfunc->winfnoid, nargs, - NIL, argtypes, + argnames, argtypes, false, NULL)); /* winstar can be set only in zero-argument aggregates */ if (wfunc->winstar) |