@@ -532,13 +532,14 @@ static void select_current_set(AggState *aggstate, int setno, bool is_hash);
532532static void initialize_phase (AggState * aggstate , int newphase );
533533static TupleTableSlot * fetch_input_tuple (AggState * aggstate );
534534static void initialize_aggregates (AggState * aggstate ,
535- AggStatePerGroup pergroup ,
535+ AggStatePerGroup * pergroups ,
536536 int numReset );
537537static void advance_transition_function (AggState * aggstate ,
538538 AggStatePerTrans pertrans ,
539539 AggStatePerGroup pergroupstate );
540- static void advance_aggregates (AggState * aggstate , AggStatePerGroup pergroup ,
541- AggStatePerGroup * pergroups );
540+ static void advance_aggregates (AggState * aggstate ,
541+ AggStatePerGroup * sort_pergroups ,
542+ AggStatePerGroup * hash_pergroups );
542543static void advance_combine_function (AggState * aggstate ,
543544 AggStatePerTrans pertrans ,
544545 AggStatePerGroup pergroupstate );
@@ -793,14 +794,16 @@ initialize_aggregate(AggState *aggstate, AggStatePerTrans pertrans,
793794 * If there are multiple grouping sets, we initialize only the first numReset
794795 * of them (the grouping sets are ordered so that the most specific one, which
795796 * is reset most often, is first). As a convenience, if numReset is 0, we
796- * reinitialize all sets. numReset is -1 to initialize a hashtable entry, in
797- * which case the caller must have used select_current_set appropriately.
797+ * reinitialize all sets.
798+ *
799+ * NB: This cannot be used for hash aggregates, as for those the grouping set
800+ * number has to be specified from further up.
798801 *
799802 * When called, CurrentMemoryContext should be the per-query context.
800803 */
801804static void
802805initialize_aggregates (AggState * aggstate ,
803- AggStatePerGroup pergroup ,
806+ AggStatePerGroup * pergroups ,
804807 int numReset )
805808{
806809 int transno ;
@@ -812,30 +815,18 @@ initialize_aggregates(AggState *aggstate,
812815 if (numReset == 0 )
813816 numReset = numGroupingSets ;
814817
815- for (transno = 0 ; transno < numTrans ; transno ++ )
818+ for (setno = 0 ; setno < numReset ; setno ++ )
816819 {
817- AggStatePerTrans pertrans = & transstates [transno ];
818-
819- if (numReset < 0 )
820- {
821- AggStatePerGroup pergroupstate ;
820+ AggStatePerGroup pergroup = pergroups [setno ];
822821
823- pergroupstate = & pergroup [ transno ] ;
822+ select_current_set ( aggstate , setno , false) ;
824823
825- initialize_aggregate (aggstate , pertrans , pergroupstate );
826- }
827- else
824+ for (transno = 0 ; transno < numTrans ; transno ++ )
828825 {
829- for (setno = 0 ; setno < numReset ; setno ++ )
830- {
831- AggStatePerGroup pergroupstate ;
832-
833- pergroupstate = & pergroup [transno + (setno * numTrans )];
826+ AggStatePerTrans pertrans = & transstates [transno ];
827+ AggStatePerGroup pergroupstate = & pergroup [transno ];
834828
835- select_current_set (aggstate , setno , false);
836-
837- initialize_aggregate (aggstate , pertrans , pergroupstate );
838- }
829+ initialize_aggregate (aggstate , pertrans , pergroupstate );
839830 }
840831 }
841832}
@@ -976,7 +967,9 @@ advance_transition_function(AggState *aggstate,
976967 * When called, CurrentMemoryContext should be the per-query context.
977968 */
978969static void
979- advance_aggregates (AggState * aggstate , AggStatePerGroup pergroup , AggStatePerGroup * pergroups )
970+ advance_aggregates (AggState * aggstate ,
971+ AggStatePerGroup * sort_pergroups ,
972+ AggStatePerGroup * hash_pergroups )
980973{
981974 int transno ;
982975 int setno = 0 ;
@@ -1019,7 +1012,7 @@ advance_aggregates(AggState *aggstate, AggStatePerGroup pergroup, AggStatePerGro
10191012 {
10201013 /* DISTINCT and/or ORDER BY case */
10211014 Assert (slot -> tts_nvalid >= (pertrans -> numInputs + inputoff ));
1022- Assert (!pergroups );
1015+ Assert (!hash_pergroups );
10231016
10241017 /*
10251018 * If the transfn is strict, we want to check for nullity before
@@ -1090,7 +1083,7 @@ advance_aggregates(AggState *aggstate, AggStatePerGroup pergroup, AggStatePerGro
10901083 fcinfo -> argnull [i + 1 ] = slot -> tts_isnull [i + inputoff ];
10911084 }
10921085
1093- if (pergroup )
1086+ if (sort_pergroups )
10941087 {
10951088 /* advance transition states for ordered grouping */
10961089
@@ -1100,13 +1093,13 @@ advance_aggregates(AggState *aggstate, AggStatePerGroup pergroup, AggStatePerGro
11001093
11011094 select_current_set (aggstate , setno , false);
11021095
1103- pergroupstate = & pergroup [ transno + ( setno * numTrans ) ];
1096+ pergroupstate = & sort_pergroups [ setno ][ transno ];
11041097
11051098 advance_transition_function (aggstate , pertrans , pergroupstate );
11061099 }
11071100 }
11081101
1109- if (pergroups )
1102+ if (hash_pergroups )
11101103 {
11111104 /* advance transition states for hashed grouping */
11121105
@@ -1116,7 +1109,7 @@ advance_aggregates(AggState *aggstate, AggStatePerGroup pergroup, AggStatePerGro
11161109
11171110 select_current_set (aggstate , setno , true);
11181111
1119- pergroupstate = & pergroups [setno ][transno ];
1112+ pergroupstate = & hash_pergroups [setno ][transno ];
11201113
11211114 advance_transition_function (aggstate , pertrans , pergroupstate );
11221115 }
@@ -2095,12 +2088,25 @@ lookup_hash_entry(AggState *aggstate)
20952088
20962089 if (isnew )
20972090 {
2098- entry -> additional = (AggStatePerGroup )
2091+ AggStatePerGroup pergroup ;
2092+ int transno ;
2093+
2094+ pergroup = (AggStatePerGroup )
20992095 MemoryContextAlloc (perhash -> hashtable -> tablecxt ,
21002096 sizeof (AggStatePerGroupData ) * aggstate -> numtrans );
2101- /* initialize aggregates for new tuple group */
2102- initialize_aggregates (aggstate , (AggStatePerGroup ) entry -> additional ,
2103- -1 );
2097+ entry -> additional = pergroup ;
2098+
2099+ /*
2100+ * Initialize aggregates for new tuple group, lookup_hash_entries()
2101+ * already has selected the relevant grouping set.
2102+ */
2103+ for (transno = 0 ; transno < aggstate -> numtrans ; transno ++ )
2104+ {
2105+ AggStatePerTrans pertrans = & aggstate -> pertrans [transno ];
2106+ AggStatePerGroup pergroupstate = & pergroup [transno ];
2107+
2108+ initialize_aggregate (aggstate , pertrans , pergroupstate );
2109+ }
21042110 }
21052111
21062112 return entry ;
@@ -2184,7 +2190,7 @@ agg_retrieve_direct(AggState *aggstate)
21842190 ExprContext * econtext ;
21852191 ExprContext * tmpcontext ;
21862192 AggStatePerAgg peragg ;
2187- AggStatePerGroup pergroup ;
2193+ AggStatePerGroup * pergroups ;
21882194 AggStatePerGroup * hash_pergroups = NULL ;
21892195 TupleTableSlot * outerslot ;
21902196 TupleTableSlot * firstSlot ;
@@ -2207,7 +2213,7 @@ agg_retrieve_direct(AggState *aggstate)
22072213 tmpcontext = aggstate -> tmpcontext ;
22082214
22092215 peragg = aggstate -> peragg ;
2210- pergroup = aggstate -> pergroup ;
2216+ pergroups = aggstate -> pergroups ;
22112217 firstSlot = aggstate -> ss .ss_ScanTupleSlot ;
22122218
22132219 /*
@@ -2409,7 +2415,7 @@ agg_retrieve_direct(AggState *aggstate)
24092415 /*
24102416 * Initialize working state for a new input tuple group.
24112417 */
2412- initialize_aggregates (aggstate , pergroup , numReset );
2418+ initialize_aggregates (aggstate , pergroups , numReset );
24132419
24142420 if (aggstate -> grp_firstTuple != NULL )
24152421 {
@@ -2446,9 +2452,9 @@ agg_retrieve_direct(AggState *aggstate)
24462452 hash_pergroups = NULL ;
24472453
24482454 if (DO_AGGSPLIT_COMBINE (aggstate -> aggsplit ))
2449- combine_aggregates (aggstate , pergroup );
2455+ combine_aggregates (aggstate , pergroups [ 0 ] );
24502456 else
2451- advance_aggregates (aggstate , pergroup , hash_pergroups );
2457+ advance_aggregates (aggstate , pergroups , hash_pergroups );
24522458
24532459 /* Reset per-input-tuple context after each tuple */
24542460 ResetExprContext (tmpcontext );
@@ -2512,7 +2518,7 @@ agg_retrieve_direct(AggState *aggstate)
25122518
25132519 finalize_aggregates (aggstate ,
25142520 peragg ,
2515- pergroup + ( currentSet * aggstate -> numtrans ) );
2521+ pergroups [ currentSet ] );
25162522
25172523 /*
25182524 * If there's no row to project right now, we must continue rather
@@ -2756,7 +2762,7 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
27562762 aggstate -> curpertrans = NULL ;
27572763 aggstate -> input_done = false;
27582764 aggstate -> agg_done = false;
2759- aggstate -> pergroup = NULL ;
2765+ aggstate -> pergroups = NULL ;
27602766 aggstate -> grp_firstTuple = NULL ;
27612767 aggstate -> sort_in = NULL ;
27622768 aggstate -> sort_out = NULL ;
@@ -3052,13 +3058,16 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
30523058
30533059 if (node -> aggstrategy != AGG_HASHED )
30543060 {
3055- AggStatePerGroup pergroup ;
3061+ AggStatePerGroup * pergroups ;
3062+
3063+ pergroups = (AggStatePerGroup * ) palloc0 (sizeof (AggStatePerGroup ) *
3064+ numGroupingSets );
30563065
3057- pergroup = ( AggStatePerGroup ) palloc0 ( sizeof ( AggStatePerGroupData )
3058- * numaggs
3059- * numGroupingSets );
3066+ for ( i = 0 ; i < numGroupingSets ; i ++ )
3067+ pergroups [ i ] = ( AggStatePerGroup ) palloc0 ( sizeof ( AggStatePerGroupData )
3068+ * numaggs );
30603069
3061- aggstate -> pergroup = pergroup ;
3070+ aggstate -> pergroups = pergroups ;
30623071 }
30633072
30643073 /*
@@ -4086,8 +4095,11 @@ ExecReScanAgg(AggState *node)
40864095 /*
40874096 * Reset the per-group state (in particular, mark transvalues null)
40884097 */
4089- MemSet (node -> pergroup , 0 ,
4090- sizeof (AggStatePerGroupData ) * node -> numaggs * numGroupingSets );
4098+ for (setno = 0 ; setno < numGroupingSets ; setno ++ )
4099+ {
4100+ MemSet (node -> pergroups [setno ], 0 ,
4101+ sizeof (AggStatePerGroupData ) * node -> numaggs );
4102+ }
40914103
40924104 /* reset to phase 1 */
40934105 initialize_phase (node , 1 );
0 commit comments