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-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"
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  */
46 static 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;
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  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  */
170  ExecStoreVirtualTuple(slot);
171  }
172 
173  return slot;
174 }
175 
176 /*
177  * ValuesRecheck -- access method routine to recheck a tuple in EvalPlanQual
178  */
179 static 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  */
195 static TupleTableSlot *
197 {
198  ValuesScanState *node = castNode(ValuesScanState, pstate);
199 
200  return ExecScan(&node->ss,
203 }
204 
205 /* ----------------------------------------------------------------
206  * ExecInitValuesScan
207  * ----------------------------------------------------------------
208  */
210 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  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  */
327 void
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:150
#define Assert(condition)
Definition: c.h:861
bool contain_subplans(Node *clause)
Definition: clauses.c:330
List * ExecInitExprList(List *nodes, PlanState *parent)
Definition: execExpr.c:330
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition: execExpr.c:224
TupleTableSlot * ExecScan(ScanState *node, ExecScanAccessMtd accessMtd, ExecScanRecheckMtd recheckMtd)
Definition: execScan.c:156
void ExecAssignScanProjectionInfo(ScanState *node)
Definition: execScan.c:270
void ExecScanReScan(ScanState *node)
Definition: execScan.c:297
const TupleTableSlotOps TTSOpsVirtual
Definition: execTuples.c:84
TupleTableSlot * ExecStoreVirtualTuple(TupleTableSlot *slot)
Definition: execTuples.c:1639
void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1898
void ExecInitResultTypeTL(PlanState *planstate)
Definition: execTuples.c:1842
TupleDesc ExecTypeFromExprList(List *exprList)
Definition: execTuples.c:2084
void ReScanExprContext(ExprContext *econtext)
Definition: execUtils.c:441
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition: execUtils.c:483
TupleTableSlot *(* ExecScanAccessMtd)(ScanState *node)
Definition: executor.h:484
bool(* ExecScanRecheckMtd)(ScanState *node, TupleTableSlot *slot)
Definition: executor.h:485
static Datum ExecEvalExpr(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:344
#define MakeExpandedObjectReadOnly(d, isnull, typlen)
int i
Definition: isn.c:73
#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)
static TupleTableSlot * ValuesNext(ValuesScanState *node)
ValuesScanState * ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags)
static bool ValuesRecheck(ValuesScanState *node, TupleTableSlot *slot)
static TupleTableSlot * ExecValuesScan(PlanState *pstate)
#define makeNode(_type_)
Definition: nodes.h:155
#define castNode(_type_, nodeptr)
Definition: nodes.h:176
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:209
#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:182
#define outerPlan(node)
Definition: plannodes.h:183
uintptr_t Datum
Definition: postgres.h:64
MemoryContextSwitchTo(old_ctx)
#define ScanDirectionIsForward(direction)
Definition: sdir.h:64
ScanDirection
Definition: sdir.h:25
ScanDirection es_direction
Definition: execnodes.h:631
int es_jit_flags
Definition: execnodes.h:723
List * es_subplanstates
Definition: execnodes.h:690
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:266
Definition: pg_list.h:54
Definition: nodes.h:129
ExprState * qual
Definition: execnodes.h:1144
Plan * plan
Definition: execnodes.h:1123
EState * state
Definition: execnodes.h:1125
ExprContext * ps_ExprContext
Definition: execnodes.h:1162
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:1161
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:1129
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1573
PlanState ps
Definition: execnodes.h:1570
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:1973
List ** exprlists
Definition: execnodes.h:1975
List ** exprstatelists
Definition: execnodes.h:1976
ExprContext * rowcontext
Definition: execnodes.h:1974
Scan scan
Definition: plannodes.h:623
List * values_lists
Definition: plannodes.h:624
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:454