PostgreSQL Source Code  git master
nodeUnique.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * nodeUnique.c
4  * Routines to handle unique'ing of queries where appropriate
5  *
6  * Unique is a very simple node type that just filters out duplicate
7  * tuples from a stream of sorted tuples from its subplan. It's essentially
8  * a dumbed-down form of Group: the duplicate-removal functionality is
9  * identical. However, Unique doesn't do projection nor qual checking,
10  * so it's marginally more efficient for cases where neither is needed.
11  * (It's debatable whether the savings justifies carrying two plan node
12  * types, though.)
13  *
14  * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
15  * Portions Copyright (c) 1994, Regents of the University of California
16  *
17  *
18  * IDENTIFICATION
19  * src/backend/executor/nodeUnique.c
20  *
21  *-------------------------------------------------------------------------
22  */
23 /*
24  * INTERFACE ROUTINES
25  * ExecUnique - generate a unique'd temporary relation
26  * ExecInitUnique - initialize node and subnodes
27  * ExecEndUnique - shutdown node and subnodes
28  *
29  * NOTES
30  * Assumes tuples returned from subplan arrive in
31  * sorted order.
32  */
33 
34 #include "postgres.h"
35 
36 #include "executor/executor.h"
37 #include "executor/nodeUnique.h"
38 #include "miscadmin.h"
39 
40 
41 /* ----------------------------------------------------------------
42  * ExecUnique
43  * ----------------------------------------------------------------
44  */
45 static TupleTableSlot * /* return: a tuple or NULL */
47 {
48  UniqueState *node = castNode(UniqueState, pstate);
49  ExprContext *econtext = node->ps.ps_ExprContext;
50  TupleTableSlot *resultTupleSlot;
51  TupleTableSlot *slot;
53 
55 
56  /*
57  * get information from the node
58  */
59  outerPlan = outerPlanState(node);
60  resultTupleSlot = node->ps.ps_ResultTupleSlot;
61 
62  /*
63  * now loop, returning only non-duplicate tuples. We assume that the
64  * tuples arrive in sorted order so we can detect duplicates easily. The
65  * first tuple of each group is returned.
66  */
67  for (;;)
68  {
69  /*
70  * fetch a tuple from the outer subplan
71  */
72  slot = ExecProcNode(outerPlan);
73  if (TupIsNull(slot))
74  {
75  /* end of subplan, so we're done */
76  ExecClearTuple(resultTupleSlot);
77  return NULL;
78  }
79 
80  /*
81  * Always return the first tuple from the subplan.
82  */
83  if (TupIsNull(resultTupleSlot))
84  break;
85 
86  /*
87  * Else test if the new tuple and the previously returned tuple match.
88  * If so then we loop back and fetch another new tuple from the
89  * subplan.
90  */
91  econtext->ecxt_innertuple = slot;
92  econtext->ecxt_outertuple = resultTupleSlot;
93  if (!ExecQualAndReset(node->eqfunction, econtext))
94  break;
95  }
96 
97  /*
98  * We have a new tuple different from the previous saved tuple (if any).
99  * Save it and return it. We must copy it because the source subplan
100  * won't guarantee that this source tuple is still accessible after
101  * fetching the next source tuple.
102  */
103  return ExecCopySlot(resultTupleSlot, slot);
104 }
105 
106 /* ----------------------------------------------------------------
107  * ExecInitUnique
108  *
109  * This initializes the unique node state structures and
110  * the node's subplan.
111  * ----------------------------------------------------------------
112  */
113 UniqueState *
114 ExecInitUnique(Unique *node, EState *estate, int eflags)
115 {
116  UniqueState *uniquestate;
117 
118  /* check for unsupported flags */
119  Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
120 
121  /*
122  * create state structure
123  */
124  uniquestate = makeNode(UniqueState);
125  uniquestate->ps.plan = (Plan *) node;
126  uniquestate->ps.state = estate;
127  uniquestate->ps.ExecProcNode = ExecUnique;
128 
129  /*
130  * create expression context
131  */
132  ExecAssignExprContext(estate, &uniquestate->ps);
133 
134  /*
135  * then initialize outer plan
136  */
137  outerPlanState(uniquestate) = ExecInitNode(outerPlan(node), estate, eflags);
138 
139  /*
140  * Initialize result slot and type. Unique nodes do no projections, so
141  * initialize projection info for this node appropriately.
142  */
144  uniquestate->ps.ps_ProjInfo = NULL;
145 
146  /*
147  * Precompute fmgr lookup data for inner loop
148  */
149  uniquestate->eqfunction =
151  node->numCols,
152  node->uniqColIdx,
153  node->uniqOperators,
154  node->uniqCollations,
155  &uniquestate->ps);
156 
157  return uniquestate;
158 }
159 
160 /* ----------------------------------------------------------------
161  * ExecEndUnique
162  *
163  * This shuts down the subplan and frees resources allocated
164  * to this node.
165  * ----------------------------------------------------------------
166  */
167 void
169 {
171 }
172 
173 
174 void
176 {
178 
179  /* must clear result tuple so first input tuple is returned */
181 
182  /*
183  * if chgParam of subnode is not null then plan will be re-scanned by
184  * first ExecProcNode.
185  */
186  if (outerPlan->chgParam == NULL)
188 }
#define Assert(condition)
Definition: c.h:858
void ExecReScan(PlanState *node)
Definition: execAmi.c:76
ExprState * execTuplesMatchPrepare(TupleDesc desc, int numCols, const AttrNumber *keyColIdx, const Oid *eqOperators, const Oid *collations, PlanState *parent)
Definition: execGrouping.c:58
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:557
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
Definition: execProcnode.c:142
void ExecInitResultTupleSlotTL(PlanState *planstate, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1886
const TupleTableSlotOps TTSOpsMinimalTuple
Definition: execTuples.c:86
TupleDesc ExecGetResultType(PlanState *planstate)
Definition: execUtils.c:493
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition: execUtils.c:483
#define outerPlanState(node)
Definition: execnodes.h:1214
#define EXEC_FLAG_BACKWARD
Definition: executor.h:68
static bool ExecQualAndReset(ExprState *state, ExprContext *econtext)
Definition: executor.h:440
#define EXEC_FLAG_MARK
Definition: executor.h:69
static TupleTableSlot * ExecProcNode(PlanState *node)
Definition: executor.h:269
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:122
static TupleTableSlot * ExecUnique(PlanState *pstate)
Definition: nodeUnique.c:46
void ExecEndUnique(UniqueState *node)
Definition: nodeUnique.c:168
void ExecReScanUnique(UniqueState *node)
Definition: nodeUnique.c:175
UniqueState * ExecInitUnique(Unique *node, EState *estate, int eflags)
Definition: nodeUnique.c:114
#define makeNode(_type_)
Definition: nodes.h:155
#define castNode(_type_, nodeptr)
Definition: nodes.h:176
#define outerPlan(node)
Definition: plannodes.h:182
TupleTableSlot * ecxt_innertuple
Definition: execnodes.h:257
TupleTableSlot * ecxt_outertuple
Definition: execnodes.h:259
Plan * plan
Definition: execnodes.h:1118
EState * state
Definition: execnodes.h:1120
ExprContext * ps_ExprContext
Definition: execnodes.h:1157
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:1156
ProjectionInfo * ps_ProjInfo
Definition: execnodes.h:1158
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:1124
PlanState ps
Definition: execnodes.h:2656
ExprState * eqfunction
Definition: execnodes.h:2657
int numCols
Definition: plannodes.h:1117
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:454
static TupleTableSlot * ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
Definition: tuptable.h:509
#define TupIsNull(slot)
Definition: tuptable.h:306