Header And Logo

PostgreSQL
| The world's most advanced open source database.

nodeUnique.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * nodeUnique.c
00004  *    Routines to handle unique'ing of queries where appropriate
00005  *
00006  * Unique is a very simple node type that just filters out duplicate
00007  * tuples from a stream of sorted tuples from its subplan.  It's essentially
00008  * a dumbed-down form of Group: the duplicate-removal functionality is
00009  * identical.  However, Unique doesn't do projection nor qual checking,
00010  * so it's marginally more efficient for cases where neither is needed.
00011  * (It's debatable whether the savings justifies carrying two plan node
00012  * types, though.)
00013  *
00014  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00015  * Portions Copyright (c) 1994, Regents of the University of California
00016  *
00017  *
00018  * IDENTIFICATION
00019  *    src/backend/executor/nodeUnique.c
00020  *
00021  *-------------------------------------------------------------------------
00022  */
00023 /*
00024  * INTERFACE ROUTINES
00025  *      ExecUnique      - generate a unique'd temporary relation
00026  *      ExecInitUnique  - initialize node and subnodes
00027  *      ExecEndUnique   - shutdown node and subnodes
00028  *
00029  * NOTES
00030  *      Assumes tuples returned from subplan arrive in
00031  *      sorted order.
00032  */
00033 
00034 #include "postgres.h"
00035 
00036 #include "executor/executor.h"
00037 #include "executor/nodeUnique.h"
00038 #include "utils/memutils.h"
00039 
00040 
00041 /* ----------------------------------------------------------------
00042  *      ExecUnique
00043  * ----------------------------------------------------------------
00044  */
00045 TupleTableSlot *                /* return: a tuple or NULL */
00046 ExecUnique(UniqueState *node)
00047 {
00048     Unique     *plannode = (Unique *) node->ps.plan;
00049     TupleTableSlot *resultTupleSlot;
00050     TupleTableSlot *slot;
00051     PlanState  *outerPlan;
00052 
00053     /*
00054      * get information from the node
00055      */
00056     outerPlan = outerPlanState(node);
00057     resultTupleSlot = node->ps.ps_ResultTupleSlot;
00058 
00059     /*
00060      * now loop, returning only non-duplicate tuples. We assume that the
00061      * tuples arrive in sorted order so we can detect duplicates easily. The
00062      * first tuple of each group is returned.
00063      */
00064     for (;;)
00065     {
00066         /*
00067          * fetch a tuple from the outer subplan
00068          */
00069         slot = ExecProcNode(outerPlan);
00070         if (TupIsNull(slot))
00071         {
00072             /* end of subplan, so we're done */
00073             ExecClearTuple(resultTupleSlot);
00074             return NULL;
00075         }
00076 
00077         /*
00078          * Always return the first tuple from the subplan.
00079          */
00080         if (TupIsNull(resultTupleSlot))
00081             break;
00082 
00083         /*
00084          * Else test if the new tuple and the previously returned tuple match.
00085          * If so then we loop back and fetch another new tuple from the
00086          * subplan.
00087          */
00088         if (!execTuplesMatch(slot, resultTupleSlot,
00089                              plannode->numCols, plannode->uniqColIdx,
00090                              node->eqfunctions,
00091                              node->tempContext))
00092             break;
00093     }
00094 
00095     /*
00096      * We have a new tuple different from the previous saved tuple (if any).
00097      * Save it and return it.  We must copy it because the source subplan
00098      * won't guarantee that this source tuple is still accessible after
00099      * fetching the next source tuple.
00100      */
00101     return ExecCopySlot(resultTupleSlot, slot);
00102 }
00103 
00104 /* ----------------------------------------------------------------
00105  *      ExecInitUnique
00106  *
00107  *      This initializes the unique node state structures and
00108  *      the node's subplan.
00109  * ----------------------------------------------------------------
00110  */
00111 UniqueState *
00112 ExecInitUnique(Unique *node, EState *estate, int eflags)
00113 {
00114     UniqueState *uniquestate;
00115 
00116     /* check for unsupported flags */
00117     Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
00118 
00119     /*
00120      * create state structure
00121      */
00122     uniquestate = makeNode(UniqueState);
00123     uniquestate->ps.plan = (Plan *) node;
00124     uniquestate->ps.state = estate;
00125 
00126     /*
00127      * Miscellaneous initialization
00128      *
00129      * Unique nodes have no ExprContext initialization because they never call
00130      * ExecQual or ExecProject.  But they do need a per-tuple memory context
00131      * anyway for calling execTuplesMatch.
00132      */
00133     uniquestate->tempContext =
00134         AllocSetContextCreate(CurrentMemoryContext,
00135                               "Unique",
00136                               ALLOCSET_DEFAULT_MINSIZE,
00137                               ALLOCSET_DEFAULT_INITSIZE,
00138                               ALLOCSET_DEFAULT_MAXSIZE);
00139 
00140     /*
00141      * Tuple table initialization
00142      */
00143     ExecInitResultTupleSlot(estate, &uniquestate->ps);
00144 
00145     /*
00146      * then initialize outer plan
00147      */
00148     outerPlanState(uniquestate) = ExecInitNode(outerPlan(node), estate, eflags);
00149 
00150     /*
00151      * unique nodes do no projections, so initialize projection info for this
00152      * node appropriately
00153      */
00154     ExecAssignResultTypeFromTL(&uniquestate->ps);
00155     uniquestate->ps.ps_ProjInfo = NULL;
00156 
00157     /*
00158      * Precompute fmgr lookup data for inner loop
00159      */
00160     uniquestate->eqfunctions =
00161         execTuplesMatchPrepare(node->numCols,
00162                                node->uniqOperators);
00163 
00164     return uniquestate;
00165 }
00166 
00167 /* ----------------------------------------------------------------
00168  *      ExecEndUnique
00169  *
00170  *      This shuts down the subplan and frees resources allocated
00171  *      to this node.
00172  * ----------------------------------------------------------------
00173  */
00174 void
00175 ExecEndUnique(UniqueState *node)
00176 {
00177     /* clean up tuple table */
00178     ExecClearTuple(node->ps.ps_ResultTupleSlot);
00179 
00180     MemoryContextDelete(node->tempContext);
00181 
00182     ExecEndNode(outerPlanState(node));
00183 }
00184 
00185 
00186 void
00187 ExecReScanUnique(UniqueState *node)
00188 {
00189     /* must clear result tuple so first input tuple is returned */
00190     ExecClearTuple(node->ps.ps_ResultTupleSlot);
00191 
00192     /*
00193      * if chgParam of subnode is not null then plan will be re-scanned by
00194      * first ExecProcNode.
00195      */
00196     if (node->ps.lefttree->chgParam == NULL)
00197         ExecReScan(node->ps.lefttree);
00198 }