summaryrefslogtreecommitdiffstats
path: root/src/backend/executor/nodeNamedtuplestorescan.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor/nodeNamedtuplestorescan.c')
-rw-r--r--src/backend/executor/nodeNamedtuplestorescan.c201
1 files changed, 201 insertions, 0 deletions
diff --git a/src/backend/executor/nodeNamedtuplestorescan.c b/src/backend/executor/nodeNamedtuplestorescan.c
new file mode 100644
index 0000000..c0d1069
--- /dev/null
+++ b/src/backend/executor/nodeNamedtuplestorescan.c
@@ -0,0 +1,201 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeNamedtuplestorescan.c
+ * routines to handle NamedTuplestoreScan nodes.
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/backend/executor/nodeNamedtuplestorescan.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "executor/execdebug.h"
+#include "executor/nodeNamedtuplestorescan.h"
+#include "miscadmin.h"
+#include "utils/queryenvironment.h"
+
+static TupleTableSlot *NamedTuplestoreScanNext(NamedTuplestoreScanState *node);
+
+/* ----------------------------------------------------------------
+ * NamedTuplestoreScanNext
+ *
+ * This is a workhorse for ExecNamedTuplestoreScan
+ * ----------------------------------------------------------------
+ */
+static TupleTableSlot *
+NamedTuplestoreScanNext(NamedTuplestoreScanState *node)
+{
+ TupleTableSlot *slot;
+
+ /* We intentionally do not support backward scan. */
+ Assert(ScanDirectionIsForward(node->ss.ps.state->es_direction));
+
+ /*
+ * Get the next tuple from tuplestore. Return NULL if no more tuples.
+ */
+ slot = node->ss.ss_ScanTupleSlot;
+ tuplestore_select_read_pointer(node->relation, node->readptr);
+ (void) tuplestore_gettupleslot(node->relation, true, false, slot);
+ return slot;
+}
+
+/*
+ * NamedTuplestoreScanRecheck -- access method routine to recheck a tuple in
+ * EvalPlanQual
+ */
+static bool
+NamedTuplestoreScanRecheck(NamedTuplestoreScanState *node, TupleTableSlot *slot)
+{
+ /* nothing to check */
+ return true;
+}
+
+/* ----------------------------------------------------------------
+ * ExecNamedTuplestoreScan(node)
+ *
+ * Scans the CTE sequentially and returns the next qualifying tuple.
+ * We call the ExecScan() routine and pass it the appropriate
+ * access method functions.
+ * ----------------------------------------------------------------
+ */
+static TupleTableSlot *
+ExecNamedTuplestoreScan(PlanState *pstate)
+{
+ NamedTuplestoreScanState *node = castNode(NamedTuplestoreScanState, pstate);
+
+ return ExecScan(&node->ss,
+ (ExecScanAccessMtd) NamedTuplestoreScanNext,
+ (ExecScanRecheckMtd) NamedTuplestoreScanRecheck);
+}
+
+
+/* ----------------------------------------------------------------
+ * ExecInitNamedTuplestoreScan
+ * ----------------------------------------------------------------
+ */
+NamedTuplestoreScanState *
+ExecInitNamedTuplestoreScan(NamedTuplestoreScan *node, EState *estate, int eflags)
+{
+ NamedTuplestoreScanState *scanstate;
+ EphemeralNamedRelation enr;
+
+ /* check for unsupported flags */
+ Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
+
+ /*
+ * NamedTuplestoreScan should not have any children.
+ */
+ Assert(outerPlan(node) == NULL);
+ Assert(innerPlan(node) == NULL);
+
+ /*
+ * create new NamedTuplestoreScanState for node
+ */
+ scanstate = makeNode(NamedTuplestoreScanState);
+ scanstate->ss.ps.plan = (Plan *) node;
+ scanstate->ss.ps.state = estate;
+ scanstate->ss.ps.ExecProcNode = ExecNamedTuplestoreScan;
+
+ enr = get_ENR(estate->es_queryEnv, node->enrname);
+ if (!enr)
+ elog(ERROR, "executor could not find named tuplestore \"%s\"",
+ node->enrname);
+
+ Assert(enr->reldata);
+ scanstate->relation = (Tuplestorestate *) enr->reldata;
+ scanstate->tupdesc = ENRMetadataGetTupDesc(&(enr->md));
+ scanstate->readptr =
+ tuplestore_alloc_read_pointer(scanstate->relation, EXEC_FLAG_REWIND);
+
+ /*
+ * The new read pointer copies its position from read pointer 0, which
+ * could be anywhere, so explicitly rewind it.
+ */
+ tuplestore_select_read_pointer(scanstate->relation, scanstate->readptr);
+ tuplestore_rescan(scanstate->relation);
+
+ /*
+ * XXX: Should we add a function to free that read pointer when done?
+ *
+ * This was attempted, but it did not improve performance or memory usage
+ * in any tested cases.
+ */
+
+ /*
+ * Miscellaneous initialization
+ *
+ * create expression context for node
+ */
+ ExecAssignExprContext(estate, &scanstate->ss.ps);
+
+ /*
+ * The scan tuple type is specified for the tuplestore.
+ */
+ ExecInitScanTupleSlot(estate, &scanstate->ss, scanstate->tupdesc,
+ &TTSOpsMinimalTuple);
+
+ /*
+ * Initialize result type and projection.
+ */
+ ExecInitResultTypeTL(&scanstate->ss.ps);
+ ExecAssignScanProjectionInfo(&scanstate->ss);
+
+ /*
+ * initialize child expressions
+ */
+ scanstate->ss.ps.qual =
+ ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
+
+ return scanstate;
+}
+
+/* ----------------------------------------------------------------
+ * ExecEndNamedTuplestoreScan
+ *
+ * frees any storage allocated through C routines.
+ * ----------------------------------------------------------------
+ */
+void
+ExecEndNamedTuplestoreScan(NamedTuplestoreScanState *node)
+{
+ /*
+ * Free exprcontext
+ */
+ ExecFreeExprContext(&node->ss.ps);
+
+ /*
+ * clean out the tuple table
+ */
+ if (node->ss.ps.ps_ResultTupleSlot)
+ ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
+ ExecClearTuple(node->ss.ss_ScanTupleSlot);
+}
+
+/* ----------------------------------------------------------------
+ * ExecReScanNamedTuplestoreScan
+ *
+ * Rescans the relation.
+ * ----------------------------------------------------------------
+ */
+void
+ExecReScanNamedTuplestoreScan(NamedTuplestoreScanState *node)
+{
+ Tuplestorestate *tuplestorestate = node->relation;
+
+ if (node->ss.ps.ps_ResultTupleSlot)
+ ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
+
+ ExecScanReScan(&node->ss);
+
+ /*
+ * Rewind my own pointer.
+ */
+ tuplestore_select_read_pointer(tuplestorestate, node->readptr);
+ tuplestore_rescan(tuplestorestate);
+}