]> granicus.if.org Git - postgresql/blob - src/backend/executor/nodeValuesscan.c
Remove obsoleted code relating to targetlist SRF evaluation.
[postgresql] / src / backend / executor / nodeValuesscan.c
1 /*-------------------------------------------------------------------------
2  *
3  * nodeValuesscan.c
4  *        Support routines for scanning Values lists
5  *        ("VALUES (...), (...), ..." in rangetable).
6  *
7  * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
8  * Portions Copyright (c) 1994, Regents of the University of California
9  *
10  *
11  * IDENTIFICATION
12  *        src/backend/executor/nodeValuesscan.c
13  *
14  *-------------------------------------------------------------------------
15  */
16 /*
17  * INTERFACE ROUTINES
18  *              ExecValuesScan                  scans a values list.
19  *              ExecValuesNext                  retrieve next tuple in sequential order.
20  *              ExecInitValuesScan              creates and initializes a valuesscan node.
21  *              ExecEndValuesScan               releases any storage allocated.
22  *              ExecReScanValuesScan    rescans the values list
23  */
24 #include "postgres.h"
25
26 #include "executor/executor.h"
27 #include "executor/nodeValuesscan.h"
28 #include "utils/expandeddatum.h"
29
30
31 static TupleTableSlot *ValuesNext(ValuesScanState *node);
32
33
34 /* ----------------------------------------------------------------
35  *                                              Scan Support
36  * ----------------------------------------------------------------
37  */
38
39 /* ----------------------------------------------------------------
40  *              ValuesNext
41  *
42  *              This is a workhorse for ExecValuesScan
43  * ----------------------------------------------------------------
44  */
45 static TupleTableSlot *
46 ValuesNext(ValuesScanState *node)
47 {
48         TupleTableSlot *slot;
49         EState     *estate;
50         ExprContext *econtext;
51         ScanDirection direction;
52         List       *exprlist;
53
54         /*
55          * get information from the estate and scan state
56          */
57         estate = node->ss.ps.state;
58         direction = estate->es_direction;
59         slot = node->ss.ss_ScanTupleSlot;
60         econtext = node->rowcontext;
61
62         /*
63          * Get the next tuple. Return NULL if no more tuples.
64          */
65         if (ScanDirectionIsForward(direction))
66         {
67                 if (node->curr_idx < node->array_len)
68                         node->curr_idx++;
69                 if (node->curr_idx < node->array_len)
70                         exprlist = node->exprlists[node->curr_idx];
71                 else
72                         exprlist = NIL;
73         }
74         else
75         {
76                 if (node->curr_idx >= 0)
77                         node->curr_idx--;
78                 if (node->curr_idx >= 0)
79                         exprlist = node->exprlists[node->curr_idx];
80                 else
81                         exprlist = NIL;
82         }
83
84         /*
85          * Always clear the result slot; this is appropriate if we are at the end
86          * of the data, and if we're not, we still need it as the first step of
87          * the store-virtual-tuple protocol.  It seems wise to clear the slot
88          * before we reset the context it might have pointers into.
89          */
90         ExecClearTuple(slot);
91
92         if (exprlist)
93         {
94                 MemoryContext oldContext;
95                 List       *exprstatelist;
96                 Datum      *values;
97                 bool       *isnull;
98                 Form_pg_attribute *att;
99                 ListCell   *lc;
100                 int                     resind;
101
102                 /*
103                  * Get rid of any prior cycle's leftovers.  We use ReScanExprContext
104                  * not just ResetExprContext because we want any registered shutdown
105                  * callbacks to be called.
106                  */
107                 ReScanExprContext(econtext);
108
109                 /*
110                  * Build the expression eval state in the econtext's per-tuple memory.
111                  * This is a tad unusual, but we want to delete the eval state again
112                  * when we move to the next row, to avoid growth of memory
113                  * requirements over a long values list.
114                  */
115                 oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
116
117                 /*
118                  * Pass NULL, not my plan node, because we don't want anything in this
119                  * transient state linking into permanent state.  The only possibility
120                  * is a SubPlan, and there shouldn't be any (any subselects in the
121                  * VALUES list should be InitPlans).
122                  */
123                 exprstatelist = (List *) ExecInitExpr((Expr *) exprlist, NULL);
124
125                 /* parser should have checked all sublists are the same length */
126                 Assert(list_length(exprstatelist) == slot->tts_tupleDescriptor->natts);
127
128                 /*
129                  * Compute the expressions and build a virtual result tuple. We
130                  * already did ExecClearTuple(slot).
131                  */
132                 values = slot->tts_values;
133                 isnull = slot->tts_isnull;
134                 att = slot->tts_tupleDescriptor->attrs;
135
136                 resind = 0;
137                 foreach(lc, exprstatelist)
138                 {
139                         ExprState  *estate = (ExprState *) lfirst(lc);
140
141                         values[resind] = ExecEvalExpr(estate,
142                                                                                   econtext,
143                                                                                   &isnull[resind]);
144
145                         /*
146                          * We must force any R/W expanded datums to read-only state, in
147                          * case they are multiply referenced in the plan node's output
148                          * expressions, or in case we skip the output projection and the
149                          * output column is multiply referenced in higher plan nodes.
150                          */
151                         values[resind] = MakeExpandedObjectReadOnly(values[resind],
152                                                                                                                 isnull[resind],
153                                                                                                                 att[resind]->attlen);
154
155                         resind++;
156                 }
157
158                 MemoryContextSwitchTo(oldContext);
159
160                 /*
161                  * And return the virtual tuple.
162                  */
163                 ExecStoreVirtualTuple(slot);
164         }
165
166         return slot;
167 }
168
169 /*
170  * ValuesRecheck -- access method routine to recheck a tuple in EvalPlanQual
171  */
172 static bool
173 ValuesRecheck(ValuesScanState *node, TupleTableSlot *slot)
174 {
175         /* nothing to check */
176         return true;
177 }
178
179 /* ----------------------------------------------------------------
180  *              ExecValuesScan(node)
181  *
182  *              Scans the values lists sequentially and returns the next qualifying
183  *              tuple.
184  *              We call the ExecScan() routine and pass it the appropriate
185  *              access method functions.
186  * ----------------------------------------------------------------
187  */
188 TupleTableSlot *
189 ExecValuesScan(ValuesScanState *node)
190 {
191         return ExecScan(&node->ss,
192                                         (ExecScanAccessMtd) ValuesNext,
193                                         (ExecScanRecheckMtd) ValuesRecheck);
194 }
195
196 /* ----------------------------------------------------------------
197  *              ExecInitValuesScan
198  * ----------------------------------------------------------------
199  */
200 ValuesScanState *
201 ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags)
202 {
203         ValuesScanState *scanstate;
204         TupleDesc       tupdesc;
205         ListCell   *vtl;
206         int                     i;
207         PlanState  *planstate;
208
209         /*
210          * ValuesScan should not have any children.
211          */
212         Assert(outerPlan(node) == NULL);
213         Assert(innerPlan(node) == NULL);
214
215         /*
216          * create new ScanState for node
217          */
218         scanstate = makeNode(ValuesScanState);
219         scanstate->ss.ps.plan = (Plan *) node;
220         scanstate->ss.ps.state = estate;
221
222         /*
223          * Miscellaneous initialization
224          */
225         planstate = &scanstate->ss.ps;
226
227         /*
228          * Create expression contexts.  We need two, one for per-sublist
229          * processing and one for execScan.c to use for quals and projections. We
230          * cheat a little by using ExecAssignExprContext() to build both.
231          */
232         ExecAssignExprContext(estate, planstate);
233         scanstate->rowcontext = planstate->ps_ExprContext;
234         ExecAssignExprContext(estate, planstate);
235
236         /*
237          * tuple table initialization
238          */
239         ExecInitResultTupleSlot(estate, &scanstate->ss.ps);
240         ExecInitScanTupleSlot(estate, &scanstate->ss);
241
242         /*
243          * initialize child expressions
244          */
245         scanstate->ss.ps.targetlist = (List *)
246                 ExecInitExpr((Expr *) node->scan.plan.targetlist,
247                                          (PlanState *) scanstate);
248         scanstate->ss.ps.qual = (List *)
249                 ExecInitExpr((Expr *) node->scan.plan.qual,
250                                          (PlanState *) scanstate);
251
252         /*
253          * get info about values list
254          */
255         tupdesc = ExecTypeFromExprList((List *) linitial(node->values_lists));
256
257         ExecAssignScanType(&scanstate->ss, tupdesc);
258
259         /*
260          * Other node-specific setup
261          */
262         scanstate->curr_idx = -1;
263         scanstate->array_len = list_length(node->values_lists);
264
265         /* convert list of sublists into array of sublists for easy addressing */
266         scanstate->exprlists = (List **)
267                 palloc(scanstate->array_len * sizeof(List *));
268         i = 0;
269         foreach(vtl, node->values_lists)
270         {
271                 scanstate->exprlists[i++] = (List *) lfirst(vtl);
272         }
273
274         /*
275          * Initialize result tuple type and projection info.
276          */
277         ExecAssignResultTypeFromTL(&scanstate->ss.ps);
278         ExecAssignScanProjectionInfo(&scanstate->ss);
279
280         return scanstate;
281 }
282
283 /* ----------------------------------------------------------------
284  *              ExecEndValuesScan
285  *
286  *              frees any storage allocated through C routines.
287  * ----------------------------------------------------------------
288  */
289 void
290 ExecEndValuesScan(ValuesScanState *node)
291 {
292         /*
293          * Free both exprcontexts
294          */
295         ExecFreeExprContext(&node->ss.ps);
296         node->ss.ps.ps_ExprContext = node->rowcontext;
297         ExecFreeExprContext(&node->ss.ps);
298
299         /*
300          * clean out the tuple table
301          */
302         ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
303         ExecClearTuple(node->ss.ss_ScanTupleSlot);
304 }
305
306 /* ----------------------------------------------------------------
307  *              ExecReScanValuesScan
308  *
309  *              Rescans the relation.
310  * ----------------------------------------------------------------
311  */
312 void
313 ExecReScanValuesScan(ValuesScanState *node)
314 {
315         ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
316
317         ExecScanReScan(&node->ss);
318
319         node->curr_idx = -1;
320 }