1 /*-------------------------------------------------------------------------
4 * Support routines for scanning Values lists
5 * ("VALUES (...), (...), ..." in rangetable).
7 * Portions Copyright (c) 1996-2017, 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/expandeddatum.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;
98 Form_pg_attribute *att;
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;
134 att = slot->tts_tupleDescriptor->attrs;
137 foreach(lc, exprstatelist)
139 ExprState *estate = (ExprState *) lfirst(lc);
141 values[resind] = ExecEvalExpr(estate,
146 * We must force any R/W expanded datums to read-only state, in
147 * case they are multiply referenced in the plan node's output
148 * expressions, or in case we skip the output projection and the
149 * output column is multiply referenced in higher plan nodes.
151 values[resind] = MakeExpandedObjectReadOnly(values[resind],
153 att[resind]->attlen);
158 MemoryContextSwitchTo(oldContext);
161 * And return the virtual tuple.
163 ExecStoreVirtualTuple(slot);
170 * ValuesRecheck -- access method routine to recheck a tuple in EvalPlanQual
173 ValuesRecheck(ValuesScanState *node, TupleTableSlot *slot)
175 /* nothing to check */
179 /* ----------------------------------------------------------------
180 * ExecValuesScan(node)
182 * Scans the values lists sequentially and returns the next qualifying
184 * We call the ExecScan() routine and pass it the appropriate
185 * access method functions.
186 * ----------------------------------------------------------------
189 ExecValuesScan(ValuesScanState *node)
191 return ExecScan(&node->ss,
192 (ExecScanAccessMtd) ValuesNext,
193 (ExecScanRecheckMtd) ValuesRecheck);
196 /* ----------------------------------------------------------------
198 * ----------------------------------------------------------------
201 ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags)
203 ValuesScanState *scanstate;
207 PlanState *planstate;
210 * ValuesScan should not have any children.
212 Assert(outerPlan(node) == NULL);
213 Assert(innerPlan(node) == NULL);
216 * create new ScanState for node
218 scanstate = makeNode(ValuesScanState);
219 scanstate->ss.ps.plan = (Plan *) node;
220 scanstate->ss.ps.state = estate;
223 * Miscellaneous initialization
225 planstate = &scanstate->ss.ps;
228 * Create expression contexts. We need two, one for per-sublist
229 * processing and one for execScan.c to use for quals and projections. We
230 * cheat a little by using ExecAssignExprContext() to build both.
232 ExecAssignExprContext(estate, planstate);
233 scanstate->rowcontext = planstate->ps_ExprContext;
234 ExecAssignExprContext(estate, planstate);
237 * tuple table initialization
239 ExecInitResultTupleSlot(estate, &scanstate->ss.ps);
240 ExecInitScanTupleSlot(estate, &scanstate->ss);
243 * initialize child expressions
245 scanstate->ss.ps.targetlist = (List *)
246 ExecInitExpr((Expr *) node->scan.plan.targetlist,
247 (PlanState *) scanstate);
248 scanstate->ss.ps.qual = (List *)
249 ExecInitExpr((Expr *) node->scan.plan.qual,
250 (PlanState *) scanstate);
253 * get info about values list
255 tupdesc = ExecTypeFromExprList((List *) linitial(node->values_lists));
257 ExecAssignScanType(&scanstate->ss, tupdesc);
260 * Other node-specific setup
262 scanstate->curr_idx = -1;
263 scanstate->array_len = list_length(node->values_lists);
265 /* convert list of sublists into array of sublists for easy addressing */
266 scanstate->exprlists = (List **)
267 palloc(scanstate->array_len * sizeof(List *));
269 foreach(vtl, node->values_lists)
271 scanstate->exprlists[i++] = (List *) lfirst(vtl);
275 * Initialize result tuple type and projection info.
277 ExecAssignResultTypeFromTL(&scanstate->ss.ps);
278 ExecAssignScanProjectionInfo(&scanstate->ss);
283 /* ----------------------------------------------------------------
286 * frees any storage allocated through C routines.
287 * ----------------------------------------------------------------
290 ExecEndValuesScan(ValuesScanState *node)
293 * Free both exprcontexts
295 ExecFreeExprContext(&node->ss.ps);
296 node->ss.ps.ps_ExprContext = node->rowcontext;
297 ExecFreeExprContext(&node->ss.ps);
300 * clean out the tuple table
302 ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
303 ExecClearTuple(node->ss.ss_ScanTupleSlot);
306 /* ----------------------------------------------------------------
307 * ExecReScanValuesScan
309 * Rescans the relation.
310 * ----------------------------------------------------------------
313 ExecReScanValuesScan(ValuesScanState *node)
315 ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
317 ExecScanReScan(&node->ss);