static void initialize_phase(AggState *aggstate, int newphase);
static TupleTableSlot *fetch_input_tuple(AggState *aggstate);
static void initialize_aggregates(AggState *aggstate,
- AggStatePerGroup pergroup,
- int numReset);
+ AggStatePerGroup *pergroups,
+ bool isHash, int numReset);
static void advance_transition_function(AggState *aggstate,
AggStatePerTrans pertrans,
AggStatePerGroup pergroupstate);
-static void advance_aggregates(AggState *aggstate, AggStatePerGroup pergroup,
- AggStatePerGroup *pergroups);
+static void advance_aggregates(AggState *aggstate, AggStatePerGroup *sort_pergroups,
+ AggStatePerGroup *hash_pergroups);
static void advance_combine_function(AggState *aggstate,
AggStatePerTrans pertrans,
AggStatePerGroup pergroupstate);
* If there are multiple grouping sets, we initialize only the first numReset
* of them (the grouping sets are ordered so that the most specific one, which
* is reset most often, is first). As a convenience, if numReset is 0, we
- * reinitialize all sets. numReset is -1 to initialize a hashtable entry, in
- * which case the caller must have used select_current_set appropriately.
+ * reinitialize all sets.
*
* When called, CurrentMemoryContext should be the per-query context.
*/
static void
initialize_aggregates(AggState *aggstate,
- AggStatePerGroup pergroup,
- int numReset)
+ AggStatePerGroup *pergroups,
+ bool isHash, int numReset)
{
int transno;
int numGroupingSets = Max(aggstate->phase->numsets, 1);
if (numReset == 0)
numReset = numGroupingSets;
- for (transno = 0; transno < numTrans; transno++)
+ for (setno = 0; setno < numReset; setno++)
{
- AggStatePerTrans pertrans = &transstates[transno];
-
- if (numReset < 0)
- {
- AggStatePerGroup pergroupstate;
+ AggStatePerGroup pergroup = pergroups[setno];
- pergroupstate = &pergroup[transno];
+ select_current_set(aggstate, setno, isHash);
- initialize_aggregate(aggstate, pertrans, pergroupstate);
- }
- else
+ for (transno = 0; transno < numTrans; transno++)
{
- for (setno = 0; setno < numReset; setno++)
- {
- AggStatePerGroup pergroupstate;
-
- pergroupstate = &pergroup[transno + (setno * numTrans)];
-
- select_current_set(aggstate, setno, false);
+ AggStatePerTrans pertrans = &transstates[transno];
+ AggStatePerGroup pergroupstate = &pergroup[transno];
- initialize_aggregate(aggstate, pertrans, pergroupstate);
- }
+ initialize_aggregate(aggstate, pertrans, pergroupstate);
}
}
}
* When called, CurrentMemoryContext should be the per-query context.
*/
static void
-advance_aggregates(AggState *aggstate, AggStatePerGroup pergroup, AggStatePerGroup *pergroups)
+advance_aggregates(AggState *aggstate, AggStatePerGroup *sort_pergroups, AggStatePerGroup *hash_pergroups)
{
int transno;
int setno = 0;
{
/* DISTINCT and/or ORDER BY case */
Assert(slot->tts_nvalid >= (pertrans->numInputs + inputoff));
- Assert(!pergroups);
+ Assert(!hash_pergroups);
/*
* If the transfn is strict, we want to check for nullity before
fcinfo->argnull[i + 1] = slot->tts_isnull[i + inputoff];
}
- if (pergroup)
+ if (sort_pergroups)
{
- /* advance transition states for ordered grouping */
+ /* advance transition states for ordered grouping */
for (setno = 0; setno < numGroupingSets; setno++)
{
select_current_set(aggstate, setno, false);
- pergroupstate = &pergroup[transno + (setno * numTrans)];
+ pergroupstate = &sort_pergroups[setno][transno];
advance_transition_function(aggstate, pertrans, pergroupstate);
}
}
- if (pergroups)
+ if (hash_pergroups)
{
/* advance transition states for hashed grouping */
select_current_set(aggstate, setno, true);
- pergroupstate = &pergroups[setno][transno];
+ pergroupstate = &hash_pergroups[setno][transno];
advance_transition_function(aggstate, pertrans, pergroupstate);
}
MemoryContextAlloc(perhash->hashtable->tablecxt,
sizeof(AggStatePerGroupData) * aggstate->numtrans);
/* initialize aggregates for new tuple group */
- initialize_aggregates(aggstate, (AggStatePerGroup) entry->additional,
- -1);
+ initialize_aggregates(aggstate, (AggStatePerGroup*) &entry->additional,
+ true, 1);
}
return entry;
ExprContext *econtext;
ExprContext *tmpcontext;
AggStatePerAgg peragg;
- AggStatePerGroup pergroup;
+ AggStatePerGroup *pergroups;
AggStatePerGroup *hash_pergroups = NULL;
TupleTableSlot *outerslot;
TupleTableSlot *firstSlot;
tmpcontext = aggstate->tmpcontext;
peragg = aggstate->peragg;
- pergroup = aggstate->pergroup;
+ pergroups = aggstate->pergroups;
firstSlot = aggstate->ss.ss_ScanTupleSlot;
/*
/*
* Initialize working state for a new input tuple group.
*/
- initialize_aggregates(aggstate, pergroup, numReset);
+ initialize_aggregates(aggstate, pergroups, false, numReset);
if (aggstate->grp_firstTuple != NULL)
{
hash_pergroups = NULL;
if (DO_AGGSPLIT_COMBINE(aggstate->aggsplit))
- combine_aggregates(aggstate, pergroup);
+ combine_aggregates(aggstate, pergroups[0]);
else
- advance_aggregates(aggstate, pergroup, hash_pergroups);
+ advance_aggregates(aggstate, pergroups, hash_pergroups);
/* Reset per-input-tuple context after each tuple */
ResetExprContext(tmpcontext);
finalize_aggregates(aggstate,
peragg,
- pergroup + (currentSet * aggstate->numtrans));
+ pergroups[currentSet]);
/*
* If there's no row to project right now, we must continue rather
aggstate->curpertrans = NULL;
aggstate->input_done = false;
aggstate->agg_done = false;
- aggstate->pergroup = NULL;
+ aggstate->pergroups = NULL;
aggstate->grp_firstTuple = NULL;
aggstate->sort_in = NULL;
aggstate->sort_out = NULL;
if (node->aggstrategy != AGG_HASHED)
{
- AggStatePerGroup pergroup;
+ AggStatePerGroup *pergroups =
+ (AggStatePerGroup*) palloc0(sizeof(AggStatePerGroup)
+ * numGroupingSets);
- pergroup = (AggStatePerGroup) palloc0(sizeof(AggStatePerGroupData)
- * numaggs
- * numGroupingSets);
+ for (i = 0; i < numGroupingSets; i++)
+ {
+ pergroups[i] = (AggStatePerGroup) palloc0(sizeof(AggStatePerGroupData)
+ * numaggs);
+ }
- aggstate->pergroup = pergroup;
+ aggstate->pergroups = pergroups;
}
/*
/*
* Reset the per-group state (in particular, mark transvalues null)
*/
- MemSet(node->pergroup, 0,
- sizeof(AggStatePerGroupData) * node->numaggs * numGroupingSets);
+ for (setno = 0; setno < numGroupingSets; setno++)
+ {
+ MemSet(node->pergroups[setno], 0,
+ sizeof(AggStatePerGroupData) * node->numaggs);
+ }
/* reset to phase 1 */
initialize_phase(node, 1);