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