]> granicus.if.org Git - postgresql/blob - src/backend/executor/nodeNamedtuplestorescan.c
Make some small planner API cleanups.
[postgresql] / src / backend / executor / nodeNamedtuplestorescan.c
1 /*-------------------------------------------------------------------------
2  *
3  * nodeNamedtuplestorescan.c
4  *        routines to handle NamedTuplestoreScan nodes.
5  *
6  * Portions Copyright (c) 1996-2019, 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 NamedTuplestoreScanNext(NamedTuplestoreScanState *node)
33 {
34         TupleTableSlot *slot;
35
36         /* We intentionally do not support backward scan. */
37         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         slot = node->ss.ss_ScanTupleSlot;
43         tuplestore_select_read_pointer(node->relation, node->readptr);
44         (void) tuplestore_gettupleslot(node->relation, true, false, slot);
45         return slot;
46 }
47
48 /*
49  * NamedTuplestoreScanRecheck -- access method routine to recheck a tuple in
50  * EvalPlanQual
51  */
52 static bool
53 NamedTuplestoreScanRecheck(NamedTuplestoreScanState *node, TupleTableSlot *slot)
54 {
55         /* nothing to check */
56         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 *
68 ExecNamedTuplestoreScan(PlanState *pstate)
69 {
70         NamedTuplestoreScanState *node = castNode(NamedTuplestoreScanState, pstate);
71
72         return ExecScan(&node->ss,
73                                         (ExecScanAccessMtd) NamedTuplestoreScanNext,
74                                         (ExecScanRecheckMtd) NamedTuplestoreScanRecheck);
75 }
76
77
78 /* ----------------------------------------------------------------
79  *              ExecInitNamedTuplestoreScan
80  * ----------------------------------------------------------------
81  */
82 NamedTuplestoreScanState *
83 ExecInitNamedTuplestoreScan(NamedTuplestoreScan *node, EState *estate, int eflags)
84 {
85         NamedTuplestoreScanState *scanstate;
86         EphemeralNamedRelation enr;
87
88         /* check for unsupported flags */
89         Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
90
91         /*
92          * NamedTuplestoreScan should not have any children.
93          */
94         Assert(outerPlan(node) == NULL);
95         Assert(innerPlan(node) == NULL);
96
97         /*
98          * create new NamedTuplestoreScanState for node
99          */
100         scanstate = makeNode(NamedTuplestoreScanState);
101         scanstate->ss.ps.plan = (Plan *) node;
102         scanstate->ss.ps.state = estate;
103         scanstate->ss.ps.ExecProcNode = ExecNamedTuplestoreScan;
104
105         enr = get_ENR(estate->es_queryEnv, node->enrname);
106         if (!enr)
107                 elog(ERROR, "executor could not find named tuplestore \"%s\"",
108                          node->enrname);
109
110         Assert(enr->reldata);
111         scanstate->relation = (Tuplestorestate *) enr->reldata;
112         scanstate->tupdesc = ENRMetadataGetTupDesc(&(enr->md));
113         scanstate->readptr =
114                 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          */
120         tuplestore_select_read_pointer(scanstate->relation, scanstate->readptr);
121         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         ExecAssignExprContext(estate, &scanstate->ss.ps);
136
137         /*
138          * The scan tuple type is specified for the tuplestore.
139          */
140         ExecInitScanTupleSlot(estate, &scanstate->ss, scanstate->tupdesc,
141                                                   &TTSOpsMinimalTuple);
142
143         /*
144          * Initialize result type and projection.
145          */
146         ExecInitResultTypeTL(&scanstate->ss.ps);
147         ExecAssignScanProjectionInfo(&scanstate->ss);
148
149         /*
150          * initialize child expressions
151          */
152         scanstate->ss.ps.qual =
153                 ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
154
155         return scanstate;
156 }
157
158 /* ----------------------------------------------------------------
159  *              ExecEndNamedTuplestoreScan
160  *
161  *              frees any storage allocated through C routines.
162  * ----------------------------------------------------------------
163  */
164 void
165 ExecEndNamedTuplestoreScan(NamedTuplestoreScanState *node)
166 {
167         /*
168          * Free exprcontext
169          */
170         ExecFreeExprContext(&node->ss.ps);
171
172         /*
173          * clean out the tuple table
174          */
175         if (node->ss.ps.ps_ResultTupleSlot)
176                 ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
177         ExecClearTuple(node->ss.ss_ScanTupleSlot);
178 }
179
180 /* ----------------------------------------------------------------
181  *              ExecReScanNamedTuplestoreScan
182  *
183  *              Rescans the relation.
184  * ----------------------------------------------------------------
185  */
186 void
187 ExecReScanNamedTuplestoreScan(NamedTuplestoreScanState *node)
188 {
189         Tuplestorestate *tuplestorestate = node->relation;
190
191         if (node->ss.ps.ps_ResultTupleSlot)
192                 ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
193
194         ExecScanReScan(&node->ss);
195
196         /*
197          * Rewind my own pointer.
198          */
199         tuplestore_select_read_pointer(tuplestorestate, node->readptr);
200         tuplestore_rescan(tuplestorestate);
201 }