@@ -532,13 +532,14 @@ static void select_current_set(AggState *aggstate, int setno, bool is_hash);
532
532
static void initialize_phase (AggState * aggstate , int newphase );
533
533
static TupleTableSlot * fetch_input_tuple (AggState * aggstate );
534
534
static void initialize_aggregates (AggState * aggstate ,
535
- AggStatePerGroup pergroup ,
535
+ AggStatePerGroup * pergroups ,
536
536
int numReset );
537
537
static void advance_transition_function (AggState * aggstate ,
538
538
AggStatePerTrans pertrans ,
539
539
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 );
542
543
static void advance_combine_function (AggState * aggstate ,
543
544
AggStatePerTrans pertrans ,
544
545
AggStatePerGroup pergroupstate );
@@ -793,14 +794,16 @@ initialize_aggregate(AggState *aggstate, AggStatePerTrans pertrans,
793
794
* If there are multiple grouping sets, we initialize only the first numReset
794
795
* of them (the grouping sets are ordered so that the most specific one, which
795
796
* 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.
798
801
*
799
802
* When called, CurrentMemoryContext should be the per-query context.
800
803
*/
801
804
static void
802
805
initialize_aggregates (AggState * aggstate ,
803
- AggStatePerGroup pergroup ,
806
+ AggStatePerGroup * pergroups ,
804
807
int numReset )
805
808
{
806
809
int transno ;
@@ -812,30 +815,18 @@ initialize_aggregates(AggState *aggstate,
812
815
if (numReset == 0 )
813
816
numReset = numGroupingSets ;
814
817
815
- for (transno = 0 ; transno < numTrans ; transno ++ )
818
+ for (setno = 0 ; setno < numReset ; setno ++ )
816
819
{
817
- AggStatePerTrans pertrans = & transstates [transno ];
818
-
819
- if (numReset < 0 )
820
- {
821
- AggStatePerGroup pergroupstate ;
820
+ AggStatePerGroup pergroup = pergroups [setno ];
822
821
823
- pergroupstate = & pergroup [ transno ] ;
822
+ select_current_set ( aggstate , setno , false) ;
824
823
825
- initialize_aggregate (aggstate , pertrans , pergroupstate );
826
- }
827
- else
824
+ for (transno = 0 ; transno < numTrans ; transno ++ )
828
825
{
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 ];
834
828
835
- select_current_set (aggstate , setno , false);
836
-
837
- initialize_aggregate (aggstate , pertrans , pergroupstate );
838
- }
829
+ initialize_aggregate (aggstate , pertrans , pergroupstate );
839
830
}
840
831
}
841
832
}
@@ -976,7 +967,9 @@ advance_transition_function(AggState *aggstate,
976
967
* When called, CurrentMemoryContext should be the per-query context.
977
968
*/
978
969
static void
979
- advance_aggregates (AggState * aggstate , AggStatePerGroup pergroup , AggStatePerGroup * pergroups )
970
+ advance_aggregates (AggState * aggstate ,
971
+ AggStatePerGroup * sort_pergroups ,
972
+ AggStatePerGroup * hash_pergroups )
980
973
{
981
974
int transno ;
982
975
int setno = 0 ;
@@ -1019,7 +1012,7 @@ advance_aggregates(AggState *aggstate, AggStatePerGroup pergroup, AggStatePerGro
1019
1012
{
1020
1013
/* DISTINCT and/or ORDER BY case */
1021
1014
Assert (slot -> tts_nvalid >= (pertrans -> numInputs + inputoff ));
1022
- Assert (!pergroups );
1015
+ Assert (!hash_pergroups );
1023
1016
1024
1017
/*
1025
1018
* If the transfn is strict, we want to check for nullity before
@@ -1090,7 +1083,7 @@ advance_aggregates(AggState *aggstate, AggStatePerGroup pergroup, AggStatePerGro
1090
1083
fcinfo -> argnull [i + 1 ] = slot -> tts_isnull [i + inputoff ];
1091
1084
}
1092
1085
1093
- if (pergroup )
1086
+ if (sort_pergroups )
1094
1087
{
1095
1088
/* advance transition states for ordered grouping */
1096
1089
@@ -1100,13 +1093,13 @@ advance_aggregates(AggState *aggstate, AggStatePerGroup pergroup, AggStatePerGro
1100
1093
1101
1094
select_current_set (aggstate , setno , false);
1102
1095
1103
- pergroupstate = & pergroup [ transno + ( setno * numTrans ) ];
1096
+ pergroupstate = & sort_pergroups [ setno ][ transno ];
1104
1097
1105
1098
advance_transition_function (aggstate , pertrans , pergroupstate );
1106
1099
}
1107
1100
}
1108
1101
1109
- if (pergroups )
1102
+ if (hash_pergroups )
1110
1103
{
1111
1104
/* advance transition states for hashed grouping */
1112
1105
@@ -1116,7 +1109,7 @@ advance_aggregates(AggState *aggstate, AggStatePerGroup pergroup, AggStatePerGro
1116
1109
1117
1110
select_current_set (aggstate , setno , true);
1118
1111
1119
- pergroupstate = & pergroups [setno ][transno ];
1112
+ pergroupstate = & hash_pergroups [setno ][transno ];
1120
1113
1121
1114
advance_transition_function (aggstate , pertrans , pergroupstate );
1122
1115
}
@@ -2095,12 +2088,25 @@ lookup_hash_entry(AggState *aggstate)
2095
2088
2096
2089
if (isnew )
2097
2090
{
2098
- entry -> additional = (AggStatePerGroup )
2091
+ AggStatePerGroup pergroup ;
2092
+ int transno ;
2093
+
2094
+ pergroup = (AggStatePerGroup )
2099
2095
MemoryContextAlloc (perhash -> hashtable -> tablecxt ,
2100
2096
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
+ }
2104
2110
}
2105
2111
2106
2112
return entry ;
@@ -2184,7 +2190,7 @@ agg_retrieve_direct(AggState *aggstate)
2184
2190
ExprContext * econtext ;
2185
2191
ExprContext * tmpcontext ;
2186
2192
AggStatePerAgg peragg ;
2187
- AggStatePerGroup pergroup ;
2193
+ AggStatePerGroup * pergroups ;
2188
2194
AggStatePerGroup * hash_pergroups = NULL ;
2189
2195
TupleTableSlot * outerslot ;
2190
2196
TupleTableSlot * firstSlot ;
@@ -2207,7 +2213,7 @@ agg_retrieve_direct(AggState *aggstate)
2207
2213
tmpcontext = aggstate -> tmpcontext ;
2208
2214
2209
2215
peragg = aggstate -> peragg ;
2210
- pergroup = aggstate -> pergroup ;
2216
+ pergroups = aggstate -> pergroups ;
2211
2217
firstSlot = aggstate -> ss .ss_ScanTupleSlot ;
2212
2218
2213
2219
/*
@@ -2409,7 +2415,7 @@ agg_retrieve_direct(AggState *aggstate)
2409
2415
/*
2410
2416
* Initialize working state for a new input tuple group.
2411
2417
*/
2412
- initialize_aggregates (aggstate , pergroup , numReset );
2418
+ initialize_aggregates (aggstate , pergroups , numReset );
2413
2419
2414
2420
if (aggstate -> grp_firstTuple != NULL )
2415
2421
{
@@ -2446,9 +2452,9 @@ agg_retrieve_direct(AggState *aggstate)
2446
2452
hash_pergroups = NULL ;
2447
2453
2448
2454
if (DO_AGGSPLIT_COMBINE (aggstate -> aggsplit ))
2449
- combine_aggregates (aggstate , pergroup );
2455
+ combine_aggregates (aggstate , pergroups [ 0 ] );
2450
2456
else
2451
- advance_aggregates (aggstate , pergroup , hash_pergroups );
2457
+ advance_aggregates (aggstate , pergroups , hash_pergroups );
2452
2458
2453
2459
/* Reset per-input-tuple context after each tuple */
2454
2460
ResetExprContext (tmpcontext );
@@ -2512,7 +2518,7 @@ agg_retrieve_direct(AggState *aggstate)
2512
2518
2513
2519
finalize_aggregates (aggstate ,
2514
2520
peragg ,
2515
- pergroup + ( currentSet * aggstate -> numtrans ) );
2521
+ pergroups [ currentSet ] );
2516
2522
2517
2523
/*
2518
2524
* If there's no row to project right now, we must continue rather
@@ -2756,7 +2762,7 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
2756
2762
aggstate -> curpertrans = NULL ;
2757
2763
aggstate -> input_done = false;
2758
2764
aggstate -> agg_done = false;
2759
- aggstate -> pergroup = NULL ;
2765
+ aggstate -> pergroups = NULL ;
2760
2766
aggstate -> grp_firstTuple = NULL ;
2761
2767
aggstate -> sort_in = NULL ;
2762
2768
aggstate -> sort_out = NULL ;
@@ -3052,13 +3058,16 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
3052
3058
3053
3059
if (node -> aggstrategy != AGG_HASHED )
3054
3060
{
3055
- AggStatePerGroup pergroup ;
3061
+ AggStatePerGroup * pergroups ;
3062
+
3063
+ pergroups = (AggStatePerGroup * ) palloc0 (sizeof (AggStatePerGroup ) *
3064
+ numGroupingSets );
3056
3065
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 );
3060
3069
3061
- aggstate -> pergroup = pergroup ;
3070
+ aggstate -> pergroups = pergroups ;
3062
3071
}
3063
3072
3064
3073
/*
@@ -4086,8 +4095,11 @@ ExecReScanAgg(AggState *node)
4086
4095
/*
4087
4096
* Reset the per-group state (in particular, mark transvalues null)
4088
4097
*/
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
+ }
4091
4103
4092
4104
/* reset to phase 1 */
4093
4105
initialize_phase (node , 1 );
0 commit comments