* nodeUnique.c
* Routines to handle unique'ing of queries where appropriate
*
- * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
+ * Unique is a very simple node type that just filters out duplicate
+ * tuples from a stream of sorted tuples from its subplan. It's essentially
+ * a dumbed-down form of Group: the duplicate-removal functionality is
+ * identical. However, Unique doesn't do projection nor qual checking,
+ * so it's marginally more efficient for cases where neither is needed.
+ * (It's debatable whether the savings justifies carrying two plan node
+ * types, though.)
+ *
+ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/nodeUnique.c,v 1.54 2007/01/05 22:19:28 momjian Exp $
+ * src/backend/executor/nodeUnique.c
*
*-------------------------------------------------------------------------
*/
/*
* INTERFACE ROUTINES
* ExecUnique - generate a unique'd temporary relation
- * ExecInitUnique - initialize node and subnodes..
+ * ExecInitUnique - initialize node and subnodes
* ExecEndUnique - shutdown node and subnodes
*
* NOTES
/* ----------------------------------------------------------------
* ExecUnique
- *
- * This is a very simple node which filters out duplicate
- * tuples from a stream of sorted tuples from a subplan.
* ----------------------------------------------------------------
*/
TupleTableSlot * /* return: a tuple or NULL */
/*
* now loop, returning only non-duplicate tuples. We assume that the
- * tuples arrive in sorted order so we can detect duplicates easily.
- *
- * We return the first tuple from each group of duplicates (or the last
- * tuple of each group, when moving backwards). At either end of the
- * subplan, clear the result slot so that we correctly return the
- * first/last tuple when reversing direction.
+ * tuples arrive in sorted order so we can detect duplicates easily. The
+ * first tuple of each group is returned.
*/
for (;;)
{
slot = ExecProcNode(outerPlan);
if (TupIsNull(slot))
{
- /* end of subplan; reset in case we change direction */
+ /* end of subplan, so we're done */
ExecClearTuple(resultTupleSlot);
return NULL;
}
/*
- * Always return the first/last tuple from the subplan.
+ * Always return the first tuple from the subplan.
*/
if (TupIsNull(resultTupleSlot))
break;
UniqueState *uniquestate;
/* check for unsupported flags */
- Assert(!(eflags & EXEC_FLAG_MARK));
+ Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
/*
* create state structure
ALLOCSET_DEFAULT_INITSIZE,
ALLOCSET_DEFAULT_MAXSIZE);
-#define UNIQUE_NSLOTS 1
-
/*
* Tuple table initialization
*/
* Precompute fmgr lookup data for inner loop
*/
uniquestate->eqfunctions =
- execTuplesMatchPrepare(ExecGetResultType(&uniquestate->ps),
- node->numCols,
- node->uniqColIdx);
+ execTuplesMatchPrepare(node->numCols,
+ node->uniqOperators);
return uniquestate;
}
-int
-ExecCountSlotsUnique(Unique *node)
-{
- return ExecCountSlotsNode(outerPlan(node)) +
- ExecCountSlotsNode(innerPlan(node)) +
- UNIQUE_NSLOTS;
-}
-
/* ----------------------------------------------------------------
* ExecEndUnique
*
void
-ExecReScanUnique(UniqueState *node, ExprContext *exprCtxt)
+ExecReScanUnique(UniqueState *node)
{
/* must clear result tuple so first input tuple is returned */
ExecClearTuple(node->ps.ps_ResultTupleSlot);
* if chgParam of subnode is not null then plan will be re-scanned by
* first ExecProcNode.
*/
- if (((PlanState *) node)->lefttree->chgParam == NULL)
- ExecReScan(((PlanState *) node)->lefttree, exprCtxt);
+ if (node->ps.lefttree->chgParam == NULL)
+ ExecReScan(node->ps.lefttree);
}