aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/execExprInterp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor/execExprInterp.c')
-rw-r--r--src/backend/executor/execExprInterp.c102
1 files changed, 102 insertions, 0 deletions
diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c
index 723770fda0e..636794ca6f1 100644
--- a/src/backend/executor/execExprInterp.c
+++ b/src/backend/executor/execExprInterp.c
@@ -502,6 +502,8 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
&&CASE_EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYREF,
&&CASE_EEOP_AGG_PLAIN_TRANS_STRICT_BYREF,
&&CASE_EEOP_AGG_PLAIN_TRANS_BYREF,
+ &&CASE_EEOP_AGG_PRESORTED_DISTINCT_SINGLE,
+ &&CASE_EEOP_AGG_PRESORTED_DISTINCT_MULTI,
&&CASE_EEOP_AGG_ORDERED_TRANS_DATUM,
&&CASE_EEOP_AGG_ORDERED_TRANS_TUPLE,
&&CASE_EEOP_LAST
@@ -1786,6 +1788,28 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
EEO_NEXT();
}
+ EEO_CASE(EEOP_AGG_PRESORTED_DISTINCT_SINGLE)
+ {
+ AggStatePerTrans pertrans = op->d.agg_presorted_distinctcheck.pertrans;
+ AggState *aggstate = castNode(AggState, state->parent);
+
+ if (ExecEvalPreOrderedDistinctSingle(aggstate, pertrans))
+ EEO_NEXT();
+ else
+ EEO_JUMP(op->d.agg_presorted_distinctcheck.jumpdistinct);
+ }
+
+ EEO_CASE(EEOP_AGG_PRESORTED_DISTINCT_MULTI)
+ {
+ AggState *aggstate = castNode(AggState, state->parent);
+ AggStatePerTrans pertrans = op->d.agg_presorted_distinctcheck.pertrans;
+
+ if (ExecEvalPreOrderedDistinctMulti(aggstate, pertrans))
+ EEO_NEXT();
+ else
+ EEO_JUMP(op->d.agg_presorted_distinctcheck.jumpdistinct);
+ }
+
/* process single-column ordered aggregate datum */
EEO_CASE(EEOP_AGG_ORDERED_TRANS_DATUM)
{
@@ -4403,6 +4427,84 @@ ExecAggTransReparent(AggState *aggstate, AggStatePerTrans pertrans,
}
/*
+ * ExecEvalPreOrderedDistinctSingle
+ * Returns true when the aggregate transition value Datum is distinct
+ * from the previous input Datum and returns false when the input Datum
+ * matches the previous input Datum.
+ */
+bool
+ExecEvalPreOrderedDistinctSingle(AggState *aggstate, AggStatePerTrans pertrans)
+{
+ Datum value = pertrans->transfn_fcinfo->args[1].value;
+ bool isnull = pertrans->transfn_fcinfo->args[1].isnull;
+
+ if (!pertrans->haslast ||
+ pertrans->lastisnull != isnull ||
+ !DatumGetBool(FunctionCall2Coll(&pertrans->equalfnOne,
+ pertrans->aggCollation,
+ pertrans->lastdatum, value)))
+ {
+ if (pertrans->haslast && !pertrans->inputtypeByVal)
+ pfree(DatumGetPointer(pertrans->lastdatum));
+
+ pertrans->haslast = true;
+ if (!isnull)
+ {
+ MemoryContext oldContext;
+
+ oldContext = MemoryContextSwitchTo(aggstate->curaggcontext->ecxt_per_tuple_memory);
+
+ pertrans->lastdatum = datumCopy(value, pertrans->inputtypeByVal,
+ pertrans->inputtypeLen);
+
+ MemoryContextSwitchTo(oldContext);
+ }
+ else
+ pertrans->lastdatum = (Datum) 0;
+ pertrans->lastisnull = isnull;
+ return true;
+ }
+
+ return false;
+}
+
+/*
+ * ExecEvalPreOrderedDistinctMulti
+ * Returns true when the aggregate input is distinct from the previous
+ * input and returns false when the input matches the previous input.
+ */
+bool
+ExecEvalPreOrderedDistinctMulti(AggState *aggstate, AggStatePerTrans pertrans)
+{
+ ExprContext *tmpcontext = aggstate->tmpcontext;
+
+ for (int i = 0; i < pertrans->numTransInputs; i++)
+ {
+ pertrans->sortslot->tts_values[i] = pertrans->transfn_fcinfo->args[i + 1].value;
+ pertrans->sortslot->tts_isnull[i] = pertrans->transfn_fcinfo->args[i + 1].isnull;
+ }
+
+ ExecClearTuple(pertrans->sortslot);
+ pertrans->sortslot->tts_nvalid = pertrans->numInputs;
+ ExecStoreVirtualTuple(pertrans->sortslot);
+
+ tmpcontext->ecxt_outertuple = pertrans->sortslot;
+ tmpcontext->ecxt_innertuple = pertrans->uniqslot;
+
+ if (!pertrans->haslast ||
+ !ExecQual(pertrans->equalfnMulti, tmpcontext))
+ {
+ if (pertrans->haslast)
+ ExecClearTuple(pertrans->uniqslot);
+
+ pertrans->haslast = true;
+ ExecCopySlot(pertrans->uniqslot, pertrans->sortslot);
+ return true;
+ }
+ return false;
+}
+
+/*
* Invoke ordered transition function, with a datum argument.
*/
void