int numGroupingSets = Max(aggstate->phase->numsets, 1);
int setno = 0;
AggStatePerTrans pertrans;
+ AggStatePerGroup pergroupstate;
if (numReset < 1)
numReset = numGroupingSets;
+ pergroupstate = &pergroup[0];
for (transno = 0, pertrans = &aggstate->pertrans[0];
transno < aggstate->numtrans; transno++, pertrans++)
{
- for (setno = 0; setno < numReset; setno++)
+ for (setno = 0; setno < numGroupingSets; setno++)
{
- AggStatePerGroup pergroupstate;
-
- pergroupstate = &pergroup[transno + (setno * (aggstate->numtrans))];
-
- aggstate->current_set = setno;
-
- initialize_aggregate(aggstate, pertrans, pergroupstate);
+ if (setno < numReset)
+ {
+ aggstate->current_set = setno;
+ initialize_aggregate(aggstate, pertrans, pergroupstate);
+ }
+ pergroupstate++;
}
}
}
*
* It doesn't matter which memory context this is called in.
*/
-static void
+static inline void
advance_transition_function(AggState *aggstate,
AggStatePerTrans pertrans,
AggStatePerGroup pergroupstate)
*
* When called, CurrentMemoryContext should be the per-query context.
*/
-static void
+static inline void
advance_aggregates(AggState *aggstate, AggStatePerGroup pergroup)
{
int transno;
int numGroupingSets = Max(aggstate->phase->numsets, 1);
int numTrans = aggstate->numtrans;
TupleTableSlot *slot = aggstate->evalslot;
+ Datum *values = slot->tts_values;
+ bool *nulls = slot->tts_isnull;
AggStatePerTrans pertrans;
+ AggStatePerGroup pergroupstate = &pergroup[0];
/* compute input for all aggregates */
if (aggstate->evalproj)
res = ExecEvalExprSwitchContext(filter, aggstate->tmpcontext,
&isnull);
if (isnull || !DatumGetBool(res))
+ {
+ pergroupstate += numGroupingSets;
continue;
+ }
}
if (pertrans->numSortCols > 0)
break;
}
if (i < numTransInputs)
+ {
+ pergroupstate += numGroupingSets;
continue;
+ }
}
for (setno = 0; setno < numGroupingSets; setno++)
/* OK, put the tuple into the tuplesort object */
if (pertrans->numInputs == 1)
tuplesort_putdatum(pertrans->sortstates[setno],
- slot->tts_values[inputoff],
- slot->tts_isnull[inputoff]);
+ values[inputoff], nulls[inputoff]);
else
{
/*
*/
ExecClearTuple(pertrans->sortslot);
memcpy(pertrans->sortslot->tts_values,
- &slot->tts_values[inputoff],
+ &values[inputoff],
pertrans->numInputs * sizeof(Datum));
memcpy(pertrans->sortslot->tts_isnull,
- &slot->tts_isnull[inputoff],
+ &nulls[inputoff],
pertrans->numInputs * sizeof(bool));
pertrans->sortslot->tts_nvalid = pertrans->numInputs;
ExecStoreVirtualTuple(pertrans->sortslot);
tuplesort_puttupleslot(pertrans->sortstates[setno], pertrans->sortslot);
}
+
+ pergroupstate++;
}
}
else
for (i = 0; i < numTransInputs; i++)
{
- fcinfo->arg[i + 1] = slot->tts_values[i + inputoff];
- fcinfo->argnull[i + 1] = slot->tts_isnull[i + inputoff];
+ fcinfo->arg[i + 1] = values[i + inputoff];
+ fcinfo->argnull[i + 1] = nulls[i + inputoff];
}
for (setno = 0; setno < numGroupingSets; setno++)
{
- AggStatePerGroup pergroupstate = &pergroup[transno + (setno * numTrans)];
-
aggstate->current_set = setno;
advance_transition_function(aggstate, pertrans, pergroupstate);
+
+ pergroupstate++;
}
}
}
bool *aggnulls = econtext->ecxt_aggnulls;
int aggno;
int transno;
+ int numGroupingSets = Max(aggstate->phase->numsets, 1);
Assert(currentSet == 0 ||
((Agg *) aggstate->ss.ps.plan)->aggstrategy != AGG_HASHED);
AggStatePerTrans pertrans = &aggstate->pertrans[transno];
AggStatePerGroup pergroupstate;
- pergroupstate = &pergroup[transno + (currentSet * (aggstate->numtrans))];
+ pergroupstate = &pergroup[(transno * numGroupingSets) + currentSet];
if (pertrans->numSortCols > 0)
{
/* Find or build hashtable entry for this tuple's group */
entry = lookup_hash_entry(aggstate, outerslot);
+ if (aggstate->phase->numsets > 1)
+ __builtin_unreachable();
+
/* Advance the aggregates */
if (DO_AGGSPLIT_COMBINE(aggstate->aggsplit))
combine_aggregates(aggstate, (AggStatePerGroup) entry->additional);