1 /*-------------------------------------------------------------------------
3 * nodeNamedtuplestorescan.c
4 * routines to handle NamedTuplestoreScan nodes.
6 * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * src/backend/executor/nodeNamedtuplestorescan.c
13 *-------------------------------------------------------------------------
18 #include "executor/execdebug.h"
19 #include "executor/nodeNamedtuplestorescan.h"
20 #include "miscadmin.h"
21 #include "utils/queryenvironment.h"
23 static TupleTableSlot *NamedTuplestoreScanNext(NamedTuplestoreScanState *node);
25 /* ----------------------------------------------------------------
26 * NamedTuplestoreScanNext
28 * This is a workhorse for ExecNamedTuplestoreScan
29 * ----------------------------------------------------------------
31 static TupleTableSlot *
32 NamedTuplestoreScanNext(NamedTuplestoreScanState *node)
36 /* We intentionally do not support backward scan. */
37 Assert(ScanDirectionIsForward(node->ss.ps.state->es_direction));
40 * Get the next tuple from tuplestore. Return NULL if no more tuples.
42 slot = node->ss.ss_ScanTupleSlot;
43 tuplestore_select_read_pointer(node->relation, node->readptr);
44 (void) tuplestore_gettupleslot(node->relation, true, false, slot);
49 * NamedTuplestoreScanRecheck -- access method routine to recheck a tuple in
53 NamedTuplestoreScanRecheck(NamedTuplestoreScanState *node, TupleTableSlot *slot)
55 /* nothing to check */
59 /* ----------------------------------------------------------------
60 * ExecNamedTuplestoreScan(node)
62 * Scans the CTE sequentially and returns the next qualifying tuple.
63 * We call the ExecScan() routine and pass it the appropriate
64 * access method functions.
65 * ----------------------------------------------------------------
67 static TupleTableSlot *
68 ExecNamedTuplestoreScan(PlanState *pstate)
70 NamedTuplestoreScanState *node = castNode(NamedTuplestoreScanState, pstate);
72 return ExecScan(&node->ss,
73 (ExecScanAccessMtd) NamedTuplestoreScanNext,
74 (ExecScanRecheckMtd) NamedTuplestoreScanRecheck);
78 /* ----------------------------------------------------------------
79 * ExecInitNamedTuplestoreScan
80 * ----------------------------------------------------------------
82 NamedTuplestoreScanState *
83 ExecInitNamedTuplestoreScan(NamedTuplestoreScan *node, EState *estate, int eflags)
85 NamedTuplestoreScanState *scanstate;
86 EphemeralNamedRelation enr;
88 /* check for unsupported flags */
89 Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
92 * NamedTuplestoreScan should not have any children.
94 Assert(outerPlan(node) == NULL);
95 Assert(innerPlan(node) == NULL);
98 * create new NamedTuplestoreScanState for node
100 scanstate = makeNode(NamedTuplestoreScanState);
101 scanstate->ss.ps.plan = (Plan *) node;
102 scanstate->ss.ps.state = estate;
103 scanstate->ss.ps.ExecProcNode = ExecNamedTuplestoreScan;
105 enr = get_ENR(estate->es_queryEnv, node->enrname);
107 elog(ERROR, "executor could not find named tuplestore \"%s\"",
110 Assert(enr->reldata);
111 scanstate->relation = (Tuplestorestate *) enr->reldata;
112 scanstate->tupdesc = ENRMetadataGetTupDesc(&(enr->md));
114 tuplestore_alloc_read_pointer(scanstate->relation, EXEC_FLAG_REWIND);
117 * The new read pointer copies its position from read pointer 0, which
118 * could be anywhere, so explicitly rewind it.
120 tuplestore_select_read_pointer(scanstate->relation, scanstate->readptr);
121 tuplestore_rescan(scanstate->relation);
124 * XXX: Should we add a function to free that read pointer when done?
126 * This was attempted, but it did not improve performance or memory usage
127 * in any tested cases.
131 * Miscellaneous initialization
133 * create expression context for node
135 ExecAssignExprContext(estate, &scanstate->ss.ps);
138 * The scan tuple type is specified for the tuplestore.
140 ExecInitScanTupleSlot(estate, &scanstate->ss, scanstate->tupdesc,
141 &TTSOpsMinimalTuple);
144 * Initialize result type and projection.
146 ExecInitResultTypeTL(&scanstate->ss.ps);
147 ExecAssignScanProjectionInfo(&scanstate->ss);
150 * initialize child expressions
152 scanstate->ss.ps.qual =
153 ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
158 /* ----------------------------------------------------------------
159 * ExecEndNamedTuplestoreScan
161 * frees any storage allocated through C routines.
162 * ----------------------------------------------------------------
165 ExecEndNamedTuplestoreScan(NamedTuplestoreScanState *node)
170 ExecFreeExprContext(&node->ss.ps);
173 * clean out the tuple table
175 if (node->ss.ps.ps_ResultTupleSlot)
176 ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
177 ExecClearTuple(node->ss.ss_ScanTupleSlot);
180 /* ----------------------------------------------------------------
181 * ExecReScanNamedTuplestoreScan
183 * Rescans the relation.
184 * ----------------------------------------------------------------
187 ExecReScanNamedTuplestoreScan(NamedTuplestoreScanState *node)
189 Tuplestorestate *tuplestorestate = node->relation;
191 if (node->ss.ps.ps_ResultTupleSlot)
192 ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
194 ExecScanReScan(&node->ss);
197 * Rewind my own pointer.
199 tuplestore_select_read_pointer(tuplestorestate, node->readptr);
200 tuplestore_rescan(tuplestorestate);