diff options
Diffstat (limited to 'src/backend/parser')
-rw-r--r-- | src/backend/parser/gram.y | 47 | ||||
-rw-r--r-- | src/backend/parser/parse_agg.c | 16 | ||||
-rw-r--r-- | src/backend/parser/parse_func.c | 16 |
3 files changed, 53 insertions, 26 deletions
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 22e82ba146b..a9812af7cfc 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -324,8 +324,9 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); reloptions opt_reloptions OptWith opt_distinct opt_definition func_args func_args_list func_args_with_defaults func_args_with_defaults_list + aggr_args aggr_args_list func_as createfunc_opt_list alterfunc_opt_list - aggr_args old_aggr_definition old_aggr_list + old_aggr_definition old_aggr_list oper_argtypes RuleActionList RuleActionMulti opt_column_list columnList opt_name_list sort_clause opt_sort_clause sortby_list index_params @@ -352,7 +353,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); %type <into> into_clause create_as_target create_mv_target %type <defelt> createfunc_opt_item common_func_opt_item dostmt_opt_item -%type <fun_param> func_arg func_arg_with_default table_func_column +%type <fun_param> func_arg func_arg_with_default table_func_column aggr_arg %type <fun_param_mode> arg_class %type <typnam> func_return func_type @@ -3659,7 +3660,7 @@ AlterExtensionContentsStmt: n->action = $4; n->objtype = OBJECT_AGGREGATE; n->objname = $6; - n->objargs = $7; + n->objargs = extractArgTypes($7); $$ = (Node *)n; } | ALTER EXTENSION name add_drop CAST '(' Typename AS Typename ')' @@ -4760,10 +4761,6 @@ def_arg: func_type { $$ = (Node *)$1; } | Sconst { $$ = (Node *)makeString($1); } ; -aggr_args: '(' type_list ')' { $$ = $2; } - | '(' '*' ')' { $$ = NIL; } - ; - old_aggr_definition: '(' old_aggr_list ')' { $$ = $2; } ; @@ -5242,7 +5239,7 @@ CommentStmt: CommentStmt *n = makeNode(CommentStmt); n->objtype = OBJECT_AGGREGATE; n->objname = $4; - n->objargs = $5; + n->objargs = extractArgTypes($5); n->comment = $7; $$ = (Node *) n; } @@ -5408,7 +5405,7 @@ SecLabelStmt: n->provider = $3; n->objtype = OBJECT_AGGREGATE; n->objname = $6; - n->objargs = $7; + n->objargs = extractArgTypes($7); n->label = $9; $$ = (Node *) n; } @@ -6395,6 +6392,28 @@ func_arg_with_default: } ; +/* Aggregate args can be most things that function args can be */ +aggr_arg: func_arg + { + if (!($1->mode == FUNC_PARAM_IN || + $1->mode == FUNC_PARAM_VARIADIC)) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("aggregates cannot have output arguments"), + parser_errposition(@1))); + $$ = $1; + } + ; + +/* Zero-argument aggregates are named with * for consistency with COUNT(*) */ +aggr_args: '(' aggr_args_list ')' { $$ = $2; } + | '(' '*' ')' { $$ = NIL; } + ; + +aggr_args_list: + aggr_arg { $$ = list_make1($1); } + | aggr_args_list ',' aggr_arg { $$ = lappend($1, $3); } + ; createfunc_opt_list: /* Must be at least one to prevent conflict */ @@ -6594,7 +6613,7 @@ RemoveAggrStmt: DropStmt *n = makeNode(DropStmt); n->removeType = OBJECT_AGGREGATE; n->objects = list_make1($3); - n->arguments = list_make1($4); + n->arguments = list_make1(extractArgTypes($4)); n->behavior = $5; n->missing_ok = false; n->concurrent = false; @@ -6605,7 +6624,7 @@ RemoveAggrStmt: DropStmt *n = makeNode(DropStmt); n->removeType = OBJECT_AGGREGATE; n->objects = list_make1($5); - n->arguments = list_make1($6); + n->arguments = list_make1(extractArgTypes($6)); n->behavior = $7; n->missing_ok = true; n->concurrent = false; @@ -6821,7 +6840,7 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name RenameStmt *n = makeNode(RenameStmt); n->renameType = OBJECT_AGGREGATE; n->object = $3; - n->objarg = $4; + n->objarg = extractArgTypes($4); n->newname = $7; n->missing_ok = false; $$ = (Node *)n; @@ -7295,7 +7314,7 @@ AlterObjectSchemaStmt: AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt); n->objectType = OBJECT_AGGREGATE; n->object = $3; - n->objarg = $4; + n->objarg = extractArgTypes($4); n->newschema = $7; n->missing_ok = false; $$ = (Node *)n; @@ -7524,7 +7543,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId AlterOwnerStmt *n = makeNode(AlterOwnerStmt); n->objectType = OBJECT_AGGREGATE; n->object = $3; - n->objarg = $4; + n->objarg = extractArgTypes($4); n->newowner = $7; $$ = (Node *)n; } diff --git a/src/backend/parser/parse_agg.c b/src/backend/parser/parse_agg.c index 4e4e1cddd83..98cb58a7cc0 100644 --- a/src/backend/parser/parse_agg.c +++ b/src/backend/parser/parse_agg.c @@ -965,6 +965,7 @@ check_ungrouped_columns_walker(Node *node, void build_aggregate_fnexprs(Oid *agg_input_types, int agg_num_inputs, + bool agg_variadic, Oid agg_state_type, Oid agg_result_type, Oid agg_input_collation, @@ -975,6 +976,7 @@ build_aggregate_fnexprs(Oid *agg_input_types, { Param *argp; List *args; + FuncExpr *fexpr; int i; /* @@ -1005,12 +1007,14 @@ build_aggregate_fnexprs(Oid *agg_input_types, args = lappend(args, argp); } - *transfnexpr = (Expr *) makeFuncExpr(transfn_oid, - agg_state_type, - args, - InvalidOid, - agg_input_collation, - COERCE_EXPLICIT_CALL); + fexpr = makeFuncExpr(transfn_oid, + agg_state_type, + args, + InvalidOid, + agg_input_collation, + COERCE_EXPLICIT_CALL); + fexpr->funcvariadic = agg_variadic; + *transfnexpr = (Expr *) fexpr; /* see if we have a final function */ if (!OidIsValid(finalfn_oid)) diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c index 1f02c9a5757..2bd24c89c87 100644 --- a/src/backend/parser/parse_func.c +++ b/src/backend/parser/parse_func.c @@ -385,7 +385,7 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, } /* - * When function is called an explicit VARIADIC labeled parameter, + * When function is called with an explicit VARIADIC labeled parameter, * and the declared_arg_type is "any", then sanity check the actual * parameter type now - it must be an array. */ @@ -425,8 +425,9 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, aggref->aggtype = rettype; /* aggcollid and inputcollid will be set by parse_collate.c */ /* args, aggorder, aggdistinct will be set by transformAggregateCall */ - aggref->aggstar = agg_star; aggref->aggfilter = agg_filter; + aggref->aggstar = agg_star; + aggref->aggvariadic = func_variadic; /* agglevelsup will be set by transformAggregateCall */ aggref->location = location; @@ -448,10 +449,13 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, parser_errposition(pstate, location))); /* - * Currently it's not possible to define an aggregate with named - * arguments, so this case should be impossible. Check anyway because - * the planner and executor wouldn't cope with NamedArgExprs in an - * Aggref node. + * We might want to support named arguments later, but disallow it for + * now. We'd need to figure out the parsed representation (should the + * NamedArgExprs go above or below the TargetEntry nodes?) and then + * teach the planner to reorder the list properly. Or maybe we could + * make transformAggregateCall do that? However, if you'd also like + * to allow default arguments for aggregates, we'd need to do it in + * planning to avoid semantic problems. */ if (argnames != NIL) ereport(ERROR, |