Add support for user-defined I/O conversion casts.
[PostgreSQL.git] / src / backend / executor / nodeValuesscan.c
blobeea09ba6f0ab43ad69cfcd94d35d44ff6429f870
1 /*-------------------------------------------------------------------------
3 * nodeValuesscan.c
4 * Support routines for scanning Values lists
5 * ("VALUES (...), (...), ..." in rangetable).
7 * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
8 * Portions Copyright (c) 1994, Regents of the University of California
11 * IDENTIFICATION
12 * $PostgreSQL$
14 *-------------------------------------------------------------------------
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
24 #include "postgres.h"
26 #include "executor/executor.h"
27 #include "executor/nodeValuesscan.h"
28 #include "utils/memutils.h"
31 static TupleTableSlot *ValuesNext(ValuesScanState *node);
34 /* ----------------------------------------------------------------
35 * Scan Support
36 * ----------------------------------------------------------------
39 /* ----------------------------------------------------------------
40 * ValuesNext
42 * This is a workhorse for ExecValuesScan
43 * ----------------------------------------------------------------
45 static TupleTableSlot *
46 ValuesNext(ValuesScanState *node)
48 TupleTableSlot *slot;
49 EState *estate;
50 ExprContext *econtext;
51 ScanDirection direction;
52 List *exprlist;
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)
68 node->curr_idx++;
69 if (node->curr_idx < node->array_len)
70 exprlist = node->exprlists[node->curr_idx];
71 else
72 exprlist = NIL;
74 else
76 if (node->curr_idx >= 0)
77 node->curr_idx--;
78 if (node->curr_idx >= 0)
79 exprlist = node->exprlists[node->curr_idx];
80 else
81 exprlist = NIL;
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.
90 ExecClearTuple(slot);
92 if (exprlist)
94 MemoryContext oldContext;
95 List *exprstatelist;
96 Datum *values;
97 bool *isnull;
98 ListCell *lc;
99 int resind;
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;
134 resind = 0;
135 foreach(lc, exprstatelist)
137 ExprState *estate = (ExprState *) lfirst(lc);
139 values[resind] = ExecEvalExpr(estate,
140 econtext,
141 &isnull[resind],
142 NULL);
143 resind++;
146 MemoryContextSwitchTo(oldContext);
149 * And return the virtual tuple.
151 ExecStoreVirtualTuple(slot);
154 return slot;
158 /* ----------------------------------------------------------------
159 * ExecValuesScan(node)
161 * Scans the values lists sequentially and returns the next qualifying
162 * tuple.
163 * It calls the ExecScan() routine and passes it the access method
164 * which retrieves tuples sequentially.
165 * ----------------------------------------------------------------
167 TupleTableSlot *
168 ExecValuesScan(ValuesScanState *node)
171 * use ValuesNext as access method
173 return ExecScan(&node->ss, (ExecScanAccessMtd) ValuesNext);
176 /* ----------------------------------------------------------------
177 * ExecInitValuesScan
178 * ----------------------------------------------------------------
180 ValuesScanState *
181 ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags)
183 ValuesScanState *scanstate;
184 TupleDesc tupdesc;
185 ListCell *vtl;
186 int i;
187 PlanState *planstate;
190 * ValuesScan should not have any children.
192 Assert(outerPlan(node) == NULL);
193 Assert(innerPlan(node) == NULL);
196 * create new ScanState for node
198 scanstate = makeNode(ValuesScanState);
199 scanstate->ss.ps.plan = (Plan *) node;
200 scanstate->ss.ps.state = estate;
203 * Miscellaneous initialization
205 planstate = &scanstate->ss.ps;
208 * Create expression contexts. We need two, one for per-sublist
209 * processing and one for execScan.c to use for quals and projections. We
210 * cheat a little by using ExecAssignExprContext() to build both.
212 ExecAssignExprContext(estate, planstate);
213 scanstate->rowcontext = planstate->ps_ExprContext;
214 ExecAssignExprContext(estate, planstate);
216 #define VALUESSCAN_NSLOTS 2
219 * tuple table initialization
221 ExecInitResultTupleSlot(estate, &scanstate->ss.ps);
222 ExecInitScanTupleSlot(estate, &scanstate->ss);
225 * initialize child expressions
227 scanstate->ss.ps.targetlist = (List *)
228 ExecInitExpr((Expr *) node->scan.plan.targetlist,
229 (PlanState *) scanstate);
230 scanstate->ss.ps.qual = (List *)
231 ExecInitExpr((Expr *) node->scan.plan.qual,
232 (PlanState *) scanstate);
235 * get info about values list
237 tupdesc = ExecTypeFromExprList((List *) linitial(node->values_lists));
239 ExecAssignScanType(&scanstate->ss, tupdesc);
242 * Other node-specific setup
244 scanstate->marked_idx = -1;
245 scanstate->curr_idx = -1;
246 scanstate->array_len = list_length(node->values_lists);
248 /* convert list of sublists into array of sublists for easy addressing */
249 scanstate->exprlists = (List **)
250 palloc(scanstate->array_len * sizeof(List *));
251 i = 0;
252 foreach(vtl, node->values_lists)
254 scanstate->exprlists[i++] = (List *) lfirst(vtl);
257 scanstate->ss.ps.ps_TupFromTlist = false;
260 * Initialize result tuple type and projection info.
262 ExecAssignResultTypeFromTL(&scanstate->ss.ps);
263 ExecAssignScanProjectionInfo(&scanstate->ss);
265 return scanstate;
269 ExecCountSlotsValuesScan(ValuesScan *node)
271 return ExecCountSlotsNode(outerPlan(node)) +
272 ExecCountSlotsNode(innerPlan(node)) +
273 VALUESSCAN_NSLOTS;
276 /* ----------------------------------------------------------------
277 * ExecEndValuesScan
279 * frees any storage allocated through C routines.
280 * ----------------------------------------------------------------
282 void
283 ExecEndValuesScan(ValuesScanState *node)
286 * Free both exprcontexts
288 ExecFreeExprContext(&node->ss.ps);
289 node->ss.ps.ps_ExprContext = node->rowcontext;
290 ExecFreeExprContext(&node->ss.ps);
293 * clean out the tuple table
295 ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
296 ExecClearTuple(node->ss.ss_ScanTupleSlot);
299 /* ----------------------------------------------------------------
300 * ExecValuesMarkPos
302 * Marks scan position.
303 * ----------------------------------------------------------------
305 void
306 ExecValuesMarkPos(ValuesScanState *node)
308 node->marked_idx = node->curr_idx;
311 /* ----------------------------------------------------------------
312 * ExecValuesRestrPos
314 * Restores scan position.
315 * ----------------------------------------------------------------
317 void
318 ExecValuesRestrPos(ValuesScanState *node)
320 node->curr_idx = node->marked_idx;
323 /* ----------------------------------------------------------------
324 * ExecValuesReScan
326 * Rescans the relation.
327 * ----------------------------------------------------------------
329 void
330 ExecValuesReScan(ValuesScanState *node, ExprContext *exprCtxt)
332 ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
333 node->ss.ps.ps_TupFromTlist = false;
335 node->curr_idx = -1;