Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * nodeNamedtuplestorescan.c
4 : * routines to handle NamedTuplestoreScan nodes.
5 : *
6 : * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
7 : * Portions Copyright (c) 1994, Regents of the University of California
8 : *
9 : *
10 : * IDENTIFICATION
11 : * src/backend/executor/nodeNamedtuplestorescan.c
12 : *
13 : *-------------------------------------------------------------------------
14 : */
15 :
16 : #include "postgres.h"
17 :
18 : #include "executor/execdebug.h"
19 : #include "executor/nodeNamedtuplestorescan.h"
20 : #include "miscadmin.h"
21 : #include "utils/queryenvironment.h"
22 :
23 : static TupleTableSlot *NamedTuplestoreScanNext(NamedTuplestoreScanState *node);
24 :
25 : /* ----------------------------------------------------------------
26 : * NamedTuplestoreScanNext
27 : *
28 : * This is a workhorse for ExecNamedTuplestoreScan
29 : * ----------------------------------------------------------------
30 : */
31 : static TupleTableSlot *
32 10944 : NamedTuplestoreScanNext(NamedTuplestoreScanState *node)
33 : {
34 : TupleTableSlot *slot;
35 :
36 : /* We intentionally do not support backward scan. */
37 10944 : Assert(ScanDirectionIsForward(node->ss.ps.state->es_direction));
38 :
39 : /*
40 : * Get the next tuple from tuplestore. Return NULL if no more tuples.
41 : */
42 10944 : slot = node->ss.ss_ScanTupleSlot;
43 10944 : (void) tuplestore_gettupleslot(node->relation, true, false, slot);
44 10944 : return slot;
45 : }
46 :
47 : /*
48 : * NamedTuplestoreScanRecheck -- access method routine to recheck a tuple in
49 : * EvalPlanQual
50 : */
51 : static bool
52 0 : NamedTuplestoreScanRecheck(NamedTuplestoreScanState *node, TupleTableSlot *slot)
53 : {
54 : /* nothing to check */
55 0 : return true;
56 : }
57 :
58 : /* ----------------------------------------------------------------
59 : * ExecNamedTuplestoreScan(node)
60 : *
61 : * Scans the CTE sequentially and returns the next qualifying tuple.
62 : * We call the ExecScan() routine and pass it the appropriate
63 : * access method functions.
64 : * ----------------------------------------------------------------
65 : */
66 : static TupleTableSlot *
67 10944 : ExecNamedTuplestoreScan(PlanState *pstate)
68 : {
69 10944 : NamedTuplestoreScanState *node = castNode(NamedTuplestoreScanState, pstate);
70 :
71 10944 : return ExecScan(&node->ss,
72 : (ExecScanAccessMtd) NamedTuplestoreScanNext,
73 : (ExecScanRecheckMtd) NamedTuplestoreScanRecheck);
74 : }
75 :
76 :
77 : /* ----------------------------------------------------------------
78 : * ExecInitNamedTuplestoreScan
79 : * ----------------------------------------------------------------
80 : */
81 : NamedTuplestoreScanState *
82 59 : ExecInitNamedTuplestoreScan(NamedTuplestoreScan *node, EState *estate, int eflags)
83 : {
84 : NamedTuplestoreScanState *scanstate;
85 : EphemeralNamedRelation enr;
86 :
87 : /* check for unsupported flags */
88 59 : Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
89 :
90 : /*
91 : * NamedTuplestoreScan should not have any children.
92 : */
93 59 : Assert(outerPlan(node) == NULL);
94 59 : Assert(innerPlan(node) == NULL);
95 :
96 : /*
97 : * create new NamedTuplestoreScanState for node
98 : */
99 59 : scanstate = makeNode(NamedTuplestoreScanState);
100 59 : scanstate->ss.ps.plan = (Plan *) node;
101 59 : scanstate->ss.ps.state = estate;
102 59 : scanstate->ss.ps.ExecProcNode = ExecNamedTuplestoreScan;
103 :
104 59 : enr = get_ENR(estate->es_queryEnv, node->enrname);
105 59 : if (!enr)
106 0 : elog(ERROR, "executor could not find named tuplestore \"%s\"",
107 : node->enrname);
108 :
109 59 : Assert(enr->reldata);
110 59 : scanstate->relation = (Tuplestorestate *) enr->reldata;
111 59 : scanstate->tupdesc = ENRMetadataGetTupDesc(&(enr->md));
112 59 : scanstate->readptr =
113 59 : tuplestore_alloc_read_pointer(scanstate->relation, EXEC_FLAG_REWIND);
114 :
115 : /*
116 : * The new read pointer copies its position from read pointer 0, which
117 : * could be anywhere, so explicitly rewind it.
118 : */
119 59 : tuplestore_rescan(scanstate->relation);
120 :
121 : /*
122 : * XXX: Should we add a function to free that read pointer when done?
123 : *
124 : * This was attempted, but it did not improve performance or memory usage
125 : * in any tested cases.
126 : */
127 :
128 : /*
129 : * Miscellaneous initialization
130 : *
131 : * create expression context for node
132 : */
133 59 : ExecAssignExprContext(estate, &scanstate->ss.ps);
134 :
135 : /*
136 : * initialize child expressions
137 : */
138 59 : scanstate->ss.ps.qual =
139 59 : ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
140 :
141 : /*
142 : * tuple table initialization
143 : */
144 59 : ExecInitResultTupleSlot(estate, &scanstate->ss.ps);
145 59 : ExecInitScanTupleSlot(estate, &scanstate->ss);
146 :
147 : /*
148 : * The scan tuple type is specified for the tuplestore.
149 : */
150 59 : ExecAssignScanType(&scanstate->ss, scanstate->tupdesc);
151 :
152 : /*
153 : * Initialize result tuple type and projection info.
154 : */
155 59 : ExecAssignResultTypeFromTL(&scanstate->ss.ps);
156 59 : ExecAssignScanProjectionInfo(&scanstate->ss);
157 :
158 59 : return scanstate;
159 : }
160 :
161 : /* ----------------------------------------------------------------
162 : * ExecEndNamedTuplestoreScan
163 : *
164 : * frees any storage allocated through C routines.
165 : * ----------------------------------------------------------------
166 : */
167 : void
168 59 : ExecEndNamedTuplestoreScan(NamedTuplestoreScanState *node)
169 : {
170 : /*
171 : * Free exprcontext
172 : */
173 59 : ExecFreeExprContext(&node->ss.ps);
174 :
175 : /*
176 : * clean out the tuple table
177 : */
178 59 : ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
179 59 : ExecClearTuple(node->ss.ss_ScanTupleSlot);
180 59 : }
181 :
182 : /* ----------------------------------------------------------------
183 : * ExecReScanNamedTuplestoreScan
184 : *
185 : * Rescans the relation.
186 : * ----------------------------------------------------------------
187 : */
188 : void
189 0 : ExecReScanNamedTuplestoreScan(NamedTuplestoreScanState *node)
190 : {
191 0 : Tuplestorestate *tuplestorestate = node->relation;
192 :
193 0 : ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
194 :
195 0 : ExecScanReScan(&node->ss);
196 :
197 : /*
198 : * Rewind my own pointer.
199 : */
200 0 : tuplestore_select_read_pointer(tuplestorestate, node->readptr);
201 0 : tuplestore_rescan(tuplestorestate);
202 0 : }
|