Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * nodeValuesscan.c
4 : * Support routines for scanning Values lists
5 : * ("VALUES (...), (...), ..." in rangetable).
6 : *
7 : * Portions Copyright (c) 1996-2024, 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 : * ExecReScanValuesScan rescans the values list
22 : */
23 : #include "postgres.h"
24 :
25 : #include "executor/executor.h"
26 : #include "executor/nodeValuesscan.h"
27 : #include "jit/jit.h"
28 : #include "optimizer/clauses.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 222416 : ValuesNext(ValuesScanState *node)
48 : {
49 : TupleTableSlot *slot;
50 : EState *estate;
51 : ExprContext *econtext;
52 : ScanDirection direction;
53 : int curr_idx;
54 :
55 : /*
56 : * get information from the estate and scan state
57 : */
58 222416 : estate = node->ss.ps.state;
59 222416 : direction = estate->es_direction;
60 222416 : slot = node->ss.ss_ScanTupleSlot;
61 222416 : econtext = node->rowcontext;
62 :
63 : /*
64 : * Get the next tuple. Return NULL if no more tuples.
65 : */
66 222416 : if (ScanDirectionIsForward(direction))
67 : {
68 222416 : if (node->curr_idx < node->array_len)
69 222416 : node->curr_idx++;
70 : }
71 : else
72 : {
73 0 : if (node->curr_idx >= 0)
74 0 : node->curr_idx--;
75 : }
76 :
77 : /*
78 : * Always clear the result slot; this is appropriate if we are at the end
79 : * of the data, and if we're not, we still need it as the first step of
80 : * the store-virtual-tuple protocol. It seems wise to clear the slot
81 : * before we reset the context it might have pointers into.
82 : */
83 222416 : ExecClearTuple(slot);
84 :
85 222416 : curr_idx = node->curr_idx;
86 222416 : if (curr_idx >= 0 && curr_idx < node->array_len)
87 : {
88 154038 : List *exprlist = node->exprlists[curr_idx];
89 154038 : List *exprstatelist = node->exprstatelists[curr_idx];
90 : MemoryContext oldContext;
91 : Datum *values;
92 : bool *isnull;
93 : ListCell *lc;
94 : int resind;
95 :
96 : /*
97 : * Get rid of any prior cycle's leftovers. We use ReScanExprContext
98 : * not just ResetExprContext because we want any registered shutdown
99 : * callbacks to be called.
100 : */
101 154038 : ReScanExprContext(econtext);
102 :
103 : /*
104 : * Do per-VALUES-row work in the per-tuple context.
105 : */
106 154038 : oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
107 :
108 : /*
109 : * Unless we already made the expression eval state for this row,
110 : * build it in the econtext's per-tuple memory. This is a tad
111 : * unusual, but we want to delete the eval state again when we move to
112 : * the next row, to avoid growth of memory requirements over a long
113 : * values list. For rows in which that won't work, we already built
114 : * the eval state at plan startup.
115 : */
116 154038 : if (exprstatelist == NIL)
117 : {
118 : /*
119 : * Pass parent as NULL, not my plan node, because we don't want
120 : * anything in this transient state linking into permanent state.
121 : * The only expression type that might wish to do so is a SubPlan,
122 : * and we already checked that there aren't any.
123 : *
124 : * Note that passing parent = NULL also disables JIT compilation
125 : * of the expressions, which is a win, because they're only going
126 : * to be used once under normal circumstances.
127 : */
128 153978 : exprstatelist = ExecInitExprList(exprlist, NULL);
129 : }
130 :
131 : /* parser should have checked all sublists are the same length */
132 : Assert(list_length(exprstatelist) == slot->tts_tupleDescriptor->natts);
133 :
134 : /*
135 : * Compute the expressions and build a virtual result tuple. We
136 : * already did ExecClearTuple(slot).
137 : */
138 154038 : values = slot->tts_values;
139 154038 : isnull = slot->tts_isnull;
140 :
141 154038 : resind = 0;
142 331874 : foreach(lc, exprstatelist)
143 : {
144 177836 : ExprState *estate = (ExprState *) lfirst(lc);
145 177836 : Form_pg_attribute attr = TupleDescAttr(slot->tts_tupleDescriptor,
146 : resind);
147 :
148 177836 : values[resind] = ExecEvalExpr(estate,
149 : econtext,
150 : &isnull[resind]);
151 :
152 : /*
153 : * We must force any R/W expanded datums to read-only state, in
154 : * case they are multiply referenced in the plan node's output
155 : * expressions, or in case we skip the output projection and the
156 : * output column is multiply referenced in higher plan nodes.
157 : */
158 177836 : values[resind] = MakeExpandedObjectReadOnly(values[resind],
159 : isnull[resind],
160 : attr->attlen);
161 :
162 177836 : resind++;
163 : }
164 :
165 154038 : MemoryContextSwitchTo(oldContext);
166 :
167 : /*
168 : * And return the virtual tuple.
169 : */
170 154038 : ExecStoreVirtualTuple(slot);
171 : }
172 :
173 222416 : return slot;
174 : }
175 :
176 : /*
177 : * ValuesRecheck -- access method routine to recheck a tuple in EvalPlanQual
178 : */
179 : static bool
180 4 : ValuesRecheck(ValuesScanState *node, TupleTableSlot *slot)
181 : {
182 : /* nothing to check */
183 4 : return true;
184 : }
185 :
186 : /* ----------------------------------------------------------------
187 : * ExecValuesScan(node)
188 : *
189 : * Scans the values lists sequentially and returns the next qualifying
190 : * tuple.
191 : * We call the ExecScan() routine and pass it the appropriate
192 : * access method functions.
193 : * ----------------------------------------------------------------
194 : */
195 : static TupleTableSlot *
196 221456 : ExecValuesScan(PlanState *pstate)
197 : {
198 221456 : ValuesScanState *node = castNode(ValuesScanState, pstate);
199 :
200 221456 : return ExecScan(&node->ss,
201 : (ExecScanAccessMtd) ValuesNext,
202 : (ExecScanRecheckMtd) ValuesRecheck);
203 : }
204 :
205 : /* ----------------------------------------------------------------
206 : * ExecInitValuesScan
207 : * ----------------------------------------------------------------
208 : */
209 : ValuesScanState *
210 8712 : ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags)
211 : {
212 : ValuesScanState *scanstate;
213 : TupleDesc tupdesc;
214 : ListCell *vtl;
215 : int i;
216 : PlanState *planstate;
217 :
218 : /*
219 : * ValuesScan should not have any children.
220 : */
221 : Assert(outerPlan(node) == NULL);
222 : Assert(innerPlan(node) == NULL);
223 :
224 : /*
225 : * create new ScanState for node
226 : */
227 8712 : scanstate = makeNode(ValuesScanState);
228 8712 : scanstate->ss.ps.plan = (Plan *) node;
229 8712 : scanstate->ss.ps.state = estate;
230 8712 : scanstate->ss.ps.ExecProcNode = ExecValuesScan;
231 :
232 : /*
233 : * Miscellaneous initialization
234 : */
235 8712 : planstate = &scanstate->ss.ps;
236 :
237 : /*
238 : * Create expression contexts. We need two, one for per-sublist
239 : * processing and one for execScan.c to use for quals and projections. We
240 : * cheat a little by using ExecAssignExprContext() to build both.
241 : */
242 8712 : ExecAssignExprContext(estate, planstate);
243 8712 : scanstate->rowcontext = planstate->ps_ExprContext;
244 8712 : ExecAssignExprContext(estate, planstate);
245 :
246 : /*
247 : * Get info about values list, initialize scan slot with it.
248 : */
249 8712 : tupdesc = ExecTypeFromExprList((List *) linitial(node->values_lists));
250 8712 : ExecInitScanTupleSlot(estate, &scanstate->ss, tupdesc, &TTSOpsVirtual);
251 :
252 : /*
253 : * Initialize result type and projection.
254 : */
255 8712 : ExecInitResultTypeTL(&scanstate->ss.ps);
256 8712 : ExecAssignScanProjectionInfo(&scanstate->ss);
257 :
258 : /*
259 : * initialize child expressions
260 : */
261 8712 : scanstate->ss.ps.qual =
262 8712 : ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
263 :
264 : /*
265 : * Other node-specific setup
266 : */
267 8712 : scanstate->curr_idx = -1;
268 8712 : scanstate->array_len = list_length(node->values_lists);
269 :
270 : /*
271 : * Convert the list of expression sublists into an array for easier
272 : * addressing at runtime. Also, detect whether any sublists contain
273 : * SubPlans; for just those sublists, go ahead and do expression
274 : * initialization. (This avoids problems with SubPlans wanting to connect
275 : * themselves up to the outer plan tree. Notably, EXPLAIN won't see the
276 : * subplans otherwise; also we will have troubles with dangling pointers
277 : * and/or leaked resources if we try to handle SubPlans the same as
278 : * simpler expressions.)
279 : */
280 8712 : scanstate->exprlists = (List **)
281 8712 : palloc(scanstate->array_len * sizeof(List *));
282 8712 : scanstate->exprstatelists = (List **)
283 8712 : palloc0(scanstate->array_len * sizeof(List *));
284 8712 : i = 0;
285 43366 : foreach(vtl, node->values_lists)
286 : {
287 34654 : List *exprs = lfirst_node(List, vtl);
288 :
289 34654 : scanstate->exprlists[i] = exprs;
290 :
291 : /*
292 : * We can avoid the cost of a contain_subplans() scan in the simple
293 : * case where there are no SubPlans anywhere.
294 : */
295 35072 : if (estate->es_subplanstates &&
296 418 : contain_subplans((Node *) exprs))
297 : {
298 : int saved_jit_flags;
299 :
300 : /*
301 : * As these expressions are only used once, disable JIT for them.
302 : * This is worthwhile because it's common to insert significant
303 : * amounts of data via VALUES(). Note that this doesn't prevent
304 : * use of JIT *within* a subplan, since that's initialized
305 : * separately; this just affects the upper-level subexpressions.
306 : */
307 18 : saved_jit_flags = estate->es_jit_flags;
308 18 : estate->es_jit_flags = PGJIT_NONE;
309 :
310 18 : scanstate->exprstatelists[i] = ExecInitExprList(exprs,
311 : &scanstate->ss.ps);
312 :
313 18 : estate->es_jit_flags = saved_jit_flags;
314 : }
315 34654 : i++;
316 : }
317 :
318 8712 : return scanstate;
319 : }
320 :
321 : /* ----------------------------------------------------------------
322 : * ExecReScanValuesScan
323 : *
324 : * Rescans the relation.
325 : * ----------------------------------------------------------------
326 : */
327 : void
328 60398 : ExecReScanValuesScan(ValuesScanState *node)
329 : {
330 60398 : if (node->ss.ps.ps_ResultTupleSlot)
331 12 : ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
332 :
333 60398 : ExecScanReScan(&node->ss);
334 :
335 60398 : node->curr_idx = -1;
336 60398 : }
|