1 /*-------------------------------------------------------------------------
4 * Support routines for scanning Values lists
5 * ("VALUES (...), (...), ..." in rangetable).
7 * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
8 * Portions Copyright (c) 1994, Regents of the University of California
12 * $PostgreSQL: pgsql/src/backend/executor/nodeValuesscan.c,v 1.11 2009/10/26 02:26:31 tgl Exp $
14 *-------------------------------------------------------------------------
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
26 #include "executor/executor.h"
27 #include "executor/nodeValuesscan.h"
28 #include "utils/memutils.h"
31 static TupleTableSlot *ValuesNext(ValuesScanState *node);
34 /* ----------------------------------------------------------------
36 * ----------------------------------------------------------------
39 /* ----------------------------------------------------------------
42 * This is a workhorse for ExecValuesScan
43 * ----------------------------------------------------------------
45 static TupleTableSlot *
46 ValuesNext(ValuesScanState *node)
50 ExprContext *econtext;
51 ScanDirection direction;
55 * get information from the estate and scan state
57 estate = node->ss.ps.state;
58 direction = estate->es_direction;
59 slot = node->ss.ss_ScanTupleSlot;
60 econtext = node->rowcontext;
63 * Get the next tuple. Return NULL if no more tuples.
65 if (ScanDirectionIsForward(direction))
67 if (node->curr_idx < node->array_len)
69 if (node->curr_idx < node->array_len)
70 exprlist = node->exprlists[node->curr_idx];
76 if (node->curr_idx >= 0)
78 if (node->curr_idx >= 0)
79 exprlist = node->exprlists[node->curr_idx];
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.
94 MemoryContext oldContext;
102 * Get rid of any prior cycle's leftovers. We use ReScanExprContext
103 * not just ResetExprContext because we want any registered shutdown
104 * callbacks to be called.
106 ReScanExprContext(econtext);
109 * Build the expression eval state in the econtext's per-tuple memory.
110 * This is a tad unusual, but we want to delete the eval state again
111 * when we move to the next row, to avoid growth of memory
112 * requirements over a long values list.
114 oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
117 * Pass NULL, not my plan node, because we don't want anything in this
118 * transient state linking into permanent state. The only possibility
119 * is a SubPlan, and there shouldn't be any (any subselects in the
120 * VALUES list should be InitPlans).
122 exprstatelist = (List *) ExecInitExpr((Expr *) exprlist, NULL);
124 /* parser should have checked all sublists are the same length */
125 Assert(list_length(exprstatelist) == slot->tts_tupleDescriptor->natts);
128 * Compute the expressions and build a virtual result tuple. We
129 * already did ExecClearTuple(slot).
131 values = slot->tts_values;
132 isnull = slot->tts_isnull;
135 foreach(lc, exprstatelist)
137 ExprState *estate = (ExprState *) lfirst(lc);
139 values[resind] = ExecEvalExpr(estate,
146 MemoryContextSwitchTo(oldContext);
149 * And return the virtual tuple.
151 ExecStoreVirtualTuple(slot);
158 * ValuesRecheck -- access method routine to recheck a tuple in EvalPlanQual
161 ValuesRecheck(ValuesScanState *node, TupleTableSlot *slot)
163 /* nothing to check */
167 /* ----------------------------------------------------------------
168 * ExecValuesScan(node)
170 * Scans the values lists sequentially and returns the next qualifying
172 * We call the ExecScan() routine and pass it the appropriate
173 * access method functions.
174 * ----------------------------------------------------------------
177 ExecValuesScan(ValuesScanState *node)
179 return ExecScan(&node->ss,
180 (ExecScanAccessMtd) ValuesNext,
181 (ExecScanRecheckMtd) ValuesRecheck);
184 /* ----------------------------------------------------------------
186 * ----------------------------------------------------------------
189 ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags)
191 ValuesScanState *scanstate;
195 PlanState *planstate;
198 * ValuesScan should not have any children.
200 Assert(outerPlan(node) == NULL);
201 Assert(innerPlan(node) == NULL);
204 * create new ScanState for node
206 scanstate = makeNode(ValuesScanState);
207 scanstate->ss.ps.plan = (Plan *) node;
208 scanstate->ss.ps.state = estate;
211 * Miscellaneous initialization
213 planstate = &scanstate->ss.ps;
216 * Create expression contexts. We need two, one for per-sublist
217 * processing and one for execScan.c to use for quals and projections. We
218 * cheat a little by using ExecAssignExprContext() to build both.
220 ExecAssignExprContext(estate, planstate);
221 scanstate->rowcontext = planstate->ps_ExprContext;
222 ExecAssignExprContext(estate, planstate);
225 * tuple table initialization
227 ExecInitResultTupleSlot(estate, &scanstate->ss.ps);
228 ExecInitScanTupleSlot(estate, &scanstate->ss);
231 * initialize child expressions
233 scanstate->ss.ps.targetlist = (List *)
234 ExecInitExpr((Expr *) node->scan.plan.targetlist,
235 (PlanState *) scanstate);
236 scanstate->ss.ps.qual = (List *)
237 ExecInitExpr((Expr *) node->scan.plan.qual,
238 (PlanState *) scanstate);
241 * get info about values list
243 tupdesc = ExecTypeFromExprList((List *) linitial(node->values_lists));
245 ExecAssignScanType(&scanstate->ss, tupdesc);
248 * Other node-specific setup
250 scanstate->marked_idx = -1;
251 scanstate->curr_idx = -1;
252 scanstate->array_len = list_length(node->values_lists);
254 /* convert list of sublists into array of sublists for easy addressing */
255 scanstate->exprlists = (List **)
256 palloc(scanstate->array_len * sizeof(List *));
258 foreach(vtl, node->values_lists)
260 scanstate->exprlists[i++] = (List *) lfirst(vtl);
263 scanstate->ss.ps.ps_TupFromTlist = false;
266 * Initialize result tuple type and projection info.
268 ExecAssignResultTypeFromTL(&scanstate->ss.ps);
269 ExecAssignScanProjectionInfo(&scanstate->ss);
274 /* ----------------------------------------------------------------
277 * frees any storage allocated through C routines.
278 * ----------------------------------------------------------------
281 ExecEndValuesScan(ValuesScanState *node)
284 * Free both exprcontexts
286 ExecFreeExprContext(&node->ss.ps);
287 node->ss.ps.ps_ExprContext = node->rowcontext;
288 ExecFreeExprContext(&node->ss.ps);
291 * clean out the tuple table
293 ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
294 ExecClearTuple(node->ss.ss_ScanTupleSlot);
297 /* ----------------------------------------------------------------
300 * Marks scan position.
301 * ----------------------------------------------------------------
304 ExecValuesMarkPos(ValuesScanState *node)
306 node->marked_idx = node->curr_idx;
309 /* ----------------------------------------------------------------
312 * Restores scan position.
313 * ----------------------------------------------------------------
316 ExecValuesRestrPos(ValuesScanState *node)
318 node->curr_idx = node->marked_idx;
321 /* ----------------------------------------------------------------
324 * Rescans the relation.
325 * ----------------------------------------------------------------
328 ExecValuesReScan(ValuesScanState *node, ExprContext *exprCtxt)
330 ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
332 ExecScanReScan(&node->ss);