summaryrefslogtreecommitdiff
path: root/src/backend/executor/nodeSetOp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor/nodeSetOp.c')
-rw-r--r--src/backend/executor/nodeSetOp.c334
1 files changed, 0 insertions, 334 deletions
diff --git a/src/backend/executor/nodeSetOp.c b/src/backend/executor/nodeSetOp.c
deleted file mode 100644
index 3d1cf2c8efa..00000000000
--- a/src/backend/executor/nodeSetOp.c
+++ /dev/null
@@ -1,334 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * nodeSetOp.c
- * Routines to handle INTERSECT and EXCEPT selection
- *
- * The input of a SetOp node consists of tuples from two relations,
- * which have been combined into one dataset and sorted on all the nonjunk
- * attributes. In addition there is a junk attribute that shows which
- * relation each tuple came from. The SetOp node scans each group of
- * identical tuples to determine how many came from each input relation.
- * Then it is a simple matter to emit the output demanded by the SQL spec
- * for INTERSECT, INTERSECT ALL, EXCEPT, or EXCEPT ALL.
- *
- * This node type is not used for UNION or UNION ALL, since those can be
- * implemented more cheaply (there's no need for the junk attribute to
- * identify the source relation).
- *
- *
- * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/nodeSetOp.c,v 1.6 2002/06/20 20:29:28 momjian Exp $
- *
- *-------------------------------------------------------------------------
- */
-/*
- * INTERFACE ROUTINES
- * ExecSetOp - filter input to generate INTERSECT/EXCEPT results
- * ExecInitSetOp - initialize node and subnodes..
- * ExecEndSetOp - shutdown node and subnodes
- */
-
-#include "postgres.h"
-
-#include "access/heapam.h"
-#include "executor/executor.h"
-#include "executor/nodeGroup.h"
-#include "executor/nodeSetOp.h"
-
-/* ----------------------------------------------------------------
- * ExecSetOp
- * ----------------------------------------------------------------
- */
-TupleTableSlot * /* return: a tuple or NULL */
-ExecSetOp(SetOp *node)
-{
- SetOpState *setopstate;
- TupleTableSlot *resultTupleSlot;
- Plan *outerPlan;
- TupleDesc tupDesc;
-
- /*
- * get information from the node
- */
- setopstate = node->setopstate;
- outerPlan = outerPlan((Plan *) node);
- resultTupleSlot = setopstate->cstate.cs_ResultTupleSlot;
- tupDesc = ExecGetResultType(&setopstate->cstate);
-
- /*
- * If the previously-returned tuple needs to be returned more than
- * once, keep returning it.
- */
- if (setopstate->numOutput > 0)
- {
- setopstate->numOutput--;
- return resultTupleSlot;
- }
-
- /* Flag that we have no current tuple */
- ExecClearTuple(resultTupleSlot);
-
- /*
- * Absorb groups of duplicate tuples, counting them, and saving the
- * first of each group as a possible return value. At the end of each
- * group, decide whether to return anything.
- *
- * We assume that the tuples arrive in sorted order so we can detect
- * duplicates easily.
- */
- for (;;)
- {
- TupleTableSlot *inputTupleSlot;
- bool endOfGroup;
-
- /*
- * fetch a tuple from the outer subplan, unless we already did.
- */
- if (setopstate->cstate.cs_OuterTupleSlot == NULL &&
- !setopstate->subplan_done)
- {
- setopstate->cstate.cs_OuterTupleSlot =
- ExecProcNode(outerPlan, (Plan *) node);
- if (TupIsNull(setopstate->cstate.cs_OuterTupleSlot))
- setopstate->subplan_done = true;
- }
- inputTupleSlot = setopstate->cstate.cs_OuterTupleSlot;
-
- if (TupIsNull(resultTupleSlot))
- {
- /*
- * First of group: save a copy in result slot, and reset
- * duplicate-counters for new group.
- */
- if (setopstate->subplan_done)
- return NULL; /* no more tuples */
- ExecStoreTuple(heap_copytuple(inputTupleSlot->val),
- resultTupleSlot,
- InvalidBuffer,
- true); /* free copied tuple at
- * ExecClearTuple */
- setopstate->numLeft = 0;
- setopstate->numRight = 0;
- endOfGroup = false;
- }
- else if (setopstate->subplan_done)
- {
- /*
- * Reached end of input, so finish processing final group
- */
- endOfGroup = true;
- }
- else
- {
- /*
- * Else test if the new tuple and the previously saved tuple
- * match.
- */
- if (execTuplesMatch(inputTupleSlot->val,
- resultTupleSlot->val,
- tupDesc,
- node->numCols, node->dupColIdx,
- setopstate->eqfunctions,
- setopstate->tempContext))
- endOfGroup = false;
- else
- endOfGroup = true;
- }
-
- if (endOfGroup)
- {
- /*
- * We've reached the end of the group containing resultTuple.
- * Decide how many copies (if any) to emit. This logic is
- * straight from the SQL92 specification.
- */
- switch (node->cmd)
- {
- case SETOPCMD_INTERSECT:
- if (setopstate->numLeft > 0 && setopstate->numRight > 0)
- setopstate->numOutput = 1;
- else
- setopstate->numOutput = 0;
- break;
- case SETOPCMD_INTERSECT_ALL:
- setopstate->numOutput =
- (setopstate->numLeft < setopstate->numRight) ?
- setopstate->numLeft : setopstate->numRight;
- break;
- case SETOPCMD_EXCEPT:
- if (setopstate->numLeft > 0 && setopstate->numRight == 0)
- setopstate->numOutput = 1;
- else
- setopstate->numOutput = 0;
- break;
- case SETOPCMD_EXCEPT_ALL:
- setopstate->numOutput =
- (setopstate->numLeft < setopstate->numRight) ?
- 0 : (setopstate->numLeft - setopstate->numRight);
- break;
- default:
- elog(ERROR, "ExecSetOp: bogus command code %d",
- (int) node->cmd);
- break;
- }
- /* Fall out of for-loop if we have tuples to emit */
- if (setopstate->numOutput > 0)
- break;
- /* Else flag that we have no current tuple, and loop around */
- ExecClearTuple(resultTupleSlot);
- }
- else
- {
- /*
- * Current tuple is member of same group as resultTuple. Count
- * it in the appropriate counter.
- */
- int flag;
- bool isNull;
-
- flag = DatumGetInt32(heap_getattr(inputTupleSlot->val,
- node->flagColIdx,
- tupDesc,
- &isNull));
- Assert(!isNull);
- if (flag)
- setopstate->numRight++;
- else
- setopstate->numLeft++;
- /* Set flag to fetch a new input tuple, and loop around */
- setopstate->cstate.cs_OuterTupleSlot = NULL;
- }
- }
-
- /*
- * If we fall out of loop, then we need to emit at least one copy of
- * resultTuple.
- */
- Assert(setopstate->numOutput > 0);
- setopstate->numOutput--;
- return resultTupleSlot;
-}
-
-/* ----------------------------------------------------------------
- * ExecInitSetOp
- *
- * This initializes the setop node state structures and
- * the node's subplan.
- * ----------------------------------------------------------------
- */
-bool /* return: initialization status */
-ExecInitSetOp(SetOp *node, EState *estate, Plan *parent)
-{
- SetOpState *setopstate;
- Plan *outerPlan;
-
- /*
- * assign execution state to node
- */
- node->plan.state = estate;
-
- /*
- * create new SetOpState for node
- */
- setopstate = makeNode(SetOpState);
- node->setopstate = setopstate;
- setopstate->cstate.cs_OuterTupleSlot = NULL;
- setopstate->subplan_done = false;
- setopstate->numOutput = 0;
-
- /*
- * Miscellaneous initialization
- *
- * SetOp 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.
- */
- setopstate->tempContext =
- AllocSetContextCreate(CurrentMemoryContext,
- "SetOp",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
-
-#define SETOP_NSLOTS 1
-
- /*
- * Tuple table initialization
- */
- ExecInitResultTupleSlot(estate, &setopstate->cstate);
-
- /*
- * then initialize outer plan
- */
- outerPlan = outerPlan((Plan *) node);
- ExecInitNode(outerPlan, estate, (Plan *) node);
-
- /*
- * setop nodes do no projections, so initialize projection info for
- * this node appropriately
- */
- ExecAssignResultTypeFromOuterPlan((Plan *) node, &setopstate->cstate);
- setopstate->cstate.cs_ProjInfo = NULL;
-
- /*
- * Precompute fmgr lookup data for inner loop
- */
- setopstate->eqfunctions =
- execTuplesMatchPrepare(ExecGetResultType(&setopstate->cstate),
- node->numCols,
- node->dupColIdx);
-
- return TRUE;
-}
-
-int
-ExecCountSlotsSetOp(SetOp *node)
-{
- return ExecCountSlotsNode(outerPlan(node)) +
- ExecCountSlotsNode(innerPlan(node)) +
- SETOP_NSLOTS;
-}
-
-/* ----------------------------------------------------------------
- * ExecEndSetOp
- *
- * This shuts down the subplan and frees resources allocated
- * to this node.
- * ----------------------------------------------------------------
- */
-void
-ExecEndSetOp(SetOp *node)
-{
- SetOpState *setopstate = node->setopstate;
-
- ExecEndNode(outerPlan((Plan *) node), (Plan *) node);
-
- MemoryContextDelete(setopstate->tempContext);
-
- /* clean up tuple table */
- ExecClearTuple(setopstate->cstate.cs_ResultTupleSlot);
- setopstate->cstate.cs_OuterTupleSlot = NULL;
-}
-
-
-void
-ExecReScanSetOp(SetOp *node, ExprContext *exprCtxt, Plan *parent)
-{
- SetOpState *setopstate = node->setopstate;
-
- ExecClearTuple(setopstate->cstate.cs_ResultTupleSlot);
- setopstate->cstate.cs_OuterTupleSlot = NULL;
- setopstate->subplan_done = false;
- setopstate->numOutput = 0;
-
- /*
- * if chgParam of subnode is not null then plan will be re-scanned by
- * first ExecProcNode.
- */
- if (((Plan *) node)->lefttree->chgParam == NULL)
- ExecReScan(((Plan *) node)->lefttree, exprCtxt, (Plan *) node);
-}