]> granicus.if.org Git - postgresql/blob - src/backend/executor/nodeUnique.c
Revert DTrace patch from Robert Lor
[postgresql] / src / backend / executor / nodeUnique.c
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-2009, PostgreSQL Global Development Group
15  * Portions Copyright (c) 1994, Regents of the University of California
16  *
17  *
18  * IDENTIFICATION
19  *        $PostgreSQL: pgsql/src/backend/executor/nodeUnique.c,v 1.60 2009/04/02 20:59:10 momjian Exp $
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 "utils/memutils.h"
39
40
41 /* ----------------------------------------------------------------
42  *              ExecUnique
43  * ----------------------------------------------------------------
44  */
45 TupleTableSlot *                                /* return: a tuple or NULL */
46 ExecUnique(UniqueState *node)
47 {
48         Unique     *plannode = (Unique *) node->ps.plan;
49         TupleTableSlot *resultTupleSlot;
50         TupleTableSlot *slot;
51         PlanState  *outerPlan;
52
53         /*
54          * get information from the node
55          */
56         outerPlan = outerPlanState(node);
57         resultTupleSlot = node->ps.ps_ResultTupleSlot;
58
59         /*
60          * now loop, returning only non-duplicate tuples. We assume that the
61          * tuples arrive in sorted order so we can detect duplicates easily.
62          * The first tuple of each group is returned.
63          */
64         for (;;)
65         {
66                 /*
67                  * fetch a tuple from the outer subplan
68                  */
69                 slot = ExecProcNode(outerPlan);
70                 if (TupIsNull(slot))
71                 {
72                         /* end of subplan, so we're done */
73                         ExecClearTuple(resultTupleSlot);
74                         return NULL;
75                 }
76
77                 /*
78                  * Always return the first tuple from the subplan.
79                  */
80                 if (TupIsNull(resultTupleSlot))
81                         break;
82
83                 /*
84                  * Else test if the new tuple and the previously returned tuple match.
85                  * If so then we loop back and fetch another new tuple from the
86                  * subplan.
87                  */
88                 if (!execTuplesMatch(slot, resultTupleSlot,
89                                                          plannode->numCols, plannode->uniqColIdx,
90                                                          node->eqfunctions,
91                                                          node->tempContext))
92                         break;
93         }
94
95         /*
96          * We have a new tuple different from the previous saved tuple (if any).
97          * Save it and return it.  We must copy it because the source subplan
98          * won't guarantee that this source tuple is still accessible after
99          * fetching the next source tuple.
100          */
101         return ExecCopySlot(resultTupleSlot, slot);
102 }
103
104 /* ----------------------------------------------------------------
105  *              ExecInitUnique
106  *
107  *              This initializes the unique node state structures and
108  *              the node's subplan.
109  * ----------------------------------------------------------------
110  */
111 UniqueState *
112 ExecInitUnique(Unique *node, EState *estate, int eflags)
113 {
114         UniqueState *uniquestate;
115
116         /* check for unsupported flags */
117         Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
118
119         /*
120          * create state structure
121          */
122         uniquestate = makeNode(UniqueState);
123         uniquestate->ps.plan = (Plan *) node;
124         uniquestate->ps.state = estate;
125
126         /*
127          * Miscellaneous initialization
128          *
129          * Unique nodes have no ExprContext initialization because they never call
130          * ExecQual or ExecProject.  But they do need a per-tuple memory context
131          * anyway for calling execTuplesMatch.
132          */
133         uniquestate->tempContext =
134                 AllocSetContextCreate(CurrentMemoryContext,
135                                                           "Unique",
136                                                           ALLOCSET_DEFAULT_MINSIZE,
137                                                           ALLOCSET_DEFAULT_INITSIZE,
138                                                           ALLOCSET_DEFAULT_MAXSIZE);
139
140 #define UNIQUE_NSLOTS 1
141
142         /*
143          * Tuple table initialization
144          */
145         ExecInitResultTupleSlot(estate, &uniquestate->ps);
146
147         /*
148          * then initialize outer plan
149          */
150         outerPlanState(uniquestate) = ExecInitNode(outerPlan(node), estate, eflags);
151
152         /*
153          * unique nodes do no projections, so initialize projection info for this
154          * node appropriately
155          */
156         ExecAssignResultTypeFromTL(&uniquestate->ps);
157         uniquestate->ps.ps_ProjInfo = NULL;
158
159         /*
160          * Precompute fmgr lookup data for inner loop
161          */
162         uniquestate->eqfunctions =
163                 execTuplesMatchPrepare(node->numCols,
164                                                            node->uniqOperators);
165
166         return uniquestate;
167 }
168
169 int
170 ExecCountSlotsUnique(Unique *node)
171 {
172         return ExecCountSlotsNode(outerPlan(node)) +
173                 ExecCountSlotsNode(innerPlan(node)) +
174                 UNIQUE_NSLOTS;
175 }
176
177 /* ----------------------------------------------------------------
178  *              ExecEndUnique
179  *
180  *              This shuts down the subplan and frees resources allocated
181  *              to this node.
182  * ----------------------------------------------------------------
183  */
184 void
185 ExecEndUnique(UniqueState *node)
186 {
187         /* clean up tuple table */
188         ExecClearTuple(node->ps.ps_ResultTupleSlot);
189
190         MemoryContextDelete(node->tempContext);
191
192         ExecEndNode(outerPlanState(node));
193 }
194
195
196 void
197 ExecReScanUnique(UniqueState *node, ExprContext *exprCtxt)
198 {
199         /* must clear result tuple so first input tuple is returned */
200         ExecClearTuple(node->ps.ps_ResultTupleSlot);
201
202         /*
203          * if chgParam of subnode is not null then plan will be re-scanned by
204          * first ExecProcNode.
205          */
206         if (((PlanState *) node)->lefttree->chgParam == NULL)
207                 ExecReScan(((PlanState *) node)->lefttree, exprCtxt);
208 }