diff --git a/src/backend/executor/execExpr.c b/src/backend/executor/execExpr.c
index 2a4dea2b052..6a03fa730e5 100644
--- a/src/backend/executor/execExpr.c
+++ b/src/backend/executor/execExpr.c
@@ -785,11 +785,23 @@ ExecInitExprRec(Expr *node, ExprState *state,
 				scratch.d.aggref.astate = astate;
 				astate->aggno = aggref->aggno;
 
+				/*
+				 * Remember this Aggref as the representative for the
+				 * aggregate. ExecInitAgg needs a representative for
+				 * initializing the states, and it can also be accessed
+				 * by the user-defined functions by AggGetAggref().
+				 */
 				if (state->parent && IsA(state->parent, AggState))
 				{
 					AggState   *aggstate = (AggState *) state->parent;
+					AggStatePerAgg peragg;
+
+					if (aggref->aggno >= aggstate->numaggs)
+						elog(ERROR, "invalid aggno %d", aggref->aggno);
+					peragg = &aggstate->peragg[aggref->aggno];
 
-					aggstate->aggs = lappend(aggstate->aggs, aggref);
+					if (peragg->aggref == NULL)
+						peragg->aggref = aggref;
 				}
 				else
 				{
diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c
index 7585689b94d..1949729a494 100644
--- a/src/backend/executor/nodeAgg.c
+++ b/src/backend/executor/nodeAgg.c
@@ -3236,13 +3236,11 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
 	Plan	   *outerPlan;
 	ExprContext *econtext;
 	TupleDesc	scanDesc;
-	int			max_aggno;
-	int			max_transno;
-	int			numaggrefs;
 	int			numaggs;
 	int			numtrans;
 	int			phase;
 	int			phaseidx;
+	int			aggno;
 	ListCell   *l;
 	Bitmapset  *all_grouped_cols = NULL;
 	int			numGroupingSets = 1;
@@ -3264,7 +3262,6 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
 	aggstate->ss.ps.state = estate;
 	aggstate->ss.ps.ExecProcNode = ExecAgg;
 
-	aggstate->aggs = NIL;
 	aggstate->numaggs = 0;
 	aggstate->numtrans = 0;
 	aggstate->aggstrategy = node->aggstrategy;
@@ -3401,6 +3398,17 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
 			aggstate->ss.ps.outeropsfixed = false;
 	}
 
+	/* Initialize the per-agg and per-trans arrays before calling ExecInitExpr() */
+	numaggs = node->numAggs;
+	peraggs = (AggStatePerAgg) palloc0(sizeof(AggStatePerAggData) * numaggs);
+	aggstate->peragg = peraggs;
+	aggstate->numaggs = numaggs;
+
+	numtrans = node->numTrans;
+	pertransstates = (AggStatePerTrans) palloc0(sizeof(AggStatePerTransData) * numtrans);
+	aggstate->pertrans = pertransstates;
+	aggstate->numtrans = numtrans;
+
 	/*
 	 * Initialize result type, slot and projection.
 	 */
@@ -3423,22 +3431,6 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
 	aggstate->ss.ps.qual =
 		ExecInitQual(node->plan.qual, (PlanState *) aggstate);
 
-	/*
-	 * We should now have found all Aggrefs in the targetlist and quals.
-	 */
-	numaggrefs = list_length(aggstate->aggs);
-	max_aggno = -1;
-	max_transno = -1;
-	foreach(l, aggstate->aggs)
-	{
-		Aggref	   *aggref = (Aggref *) lfirst(l);
-
-		max_aggno = Max(max_aggno, aggref->aggno);
-		max_transno = Max(max_transno, aggref->aggtransno);
-	}
-	numaggs = max_aggno + 1;
-	numtrans = max_transno + 1;
-
 	/*
 	 * For each phase, prepare grouping set data and fmgr lookup data for
 	 * compare functions.  Accumulate all_grouped_cols in passing.
@@ -3607,13 +3599,6 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
 	econtext->ecxt_aggvalues = (Datum *) palloc0(sizeof(Datum) * numaggs);
 	econtext->ecxt_aggnulls = (bool *) palloc0(sizeof(bool) * numaggs);
 
-	peraggs = (AggStatePerAgg) palloc0(sizeof(AggStatePerAggData) * numaggs);
-	pertransstates = (AggStatePerTrans) palloc0(sizeof(AggStatePerTransData) * numtrans);
-
-	aggstate->peragg = peraggs;
-	aggstate->pertrans = pertransstates;
-
-
 	aggstate->all_pergroups =
 		(AggStatePerGroup *) palloc0(sizeof(AggStatePerGroup)
 									 * (numGroupingSets + numHashes));
@@ -3699,11 +3684,11 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
 	 * Perform lookups of aggregate function info, and initialize the
 	 * unchanging fields of the per-agg and per-trans data.
 	 */
-	foreach(l, aggstate->aggs)
+	for (aggno = 0; aggno < numaggs; aggno++)
 	{
-		Aggref	   *aggref = lfirst(l);
-		AggStatePerAgg peragg;
+		AggStatePerAgg peragg = &peraggs[aggno];
 		AggStatePerTrans pertrans;
+		Aggref	   *aggref;
 		Oid			inputTypes[FUNC_MAX_ARGS];
 		int			numArguments;
 		int			numDirectArgs;
@@ -3717,18 +3702,18 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
 		Expr	   *finalfnexpr;
 		Oid			aggtranstype;
 
+		if (peragg->aggref == NULL)
+		{
+			elog(ERROR, "aggregate %d of %d was not found in expression initialization",
+				 aggno, numaggs);
+		}
+		aggref = peragg->aggref;
+
 		/* Planner should have assigned aggregate to correct level */
 		Assert(aggref->agglevelsup == 0);
 		/* ... and the split mode should match */
 		Assert(aggref->aggsplit == aggstate->aggsplit);
 
-		peragg = &peraggs[aggref->aggno];
-
-		/* Check if we initialized the state for this aggregate already. */
-		if (peragg->aggref != NULL)
-			continue;
-
-		peragg->aggref = aggref;
 		peragg->transno = aggref->aggtransno;
 
 		/* Fetch the pg_aggregate row */
@@ -3934,13 +3919,6 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
 		ReleaseSysCache(aggTuple);
 	}
 
-	/*
-	 * Update aggstate->numaggs to be the number of unique aggregates found.
-	 * Also set numstates to the number of unique transition states found.
-	 */
-	aggstate->numaggs = numaggs;
-	aggstate->numtrans = numtrans;
-
 	/*
 	 * Last, check whether any more aggregates got added onto the node while
 	 * we processed the expressions for the aggregate arguments (including not
@@ -3951,10 +3929,13 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
 	 * need to work hard on a helpful error message; but we defend against it
 	 * here anyway, just to be sure.)
 	 */
+	/* FIXME: need another way to sanity check this now. Not hard. Or just remove this */
+#if 0
 	if (numaggrefs != list_length(aggstate->aggs))
 		ereport(ERROR,
 				(errcode(ERRCODE_GROUPING_ERROR),
 				 errmsg("aggregate function calls cannot be nested")));
+#endif
 
 	/*
 	 * Build expressions doing all the transition work at once. We build a
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index d15866de89f..812735576f2 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -1024,6 +1024,8 @@ _copyAgg(const Agg *from)
 	COPY_BITMAPSET_FIELD(aggParams);
 	COPY_NODE_FIELD(groupingSets);
 	COPY_NODE_FIELD(chain);
+	COPY_SCALAR_FIELD(numAggs);
+	COPY_SCALAR_FIELD(numTrans);
 
 	return newnode;
 }
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index 3c740b805f3..e3c168531f9 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -785,6 +785,8 @@ _outAgg(StringInfo str, const Agg *node)
 	WRITE_BITMAPSET_FIELD(aggParams);
 	WRITE_NODE_FIELD(groupingSets);
 	WRITE_NODE_FIELD(chain);
+	WRITE_INT_FIELD(numAggs);
+	WRITE_INT_FIELD(numTrans);
 }
 
 static void
diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c
index 169d5581b91..43533e13daa 100644
--- a/src/backend/nodes/readfuncs.c
+++ b/src/backend/nodes/readfuncs.c
@@ -2235,6 +2235,8 @@ _readAgg(void)
 	READ_BITMAPSET_FIELD(aggParams);
 	READ_NODE_FIELD(groupingSets);
 	READ_NODE_FIELD(chain);
+	READ_INT_FIELD(numAggs);
+	READ_INT_FIELD(numTrans);
 
 	READ_DONE();
 }
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index 94280a730c4..b5e88acf055 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -1657,7 +1657,7 @@ create_unique_plan(PlannerInfo *root, UniquePath *best_path, int flags)
 								 NIL,
 								 NIL,
 								 best_path->path.rows,
-								 0,
+								 0, 0, 0,
 								 subplan);
 	}
 	else
@@ -2139,6 +2139,7 @@ create_agg_plan(PlannerInfo *root, AggPath *best_path)
 					NIL,
 					best_path->numGroups,
 					best_path->transitionSpace,
+					list_length(root->agginfos), list_length(root->aggtransinfos),
 					subplan);
 
 	copy_generic_path_info(&plan->plan, (Path *) best_path);
@@ -2301,6 +2302,8 @@ create_groupingsets_plan(PlannerInfo *root, GroupingSetsPath *best_path)
 										 NIL,
 										 rollup->numGroups,
 										 best_path->transitionSpace,
+										 list_length(root->agginfos),
+										 list_length(root->aggtransinfos),
 										 sort_plan);
 
 			/*
@@ -2340,6 +2343,8 @@ create_groupingsets_plan(PlannerInfo *root, GroupingSetsPath *best_path)
 						chain,
 						rollup->numGroups,
 						best_path->transitionSpace,
+						list_length(root->agginfos),
+						list_length(root->aggtransinfos),
 						subplan);
 
 		/* Copy cost data from Path to Plan */
@@ -6350,7 +6355,7 @@ make_agg(List *tlist, List *qual,
 		 AggStrategy aggstrategy, AggSplit aggsplit,
 		 int numGroupCols, AttrNumber *grpColIdx, Oid *grpOperators, Oid *grpCollations,
 		 List *groupingSets, List *chain, double dNumGroups,
-		 Size transitionSpace, Plan *lefttree)
+		 Size transitionSpace, int numAggs, int numTrans, Plan *lefttree)
 {
 	Agg		   *node = makeNode(Agg);
 	Plan	   *plan = &node->plan;
@@ -6370,6 +6375,8 @@ make_agg(List *tlist, List *qual,
 	node->aggParams = NULL;		/* SS_finalize_plan() will fill this */
 	node->groupingSets = groupingSets;
 	node->chain = chain;
+	node->numAggs = numAggs;
+	node->numTrans = numTrans;
 
 	plan->qual = qual;
 	plan->targetlist = tlist;
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index fc5698cff20..ce47d7869dc 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -2140,7 +2140,6 @@ typedef struct AggStatePerHashData *AggStatePerHash;
 typedef struct AggState
 {
 	ScanState	ss;				/* its first field is NodeTag */
-	List	   *aggs;			/* all Aggref nodes in targetlist & quals */
 	int			numaggs;		/* length of list (could be zero!) */
 	int			numtrans;		/* number of pertrans items */
 	AggStrategy aggstrategy;	/* strategy mode */
@@ -2153,15 +2152,15 @@ typedef struct AggState
 	ExprContext *hashcontext;	/* econtexts for long-lived data (hashtable) */
 	ExprContext **aggcontexts;	/* econtexts for long-lived data (per GS) */
 	ExprContext *tmpcontext;	/* econtext for input expressions */
-#define FIELDNO_AGGSTATE_CURAGGCONTEXT 14
+#define FIELDNO_AGGSTATE_CURAGGCONTEXT 13
 	ExprContext *curaggcontext; /* currently active aggcontext */
 	AggStatePerAgg curperagg;	/* currently active aggregate, if any */
-#define FIELDNO_AGGSTATE_CURPERTRANS 16
+#define FIELDNO_AGGSTATE_CURPERTRANS 15
 	AggStatePerTrans curpertrans;	/* currently active trans state, if any */
 	bool		input_done;		/* indicates end of input */
 	bool		agg_done;		/* indicates completion of Agg scan */
 	int			projected_set;	/* The last projected grouping set */
-#define FIELDNO_AGGSTATE_CURRENT_SET 20
+#define FIELDNO_AGGSTATE_CURRENT_SET 19
 	int			current_set;	/* The current grouping set being evaluated */
 	Bitmapset  *grouped_cols;	/* grouped cols in current projection */
 	List	   *all_grouped_cols;	/* list of all grouped cols in DESC order */
@@ -2207,7 +2206,7 @@ typedef struct AggState
 										 * per-group pointers */
 
 	/* support for evaluation of agg input expressions: */
-#define FIELDNO_AGGSTATE_ALL_PERGROUPS 53
+#define FIELDNO_AGGSTATE_ALL_PERGROUPS 52
 	AggStatePerGroup *all_pergroups;	/* array of first ->pergroups, than
 										 * ->hash_pergroup */
 	ProjectionInfo *combinedproj;	/* projection machinery */
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
index 7e6b10f86b9..f60f301a2b1 100644
--- a/src/include/nodes/plannodes.h
+++ b/src/include/nodes/plannodes.h
@@ -828,6 +828,9 @@ typedef struct Agg
 	/* Note: planner provides numGroups & aggParams only in HASHED/MIXED case */
 	List	   *groupingSets;	/* grouping sets to use */
 	List	   *chain;			/* chained Agg/Sort nodes */
+
+	int			numAggs;
+	int			numTrans;
 } Agg;
 
 /* ----------------
diff --git a/src/include/optimizer/planmain.h b/src/include/optimizer/planmain.h
index f3cefe67b8d..d64f7c1344b 100644
--- a/src/include/optimizer/planmain.h
+++ b/src/include/optimizer/planmain.h
@@ -55,7 +55,7 @@ extern Agg *make_agg(List *tlist, List *qual,
 					 AggStrategy aggstrategy, AggSplit aggsplit,
 					 int numGroupCols, AttrNumber *grpColIdx, Oid *grpOperators, Oid *grpCollations,
 					 List *groupingSets, List *chain, double dNumGroups,
-					 Size transitionSpace, Plan *lefttree);
+					 Size transitionSpace, int numAggs, int numTrans, Plan *lefttree);
 extern Limit *make_limit(Plan *lefttree, Node *limitOffset, Node *limitCount,
 						 LimitOption limitOption, int uniqNumCols,
 						 AttrNumber *uniqColIdx, Oid *uniqOperators,
