diff options
Diffstat (limited to 'src/backend/parser')
-rw-r--r-- | src/backend/parser/gram.y | 19 | ||||
-rw-r--r-- | src/backend/parser/parse_func.c | 9 |
2 files changed, 23 insertions, 5 deletions
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index f1def67ac7c..57bf7a7c7f2 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -632,7 +632,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); %type <list> window_clause window_definition_list opt_partition_clause %type <windef> window_definition over_clause window_specification opt_frame_clause frame_extent frame_bound -%type <ival> opt_window_exclusion_clause +%type <ival> null_treatment opt_window_exclusion_clause %type <str> opt_existing_window_name %type <boolean> opt_if_not_exists %type <boolean> opt_unique_null_treatment @@ -730,7 +730,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); HANDLER HAVING HEADER_P HOLD HOUR_P - IDENTITY_P IF_P ILIKE IMMEDIATE IMMUTABLE IMPLICIT_P IMPORT_P IN_P INCLUDE + IDENTITY_P IF_P IGNORE_P ILIKE IMMEDIATE IMMUTABLE IMPLICIT_P IMPORT_P IN_P INCLUDE INCLUDING INCREMENT INDENT INDEX INDEXES INHERIT INHERITS INITIALLY INLINE_P INNER_P INOUT INPUT_P INSENSITIVE INSERT INSTEAD INT_P INTEGER INTERSECT INTERVAL INTO INVOKER IS ISNULL ISOLATION @@ -765,7 +765,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); RANGE READ REAL REASSIGN RECURSIVE REF_P REFERENCES REFERENCING REFRESH REINDEX RELATIVE_P RELEASE RENAME REPEATABLE REPLACE REPLICA - RESET RESTART RESTRICT RETURN RETURNING RETURNS REVOKE RIGHT ROLE ROLLBACK ROLLUP + RESET RESPECT_P RESTART RESTRICT RETURN RETURNING RETURNS REVOKE RIGHT ROLE ROLLBACK ROLLUP ROUTINE ROUTINES ROW ROWS RULE SAVEPOINT SCALAR SCHEMA SCHEMAS SCROLL SEARCH SECOND_P SECURITY SELECT @@ -15805,7 +15805,7 @@ func_application: func_name '(' ')' * (Note that many of the special SQL functions wouldn't actually make any * sense as functional index entries, but we ignore that consideration here.) */ -func_expr: func_application within_group_clause filter_clause over_clause +func_expr: func_application within_group_clause filter_clause null_treatment over_clause { FuncCall *n = (FuncCall *) $1; @@ -15838,7 +15838,8 @@ func_expr: func_application within_group_clause filter_clause over_clause n->agg_within_group = true; } n->agg_filter = $3; - n->over = $4; + n->ignore_nulls = $4; + n->over = $5; $$ = (Node *) n; } | json_aggregate_func filter_clause over_clause @@ -16434,6 +16435,12 @@ filter_clause: /* * Window Definitions */ +null_treatment: + IGNORE_P NULLS_P { $$ = PARSER_IGNORE_NULLS; } + | RESPECT_P NULLS_P { $$ = PARSER_RESPECT_NULLS; } + | /*EMPTY*/ { $$ = NO_NULLTREATMENT; } + ; + window_clause: WINDOW window_definition_list { $$ = $2; } | /*EMPTY*/ { $$ = NIL; } @@ -17861,6 +17868,7 @@ unreserved_keyword: | HOUR_P | IDENTITY_P | IF_P + | IGNORE_P | IMMEDIATE | IMMUTABLE | IMPLICIT_P @@ -17979,6 +17987,7 @@ unreserved_keyword: | REPLACE | REPLICA | RESET + | RESPECT_P | RESTART | RESTRICT | RETURN diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c index c43020a769d..778d69c6f3c 100644 --- a/src/backend/parser/parse_func.c +++ b/src/backend/parser/parse_func.c @@ -100,6 +100,7 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, bool agg_star = (fn ? fn->agg_star : false); bool agg_distinct = (fn ? fn->agg_distinct : false); bool func_variadic = (fn ? fn->func_variadic : false); + int ignore_nulls = (fn ? fn->ignore_nulls : NO_NULLTREATMENT); CoercionForm funcformat = (fn ? fn->funcformat : COERCE_EXPLICIT_CALL); bool could_be_projection; Oid rettype; @@ -518,6 +519,13 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, errmsg("%s is not an ordered-set aggregate, so it cannot have WITHIN GROUP", NameListToString(funcname)), parser_errposition(pstate, location))); + + /* It also can't treat nulls as a window function */ + if (ignore_nulls != NO_NULLTREATMENT) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("aggregate functions do not accept RESPECT/IGNORE NULLS"), + parser_errposition(pstate, location))); } } else if (fdresult == FUNCDETAIL_WINDOWFUNC) @@ -840,6 +848,7 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, wfunc->winstar = agg_star; wfunc->winagg = (fdresult == FUNCDETAIL_AGGREGATE); wfunc->aggfilter = agg_filter; + wfunc->ignore_nulls = ignore_nulls; wfunc->runCondition = NIL; wfunc->location = location; |