1 /*-------------------------------------------------------------------------
4 * Support routines for scanning Values lists
5 * ("VALUES (...), (...), ..." in rangetable).
7 * Portions Copyright (c) 1996-2007, 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.6 2007/02/19 02:23:11 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 "parser/parsetree.h"
29 #include "utils/memutils.h"
32 static TupleTableSlot *ValuesNext(ValuesScanState *node);
35 /* ----------------------------------------------------------------
37 * ----------------------------------------------------------------
40 /* ----------------------------------------------------------------
43 * This is a workhorse for ExecValuesScan
44 * ----------------------------------------------------------------
46 static TupleTableSlot *
47 ValuesNext(ValuesScanState *node)
51 ExprContext *econtext;
52 ScanDirection direction;
56 * get information from the estate and scan state
58 estate = node->ss.ps.state;
59 direction = estate->es_direction;
60 slot = node->ss.ss_ScanTupleSlot;
61 econtext = node->rowcontext;
64 * Get the next tuple. Return NULL if no more tuples.
66 if (ScanDirectionIsForward(direction))
68 if (node->curr_idx < node->array_len)
70 if (node->curr_idx < node->array_len)
71 exprlist = node->exprlists[node->curr_idx];
77 if (node->curr_idx >= 0)
79 if (node->curr_idx >= 0)
80 exprlist = node->exprlists[node->curr_idx];
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.
95 MemoryContext oldContext;
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.
107 ReScanExprContext(econtext);
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.
115 oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
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).
123 exprstatelist = (List *) ExecInitExpr((Expr *) exprlist, NULL);
125 /* parser should have checked all sublists are the same length */
126 Assert(list_length(exprstatelist) == slot->tts_tupleDescriptor->natts);
129 * Compute the expressions and build a virtual result tuple. We
130 * already did ExecClearTuple(slot).
132 values = slot->tts_values;
133 isnull = slot->tts_isnull;
136 foreach(lc, exprstatelist)
138 ExprState *estate = (ExprState *) lfirst(lc);
140 values[resind] = ExecEvalExpr(estate,
147 MemoryContextSwitchTo(oldContext);
150 * And return the virtual tuple.
152 ExecStoreVirtualTuple(slot);
159 /* ----------------------------------------------------------------
160 * ExecValuesScan(node)
162 * Scans the values lists sequentially and returns the next qualifying
164 * It calls the ExecScan() routine and passes it the access method
165 * which retrieves tuples sequentially.
166 * ----------------------------------------------------------------
169 ExecValuesScan(ValuesScanState *node)
172 * use ValuesNext as access method
174 return ExecScan(&node->ss, (ExecScanAccessMtd) ValuesNext);
177 /* ----------------------------------------------------------------
179 * ----------------------------------------------------------------
182 ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags)
184 ValuesScanState *scanstate;
188 PlanState *planstate;
191 * ValuesScan should not have any children.
193 Assert(outerPlan(node) == NULL);
194 Assert(innerPlan(node) == NULL);
197 * create new ScanState for node
199 scanstate = makeNode(ValuesScanState);
200 scanstate->ss.ps.plan = (Plan *) node;
201 scanstate->ss.ps.state = estate;
204 * Miscellaneous initialization
206 planstate = &scanstate->ss.ps;
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.
213 ExecAssignExprContext(estate, planstate);
214 scanstate->rowcontext = planstate->ps_ExprContext;
215 ExecAssignExprContext(estate, planstate);
217 #define VALUESSCAN_NSLOTS 2
220 * tuple table initialization
222 ExecInitResultTupleSlot(estate, &scanstate->ss.ps);
223 ExecInitScanTupleSlot(estate, &scanstate->ss);
226 * initialize child expressions
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);
236 * get info about values list
238 tupdesc = ExecTypeFromExprList((List *) linitial(node->values_lists));
240 ExecAssignScanType(&scanstate->ss, tupdesc);
243 * Other node-specific setup
245 scanstate->marked_idx = -1;
246 scanstate->curr_idx = -1;
247 scanstate->array_len = list_length(node->values_lists);
249 /* convert list of sublists into array of sublists for easy addressing */
250 scanstate->exprlists = (List **)
251 palloc(scanstate->array_len * sizeof(List *));
253 foreach(vtl, node->values_lists)
255 scanstate->exprlists[i++] = (List *) lfirst(vtl);
258 scanstate->ss.ps.ps_TupFromTlist = false;
261 * Initialize result tuple type and projection info.
263 ExecAssignResultTypeFromTL(&scanstate->ss.ps);
264 ExecAssignScanProjectionInfo(&scanstate->ss);
270 ExecCountSlotsValuesScan(ValuesScan *node)
272 return ExecCountSlotsNode(outerPlan(node)) +
273 ExecCountSlotsNode(innerPlan(node)) +
277 /* ----------------------------------------------------------------
280 * frees any storage allocated through C routines.
281 * ----------------------------------------------------------------
284 ExecEndValuesScan(ValuesScanState *node)
287 * Free both exprcontexts
289 ExecFreeExprContext(&node->ss.ps);
290 node->ss.ps.ps_ExprContext = node->rowcontext;
291 ExecFreeExprContext(&node->ss.ps);
294 * clean out the tuple table
296 ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
297 ExecClearTuple(node->ss.ss_ScanTupleSlot);
300 /* ----------------------------------------------------------------
303 * Marks scan position.
304 * ----------------------------------------------------------------
307 ExecValuesMarkPos(ValuesScanState *node)
309 node->marked_idx = node->curr_idx;
312 /* ----------------------------------------------------------------
315 * Restores scan position.
316 * ----------------------------------------------------------------
319 ExecValuesRestrPos(ValuesScanState *node)
321 node->curr_idx = node->marked_idx;
324 /* ----------------------------------------------------------------
327 * Rescans the relation.
328 * ----------------------------------------------------------------
331 ExecValuesReScan(ValuesScanState *node, ExprContext *exprCtxt)
333 ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
334 node->ss.ps.ps_TupFromTlist = false;