1/*-------------------------------------------------------------------------
4 * Routines to handle group nodes (used for queries with GROUP BY clause).
6 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * The Group node is designed for handling queries with a GROUP BY clause.
12 * Its outer plan must deliver tuples that are sorted in the order
13 * specified by the grouping columns (ie. tuples from the same group are
14 * consecutive). That way, we just have to compare adjacent tuples to
15 * locate group boundaries.
18 * src/backend/executor/nodeGroup.c
20 *-------------------------------------------------------------------------
33 * Return one tuple for each group of matching input tuples.
46 * get state info from node
53 * The ScanTupleSlot holds the (copied) first tuple of each group.
58 * We need not call ResetExprContext here because ExecQualAndReset() will
59 * reset the per-tuple memory context once per input tuple.
63 * If first time through, acquire first input tuple and determine whether
64 * to return it or not.
71 /* empty input, so return nothing */
75 /* Copy tuple into firsttupleslot */
79 * Set it up as input for qual test and projection. The expressions
80 * will access the input tuple as varno OUTER.
85 * Check the qual (HAVING clause); if the group does not match, ignore
86 * it and fall into scan loop.
91 * Form and return a projection tuple using the first input tuple.
100 * This loop iterates once per input tuple group. At the head of the
101 * loop, we have finished processing the first tuple of the group and now
102 * need to scan over all the other group members.
107 * Scan over all remaining tuples that belong to this group
114 /* no more groups, so we're done */
120 * Compare with first tuple and see if this tuple is of the same
121 * group. If so, ignore it and keep scanning.
130 * We have the first tuple of the next input group. See if we want to
133 /* Copy tuple, set up as input for qual test and projection */
138 * Check the qual (HAVING clause); if the group does not match, ignore
139 * it and loop back to scan the rest of the group.
144 * Form and return a projection tuple using the first input tuple.
156 * Creates the run-time information for the group node produced by the
157 * planner and initializes its outer subtree
166 /* check for unsupported flags */
170 * create state structure
179 * create expression context
184 * initialize child nodes
189 * Initialize scan slot and type.
195 * Initialize result slot, type and projection.
201 * initialize child expressions
207 * Precompute fmgr lookup data for inner loop
220/* ------------------------
223 * -----------------------
240 /* must clear first tuple */
244 * if chgParam of subnode is not null then plan will be re-scanned by
245 * first ExecProcNode.
void ExecReScan(PlanState *node)
ExprState * ExecInitQual(List *qual, PlanState *parent)
ExprState * execTuplesMatchPrepare(TupleDesc desc, int numCols, const AttrNumber *keyColIdx, const Oid *eqOperators, const Oid *collations, PlanState *parent)
void ExecEndNode(PlanState *node)
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
const TupleTableSlotOps TTSOpsVirtual
void ExecInitResultTupleSlotTL(PlanState *planstate, const TupleTableSlotOps *tts_ops)
TupleDesc ExecGetResultType(PlanState *planstate)
void ExecCreateScanSlotFromOuterPlan(EState *estate, ScanState *scanstate, const TupleTableSlotOps *tts_ops)
void ExecAssignExprContext(EState *estate, PlanState *planstate)
void ExecAssignProjectionInfo(PlanState *planstate, TupleDesc inputDesc)
const TupleTableSlotOps * ExecGetResultSlotOps(PlanState *planstate, bool *isfixed)
#define InstrCountFiltered1(node, delta)
#define outerPlanState(node)
#define EXEC_FLAG_BACKWARD
static TupleTableSlot * ExecProject(ProjectionInfo *projInfo)
static bool ExecQual(ExprState *state, ExprContext *econtext)
static bool ExecQualAndReset(ExprState *state, ExprContext *econtext)
static TupleTableSlot * ExecProcNode(PlanState *node)
Assert(PointerIsAligned(start, uint64))
#define CHECK_FOR_INTERRUPTS()
GroupState * ExecInitGroup(Group *node, EState *estate, int eflags)
static TupleTableSlot * ExecGroup(PlanState *pstate)
void ExecReScanGroup(GroupState *node)
void ExecEndGroup(GroupState *node)
#define castNode(_type_, nodeptr)
TupleTableSlot * ecxt_innertuple
TupleTableSlot * ecxt_outertuple
ExprContext * ps_ExprContext
ProjectionInfo * ps_ProjInfo
ExecProcNodeMtd ExecProcNode
TupleTableSlot * ss_ScanTupleSlot
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
static TupleTableSlot * ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)