* nodeGroup.c
* Routines to handle group nodes (used for queries with GROUP BY clause).
*
- * Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
#include "executor/executor.h"
#include "executor/nodeGroup.h"
#include "miscadmin.h"
+#include "utils/memutils.h"
/*
{
GroupState *node = castNode(GroupState, pstate);
ExprContext *econtext;
- int numCols;
- AttrNumber *grpColIdx;
TupleTableSlot *firsttupleslot;
TupleTableSlot *outerslot;
if (node->grp_done)
return NULL;
econtext = node->ss.ps.ps_ExprContext;
- numCols = ((Group *) node->ss.ps.plan)->numCols;
- grpColIdx = ((Group *) node->ss.ps.plan)->grpColIdx;
/*
* The ScanTupleSlot holds the (copied) first tuple of each group.
firsttupleslot = node->ss.ss_ScanTupleSlot;
/*
- * We need not call ResetExprContext here because execTuplesMatch will
+ * We need not call ResetExprContext here because ExecQualAndReset() will
* reset the per-tuple memory context once per input tuple.
*/
* Compare with first tuple and see if this tuple is of the same
* group. If so, ignore it and keep scanning.
*/
- if (!execTuplesMatch(firsttupleslot, outerslot,
- numCols, grpColIdx,
- node->eqfunctions,
- econtext->ecxt_per_tuple_memory))
+ econtext->ecxt_innertuple = firsttupleslot;
+ econtext->ecxt_outertuple = outerslot;
+ if (!ExecQualAndReset(node->eqfunction, econtext))
break;
}
ExecInitGroup(Group *node, EState *estate, int eflags)
{
GroupState *grpstate;
+ const TupleTableSlotOps *tts_ops;
/* check for unsupported flags */
Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
*/
ExecAssignExprContext(estate, &grpstate->ss.ps);
- /*
- * tuple table initialization
- */
- ExecInitScanTupleSlot(estate, &grpstate->ss);
- ExecInitResultTupleSlot(estate, &grpstate->ss.ps);
-
- /*
- * initialize child expressions
- */
- grpstate->ss.ps.qual =
- ExecInitQual(node->plan.qual, (PlanState *) grpstate);
-
/*
* initialize child nodes
*/
outerPlanState(grpstate) = ExecInitNode(outerPlan(node), estate, eflags);
/*
- * initialize tuple type.
+ * Initialize scan slot and type.
*/
- ExecAssignScanTypeFromOuterPlan(&grpstate->ss);
+ tts_ops = ExecGetResultSlotOps(outerPlanState(&grpstate->ss), NULL);
+ ExecCreateScanSlotFromOuterPlan(estate, &grpstate->ss, tts_ops);
/*
- * Initialize result tuple type and projection info.
+ * Initialize result slot, type and projection.
*/
- ExecAssignResultTypeFromTL(&grpstate->ss.ps);
+ ExecInitResultTupleSlotTL(&grpstate->ss.ps, &TTSOpsVirtual);
ExecAssignProjectionInfo(&grpstate->ss.ps, NULL);
+ /*
+ * initialize child expressions
+ */
+ grpstate->ss.ps.qual =
+ ExecInitQual(node->plan.qual, (PlanState *) grpstate);
+
/*
* Precompute fmgr lookup data for inner loop
*/
- grpstate->eqfunctions =
- execTuplesMatchPrepare(node->numCols,
- node->grpOperators);
+ grpstate->eqfunction =
+ execTuplesMatchPrepare(ExecGetResultType(outerPlanState(grpstate)),
+ node->numCols,
+ node->grpColIdx,
+ node->grpOperators,
+ &grpstate->ss.ps);
return grpstate;
}