PostgreSQL Source Code git master
nodeValuesscan.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * nodeValuesscan.c
4 * Support routines for scanning Values lists
5 * ("VALUES (...), (...), ..." in rangetable).
6 *
7 * Portions Copyright (c) 1996-2025, 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"
27#include "jit/jit.h"
28#include "optimizer/clauses.h"
29#include "utils/expandeddatum.h"
30
31
33
34
35/* ----------------------------------------------------------------
36 * Scan Support
37 * ----------------------------------------------------------------
38 */
39
40/* ----------------------------------------------------------------
41 * ValuesNext
42 *
43 * This is a workhorse for ExecValuesScan
44 * ----------------------------------------------------------------
45 */
46static TupleTableSlot *
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 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 }
71 else
72 {
73 if (node->curr_idx >= 0)
74 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 ExecClearTuple(slot);
84
85 curr_idx = node->curr_idx;
86 if (curr_idx >= 0 && curr_idx < node->array_len)
87 {
88 List *exprlist = node->exprlists[curr_idx];
89 List *exprstatelist = node->exprstatelists[curr_idx];
90 MemoryContext oldContext;
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 ReScanExprContext(econtext);
102
103 /*
104 * Do per-VALUES-row work in the per-tuple context.
105 */
106 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 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 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 values = slot->tts_values;
139 isnull = slot->tts_isnull;
140
141 resind = 0;
142 foreach(lc, exprstatelist)
143 {
144 ExprState *estate = (ExprState *) lfirst(lc);
146 resind);
147
148 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 values[resind] = MakeExpandedObjectReadOnly(values[resind],
159 isnull[resind],
160 attr->attlen);
161
162 resind++;
163 }
164
165 MemoryContextSwitchTo(oldContext);
166
167 /*
168 * And return the virtual tuple.
169 */
171 }
172
173 return slot;
174}
175
176/*
177 * ValuesRecheck -- access method routine to recheck a tuple in EvalPlanQual
178 */
179static bool
181{
182 /* nothing to check */
183 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 */
195static TupleTableSlot *
197{
199
200 return ExecScan(&node->ss,
203}
204
205/* ----------------------------------------------------------------
206 * ExecInitValuesScan
207 * ----------------------------------------------------------------
208 */
210ExecInitValuesScan(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 scanstate = makeNode(ValuesScanState);
228 scanstate->ss.ps.plan = (Plan *) node;
229 scanstate->ss.ps.state = estate;
230 scanstate->ss.ps.ExecProcNode = ExecValuesScan;
231
232 /*
233 * Miscellaneous initialization
234 */
235 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 ExecAssignExprContext(estate, planstate);
243 scanstate->rowcontext = planstate->ps_ExprContext;
244 ExecAssignExprContext(estate, planstate);
245
246 /*
247 * Get info about values list, initialize scan slot with it.
248 */
249 tupdesc = ExecTypeFromExprList((List *) linitial(node->values_lists));
250 ExecInitScanTupleSlot(estate, &scanstate->ss, tupdesc, &TTSOpsVirtual);
251
252 /*
253 * Initialize result type and projection.
254 */
255 ExecInitResultTypeTL(&scanstate->ss.ps);
256 ExecAssignScanProjectionInfo(&scanstate->ss);
257
258 /*
259 * initialize child expressions
260 */
261 scanstate->ss.ps.qual =
262 ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
263
264 /*
265 * Other node-specific setup
266 */
267 scanstate->curr_idx = -1;
268 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 scanstate->exprlists = (List **)
281 palloc(scanstate->array_len * sizeof(List *));
282 scanstate->exprstatelists = (List **)
283 palloc0(scanstate->array_len * sizeof(List *));
284 i = 0;
285 foreach(vtl, node->values_lists)
286 {
287 List *exprs = lfirst_node(List, vtl);
288
289 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 if (estate->es_subplanstates &&
296 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 saved_jit_flags = estate->es_jit_flags;
308 estate->es_jit_flags = PGJIT_NONE;
309
310 scanstate->exprstatelists[i] = ExecInitExprList(exprs,
311 &scanstate->ss.ps);
312
313 estate->es_jit_flags = saved_jit_flags;
314 }
315 i++;
316 }
317
318 return scanstate;
319}
320
321/* ----------------------------------------------------------------
322 * ExecReScanValuesScan
323 *
324 * Rescans the relation.
325 * ----------------------------------------------------------------
326 */
327void
329{
330 if (node->ss.ps.ps_ResultTupleSlot)
332
333 ExecScanReScan(&node->ss);
334
335 node->curr_idx = -1;
336}
static Datum values[MAXATTR]
Definition: bootstrap.c:151
#define Assert(condition)
Definition: c.h:815
bool contain_subplans(Node *clause)
Definition: clauses.c:329
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition: execExpr.c:229
List * ExecInitExprList(List *nodes, PlanState *parent)
Definition: execExpr.c:335
TupleTableSlot * ExecScan(ScanState *node, ExecScanAccessMtd accessMtd, ExecScanRecheckMtd recheckMtd)
Definition: execScan.c:47
void ExecAssignScanProjectionInfo(ScanState *node)
Definition: execScan.c:81
void ExecScanReScan(ScanState *node)
Definition: execScan.c:108
const TupleTableSlotOps TTSOpsVirtual
Definition: execTuples.c:84
TupleTableSlot * ExecStoreVirtualTuple(TupleTableSlot *slot)
Definition: execTuples.c:1739
void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1998
void ExecInitResultTypeTL(PlanState *planstate)
Definition: execTuples.c:1942
TupleDesc ExecTypeFromExprList(List *exprList)
Definition: execTuples.c:2184
void ReScanExprContext(ExprContext *econtext)
Definition: execUtils.c:444
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition: execUtils.c:486
bool(* ExecScanRecheckMtd)(ScanState *node, TupleTableSlot *slot)
Definition: executor.h:487
TupleTableSlot *(* ExecScanAccessMtd)(ScanState *node)
Definition: executor.h:486
static Datum ExecEvalExpr(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:346
#define MakeExpandedObjectReadOnly(d, isnull, typlen)
int i
Definition: isn.c:72
#define PGJIT_NONE
Definition: jit.h:19
void * palloc0(Size size)
Definition: mcxt.c:1347
void * palloc(Size size)
Definition: mcxt.c:1317
void ExecReScanValuesScan(ValuesScanState *node)
ValuesScanState * ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags)
static TupleTableSlot * ValuesNext(ValuesScanState *node)
static TupleTableSlot * ExecValuesScan(PlanState *pstate)
static bool ValuesRecheck(ValuesScanState *node, TupleTableSlot *slot)
#define makeNode(_type_)
Definition: nodes.h:155
#define castNode(_type_, nodeptr)
Definition: nodes.h:176
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
#define lfirst(lc)
Definition: pg_list.h:172
#define lfirst_node(type, lc)
Definition: pg_list.h:176
static int list_length(const List *l)
Definition: pg_list.h:152
#define NIL
Definition: pg_list.h:68
#define linitial(l)
Definition: pg_list.h:178
#define innerPlan(node)
Definition: plannodes.h:230
#define outerPlan(node)
Definition: plannodes.h:231
uintptr_t Datum
Definition: postgres.h:69
#define ScanDirectionIsForward(direction)
Definition: sdir.h:64
ScanDirection
Definition: sdir.h:25
int16 attlen
Definition: tupdesc.h:71
ScanDirection es_direction
Definition: execnodes.h:649
int es_jit_flags
Definition: execnodes.h:753
List * es_subplanstates
Definition: execnodes.h:715
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:275
Definition: pg_list.h:54
Definition: nodes.h:129
ExprState * qual
Definition: execnodes.h:1171
Plan * plan
Definition: execnodes.h:1150
EState * state
Definition: execnodes.h:1152
ExprContext * ps_ExprContext
Definition: execnodes.h:1189
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:1188
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:1156
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1609
PlanState ps
Definition: execnodes.h:1606
TupleDesc tts_tupleDescriptor
Definition: tuptable.h:123
bool * tts_isnull
Definition: tuptable.h:127
Datum * tts_values
Definition: tuptable.h:125
ScanState ss
Definition: execnodes.h:2007
List ** exprlists
Definition: execnodes.h:2009
List ** exprstatelists
Definition: execnodes.h:2010
ExprContext * rowcontext
Definition: execnodes.h:2008
Scan scan
Definition: plannodes.h:728
List * values_lists
Definition: plannodes.h:730
static CompactAttribute * TupleDescCompactAttr(TupleDesc tupdesc, int i)
Definition: tupdesc.h:169
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:454