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 | |
32 | static 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 | */ |
46 | static TupleTableSlot * |
47 | ValuesNext(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 | */ |
193 | static bool |
194 | ValuesRecheck(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 | */ |
209 | static TupleTableSlot * |
210 | ExecValuesScan(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 | */ |
223 | ValuesScanState * |
224 | ExecInitValuesScan(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 | */ |
302 | void |
303 | ExecEndValuesScan(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 | */ |
326 | void |
327 | ExecReScanValuesScan(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 | |