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-2023, 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 #include "utils/memutils.h"
40 
41 
42 /* ----------------------------------------------------------------
43  * ExecUnique
44  * ----------------------------------------------------------------
45  */
46 static TupleTableSlot * /* return: a tuple or NULL */
48 {
49  UniqueState *node = castNode(UniqueState, pstate);
50  ExprContext *econtext = node->ps.ps_ExprContext;
51  TupleTableSlot *resultTupleSlot;
52  TupleTableSlot *slot;
54 
56 
57  /*
58  * get information from the node
59  */
60  outerPlan = outerPlanState(node);
61  resultTupleSlot = node->ps.ps_ResultTupleSlot;
62 
63  /*
64  * now loop, returning only non-duplicate tuples. We assume that the
65  * tuples arrive in sorted order so we can detect duplicates easily. The
66  * first tuple of each group is returned.
67  */
68  for (;;)
69  {
70  /*
71  * fetch a tuple from the outer subplan
72  */
73  slot = ExecProcNode(outerPlan);
74  if (TupIsNull(slot))
75  {
76  /* end of subplan, so we're done */
77  ExecClearTuple(resultTupleSlot);
78  return NULL;
79  }
80 
81  /*
82  * Always return the first tuple from the subplan.
83  */
84  if (TupIsNull(resultTupleSlot))
85  break;
86 
87  /*
88  * Else test if the new tuple and the previously returned tuple match.
89  * If so then we loop back and fetch another new tuple from the
90  * subplan.
91  */
92  econtext->ecxt_innertuple = slot;
93  econtext->ecxt_outertuple = resultTupleSlot;
94  if (!ExecQualAndReset(node->eqfunction, econtext))
95  break;
96  }
97 
98  /*
99  * We have a new tuple different from the previous saved tuple (if any).
100  * Save it and return it. We must copy it because the source subplan
101  * won't guarantee that this source tuple is still accessible after
102  * fetching the next source tuple.
103  */
104  return ExecCopySlot(resultTupleSlot, slot);
105 }
106 
107 /* ----------------------------------------------------------------
108  * ExecInitUnique
109  *
110  * This initializes the unique node state structures and
111  * the node's subplan.
112  * ----------------------------------------------------------------
113  */
114 UniqueState *
115 ExecInitUnique(Unique *node, EState *estate, int eflags)
116 {
117  UniqueState *uniquestate;
118 
119  /* check for unsupported flags */
120  Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
121 
122  /*
123  * create state structure
124  */
125  uniquestate = makeNode(UniqueState);
126  uniquestate->ps.plan = (Plan *) node;
127  uniquestate->ps.state = estate;
128  uniquestate->ps.ExecProcNode = ExecUnique;
129 
130  /*
131  * create expression context
132  */
133  ExecAssignExprContext(estate, &uniquestate->ps);
134 
135  /*
136  * then initialize outer plan
137  */
138  outerPlanState(uniquestate) = ExecInitNode(outerPlan(node), estate, eflags);
139 
140  /*
141  * Initialize result slot and type. Unique nodes do no projections, so
142  * initialize projection info for this node appropriately.
143  */
145  uniquestate->ps.ps_ProjInfo = NULL;
146 
147  /*
148  * Precompute fmgr lookup data for inner loop
149  */
150  uniquestate->eqfunction =
152  node->numCols,
153  node->uniqColIdx,
154  node->uniqOperators,
155  node->uniqCollations,
156  &uniquestate->ps);
157 
158  return uniquestate;
159 }
160 
161 /* ----------------------------------------------------------------
162  * ExecEndUnique
163  *
164  * This shuts down the subplan and frees resources allocated
165  * to this node.
166  * ----------------------------------------------------------------
167  */
168 void
170 {
172 }
173 
174 
175 void
177 {
179 
180  /* must clear result tuple so first input tuple is returned */
182 
183  /*
184  * if chgParam of subnode is not null then plan will be re-scanned by
185  * first ExecProcNode.
186  */
187  if (outerPlan->chgParam == NULL)
189 }
void ExecReScan(PlanState *node)
Definition: execAmi.c:78
ExprState * execTuplesMatchPrepare(TupleDesc desc, int numCols, const AttrNumber *keyColIdx, const Oid *eqOperators, const Oid *collations, PlanState *parent)
Definition: execGrouping.c:59
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:1798
const TupleTableSlotOps TTSOpsMinimalTuple
Definition: execTuples.c:85
TupleDesc ExecGetResultType(PlanState *planstate)
Definition: execUtils.c:498
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition: execUtils.c:488
#define outerPlanState(node)
Definition: execnodes.h:1132
#define EXEC_FLAG_BACKWARD
Definition: executor.h:68
static bool ExecQualAndReset(ExprState *state, ExprContext *econtext)
Definition: executor.h:439
#define EXEC_FLAG_MARK
Definition: executor.h:69
static TupleTableSlot * ExecProcNode(PlanState *node)
Definition: executor.h:268
Assert(fmt[strlen(fmt) - 1] !='\n')
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:121
static TupleTableSlot * ExecUnique(PlanState *pstate)
Definition: nodeUnique.c:47
void ExecEndUnique(UniqueState *node)
Definition: nodeUnique.c:169
void ExecReScanUnique(UniqueState *node)
Definition: nodeUnique.c:176
UniqueState * ExecInitUnique(Unique *node, EState *estate, int eflags)
Definition: nodeUnique.c:115
#define makeNode(_type_)
Definition: nodes.h:176
#define castNode(_type_, nodeptr)
Definition: nodes.h:197
#define outerPlan(node)
Definition: plannodes.h:182
TupleTableSlot * ecxt_innertuple
Definition: execnodes.h:250
TupleTableSlot * ecxt_outertuple
Definition: execnodes.h:252
Plan * plan
Definition: execnodes.h:1036
EState * state
Definition: execnodes.h:1038
ExprContext * ps_ExprContext
Definition: execnodes.h:1075
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:1074
ProjectionInfo * ps_ProjInfo
Definition: execnodes.h:1076
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:1042
PlanState ps
Definition: execnodes.h:2572
ExprState * eqfunction
Definition: execnodes.h:2573
int numCols
Definition: plannodes.h:1115
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:433
static TupleTableSlot * ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
Definition: tuptable.h:488
#define TupIsNull(slot)
Definition: tuptable.h:300