1 /*-------------------------------------------------------------------------
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
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 /* ----------------------------------------------------------------
159 * ExecValuesScan(node)
161 * Scans the values lists sequentially and returns the next qualifying
163 * It calls the ExecScan() routine and passes it the access method
164 * which retrieves tuples sequentially.
165 * ----------------------------------------------------------------
168 ExecValuesScan(ValuesScanState
*node
)
171 * use ValuesNext as access method
173 return ExecScan(&node
->ss
, (ExecScanAccessMtd
) ValuesNext
);
176 /* ----------------------------------------------------------------
178 * ----------------------------------------------------------------
181 ExecInitValuesScan(ValuesScan
*node
, EState
*estate
, int eflags
)
183 ValuesScanState
*scanstate
;
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
*));
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
);
269 ExecCountSlotsValuesScan(ValuesScan
*node
)
271 return ExecCountSlotsNode(outerPlan(node
)) +
272 ExecCountSlotsNode(innerPlan(node
)) +
276 /* ----------------------------------------------------------------
279 * frees any storage allocated through C routines.
280 * ----------------------------------------------------------------
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 /* ----------------------------------------------------------------
302 * Marks scan position.
303 * ----------------------------------------------------------------
306 ExecValuesMarkPos(ValuesScanState
*node
)
308 node
->marked_idx
= node
->curr_idx
;
311 /* ----------------------------------------------------------------
314 * Restores scan position.
315 * ----------------------------------------------------------------
318 ExecValuesRestrPos(ValuesScanState
*node
)
320 node
->curr_idx
= node
->marked_idx
;
323 /* ----------------------------------------------------------------
326 * Rescans the relation.
327 * ----------------------------------------------------------------
330 ExecValuesReScan(ValuesScanState
*node
, ExprContext
*exprCtxt
)
332 ExecClearTuple(node
->ss
.ps
.ps_ResultTupleSlot
);
333 node
->ss
.ps
.ps_TupFromTlist
= false;