]> granicus.if.org Git - postgresql/blob - src/backend/executor/nodeValuesscan.c
Put function expressions and values lists into FunctionScan and ValuesScan
[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-2007, PostgreSQL Global Development Group
8  * Portions Copyright (c) 1994, Regents of the University of California
9  *
10  *
11  * IDENTIFICATION
12  *        $PostgreSQL: pgsql/src/backend/executor/nodeValuesscan.c,v 1.6 2007/02/19 02:23:11 tgl Exp $
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  *              ExecValuesReScan                rescans the values list
23  */
24 #include "postgres.h"
25
26 #include "executor/executor.h"
27 #include "executor/nodeValuesscan.h"
28 #include "parser/parsetree.h"
29 #include "utils/memutils.h"
30
31
32 static TupleTableSlot *ValuesNext(ValuesScanState *node);
33
34
35 /* ----------------------------------------------------------------
36  *                                              Scan Support
37  * ----------------------------------------------------------------
38  */
39
40 /* ----------------------------------------------------------------
41  *              ValuesNext
42  *
43  *              This is a workhorse for ExecValuesScan
44  * ----------------------------------------------------------------
45  */
46 static TupleTableSlot *
47 ValuesNext(ValuesScanState *node)
48 {
49         TupleTableSlot *slot;
50         EState     *estate;
51         ExprContext *econtext;
52         ScanDirection direction;
53         List       *exprlist;
54
55         /*
56          * get information from the estate and scan state
57          */
58         estate = node->ss.ps.state;
59         direction = estate->es_direction;
60         slot = node->ss.ss_ScanTupleSlot;
61         econtext = node->rowcontext;
62
63         /*
64          * Get the next tuple. Return NULL if no more tuples.
65          */
66         if (ScanDirectionIsForward(direction))
67         {
68                 if (node->curr_idx < node->array_len)
69                         node->curr_idx++;
70                 if (node->curr_idx < node->array_len)
71                         exprlist = node->exprlists[node->curr_idx];
72                 else
73                         exprlist = NIL;
74         }
75         else
76         {
77                 if (node->curr_idx >= 0)
78                         node->curr_idx--;
79                 if (node->curr_idx >= 0)
80                         exprlist = node->exprlists[node->curr_idx];
81                 else
82                         exprlist = NIL;
83         }
84
85         /*
86          * Always clear the result slot; this is appropriate if we are at the end
87          * of the data, and if we're not, we still need it as the first step of
88          * the store-virtual-tuple protocol.  It seems wise to clear the slot
89          * before we reset the context it might have pointers into.
90          */
91         ExecClearTuple(slot);
92
93         if (exprlist)
94         {
95                 MemoryContext oldContext;
96                 List       *exprstatelist;
97                 Datum      *values;
98                 bool       *isnull;
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
135                 resind = 0;
136                 foreach(lc, exprstatelist)
137                 {
138                         ExprState  *estate = (ExprState *) lfirst(lc);
139
140                         values[resind] = ExecEvalExpr(estate,
141                                                                                   econtext,
142                                                                                   &isnull[resind],
143                                                                                   NULL);
144                         resind++;
145                 }
146
147                 MemoryContextSwitchTo(oldContext);
148
149                 /*
150                  * And return the virtual tuple.
151                  */
152                 ExecStoreVirtualTuple(slot);
153         }
154
155         return slot;
156 }
157
158
159 /* ----------------------------------------------------------------
160  *              ExecValuesScan(node)
161  *
162  *              Scans the values lists sequentially and returns the next qualifying
163  *              tuple.
164  *              It calls the ExecScan() routine and passes it the access method
165  *              which retrieves tuples sequentially.
166  * ----------------------------------------------------------------
167  */
168 TupleTableSlot *
169 ExecValuesScan(ValuesScanState *node)
170 {
171         /*
172          * use ValuesNext as access method
173          */
174         return ExecScan(&node->ss, (ExecScanAccessMtd) ValuesNext);
175 }
176
177 /* ----------------------------------------------------------------
178  *              ExecInitValuesScan
179  * ----------------------------------------------------------------
180  */
181 ValuesScanState *
182 ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags)
183 {
184         ValuesScanState *scanstate;
185         TupleDesc       tupdesc;
186         ListCell   *vtl;
187         int                     i;
188         PlanState  *planstate;
189
190         /*
191          * ValuesScan should not have any children.
192          */
193         Assert(outerPlan(node) == NULL);
194         Assert(innerPlan(node) == NULL);
195
196         /*
197          * create new ScanState for node
198          */
199         scanstate = makeNode(ValuesScanState);
200         scanstate->ss.ps.plan = (Plan *) node;
201         scanstate->ss.ps.state = estate;
202
203         /*
204          * Miscellaneous initialization
205          */
206         planstate = &scanstate->ss.ps;
207
208         /*
209          * Create expression contexts.  We need two, one for per-sublist
210          * processing and one for execScan.c to use for quals and projections. We
211          * cheat a little by using ExecAssignExprContext() to build both.
212          */
213         ExecAssignExprContext(estate, planstate);
214         scanstate->rowcontext = planstate->ps_ExprContext;
215         ExecAssignExprContext(estate, planstate);
216
217 #define VALUESSCAN_NSLOTS 2
218
219         /*
220          * tuple table initialization
221          */
222         ExecInitResultTupleSlot(estate, &scanstate->ss.ps);
223         ExecInitScanTupleSlot(estate, &scanstate->ss);
224
225         /*
226          * initialize child expressions
227          */
228         scanstate->ss.ps.targetlist = (List *)
229                 ExecInitExpr((Expr *) node->scan.plan.targetlist,
230                                          (PlanState *) scanstate);
231         scanstate->ss.ps.qual = (List *)
232                 ExecInitExpr((Expr *) node->scan.plan.qual,
233                                          (PlanState *) scanstate);
234
235         /*
236          * get info about values list
237          */
238         tupdesc = ExecTypeFromExprList((List *) linitial(node->values_lists));
239
240         ExecAssignScanType(&scanstate->ss, tupdesc);
241
242         /*
243          * Other node-specific setup
244          */
245         scanstate->marked_idx = -1;
246         scanstate->curr_idx = -1;
247         scanstate->array_len = list_length(node->values_lists);
248
249         /* convert list of sublists into array of sublists for easy addressing */
250         scanstate->exprlists = (List **)
251                 palloc(scanstate->array_len * sizeof(List *));
252         i = 0;
253         foreach(vtl, node->values_lists)
254         {
255                 scanstate->exprlists[i++] = (List *) lfirst(vtl);
256         }
257
258         scanstate->ss.ps.ps_TupFromTlist = false;
259
260         /*
261          * Initialize result tuple type and projection info.
262          */
263         ExecAssignResultTypeFromTL(&scanstate->ss.ps);
264         ExecAssignScanProjectionInfo(&scanstate->ss);
265
266         return scanstate;
267 }
268
269 int
270 ExecCountSlotsValuesScan(ValuesScan *node)
271 {
272         return ExecCountSlotsNode(outerPlan(node)) +
273                 ExecCountSlotsNode(innerPlan(node)) +
274                 VALUESSCAN_NSLOTS;
275 }
276
277 /* ----------------------------------------------------------------
278  *              ExecEndValuesScan
279  *
280  *              frees any storage allocated through C routines.
281  * ----------------------------------------------------------------
282  */
283 void
284 ExecEndValuesScan(ValuesScanState *node)
285 {
286         /*
287          * Free both exprcontexts
288          */
289         ExecFreeExprContext(&node->ss.ps);
290         node->ss.ps.ps_ExprContext = node->rowcontext;
291         ExecFreeExprContext(&node->ss.ps);
292
293         /*
294          * clean out the tuple table
295          */
296         ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
297         ExecClearTuple(node->ss.ss_ScanTupleSlot);
298 }
299
300 /* ----------------------------------------------------------------
301  *              ExecValuesMarkPos
302  *
303  *              Marks scan position.
304  * ----------------------------------------------------------------
305  */
306 void
307 ExecValuesMarkPos(ValuesScanState *node)
308 {
309         node->marked_idx = node->curr_idx;
310 }
311
312 /* ----------------------------------------------------------------
313  *              ExecValuesRestrPos
314  *
315  *              Restores scan position.
316  * ----------------------------------------------------------------
317  */
318 void
319 ExecValuesRestrPos(ValuesScanState *node)
320 {
321         node->curr_idx = node->marked_idx;
322 }
323
324 /* ----------------------------------------------------------------
325  *              ExecValuesReScan
326  *
327  *              Rescans the relation.
328  * ----------------------------------------------------------------
329  */
330 void
331 ExecValuesReScan(ValuesScanState *node, ExprContext *exprCtxt)
332 {
333         ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
334         node->ss.ps.ps_TupFromTlist = false;
335
336         node->curr_idx = -1;
337 }