1 /*-------------------------------------------------------------------------
4 * Support routines for scanning Values lists
5 * ("VALUES (...), (...), ..." in rangetable).
7 * Portions Copyright (c) 1996-2006, 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.4 2006/12/26 19:26:46 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;
189 PlanState *planstate;
192 * ValuesScan should not have any children.
194 Assert(outerPlan(node) == NULL);
195 Assert(innerPlan(node) == NULL);
198 * create new ScanState for node
200 scanstate = makeNode(ValuesScanState);
201 scanstate->ss.ps.plan = (Plan *) node;
202 scanstate->ss.ps.state = estate;
205 * Miscellaneous initialization
207 planstate = &scanstate->ss.ps;
210 * Create expression contexts. We need two, one for per-sublist
211 * processing and one for execScan.c to use for quals and projections. We
212 * cheat a little by using ExecAssignExprContext() to build both.
214 ExecAssignExprContext(estate, planstate);
215 scanstate->rowcontext = planstate->ps_ExprContext;
216 ExecAssignExprContext(estate, planstate);
218 #define VALUESSCAN_NSLOTS 2
221 * tuple table initialization
223 ExecInitResultTupleSlot(estate, &scanstate->ss.ps);
224 ExecInitScanTupleSlot(estate, &scanstate->ss);
227 * initialize child expressions
229 scanstate->ss.ps.targetlist = (List *)
230 ExecInitExpr((Expr *) node->scan.plan.targetlist,
231 (PlanState *) scanstate);
232 scanstate->ss.ps.qual = (List *)
233 ExecInitExpr((Expr *) node->scan.plan.qual,
234 (PlanState *) scanstate);
237 * get info about values list
239 rte = rt_fetch(node->scan.scanrelid, estate->es_range_table);
240 Assert(rte->rtekind == RTE_VALUES);
241 tupdesc = ExecTypeFromExprList((List *) linitial(rte->values_lists));
243 ExecAssignScanType(&scanstate->ss, tupdesc);
246 * Other node-specific setup
248 scanstate->marked_idx = -1;
249 scanstate->curr_idx = -1;
250 scanstate->array_len = list_length(rte->values_lists);
252 /* convert list of sublists into array of sublists for easy addressing */
253 scanstate->exprlists = (List **)
254 palloc(scanstate->array_len * sizeof(List *));
256 foreach(vtl, rte->values_lists)
258 scanstate->exprlists[i++] = (List *) lfirst(vtl);
261 scanstate->ss.ps.ps_TupFromTlist = false;
264 * Initialize result tuple type and projection info.
266 ExecAssignResultTypeFromTL(&scanstate->ss.ps);
267 ExecAssignScanProjectionInfo(&scanstate->ss);
273 ExecCountSlotsValuesScan(ValuesScan *node)
275 return ExecCountSlotsNode(outerPlan(node)) +
276 ExecCountSlotsNode(innerPlan(node)) +
280 /* ----------------------------------------------------------------
283 * frees any storage allocated through C routines.
284 * ----------------------------------------------------------------
287 ExecEndValuesScan(ValuesScanState *node)
290 * Free both exprcontexts
292 ExecFreeExprContext(&node->ss.ps);
293 node->ss.ps.ps_ExprContext = node->rowcontext;
294 ExecFreeExprContext(&node->ss.ps);
297 * clean out the tuple table
299 ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
300 ExecClearTuple(node->ss.ss_ScanTupleSlot);
303 /* ----------------------------------------------------------------
306 * Marks scan position.
307 * ----------------------------------------------------------------
310 ExecValuesMarkPos(ValuesScanState *node)
312 node->marked_idx = node->curr_idx;
315 /* ----------------------------------------------------------------
318 * Restores scan position.
319 * ----------------------------------------------------------------
322 ExecValuesRestrPos(ValuesScanState *node)
324 node->curr_idx = node->marked_idx;
327 /* ----------------------------------------------------------------
330 * Rescans the relation.
331 * ----------------------------------------------------------------
334 ExecValuesReScan(ValuesScanState *node, ExprContext *exprCtxt)
336 ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
337 node->ss.ps.ps_TupFromTlist = false;