Age Owner TLA Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * nodeNamedtuplestorescan.c
4 : * routines to handle NamedTuplestoreScan nodes.
5 : *
6 : * Portions Copyright (c) 1996-2023, 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 *
2200 kgrittn 32 CBC 33306 : NamedTuplestoreScanNext(NamedTuplestoreScanState *node)
33 : {
34 : TupleTableSlot *slot;
35 :
36 : /* We intentionally do not support backward scan. */
37 33306 : 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 33306 : slot = node->ss.ss_ScanTupleSlot;
1867 tgl 43 33306 : tuplestore_select_read_pointer(node->relation, node->readptr);
2200 kgrittn 44 33306 : (void) tuplestore_gettupleslot(node->relation, true, false, slot);
45 33306 : return slot;
46 : }
47 :
48 : /*
49 : * NamedTuplestoreScanRecheck -- access method routine to recheck a tuple in
50 : * EvalPlanQual
51 : */
52 : static bool
2200 kgrittn 53 UBC 0 : NamedTuplestoreScanRecheck(NamedTuplestoreScanState *node, TupleTableSlot *slot)
54 : {
55 : /* nothing to check */
56 0 : return true;
57 : }
58 :
59 : /* ----------------------------------------------------------------
60 : * ExecNamedTuplestoreScan(node)
61 : *
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 : * ----------------------------------------------------------------
66 : */
67 : static TupleTableSlot *
2092 andres 68 CBC 33306 : ExecNamedTuplestoreScan(PlanState *pstate)
69 : {
70 33306 : NamedTuplestoreScanState *node = castNode(NamedTuplestoreScanState, pstate);
71 :
2200 kgrittn 72 33306 : return ExecScan(&node->ss,
73 : (ExecScanAccessMtd) NamedTuplestoreScanNext,
74 : (ExecScanRecheckMtd) NamedTuplestoreScanRecheck);
75 : }
76 :
77 :
78 : /* ----------------------------------------------------------------
79 : * ExecInitNamedTuplestoreScan
80 : * ----------------------------------------------------------------
81 : */
82 : NamedTuplestoreScanState *
83 330 : ExecInitNamedTuplestoreScan(NamedTuplestoreScan *node, EState *estate, int eflags)
84 : {
85 : NamedTuplestoreScanState *scanstate;
86 : EphemeralNamedRelation enr;
87 :
88 : /* check for unsupported flags */
89 330 : Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
90 :
91 : /*
92 : * NamedTuplestoreScan should not have any children.
93 : */
94 330 : Assert(outerPlan(node) == NULL);
95 330 : Assert(innerPlan(node) == NULL);
96 :
97 : /*
98 : * create new NamedTuplestoreScanState for node
99 : */
100 330 : scanstate = makeNode(NamedTuplestoreScanState);
101 330 : scanstate->ss.ps.plan = (Plan *) node;
102 330 : scanstate->ss.ps.state = estate;
2092 andres 103 330 : scanstate->ss.ps.ExecProcNode = ExecNamedTuplestoreScan;
104 :
2200 kgrittn 105 330 : enr = get_ENR(estate->es_queryEnv, node->enrname);
106 330 : if (!enr)
2200 kgrittn 107 UBC 0 : elog(ERROR, "executor could not find named tuplestore \"%s\"",
108 : node->enrname);
109 :
2200 kgrittn 110 CBC 330 : Assert(enr->reldata);
111 330 : scanstate->relation = (Tuplestorestate *) enr->reldata;
112 330 : scanstate->tupdesc = ENRMetadataGetTupDesc(&(enr->md));
113 330 : scanstate->readptr =
2161 rhaas 114 330 : tuplestore_alloc_read_pointer(scanstate->relation, EXEC_FLAG_REWIND);
115 :
116 : /*
117 : * The new read pointer copies its position from read pointer 0, which
118 : * could be anywhere, so explicitly rewind it.
119 : */
1867 tgl 120 330 : tuplestore_select_read_pointer(scanstate->relation, scanstate->readptr);
2200 kgrittn 121 330 : tuplestore_rescan(scanstate->relation);
122 :
123 : /*
124 : * XXX: Should we add a function to free that read pointer when done?
125 : *
126 : * This was attempted, but it did not improve performance or memory usage
127 : * in any tested cases.
128 : */
129 :
130 : /*
131 : * Miscellaneous initialization
132 : *
133 : * create expression context for node
134 : */
135 330 : ExecAssignExprContext(estate, &scanstate->ss.ps);
136 :
137 : /*
138 : * The scan tuple type is specified for the tuplestore.
139 : */
1606 andres 140 330 : ExecInitScanTupleSlot(estate, &scanstate->ss, scanstate->tupdesc,
141 : &TTSOpsMinimalTuple);
142 :
143 : /*
144 : * Initialize result type and projection.
145 : */
1612 146 330 : ExecInitResultTypeTL(&scanstate->ss.ps);
147 330 : ExecAssignScanProjectionInfo(&scanstate->ss);
148 :
149 : /*
150 : * initialize child expressions
151 : */
152 330 : scanstate->ss.ps.qual =
153 330 : ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
154 :
2200 kgrittn 155 330 : return scanstate;
156 : }
157 :
158 : /* ----------------------------------------------------------------
159 : * ExecEndNamedTuplestoreScan
160 : *
161 : * frees any storage allocated through C routines.
162 : * ----------------------------------------------------------------
163 : */
164 : void
165 330 : ExecEndNamedTuplestoreScan(NamedTuplestoreScanState *node)
166 : {
167 : /*
168 : * Free exprcontext
169 : */
170 330 : ExecFreeExprContext(&node->ss.ps);
171 :
172 : /*
173 : * clean out the tuple table
174 : */
1612 andres 175 330 : if (node->ss.ps.ps_ResultTupleSlot)
176 294 : ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
2200 kgrittn 177 330 : ExecClearTuple(node->ss.ss_ScanTupleSlot);
178 330 : }
179 :
180 : /* ----------------------------------------------------------------
181 : * ExecReScanNamedTuplestoreScan
182 : *
183 : * Rescans the relation.
184 : * ----------------------------------------------------------------
185 : */
186 : void
2200 kgrittn 187 UBC 0 : ExecReScanNamedTuplestoreScan(NamedTuplestoreScanState *node)
188 : {
189 0 : Tuplestorestate *tuplestorestate = node->relation;
190 :
1612 andres 191 0 : if (node->ss.ps.ps_ResultTupleSlot)
192 0 : ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
193 :
2200 kgrittn 194 0 : ExecScanReScan(&node->ss);
195 :
196 : /*
197 : * Rewind my own pointer.
198 : */
199 0 : tuplestore_select_read_pointer(tuplestorestate, node->readptr);
200 0 : tuplestore_rescan(tuplestorestate);
201 0 : }
|