1996-07-09 08:22:35 +02:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
1999-02-14 00:22:53 +01:00
|
|
|
* nodeUnique.c
|
1997-09-07 07:04:48 +02:00
|
|
|
* Routines to handle unique'ing of queries where appropriate
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
2004-12-31 23:04:05 +01:00
|
|
|
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
2000-01-26 06:58:53 +01:00
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
2005-11-22 19:17:34 +01:00
|
|
|
* $PostgreSQL: pgsql/src/backend/executor/nodeUnique.c,v 1.49 2005/11/22 18:17:10 momjian Exp $
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
* INTERFACE ROUTINES
|
1997-09-07 07:04:48 +02:00
|
|
|
* ExecUnique - generate a unique'd temporary relation
|
|
|
|
* ExecInitUnique - initialize node and subnodes..
|
|
|
|
* ExecEndUnique - shutdown node and subnodes
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
* NOTES
|
1997-09-07 07:04:48 +02:00
|
|
|
* Assumes tuples returned from subplan arrive in
|
|
|
|
* sorted order.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
1997-01-10 21:19:49 +01:00
|
|
|
|
1996-10-31 11:12:26 +01:00
|
|
|
#include "postgres.h"
|
|
|
|
|
1996-11-08 07:02:30 +01:00
|
|
|
#include "access/heapam.h"
|
1999-07-16 07:00:38 +02:00
|
|
|
#include "executor/executor.h"
|
|
|
|
#include "executor/nodeUnique.h"
|
2005-05-06 19:24:55 +02:00
|
|
|
#include "utils/memutils.h"
|
1996-07-09 08:22:35 +02:00
|
|
|
|
2003-01-11 00:54:24 +01:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/* ----------------------------------------------------------------
|
1997-09-07 07:04:48 +02:00
|
|
|
* ExecUnique
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
1997-09-07 07:04:48 +02:00
|
|
|
* This is a very simple node which filters out duplicate
|
|
|
|
* tuples from a stream of sorted tuples from a subplan.
|
1996-07-09 08:22:35 +02:00
|
|
|
* ----------------------------------------------------------------
|
|
|
|
*/
|
1997-09-07 07:04:48 +02:00
|
|
|
TupleTableSlot * /* return: a tuple or NULL */
|
2002-12-05 16:50:39 +01:00
|
|
|
ExecUnique(UniqueState *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2002-12-05 16:50:39 +01:00
|
|
|
Unique *plannode = (Unique *) node->ps.plan;
|
1997-09-07 07:04:48 +02:00
|
|
|
TupleTableSlot *resultTupleSlot;
|
|
|
|
TupleTableSlot *slot;
|
2002-12-05 16:50:39 +01:00
|
|
|
PlanState *outerPlan;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2001-03-22 07:16:21 +01:00
|
|
|
/*
|
|
|
|
* get information from the node
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
2002-12-05 16:50:39 +01:00
|
|
|
outerPlan = outerPlanState(node);
|
|
|
|
resultTupleSlot = node->ps.ps_ResultTupleSlot;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2001-03-22 07:16:21 +01:00
|
|
|
/*
|
|
|
|
* now loop, returning only non-duplicate tuples. We assume that the
|
|
|
|
* tuples arrive in sorted order so we can detect duplicates easily.
|
2003-02-02 20:08:57 +01:00
|
|
|
*
|
2005-11-22 19:17:34 +01:00
|
|
|
* 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.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
1997-09-07 07:04:48 +02:00
|
|
|
for (;;)
|
|
|
|
{
|
2001-03-22 07:16:21 +01:00
|
|
|
/*
|
|
|
|
* fetch a tuple from the outer subplan
|
1997-09-07 07:04:48 +02:00
|
|
|
*/
|
2002-12-05 16:50:39 +01:00
|
|
|
slot = ExecProcNode(outerPlan);
|
1997-09-07 07:04:48 +02:00
|
|
|
if (TupIsNull(slot))
|
2003-02-02 20:08:57 +01:00
|
|
|
{
|
|
|
|
/* end of subplan; reset in case we change direction */
|
2005-03-16 22:38:10 +01:00
|
|
|
ExecClearTuple(resultTupleSlot);
|
1997-09-07 07:04:48 +02:00
|
|
|
return NULL;
|
2003-02-02 20:08:57 +01:00
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2001-03-22 07:16:21 +01:00
|
|
|
/*
|
2003-02-02 20:08:57 +01:00
|
|
|
* Always return the first/last tuple from the subplan.
|
1997-09-07 07:04:48 +02:00
|
|
|
*/
|
2005-03-16 22:38:10 +01:00
|
|
|
if (TupIsNull(resultTupleSlot))
|
1997-09-07 07:04:48 +02:00
|
|
|
break;
|
|
|
|
|
2001-03-22 07:16:21 +01:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* Else test if the new tuple and the previously returned tuple match.
|
|
|
|
* If so then we loop back and fetch another new tuple from the
|
|
|
|
* subplan.
|
1997-09-07 07:04:48 +02:00
|
|
|
*/
|
2005-03-16 22:38:10 +01:00
|
|
|
if (!execTuplesMatch(slot, resultTupleSlot,
|
2002-12-05 16:50:39 +01:00
|
|
|
plannode->numCols, plannode->uniqColIdx,
|
|
|
|
node->eqfunctions,
|
|
|
|
node->tempContext))
|
2000-01-27 19:11:50 +01:00
|
|
|
break;
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
|
|
|
|
2001-03-22 07:16:21 +01:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* We have a new tuple different from the previous saved tuple (if any).
|
|
|
|
* Save it and return it. We must copy it because the source subplan
|
|
|
|
* won't guarantee that this source tuple is still accessible after
|
|
|
|
* fetching the next source tuple.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
2005-03-16 22:38:10 +01:00
|
|
|
return ExecCopySlot(resultTupleSlot, slot);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ----------------------------------------------------------------
|
1997-09-07 07:04:48 +02:00
|
|
|
* ExecInitUnique
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
1997-09-07 07:04:48 +02:00
|
|
|
* This initializes the unique node state structures and
|
|
|
|
* the node's subplan.
|
1996-07-09 08:22:35 +02:00
|
|
|
* ----------------------------------------------------------------
|
|
|
|
*/
|
2002-12-05 16:50:39 +01:00
|
|
|
UniqueState *
|
|
|
|
ExecInitUnique(Unique *node, EState *estate)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
UniqueState *uniquestate;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2001-03-22 07:16:21 +01:00
|
|
|
/*
|
2002-12-05 16:50:39 +01:00
|
|
|
* create state structure
|
1997-09-07 07:04:48 +02:00
|
|
|
*/
|
|
|
|
uniquestate = makeNode(UniqueState);
|
2002-12-05 16:50:39 +01:00
|
|
|
uniquestate->ps.plan = (Plan *) node;
|
|
|
|
uniquestate->ps.state = estate;
|
|
|
|
|
2001-03-22 07:16:21 +01:00
|
|
|
/*
|
|
|
|
* Miscellaneous initialization
|
1997-09-07 07:04:48 +02:00
|
|
|
*
|
2005-10-15 04:49:52 +02:00
|
|
|
* Unique nodes have no ExprContext initialization because they never call
|
|
|
|
* ExecQual or ExecProject. But they do need a per-tuple memory context
|
|
|
|
* anyway for calling execTuplesMatch.
|
1997-09-07 07:04:48 +02:00
|
|
|
*/
|
2000-07-12 04:37:39 +02:00
|
|
|
uniquestate->tempContext =
|
|
|
|
AllocSetContextCreate(CurrentMemoryContext,
|
|
|
|
"Unique",
|
|
|
|
ALLOCSET_DEFAULT_MINSIZE,
|
|
|
|
ALLOCSET_DEFAULT_INITSIZE,
|
|
|
|
ALLOCSET_DEFAULT_MAXSIZE);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
#define UNIQUE_NSLOTS 1
|
2001-03-22 07:16:21 +01:00
|
|
|
|
|
|
|
/*
|
1997-09-07 07:04:48 +02:00
|
|
|
* Tuple table initialization
|
|
|
|
*/
|
2002-12-05 16:50:39 +01:00
|
|
|
ExecInitResultTupleSlot(estate, &uniquestate->ps);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2001-03-22 07:16:21 +01:00
|
|
|
/*
|
|
|
|
* then initialize outer plan
|
1997-09-07 07:04:48 +02:00
|
|
|
*/
|
2002-12-05 16:50:39 +01:00
|
|
|
outerPlanState(uniquestate) = ExecInitNode(outerPlan(node), estate);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2001-03-22 07:16:21 +01:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* unique nodes do no projections, so initialize projection info for this
|
|
|
|
* node appropriately
|
1997-09-07 07:04:48 +02:00
|
|
|
*/
|
2002-12-05 16:50:39 +01:00
|
|
|
ExecAssignResultTypeFromOuterPlan(&uniquestate->ps);
|
|
|
|
uniquestate->ps.ps_ProjInfo = NULL;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2000-01-27 19:11:50 +01:00
|
|
|
/*
|
|
|
|
* Precompute fmgr lookup data for inner loop
|
1997-09-07 07:04:48 +02:00
|
|
|
*/
|
2000-01-27 19:11:50 +01:00
|
|
|
uniquestate->eqfunctions =
|
2002-12-05 16:50:39 +01:00
|
|
|
execTuplesMatchPrepare(ExecGetResultType(&uniquestate->ps),
|
2000-01-27 19:11:50 +01:00
|
|
|
node->numCols,
|
|
|
|
node->uniqColIdx);
|
|
|
|
|
2002-12-05 16:50:39 +01:00
|
|
|
return uniquestate;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
1997-09-08 23:56:23 +02:00
|
|
|
ExecCountSlotsUnique(Unique *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1997-09-07 07:04:48 +02:00
|
|
|
return ExecCountSlotsNode(outerPlan(node)) +
|
2001-10-25 07:50:21 +02:00
|
|
|
ExecCountSlotsNode(innerPlan(node)) +
|
|
|
|
UNIQUE_NSLOTS;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ----------------------------------------------------------------
|
1997-09-07 07:04:48 +02:00
|
|
|
* ExecEndUnique
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
1997-09-07 07:04:48 +02:00
|
|
|
* This shuts down the subplan and frees resources allocated
|
|
|
|
* to this node.
|
1996-07-09 08:22:35 +02:00
|
|
|
* ----------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
void
|
2002-12-05 16:50:39 +01:00
|
|
|
ExecEndUnique(UniqueState *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2000-01-27 19:11:50 +01:00
|
|
|
/* clean up tuple table */
|
2002-12-05 16:50:39 +01:00
|
|
|
ExecClearTuple(node->ps.ps_ResultTupleSlot);
|
|
|
|
|
|
|
|
MemoryContextDelete(node->tempContext);
|
2002-12-15 17:17:59 +01:00
|
|
|
|
|
|
|
ExecEndNode(outerPlanState(node));
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1998-02-23 07:28:16 +01:00
|
|
|
|
|
|
|
|
|
|
|
void
|
2002-12-05 16:50:39 +01:00
|
|
|
ExecReScanUnique(UniqueState *node, ExprContext *exprCtxt)
|
1998-02-23 07:28:16 +01:00
|
|
|
{
|
2005-03-16 22:38:10 +01:00
|
|
|
/* must clear result tuple so first input tuple is returned */
|
2002-12-05 16:50:39 +01:00
|
|
|
ExecClearTuple(node->ps.ps_ResultTupleSlot);
|
1998-02-26 05:46:47 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* if chgParam of subnode is not null then plan will be re-scanned by
|
|
|
|
* first ExecProcNode.
|
1998-02-23 07:28:16 +01:00
|
|
|
*/
|
2002-12-05 16:50:39 +01:00
|
|
|
if (((PlanState *) node)->lefttree->chgParam == NULL)
|
|
|
|
ExecReScan(((PlanState *) node)->lefttree, exprCtxt);
|
1998-02-23 07:28:16 +01:00
|
|
|
}
|