@@ -268,7 +268,12 @@ typedef struct AggStatePerTransData
268268 */
269269 int numInputs ;
270270
271- /* offset of input columns in AggState->evalslot */
271+ /*
272+ * At each input row, we evaluate all argument expressions needed for all
273+ * the aggregates in this Agg node in a single ExecProject call. inputoff
274+ * is the starting index of this aggregate's argument expressions in the
275+ * resulting tuple (in AggState->evalslot).
276+ */
272277 int inputoff ;
273278
274279 /*
@@ -2799,10 +2804,11 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
27992804 /*
28002805 * initialize child expressions
28012806 *
2802- * We rely on the parser to have checked that no aggs contain other agg
2803- * calls in their arguments. This would make no sense under SQL semantics
2804- * (and it's forbidden by the spec). Because it is true, we don't need to
2805- * worry about evaluating the aggs in any particular order.
2807+ * We expect the parser to have checked that no aggs contain other agg
2808+ * calls in their arguments (and just to be sure, we verify it again while
2809+ * initializing the plan node). This would make no sense under SQL
2810+ * semantics, and it's forbidden by the spec. Because it is true, we
2811+ * don't need to worry about evaluating the aggs in any particular order.
28062812 *
28072813 * Note: execExpr.c finds Aggrefs for us, and adds their AggrefExprState
28082814 * nodes to aggstate->aggs. Aggrefs in the qual are found here; Aggrefs
@@ -2841,17 +2847,6 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
28412847 */
28422848 numaggs = aggstate -> numaggs ;
28432849 Assert (numaggs == list_length (aggstate -> aggs ));
2844- if (numaggs <= 0 )
2845- {
2846- /*
2847- * This is not an error condition: we might be using the Agg node just
2848- * to do hash-based grouping. Even in the regular case,
2849- * constant-expression simplification could optimize away all of the
2850- * Aggrefs in the targetlist and qual. So keep going, but force local
2851- * copy of numaggs positive so that palloc()s below don't choke.
2852- */
2853- numaggs = 1 ;
2854- }
28552850
28562851 /*
28572852 * For each phase, prepare grouping set data and fmgr lookup data for
@@ -3343,19 +3338,19 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
33433338 }
33443339
33453340 /*
3346- * Update numaggs to match the number of unique aggregates found. Also set
3347- * numstates to the number of unique aggregate states found.
3341+ * Update aggstate-> numaggs to be the number of unique aggregates found.
3342+ * Also set numstates to the number of unique transition states found.
33483343 */
33493344 aggstate -> numaggs = aggno + 1 ;
33503345 aggstate -> numtrans = transno + 1 ;
33513346
33523347 /*
33533348 * Build a single projection computing the aggregate arguments for all
3354- * aggregates at once, that 's considerably faster than doing it separately
3355- * for each.
3349+ * aggregates at once; if there 's more than one, that's considerably
3350+ * faster than doing it separately for each.
33563351 *
3357- * First create a targetlist combining the targetlist of all the
3358- * transitions .
3352+ * First create a targetlist combining the targetlists of all the
3353+ * per-trans states .
33593354 */
33603355 combined_inputeval = NIL ;
33613356 column_offset = 0 ;
@@ -3364,10 +3359,14 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
33643359 AggStatePerTrans pertrans = & pertransstates [transno ];
33653360 ListCell * arg ;
33663361
3362+ /*
3363+ * Mark this per-trans state with its starting column in the combined
3364+ * slot.
3365+ */
33673366 pertrans -> inputoff = column_offset ;
33683367
33693368 /*
3370- * Adjust resno in a copied target entries, to point into the combined
3369+ * Adjust resnos in the copied target entries to match the combined
33713370 * slot.
33723371 */
33733372 foreach (arg , pertrans -> aggref -> args )
@@ -3384,7 +3383,7 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
33843383 column_offset += list_length (pertrans -> aggref -> args );
33853384 }
33863385
3387- /* and then create a projection for that targetlist */
3386+ /* Now create a projection for the combined targetlist */
33883387 aggstate -> evaldesc = ExecTypeFromTL (combined_inputeval , false);
33893388 aggstate -> evalslot = ExecInitExtraTupleSlot (estate );
33903389 aggstate -> evalproj = ExecBuildProjectionInfo (combined_inputeval ,
@@ -3394,6 +3393,21 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
33943393 NULL );
33953394 ExecSetSlotDescriptor (aggstate -> evalslot , aggstate -> evaldesc );
33963395
3396+ /*
3397+ * Last, check whether any more aggregates got added onto the node while
3398+ * we processed the expressions for the aggregate arguments (including not
3399+ * only the regular arguments handled immediately above, but any FILTER
3400+ * expressions and direct arguments we might've handled earlier). If so,
3401+ * we have nested aggregate functions, which is semantically nonsensical,
3402+ * so complain. (This should have been caught by the parser, so we don't
3403+ * need to work hard on a helpful error message; but we defend against it
3404+ * here anyway, just to be sure.)
3405+ */
3406+ if (numaggs != list_length (aggstate -> aggs ))
3407+ ereport (ERROR ,
3408+ (errcode (ERRCODE_GROUPING_ERROR ),
3409+ errmsg ("aggregate function calls cannot be nested" )));
3410+
33973411 return aggstate ;
33983412}
33993413
@@ -3423,7 +3437,6 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans,
34233437 List * sortlist ;
34243438 int numSortCols ;
34253439 int numDistinctCols ;
3426- int naggs ;
34273440 int i ;
34283441
34293442 /* Begin filling in the pertrans data */
@@ -3565,22 +3578,11 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans,
35653578 }
35663579
35673580 /* Initialize the input and FILTER expressions */
3568- naggs = aggstate -> numaggs ;
35693581 pertrans -> aggfilter = ExecInitExpr (aggref -> aggfilter ,
35703582 (PlanState * ) aggstate );
35713583 pertrans -> aggdirectargs = ExecInitExprList (aggref -> aggdirectargs ,
35723584 (PlanState * ) aggstate );
35733585
3574- /*
3575- * Complain if the aggregate's arguments contain any aggregates; nested
3576- * agg functions are semantically nonsensical. (This should have been
3577- * caught earlier, but we defend against it here anyway.)
3578- */
3579- if (naggs != aggstate -> numaggs )
3580- ereport (ERROR ,
3581- (errcode (ERRCODE_GROUPING_ERROR ),
3582- errmsg ("aggregate function calls cannot be nested" )));
3583-
35843586 /*
35853587 * If we're doing either DISTINCT or ORDER BY for a plain agg, then we
35863588 * have a list of SortGroupClause nodes; fish out the data in them and
0 commit comments