1/*-------------------------------------------------------------------------
2 *
3 * nodeValuesscan.c
4 * Support routines for scanning Values lists
5 * ("VALUES (...), (...), ..." in rangetable).
6 *
7 * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
8 * Portions Copyright (c) 1994, Regents of the University of California
9 *
10 *
11 * IDENTIFICATION
12 * src/backend/executor/nodeValuesscan.c
13 *
14 *-------------------------------------------------------------------------
15 */
16/*
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 * ExecReScanValuesScan rescans the values list
23 */
24#include "postgres.h"
25
26#include "executor/executor.h"
27#include "executor/nodeValuesscan.h"
28#include "jit/jit.h"
29#include "utils/expandeddatum.h"
30
31
32static TupleTableSlot *ValuesNext(ValuesScanState *node);
33
34
35/* ----------------------------------------------------------------
36 * Scan Support
37 * ----------------------------------------------------------------
38 */
39
40/* ----------------------------------------------------------------
41 * ValuesNext
42 *
43 * This is a workhorse for ExecValuesScan
44 * ----------------------------------------------------------------
45 */
46static TupleTableSlot *
47ValuesNext(ValuesScanState *node)
48{
49 TupleTableSlot *slot;
50 EState *estate;
51 ExprContext *econtext;
52 ScanDirection direction;
53 List *exprlist;
54
55 /*
56 * get information from the estate and scan state
57 */
58 estate = node->ss.ps.state;
59 direction = estate->es_direction;
60 slot = node->ss.ss_ScanTupleSlot;
61 econtext = node->rowcontext;
62
63 /*
64 * Get the next tuple. Return NULL if no more tuples.
65 */
66 if (ScanDirectionIsForward(direction))
67 {
68 if (node->curr_idx < node->array_len)
69 node->curr_idx++;
70 if (node->curr_idx < node->array_len)
71 exprlist = node->exprlists[node->curr_idx];
72 else
73 exprlist = NIL;
74 }
75 else
76 {
77 if (node->curr_idx >= 0)
78 node->curr_idx--;
79 if (node->curr_idx >= 0)
80 exprlist = node->exprlists[node->curr_idx];
81 else
82 exprlist = NIL;
83 }
84
85 /*
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.
90 */
91 ExecClearTuple(slot);
92
93 if (exprlist)
94 {
95 MemoryContext oldContext;
96 List *oldsubplans;
97 List *exprstatelist;
98 Datum *values;
99 bool *isnull;
100 ListCell *lc;
101 int resind;
102 int saved_jit_flags;
103
104 /*
105 * Get rid of any prior cycle's leftovers. We use ReScanExprContext
106 * not just ResetExprContext because we want any registered shutdown
107 * callbacks to be called.
108 */
109 ReScanExprContext(econtext);
110
111 /*
112 * Build the expression eval state in the econtext's per-tuple memory.
113 * This is a tad unusual, but we want to delete the eval state again
114 * when we move to the next row, to avoid growth of memory
115 * requirements over a long values list.
116 */
117 oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
118
119 /*
120 * The expressions might contain SubPlans (this is currently only
121 * possible if there's a sub-select containing a LATERAL reference,
122 * otherwise sub-selects in a VALUES list should be InitPlans). Those
123 * subplans will want to hook themselves into our subPlan list, which
124 * would result in a corrupted list after we delete the eval state. We
125 * can work around this by saving and restoring the subPlan list.
126 * (There's no need for the functionality that would be enabled by
127 * having the list entries, since the SubPlans aren't going to be
128 * re-executed anyway.)
129 */
130 oldsubplans = node->ss.ps.subPlan;
131 node->ss.ps.subPlan = NIL;
132
133 /*
134 * As the expressions are only ever used once, disable JIT for them.
135 * This is worthwhile because it's common to insert significant
136 * amounts of data via VALUES().
137 */
138 saved_jit_flags = econtext->ecxt_estate->es_jit_flags;
139 econtext->ecxt_estate->es_jit_flags = PGJIT_NONE;
140 exprstatelist = ExecInitExprList(exprlist, &node->ss.ps);
141 econtext->ecxt_estate->es_jit_flags = saved_jit_flags;
142
143 node->ss.ps.subPlan = oldsubplans;
144
145 /* parser should have checked all sublists are the same length */
146 Assert(list_length(exprstatelist) == slot->tts_tupleDescriptor->natts);
147
148 /*
149 * Compute the expressions and build a virtual result tuple. We
150 * already did ExecClearTuple(slot).
151 */
152 values = slot->tts_values;
153 isnull = slot->tts_isnull;
154
155 resind = 0;
156 foreach(lc, exprstatelist)
157 {
158 ExprState *estate = (ExprState *) lfirst(lc);
159 Form_pg_attribute attr = TupleDescAttr(slot->tts_tupleDescriptor,
160 resind);
161
162 values[resind] = ExecEvalExpr(estate,
163 econtext,
164 &isnull[resind]);
165
166 /*
167 * We must force any R/W expanded datums to read-only state, in
168 * case they are multiply referenced in the plan node's output
169 * expressions, or in case we skip the output projection and the
170 * output column is multiply referenced in higher plan nodes.
171 */
172 values[resind] = MakeExpandedObjectReadOnly(values[resind],
173 isnull[resind],
174 attr->attlen);
175
176 resind++;
177 }
178
179 MemoryContextSwitchTo(oldContext);
180
181 /*
182 * And return the virtual tuple.
183 */
184 ExecStoreVirtualTuple(slot);
185 }
186
187 return slot;
188}
189
190/*
191 * ValuesRecheck -- access method routine to recheck a tuple in EvalPlanQual
192 */
193static bool
194ValuesRecheck(ValuesScanState *node, TupleTableSlot *slot)
195{
196 /* nothing to check */
197 return true;
198}
199
200/* ----------------------------------------------------------------
201 * ExecValuesScan(node)
202 *
203 * Scans the values lists sequentially and returns the next qualifying
204 * tuple.
205 * We call the ExecScan() routine and pass it the appropriate
206 * access method functions.
207 * ----------------------------------------------------------------
208 */
209static TupleTableSlot *
210ExecValuesScan(PlanState *pstate)
211{
212 ValuesScanState *node = castNode(ValuesScanState, pstate);
213
214 return ExecScan(&node->ss,
215 (ExecScanAccessMtd) ValuesNext,
216 (ExecScanRecheckMtd) ValuesRecheck);
217}
218
219/* ----------------------------------------------------------------
220 * ExecInitValuesScan
221 * ----------------------------------------------------------------
222 */
223ValuesScanState *
224ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags)
225{
226 ValuesScanState *scanstate;
227 TupleDesc tupdesc;
228 ListCell *vtl;
229 int i;
230 PlanState *planstate;
231
232 /*
233 * ValuesScan should not have any children.
234 */
235 Assert(outerPlan(node) == NULL);
236 Assert(innerPlan(node) == NULL);
237
238 /*
239 * create new ScanState for node
240 */
241 scanstate = makeNode(ValuesScanState);
242 scanstate->ss.ps.plan = (Plan *) node;
243 scanstate->ss.ps.state = estate;
244 scanstate->ss.ps.ExecProcNode = ExecValuesScan;
245
246 /*
247 * Miscellaneous initialization
248 */
249 planstate = &scanstate->ss.ps;
250
251 /*
252 * Create expression contexts. We need two, one for per-sublist
253 * processing and one for execScan.c to use for quals and projections. We
254 * cheat a little by using ExecAssignExprContext() to build both.
255 */
256 ExecAssignExprContext(estate, planstate);
257 scanstate->rowcontext = planstate->ps_ExprContext;
258 ExecAssignExprContext(estate, planstate);
259
260 /*
261 * Get info about values list, initialize scan slot with it.
262 */
263 tupdesc = ExecTypeFromExprList((List *) linitial(node->values_lists));
264 ExecInitScanTupleSlot(estate, &scanstate->ss, tupdesc, &TTSOpsVirtual);
265
266 /*
267 * Initialize result type and projection.
268 */
269 ExecInitResultTypeTL(&scanstate->ss.ps);
270 ExecAssignScanProjectionInfo(&scanstate->ss);
271
272 /*
273 * initialize child expressions
274 */
275 scanstate->ss.ps.qual =
276 ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
277
278 /*
279 * Other node-specific setup
280 */
281 scanstate->curr_idx = -1;
282 scanstate->array_len = list_length(node->values_lists);
283
284 /* convert list of sublists into array of sublists for easy addressing */
285 scanstate->exprlists = (List **)
286 palloc(scanstate->array_len * sizeof(List *));
287 i = 0;
288 foreach(vtl, node->values_lists)
289 {
290 scanstate->exprlists[i++] = (List *) lfirst(vtl);
291 }
292
293 return scanstate;
294}
295
296/* ----------------------------------------------------------------
297 * ExecEndValuesScan
298 *
299 * frees any storage allocated through C routines.
300 * ----------------------------------------------------------------
301 */
302void
303ExecEndValuesScan(ValuesScanState *node)
304{
305 /*
306 * Free both exprcontexts
307 */
308 ExecFreeExprContext(&node->ss.ps);
309 node->ss.ps.ps_ExprContext = node->rowcontext;
310 ExecFreeExprContext(&node->ss.ps);
311
312 /*
313 * clean out the tuple table
314 */
315 if (node->ss.ps.ps_ResultTupleSlot)
316 ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
317 ExecClearTuple(node->ss.ss_ScanTupleSlot);
318}
319
320/* ----------------------------------------------------------------
321 * ExecReScanValuesScan
322 *
323 * Rescans the relation.
324 * ----------------------------------------------------------------
325 */
326void
327ExecReScanValuesScan(ValuesScanState *node)
328{
329 if (node->ss.ps.ps_ResultTupleSlot)
330 ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
331
332 ExecScanReScan(&node->ss);
333
334 node->curr_idx = -1;
335}
336