Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitbb45c64

Browse files
committed
Support default arguments and named-argument notation for window functions.
These things didn't work because the planner omitted to do the necessarypreprocessing of a WindowFunc's argument list. Add the few dozen linesof code needed to handle that.Although this sounds like a feature addition, it's really a bug fix becausethe default-argument case was likely to crash previously, due to lack ofchecking of the number of supplied arguments in the built-in windowfunctions. It's not a security issue because there's no way for anon-superuser to create a window function definition with defaults thatrefers to a built-in C function, but nonetheless people might be annoyedthat it crashes rather than producing a useful error message. Soback-patch as far as the patch applies easily, which turns out to be 9.2.I'll put a band-aid in earlier versions as a separate patch.(Note that these features still don't work for aggregates, and fixing thatcase will be harder since we represent aggregate arg lists as target listsnot bare expression lists. There's no crash risk though because CREATEAGGREGATE doesn't accept defaults, and we reject named-argument notationwhen parsing an aggregate call.)
1 parent5829082 commitbb45c64

File tree

6 files changed

+103
-15
lines changed

6 files changed

+103
-15
lines changed

‎doc/src/sgml/syntax.sgml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2533,8 +2533,9 @@ SELECT concat_lower_or_upper('Hello', 'World', uppercase := true);
25332533

25342534
<note>
25352535
<para>
2536-
Named and mixed call notations can currently be used only with regular
2537-
functions, not with aggregate functions or window functions.
2536+
Named and mixed call notations currently cannot be used when calling an
2537+
aggregate function (but they do work when an aggregate function is used
2538+
as a window function).
25382539
</para>
25392540
</note>
25402541
</sect2>

‎src/backend/optimizer/util/clauses.c

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2251,6 +2251,56 @@ eval_const_expressions_mutator(Node *node,
22512251
*/
22522252
return (Node*)copyObject(param);
22532253
}
2254+
caseT_WindowFunc:
2255+
{
2256+
WindowFunc*expr= (WindowFunc*)node;
2257+
Oidfuncid=expr->winfnoid;
2258+
List*args;
2259+
Expr*aggfilter;
2260+
HeapTuplefunc_tuple;
2261+
WindowFunc*newexpr;
2262+
2263+
/*
2264+
* We can't really simplify a WindowFunc node, but we mustn't
2265+
* just fall through to the default processing, because we
2266+
* have to apply expand_function_arguments to its argument
2267+
* list. That takes care of inserting default arguments and
2268+
* expanding named-argument notation.
2269+
*/
2270+
func_tuple=SearchSysCache1(PROCOID,ObjectIdGetDatum(funcid));
2271+
if (!HeapTupleIsValid(func_tuple))
2272+
elog(ERROR,"cache lookup failed for function %u",funcid);
2273+
2274+
args=expand_function_arguments(expr->args,expr->wintype,
2275+
func_tuple);
2276+
2277+
ReleaseSysCache(func_tuple);
2278+
2279+
/* Now, recursively simplify the args (which are a List) */
2280+
args= (List*)
2281+
expression_tree_mutator((Node*)args,
2282+
eval_const_expressions_mutator,
2283+
(void*)context);
2284+
/* ... and the filter expression, which isn't */
2285+
aggfilter= (Expr*)
2286+
eval_const_expressions_mutator((Node*)expr->aggfilter,
2287+
context);
2288+
2289+
/* And build the replacement WindowFunc node */
2290+
newexpr=makeNode(WindowFunc);
2291+
newexpr->winfnoid=expr->winfnoid;
2292+
newexpr->wintype=expr->wintype;
2293+
newexpr->wincollid=expr->wincollid;
2294+
newexpr->inputcollid=expr->inputcollid;
2295+
newexpr->args=args;
2296+
newexpr->aggfilter=aggfilter;
2297+
newexpr->winref=expr->winref;
2298+
newexpr->winstar=expr->winstar;
2299+
newexpr->winagg=expr->winagg;
2300+
newexpr->location=expr->location;
2301+
2302+
return (Node*)newexpr;
2303+
}
22542304
caseT_FuncExpr:
22552305
{
22562306
FuncExpr*expr= (FuncExpr*)node;

‎src/backend/parser/parse_func.c

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -537,17 +537,6 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
537537
errmsg("window functions cannot return sets"),
538538
parser_errposition(pstate,location)));
539539

