aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/nodeWorktablescan.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor/nodeWorktablescan.c')
-rw-r--r--src/backend/executor/nodeWorktablescan.c194
1 files changed, 194 insertions, 0 deletions
diff --git a/src/backend/executor/nodeWorktablescan.c b/src/backend/executor/nodeWorktablescan.c
new file mode 100644
index 00000000000..2f09c5e22dd
--- /dev/null
+++ b/src/backend/executor/nodeWorktablescan.c
@@ -0,0 +1,194 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeWorktablescan.c
+ * routines to handle WorkTableScan nodes.
+ *
+ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * $PostgreSQL: pgsql/src/backend/executor/nodeWorktablescan.c,v 1.1 2008/10/04 21:56:53 tgl Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "executor/execdebug.h"
+#include "executor/nodeWorktablescan.h"
+
+static TupleTableSlot *WorkTableScanNext(WorkTableScanState *node);
+
+/* ----------------------------------------------------------------
+ * WorkTableScanNext
+ *
+ * This is a workhorse for ExecWorkTableScan
+ * ----------------------------------------------------------------
+ */
+static TupleTableSlot *
+WorkTableScanNext(WorkTableScanState *node)
+{
+ TupleTableSlot *slot;
+ EState *estate;
+ ScanDirection direction;
+ Tuplestorestate *tuplestorestate;
+
+ /*
+ * get information from the estate and scan state
+ */
+ estate = node->ss.ps.state;
+ direction = estate->es_direction;
+
+ tuplestorestate = node->rustate->working_table;
+
+ /*
+ * Get the next tuple from tuplestore. Return NULL if no more tuples.
+ */
+ slot = node->ss.ss_ScanTupleSlot;
+ (void) tuplestore_gettupleslot(tuplestorestate,
+ ScanDirectionIsForward(direction),
+ slot);
+ return slot;
+}
+
+/* ----------------------------------------------------------------
+ * ExecWorkTableScan(node)
+ *
+ * Scans the worktable sequentially and returns the next qualifying tuple.
+ * It calls the ExecScan() routine and passes it the access method
+ * which retrieves tuples sequentially.
+ * ----------------------------------------------------------------
+ */
+TupleTableSlot *
+ExecWorkTableScan(WorkTableScanState *node)
+{
+ /*
+ * use WorkTableScanNext as access method
+ */
+ return ExecScan(&node->ss, (ExecScanAccessMtd) WorkTableScanNext);
+}
+
+
+/* ----------------------------------------------------------------
+ * ExecInitWorkTableScan
+ * ----------------------------------------------------------------
+ */
+WorkTableScanState *
+ExecInitWorkTableScan(WorkTableScan *node, EState *estate, int eflags)
+{
+ WorkTableScanState *scanstate;
+ ParamExecData *prmdata;
+
+ /* check for unsupported flags */
+ Assert(!(eflags & EXEC_FLAG_MARK));
+
+ /*
+ * WorkTableScan should not have any children.
+ */
+ Assert(outerPlan(node) == NULL);
+ Assert(innerPlan(node) == NULL);
+
+ /*
+ * create new WorkTableScanState for node
+ */
+ scanstate = makeNode(WorkTableScanState);
+ scanstate->ss.ps.plan = (Plan *) node;
+ scanstate->ss.ps.state = estate;
+
+ /*
+ * Find the ancestor RecursiveUnion's state
+ * via the Param slot reserved for it.
+ */
+ prmdata = &(estate->es_param_exec_vals[node->wtParam]);
+ Assert(prmdata->execPlan == NULL);
+ Assert(!prmdata->isnull);
+ scanstate->rustate = (RecursiveUnionState *) DatumGetPointer(prmdata->value);
+ Assert(scanstate->rustate && IsA(scanstate->rustate, RecursiveUnionState));
+
+ /*
+ * Miscellaneous initialization
+ *
+ * create expression context for node
+ */
+ ExecAssignExprContext(estate, &scanstate->ss.ps);
+
+ /*
+ * initialize child expressions
+ */
+ scanstate->ss.ps.targetlist = (List *)
+ ExecInitExpr((Expr *) node->scan.plan.targetlist,
+ (PlanState *) scanstate);
+ scanstate->ss.ps.qual = (List *)
+ ExecInitExpr((Expr *) node->scan.plan.qual,
+ (PlanState *) scanstate);
+
+#define WORKTABLESCAN_NSLOTS 2
+
+ /*
+ * tuple table initialization
+ */
+ ExecInitResultTupleSlot(estate, &scanstate->ss.ps);
+ ExecInitScanTupleSlot(estate, &scanstate->ss);
+
+ /*
+ * The scan tuple type (ie, the rowtype we expect to find in the work
+ * table) is the same as the result rowtype of the ancestor RecursiveUnion
+ * node. Note this depends on the assumption that RecursiveUnion doesn't
+ * allow projection.
+ */
+ ExecAssignScanType(&scanstate->ss,
+ ExecGetResultType(&scanstate->rustate->ps));
+
+ /*
+ * Initialize result tuple type and projection info.
+ */
+ ExecAssignResultTypeFromTL(&scanstate->ss.ps);
+ ExecAssignScanProjectionInfo(&scanstate->ss);
+
+ scanstate->ss.ps.ps_TupFromTlist = false;
+
+ return scanstate;
+}
+
+int
+ExecCountSlotsWorkTableScan(WorkTableScan *node)
+{
+ return ExecCountSlotsNode(outerPlan(node)) +
+ ExecCountSlotsNode(innerPlan(node)) +
+ WORKTABLESCAN_NSLOTS;
+}
+
+/* ----------------------------------------------------------------
+ * ExecEndWorkTableScan
+ *
+ * frees any storage allocated through C routines.
+ * ----------------------------------------------------------------
+ */
+void
+ExecEndWorkTableScan(WorkTableScanState *node)
+{
+ /*
+ * Free exprcontext
+ */
+ ExecFreeExprContext(&node->ss.ps);
+
+ /*
+ * clean out the tuple table
+ */
+ ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
+ ExecClearTuple(node->ss.ss_ScanTupleSlot);
+}
+
+/* ----------------------------------------------------------------
+ * ExecWorkTableScanReScan
+ *
+ * Rescans the relation.
+ * ----------------------------------------------------------------
+ */
+void
+ExecWorkTableScanReScan(WorkTableScanState *node, ExprContext *exprCtxt)
+{
+ ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
+ tuplestore_rescan(node->rustate->working_table);
+}