Fix pg_dump bug in the database-level collation patch. "datcollate" and
[PostgreSQL.git] / src / backend / executor / nodeUnique.c
blobd655485d8b196f98554f263cdb7427823f7798e3
1 /*-------------------------------------------------------------------------
3 * nodeUnique.c
4 * Routines to handle unique'ing of queries where appropriate
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.)
14 * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
15 * Portions Copyright (c) 1994, Regents of the University of California
18 * IDENTIFICATION
19 * $PostgreSQL$
21 *-------------------------------------------------------------------------
24 * INTERFACE ROUTINES
25 * ExecUnique - generate a unique'd temporary relation
26 * ExecInitUnique - initialize node and subnodes
27 * ExecEndUnique - shutdown node and subnodes
29 * NOTES
30 * Assumes tuples returned from subplan arrive in
31 * sorted order.
34 #include "postgres.h"
36 #include "executor/executor.h"
37 #include "executor/nodeUnique.h"
38 #include "utils/memutils.h"
41 /* ----------------------------------------------------------------
42 * ExecUnique
43 * ----------------------------------------------------------------
45 TupleTableSlot * /* return: a tuple or NULL */
46 ExecUnique(UniqueState *node)
48 Unique *plannode = (Unique *) node->ps.plan;
49 TupleTableSlot *resultTupleSlot;
50 TupleTableSlot *slot;
51 PlanState *outerPlan;
54 * get information from the node
56 outerPlan = outerPlanState(node);
57 resultTupleSlot = node->ps.ps_ResultTupleSlot;
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.
64 for (;;)
67 * fetch a tuple from the outer subplan
69 slot = ExecProcNode(outerPlan);
70 if (TupIsNull(slot))
72 /* end of subplan, so we're done */
73 ExecClearTuple(resultTupleSlot);
74 return NULL;
78 * Always return the first tuple from the subplan.
80 if (TupIsNull(resultTupleSlot))
81 break;
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.
88 if (!execTuplesMatch(slot, resultTupleSlot,
89 plannode->numCols, plannode->uniqColIdx,
90 node->eqfunctions,
91 node->tempContext))
92 break;
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.
101 return ExecCopySlot(resultTupleSlot, slot);
104 /* ----------------------------------------------------------------
105 * ExecInitUnique
107 * This initializes the unique node state structures and
108 * the node's subplan.
109 * ----------------------------------------------------------------
111 UniqueState *
112 ExecInitUnique(Unique *node, EState *estate, int eflags)
114 UniqueState *uniquestate;
116 /* check for unsupported flags */
117 Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
120 * create state structure
122 uniquestate = makeNode(UniqueState);
123 uniquestate->ps.plan = (Plan *) node;
124 uniquestate->ps.state = estate;
127 * Miscellaneous initialization
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.
133 uniquestate->tempContext =
134 AllocSetContextCreate(CurrentMemoryContext,
135 "Unique",
136 ALLOCSET_DEFAULT_MINSIZE,
137 ALLOCSET_DEFAULT_INITSIZE,
138 ALLOCSET_DEFAULT_MAXSIZE);
140 #define UNIQUE_NSLOTS 1
143 * Tuple table initialization
145 ExecInitResultTupleSlot(estate, &uniquestate->ps);
148 * then initialize outer plan
150 outerPlanState(uniquestate) = ExecInitNode(outerPlan(node), estate, eflags);
153 * unique nodes do no projections, so initialize projection info for this
154 * node appropriately
156 ExecAssignResultTypeFromTL(&uniquestate->ps);
157 uniquestate->ps.ps_ProjInfo = NULL;
160 * Precompute fmgr lookup data for inner loop
162 uniquestate->eqfunctions =
163 execTuplesMatchPrepare(node->numCols,
164 node->uniqOperators);
166 return uniquestate;
170 ExecCountSlotsUnique(Unique *node)
172 return ExecCountSlotsNode(outerPlan(node)) +
173 ExecCountSlotsNode(innerPlan(node)) +
174 UNIQUE_NSLOTS;
177 /* ----------------------------------------------------------------
178 * ExecEndUnique
180 * This shuts down the subplan and frees resources allocated
181 * to this node.
182 * ----------------------------------------------------------------
184 void
185 ExecEndUnique(UniqueState *node)
187 /* clean up tuple table */
188 ExecClearTuple(node->ps.ps_ResultTupleSlot);
190 MemoryContextDelete(node->tempContext);
192 ExecEndNode(outerPlanState(node));
196 void
197 ExecReScanUnique(UniqueState *node, ExprContext *exprCtxt)
199 /* must clear result tuple so first input tuple is returned */
200 ExecClearTuple(node->ps.ps_ResultTupleSlot);
203 * if chgParam of subnode is not null then plan will be re-scanned by
204 * first ExecProcNode.
206 if (((PlanState *) node)->lefttree->chgParam == NULL)
207 ExecReScan(((PlanState *) node)->lefttree, exprCtxt);