540-
/*
541-
* We might want to support this later, but for now reject it because
542-
* the planner and executor wouldn't cope with NamedArgExprs in a
543-
* WindowFunc node.
544-
*/
545-
if (argnames!=NIL)
546-
ereport(ERROR,
547-
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
548-
errmsg("window functions cannot use named arguments"),
549-
parser_errposition(pstate,location)));
550-
551540
/* parse_agg.c does additional window-func-specific processing */
552541
transformWindowFuncCall(pstate,wfunc,over);
553542

‎src/backend/utils/adt/ruleutils.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7461,25 +7461,28 @@ get_windowfunc_expr(WindowFunc *wfunc, deparse_context *context)
74617461
StringInfobuf=context->buf;
74627462
Oidargtypes[FUNC_MAX_ARGS];
74637463
intnargs;
7464+
List*argnames;
74647465
ListCell*l;
74657466

74667467
if (list_length(wfunc->args)>FUNC_MAX_ARGS)
74677468
ereport(ERROR,
74687469
(errcode(ERRCODE_TOO_MANY_ARGUMENTS),
74697470
errmsg("too many arguments")));
74707471
nargs=0;
7472+
argnames=NIL;
74717473
foreach(l,wfunc->args)
74727474
{
74737475
Node*arg= (Node*)lfirst(l);
74747476

7475-
Assert(!IsA(arg,NamedArgExpr));
7477+
if (IsA(arg,NamedArgExpr))
7478+
argnames=lappend(argnames, ((NamedArgExpr*)arg)->name);
74767479
argtypes[nargs]=exprType(arg);
74777480
nargs++;
74787481
}
74797482

74807483
appendStringInfo(buf,"%s(",
74817484
generate_function_name(wfunc->winfnoid,nargs,
7482-
NIL,argtypes,
7485+
argnames,argtypes,
74837486
false,NULL));
74847487
/* winstar can be set only in zero-argument aggregates */
74857488
if (wfunc->winstar)

‎src/test/regress/expected/window.out

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1035,3 +1035,38 @@ FROM empsalary GROUP BY depname;
10351035

10361036
-- cleanup
10371037
DROP TABLE empsalary;
1038+
-- test user-defined window function with named args and default args
1039+
CREATE FUNCTION nth_value_def(val anyelement, n integer = 1) RETURNS anyelement
1040+
LANGUAGE internal WINDOW IMMUTABLE STRICT AS 'window_nth_value';
1041+
SELECT nth_value_def(n := 2, val := ten) OVER (PARTITION BY four), ten, four
1042+
FROM (SELECT * FROM tenk1 WHERE unique2 < 10 ORDER BY four, ten) s;
1043+
nth_value_def | ten | four
1044+
---------------+-----+------
1045+
0 | 0 | 0
1046+
0 | 0 | 0
1047+
0 | 4 | 0
1048+
1 | 1 | 1
1049+
1 | 1 | 1
1050+
1 | 7 | 1
1051+
1 | 9 | 1
1052+
| 0 | 2
1053+
3 | 1 | 3
1054+
3 | 3 | 3
1055+
(10 rows)
1056+
1057+
SELECT nth_value_def(ten) OVER (PARTITION BY four), ten, four
1058+
FROM (SELECT * FROM tenk1 WHERE unique2 < 10 ORDER BY four, ten) s;
1059+
nth_value_def | ten | four
1060+
---------------+-----+------
1061+
0 | 0 | 0
1062+
0 | 0 | 0
1063+
0 | 4 | 0
1064+
1 | 1 | 1
1065+
1 | 1 | 1
1066+
1 | 7 | 1
1067+
1 | 9 | 1
1068+
0 | 0 | 2
1069+
1 | 1 | 3
1070+
1 | 3 | 3
1071+
(10 rows)
1072+

‎src/test/regress/sql/window.sql

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,3 +274,13 @@ FROM empsalary GROUP BY depname;
274274

275275
-- cleanup
276276
DROPTABLE empsalary;
277+
278+
-- test user-defined window function with named args and default args
279+
CREATEFUNCTIONnth_value_def(val anyelement, ninteger=1) RETURNS anyelement
280+
LANGUAGE internal WINDOW IMMUTABLE STRICTAS'window_nth_value';
281+
282+
SELECT nth_value_def(n :=2, val := ten) OVER (PARTITION BY four), ten, four
283+
FROM (SELECT*FROM tenk1WHERE unique2<10ORDER BY four, ten) s;
284+
285+
SELECT nth_value_def(ten) OVER (PARTITION BY four), ten, four
286+
FROM (SELECT*FROM tenk1WHERE unique2<10ORDER BY four, ten) s;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp