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  * ExecEndValuesScan releases any storage allocated.
22  * ExecReScanValuesScan rescans the values list
23  */
24 #include "postgres.h"
25 
26 #include "executor/executor.h"
28 #include "jit/jit.h"
29 #include "optimizer/clauses.h"
30 #include "utils/expandeddatum.h"
31 
32 
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 *
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  estate = node->ss.ps.state;
60  direction = estate->es_direction;
61  slot = node->ss.ss_ScanTupleSlot;
62  econtext = node->rowcontext;
63 
64  /*
65  * Get the next tuple. Return NULL if no more tuples.
66  */
67  if (ScanDirectionIsForward(direction))
68  {
69  if (node->curr_idx < node->array_len)
70  node->curr_idx++;
71  }
72  else
73  {
74  if (node->curr_idx >= 0)
75  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  */
84  ExecClearTuple(slot);
85 
86  curr_idx = node->curr_idx;
87  if (curr_idx >= 0 && curr_idx < node->array_len)
88  {
89  List *exprlist = node->exprlists[curr_idx];
90  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  */
102  ReScanExprContext(econtext);
103 
104  /*
105  * Do per-VALUES-row work in the per-tuple context.
106  */
107  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  */
117  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  exprstatelist = ExecInitExprList(exprlist, NULL);
130  }
131 
132  /* parser should have checked all sublists are the same length */
133  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  values = slot->tts_values;
140  isnull = slot->tts_isnull;
141 
142  resind = 0;
143  foreach(lc, exprstatelist)
144  {
145  ExprState *estate = (ExprState *) lfirst(lc);
147  resind);
148 
149  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  */
159  values[resind] = MakeExpandedObjectReadOnly(values[resind],
160  isnull[resind],
161  attr->attlen);
162 
163  resind++;
164  }
165 
166  MemoryContextSwitchTo(oldContext);
167 
168  /*
169  * And return the virtual tuple.
170  */
171  ExecStoreVirtualTuple(slot);
172  }
173 
174  return slot;
175 }
176 
177 /*
178  * ValuesRecheck -- access method routine to recheck a tuple in EvalPlanQual
179  */
180 static bool
182 {
183  /* nothing to check */
184  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 *
198 {
199  ValuesScanState *node = castNode(ValuesScanState, pstate);
200 
201  return ExecScan(&node->ss,
204 }
205 
206 /* ----------------------------------------------------------------
207  * ExecInitValuesScan
208  * ----------------------------------------------------------------
209  */
211 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  Assert(outerPlan(node) == NULL);
223  Assert(innerPlan(node) == NULL);
224 
225  /*
226  * create new ScanState for node
227  */
228  scanstate = makeNode(ValuesScanState);
229  scanstate->ss.ps.plan = (Plan *) node;
230  scanstate->ss.ps.state = estate;
231  scanstate->ss.ps.ExecProcNode = ExecValuesScan;
232 
233  /*
234  * Miscellaneous initialization
235  */
236  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  */
243  ExecAssignExprContext(estate, planstate);
244  scanstate->rowcontext = planstate->ps_ExprContext;
245  ExecAssignExprContext(estate, planstate);
246 
247  /*
248  * Get info about values list, initialize scan slot with it.
249  */
250  tupdesc = ExecTypeFromExprList((List *) linitial(node->values_lists));
251  ExecInitScanTupleSlot(estate, &scanstate->ss, tupdesc, &TTSOpsVirtual);
252 
253  /*
254  * Initialize result type and projection.
255  */
256  ExecInitResultTypeTL(&scanstate->ss.ps);
257  ExecAssignScanProjectionInfo(&scanstate->ss);
258 
259  /*
260  * initialize child expressions
261  */
262  scanstate->ss.ps.qual =
263  ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
264 
265  /*
266  * Other node-specific setup
267  */
268  scanstate->curr_idx = -1;
269  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  */
281  scanstate->exprlists = (List **)
282  palloc(scanstate->array_len * sizeof(List *));
283  scanstate->exprstatelists = (List **)
284  palloc0(scanstate->array_len * sizeof(List *));
285  i = 0;
286  foreach(vtl, node->values_lists)
287  {
288  List *exprs = lfirst_node(List, vtl);
289 
290  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  if (estate->es_subplanstates &&
297  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  saved_jit_flags = estate->es_jit_flags;
309  estate->es_jit_flags = PGJIT_NONE;
310 
311  scanstate->exprstatelists[i] = ExecInitExprList(exprs,
312  &scanstate->ss.ps);
313 
314  estate->es_jit_flags = saved_jit_flags;
315  }
316  i++;
317  }
318 
319  return scanstate;
320 }
321 
322 /* ----------------------------------------------------------------
323  * ExecReScanValuesScan
324  *
325  * Rescans the relation.
326  * ----------------------------------------------------------------
327  */
328 void
330 {
331  if (node->ss.ps.ps_ResultTupleSlot)
333 
334  ExecScanReScan(&node->ss);
335 
336  node->curr_idx = -1;
337 }
static Datum values[MAXATTR]
Definition: bootstrap.c:152
bool contain_subplans(Node *clause)
Definition: clauses.c:329
List * ExecInitExprList(List *nodes, PlanState *parent)
Definition: execExpr.c:319
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition: execExpr.c:213
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:83
TupleTableSlot * ExecStoreVirtualTuple(TupleTableSlot *slot)
Definition: execTuples.c:1551
void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1810
void ExecInitResultTypeTL(PlanState *planstate)
Definition: execTuples.c:1754
TupleDesc ExecTypeFromExprList(List *exprList)
Definition: execTuples.c:1996
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:473
bool(* ExecScanRecheckMtd)(ScanState *node, TupleTableSlot *slot)
Definition: executor.h:474
static Datum ExecEvalExpr(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:333
#define MakeExpandedObjectReadOnly(d, isnull, typlen)
int i
Definition: isn.c:73
#define PGJIT_NONE
Definition: jit.h:19
Assert(fmt[strlen(fmt) - 1] !='\n')
void * palloc0(Size size)
Definition: mcxt.c:1334
void * palloc(Size size)
Definition: mcxt.c:1304
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
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
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:181
#define outerPlan(node)
Definition: plannodes.h:182
uintptr_t Datum
Definition: postgres.h:64
#define ScanDirectionIsForward(direction)
Definition: sdir.h:64
ScanDirection
Definition: sdir.h:25
ScanDirection es_direction
Definition: execnodes.h:621
int es_jit_flags
Definition: execnodes.h:713
List * es_subplanstates
Definition: execnodes.h:680
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:263
Definition: pg_list.h:54
Definition: nodes.h:129
ExprState * qual
Definition: execnodes.h:1064
Plan * plan
Definition: execnodes.h:1043
EState * state
Definition: execnodes.h:1045
ExprContext * ps_ExprContext
Definition: execnodes.h:1082
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:1081
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:1049
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1486
PlanState ps
Definition: execnodes.h:1483
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:1863
List ** exprlists
Definition: execnodes.h:1865
List ** exprstatelists
Definition: execnodes.h:1866
ExprContext * rowcontext
Definition: execnodes.h:1864
Scan scan
Definition: plannodes.h:620
List * values_lists
Definition: plannodes.h:621
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:433