aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/parser')
-rw-r--r--src/backend/parser/parse_agg.c46
-rw-r--r--src/backend/parser/parse_func.c4
2 files changed, 26 insertions, 24 deletions
diff --git a/src/backend/parser/parse_agg.c b/src/backend/parser/parse_agg.c
index 91bfe66c590..b9ca066698e 100644
--- a/src/backend/parser/parse_agg.c
+++ b/src/backend/parser/parse_agg.c
@@ -77,10 +77,10 @@ static List *expand_groupingset_node(GroupingSet *gs);
* Finish initial transformation of an aggregate call
*
* parse_func.c has recognized the function as an aggregate, and has set up
- * all the fields of the Aggref except aggdirectargs, args, aggorder,
- * aggdistinct and agglevelsup. The passed-in args list has been through
- * standard expression transformation and type coercion to match the agg's
- * declared arg types, while the passed-in aggorder list hasn't been
+ * all the fields of the Aggref except aggargtypes, aggdirectargs, args,
+ * aggorder, aggdistinct and agglevelsup. The passed-in args list has been
+ * through standard expression transformation and type coercion to match the
+ * agg's declared arg types, while the passed-in aggorder list hasn't been
* transformed at all.
*
* Here we separate the args list into direct and aggregated args, storing the
@@ -101,6 +101,7 @@ void
transformAggregateCall(ParseState *pstate, Aggref *agg,
List *args, List *aggorder, bool agg_distinct)
{
+ List *argtypes = NIL;
List *tlist = NIL;
List *torder = NIL;
List *tdistinct = NIL;
@@ -108,6 +109,18 @@ transformAggregateCall(ParseState *pstate, Aggref *agg,
int save_next_resno;
ListCell *lc;
+ /*
+ * Before separating the args into direct and aggregated args, make a list
+ * of their data type OIDs for use later.
+ */
+ foreach(lc, args)
+ {
+ Expr *arg = (Expr *) lfirst(lc);
+
+ argtypes = lappend_oid(argtypes, exprType((Node *) arg));
+ }
+ agg->aggargtypes = argtypes;
+
if (AGGKIND_IS_ORDERED_SET(agg->aggkind))
{
/*
@@ -1763,26 +1776,11 @@ get_aggregate_argtypes(Aggref *aggref, Oid *inputTypes)
int numArguments = 0;
ListCell *lc;
- /* Any direct arguments of an ordered-set aggregate come first */
- foreach(lc, aggref->aggdirectargs)
- {
- Node *expr = (Node *) lfirst(lc);
-
- inputTypes[numArguments] = exprType(expr);
- numArguments++;
- }
+ Assert(list_length(aggref->aggargtypes) <= FUNC_MAX_ARGS);
- /* Now get the regular (aggregated) arguments */
- foreach(lc, aggref->args)
+ foreach(lc, aggref->aggargtypes)
{
- TargetEntry *tle = (TargetEntry *) lfirst(lc);
-
- /* Ignore ordering columns of a plain aggregate */
- if (tle->resjunk)
- continue;
-
- inputTypes[numArguments] = exprType((Node *) tle->expr);
- numArguments++;
+ inputTypes[numArguments++] = lfirst_oid(lc);
}
return numArguments;
@@ -1795,8 +1793,8 @@ get_aggregate_argtypes(Aggref *aggref, Oid *inputTypes)
* This function resolves a polymorphic aggregate's state datatype.
* It must be passed the aggtranstype from the aggregate's catalog entry,
* as well as the actual argument types extracted by get_aggregate_argtypes.
- * (We could fetch these values internally, but for all existing callers that
- * would just duplicate work the caller has to do too, so we pass them in.)
+ * (We could fetch pg_aggregate.aggtranstype internally, but all existing
+ * callers already have the value at hand, so we make them pass it.)
*/
Oid
resolve_aggregate_transtype(Oid aggfuncid,
diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c
index 485960f753c..d36d352fe9e 100644
--- a/src/backend/parser/parse_func.c
+++ b/src/backend/parser/parse_func.c
@@ -650,11 +650,15 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
/* default the outputtype to be the same as aggtype */
aggref->aggtype = aggref->aggoutputtype = rettype;
/* aggcollid and inputcollid will be set by parse_collate.c */
+ aggref->aggtranstype = InvalidOid; /* will be set by planner */
+ /* aggargtypes will be set by transformAggregateCall */
/* aggdirectargs and args will be set by transformAggregateCall */
/* aggorder and aggdistinct will be set by transformAggregateCall */
aggref->aggfilter = agg_filter;
aggref->aggstar = agg_star;
aggref->aggvariadic = func_variadic;
+ /* at this point, the Aggref is never partial or combining */
+ aggref->aggcombine = aggref->aggpartial = false;
aggref->aggkind = aggkind;
/* agglevelsup will be set by transformAggregateCall */
aggref->location = location;