1
/*-------------------------------------------------------------------------
4
* Support routines for scanning Values lists
5
* ("VALUES (...), (...), ..." in rangetable).
7
* Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
8
* Portions Copyright (c) 1994, Regents of the University of California
12
* src/backend/executor/nodeValuesscan.c
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
* ExecReScanValuesScan 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
/* ----------------------------------------------------------------
322
* ExecReScanValuesScan
324
* Rescans the relation.
325
* ----------------------------------------------------------------
328
ExecReScanValuesScan(ValuesScanState *node)
330
ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
332
ExecScanReScan(&node->ss);