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