PostgreSQL Source Code git master
Loading...
Searching...
No Matches
execScan.h
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 * execScan.h
3 * Inline-able support functions for Scan nodes
4 *
5 * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
6 * Portions Copyright (c) 1994, Regents of the University of California
7 *
8 * IDENTIFICATION
9 * src/include/executor/execScan.h
10 *-------------------------------------------------------------------------
11 */
12
13#ifndef EXECSCAN_H
14#define EXECSCAN_H
15
16#include "miscadmin.h"
17#include "executor/executor.h"
18#include "executor/instrument.h"
19#include "nodes/execnodes.h"
20
21/*
22 * ExecScanFetch -- check interrupts & fetch next potential tuple
23 *
24 * This routine substitutes a test tuple if inside an EvalPlanQual recheck.
25 * Otherwise, it simply executes the access method's next-tuple routine.
26 *
27 * The pg_attribute_always_inline attribute allows the compiler to inline
28 * this function into its caller. When EPQState is NULL, the EvalPlanQual
29 * logic is completely eliminated at compile time, avoiding unnecessary
30 * run-time checks and code for cases where EPQ is not required.
31 */
34 EPQState *epqstate,
37{
39
40 if (epqstate != NULL)
41 {
42 /*
43 * We are inside an EvalPlanQual recheck. Return the test tuple if
44 * one is available, after rechecking any access-method-specific
45 * conditions.
46 */
47 Index scanrelid = ((Scan *) node->ps.plan)->scanrelid;
48
49 if (scanrelid == 0)
50 {
51 /*
52 * This is a ForeignScan or CustomScan which has pushed down a
53 * join to the remote side. If it is a descendant node in the EPQ
54 * recheck plan tree, run the recheck method function. Otherwise,
55 * run the access method function below.
56 */
57 if (bms_is_member(epqstate->epqParam, node->ps.plan->extParam))
58 {
59 /*
60 * The recheck method is responsible not only for rechecking
61 * the scan/join quals but also for storing the correct tuple
62 * in the slot.
63 */
64
65 TupleTableSlot *slot = node->ss_ScanTupleSlot;
66
67 if (!(*recheckMtd) (node, slot))
68 ExecClearTuple(slot); /* would not be returned by scan */
69 return slot;
70 }
71 }
72 else if (epqstate->relsubs_done[scanrelid - 1])
73 {
74 /*
75 * Return empty slot, as either there is no EPQ tuple for this rel
76 * or we already returned it.
77 */
78
79 TupleTableSlot *slot = node->ss_ScanTupleSlot;
80
81 return ExecClearTuple(slot);
82 }
83 else if (epqstate->relsubs_slot[scanrelid - 1] != NULL)
84 {
85 /*
86 * Return replacement tuple provided by the EPQ caller.
87 */
88
89 TupleTableSlot *slot = epqstate->relsubs_slot[scanrelid - 1];
90
91 Assert(epqstate->relsubs_rowmark[scanrelid - 1] == NULL);
92
93 /* Mark to remember that we shouldn't return it again */
94 epqstate->relsubs_done[scanrelid - 1] = true;
95
96 /* Return empty slot if we haven't got a test tuple */
97 if (TupIsNull(slot))
98 return NULL;
99
100 /* Check if it meets the access-method conditions */
101 if (!(*recheckMtd) (node, slot))
102 return ExecClearTuple(slot); /* would not be returned by
103 * scan */
104 return slot;
105 }
106 else if (epqstate->relsubs_rowmark[scanrelid - 1] != NULL)
107 {
108 /*
109 * Fetch and return replacement tuple using a non-locking rowmark.
110 */
111
112 TupleTableSlot *slot = node->ss_ScanTupleSlot;
113
114 /* Mark to remember that we shouldn't return more */
115 epqstate->relsubs_done[scanrelid - 1] = true;
116
117 if (!EvalPlanQualFetchRowMark(epqstate, scanrelid, slot))
118 return NULL;
119
120 /* Return empty slot if we haven't got a test tuple */
121 if (TupIsNull(slot))
122 return NULL;
123
124 /* Check if it meets the access-method conditions */
125 if (!(*recheckMtd) (node, slot))
126 return ExecClearTuple(slot); /* would not be returned by
127 * scan */
128 return slot;
129 }
130 }
131
132 /*
133 * Run the node-type-specific access method function to get the next tuple
134 */
135 return (*accessMtd) (node);
136}
137
138/* ----------------------------------------------------------------
139 * ExecScanExtended
140 * Scans the relation using the specified 'access method' and returns the
141 * next tuple. Optionally checks the tuple against 'qual' and applies
142 * 'projInfo' if provided.
143 *
144 * The 'recheck method' validates an arbitrary tuple of the relation against
145 * conditions enforced by the access method.
146 *
147 * This function is an alternative to ExecScan, used when callers may omit
148 * 'qual' or 'projInfo'. The pg_attribute_always_inline attribute allows the
149 * compiler to eliminate non-relevant branches at compile time, avoiding
150 * run-time checks in those cases.
151 *
152 * Conditions:
153 * -- The AMI "cursor" is positioned at the previously returned tuple.
154 *
155 * Initial States:
156 * -- The relation is opened for scanning, with the "cursor"
157 * positioned before the first qualifying tuple.
158 * ----------------------------------------------------------------
159 */
162 ExecScanAccessMtd accessMtd, /* function returning a tuple */
164 EPQState *epqstate,
165 ExprState *qual,
167{
168 ExprContext *econtext = node->ps.ps_ExprContext;
169
170 /* interrupt checks are in ExecScanFetch */
171
172 /*
173 * If we have neither a qual to check nor a projection to do, just skip
174 * all the overhead and return the raw scan tuple.
175 */
176 if (!qual && !projInfo)
177 {
178 ResetExprContext(econtext);
179 return ExecScanFetch(node, epqstate, accessMtd, recheckMtd);
180 }
181
182 /*
183 * Reset per-tuple memory context to free any expression evaluation
184 * storage allocated in the previous tuple cycle.
185 */
186 ResetExprContext(econtext);
187
188 /*
189 * get a tuple from the access method. Loop until we obtain a tuple that
190 * passes the qualification.
191 */
192 for (;;)
193 {
194 TupleTableSlot *slot;
195
196 slot = ExecScanFetch(node, epqstate, accessMtd, recheckMtd);
197
198 /*
199 * if the slot returned by the accessMtd contains NULL, then it means
200 * there is nothing more to scan so we just return an empty slot,
201 * being careful to use the projection result slot so it has correct
202 * tupleDesc.
203 */
204 if (TupIsNull(slot))
205 {
206 if (projInfo)
207 return ExecClearTuple(projInfo->pi_state.resultslot);
208 else
209 return slot;
210 }
211
212 /*
213 * place the current tuple into the expr context
214 */
215 econtext->ecxt_scantuple = slot;
216
217 /*
218 * check that the current tuple satisfies the qual-clause
219 *
220 * check for non-null qual here to avoid a function call to ExecQual()
221 * when the qual is null ... saves only a few cycles, but they add up
222 * ...
223 */
224 if (qual == NULL || ExecQual(qual, econtext))
225 {
226 /*
227 * Found a satisfactory scan tuple.
228 */
229 if (projInfo)
230 {
231 /*
232 * Form a projection tuple, store it in the result tuple slot
233 * and return it.
234 */
235 return ExecProject(projInfo);
236 }
237 else
238 {
239 /*
240 * Here, we aren't projecting, so just return scan tuple.
241 */
242 return slot;
243 }
244 }
245 else
246 InstrCountFiltered1(node, 1);
247
248 /*
249 * Tuple fails qual, so free per-tuple memory and try again.
250 */
251 ResetExprContext(econtext);
252 }
253}
254
255#endif /* EXECSCAN_H */
bool bms_is_member(int x, const Bitmapset *a)
Definition bitmapset.c:510
#define Assert(condition)
Definition c.h:945
#define pg_attribute_always_inline
Definition c.h:299
unsigned int Index
Definition c.h:700
bool EvalPlanQualFetchRowMark(EPQState *epqstate, Index rti, TupleTableSlot *slot)
Definition execMain.c:2823
static pg_attribute_always_inline TupleTableSlot * ExecScanFetch(ScanState *node, EPQState *epqstate, ExecScanAccessMtd accessMtd, ExecScanRecheckMtd recheckMtd)
Definition execScan.h:33
static pg_attribute_always_inline TupleTableSlot * ExecScanExtended(ScanState *node, ExecScanAccessMtd accessMtd, ExecScanRecheckMtd recheckMtd, EPQState *epqstate, ExprState *qual, ProjectionInfo *projInfo)
Definition execScan.h:161
#define InstrCountFiltered1(node, delta)
Definition execnodes.h:1281
static TupleTableSlot * ExecProject(ProjectionInfo *projInfo)
Definition executor.h:486
#define ResetExprContext(econtext)
Definition executor.h:654
static bool ExecQual(ExprState *state, ExprContext *econtext)
Definition executor.h:522
bool(* ExecScanRecheckMtd)(ScanState *node, TupleTableSlot *slot)
Definition executor.h:583
TupleTableSlot *(* ExecScanAccessMtd)(ScanState *node)
Definition executor.h:582
#define CHECK_FOR_INTERRUPTS()
Definition miscadmin.h:123
static int fb(int x)
ExecAuxRowMark ** relsubs_rowmark
Definition execnodes.h:1352
TupleTableSlot ** relsubs_slot
Definition execnodes.h:1324
int epqParam
Definition execnodes.h:1314
bool * relsubs_done
Definition execnodes.h:1359
TupleTableSlot * ecxt_scantuple
Definition execnodes.h:284
Plan * plan
Definition execnodes.h:1177
ExprContext * ps_ExprContext
Definition execnodes.h:1216
Bitmapset * extParam
Definition plannodes.h:253
TupleTableSlot * ss_ScanTupleSlot
Definition execnodes.h:1636
PlanState ps
Definition execnodes.h:1633
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition tuptable.h:476
#define TupIsNull(slot)
Definition tuptable.h:325