aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/parser')
-rw-r--r--src/backend/parser/gram.y47
-rw-r--r--src/backend/parser/parse_agg.c16
-rw-r--r--src/backend/parser/parse_func.c16
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,