PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
execScan.c File Reference
#include "postgres.h"
#include "executor/executor.h"
#include "miscadmin.h"
Include dependency graph for execScan.c:

Go to the source code of this file.

Functions

static TupleTableSlotExecScanFetch (ScanState *node, ExecScanAccessMtd accessMtd, ExecScanRecheckMtd recheckMtd)
 
TupleTableSlotExecScan (ScanState *node, ExecScanAccessMtd accessMtd, ExecScanRecheckMtd recheckMtd)
 
void ExecAssignScanProjectionInfo (ScanState *node)
 
void ExecAssignScanProjectionInfoWithVarno (ScanState *node, int varno)
 
void ExecScanReScan (ScanState *node)
 

Function Documentation

◆ ExecAssignScanProjectionInfo()

void ExecAssignScanProjectionInfo ( ScanState node)

◆ ExecAssignScanProjectionInfoWithVarno()

void ExecAssignScanProjectionInfoWithVarno ( ScanState node,
int  varno 
)

◆ ExecScan()

TupleTableSlot * ExecScan ( ScanState node,
ExecScanAccessMtd  accessMtd,
ExecScanRecheckMtd  recheckMtd 
)

Definition at line 156 of file execScan.c.

159{
160 ExprContext *econtext;
161 ExprState *qual;
162 ProjectionInfo *projInfo;
163
164 /*
165 * Fetch data from node
166 */
167 qual = node->ps.qual;
168 projInfo = node->ps.ps_ProjInfo;
169 econtext = node->ps.ps_ExprContext;
170
171 /* interrupt checks are in ExecScanFetch */
172
173 /*
174 * If we have neither a qual to check nor a projection to do, just skip
175 * all the overhead and return the raw scan tuple.
176 */
177 if (!qual && !projInfo)
178 {
179 ResetExprContext(econtext);
180 return ExecScanFetch(node, accessMtd, recheckMtd);
181 }
182
183 /*
184 * Reset per-tuple memory context to free any expression evaluation
185 * storage allocated in the previous tuple cycle.
186 */
187 ResetExprContext(econtext);
188
189 /*
190 * get a tuple from the access method. Loop until we obtain a tuple that
191 * passes the qualification.
192 */
193 for (;;)
194 {
195 TupleTableSlot *slot;
196
197 slot = ExecScanFetch(node, accessMtd, recheckMtd);
198
199 /*
200 * if the slot returned by the accessMtd contains NULL, then it means
201 * there is nothing more to scan so we just return an empty slot,
202 * being careful to use the projection result slot so it has correct
203 * tupleDesc.
204 */
205 if (TupIsNull(slot))
206 {
207 if (projInfo)
208 return ExecClearTuple(projInfo->pi_state.resultslot);
209 else
210 return slot;
211 }
212
213 /*
214 * place the current tuple into the expr context
215 */
216 econtext->ecxt_scantuple = slot;
217
218 /*
219 * check that the current tuple satisfies the qual-clause
220 *
221 * check for non-null qual here to avoid a function call to ExecQual()
222 * when the qual is null ... saves only a few cycles, but they add up
223 * ...
224 */
225 if (qual == NULL || ExecQual(qual, econtext))
226 {
227 /*
228 * Found a satisfactory scan tuple.
229 */
230 if (projInfo)
231 {
232 /*
233 * Form a projection tuple, store it in the result tuple slot
234 * and return it.
235 */
236 return ExecProject(projInfo);
237 }
238 else
239 {
240 /*
241 * Here, we aren't projecting, so just return scan tuple.
242 */
243 return slot;
244 }
245 }
246 else
247 InstrCountFiltered1(node, 1);
248
249 /*
250 * Tuple fails qual, so free per-tuple memory and try again.
251 */
252 ResetExprContext(econtext);
253 }
254}
static TupleTableSlot * ExecScanFetch(ScanState *node, ExecScanAccessMtd accessMtd, ExecScanRecheckMtd recheckMtd)
Definition: execScan.c:34
#define InstrCountFiltered1(node, delta)
Definition: execnodes.h:1230
static TupleTableSlot * ExecProject(ProjectionInfo *projInfo)
Definition: executor.h:389
#define ResetExprContext(econtext)
Definition: executor.h:557
static bool ExecQual(ExprState *state, ExprContext *econtext)
Definition: executor.h:426
TupleTableSlot * ecxt_scantuple
Definition: execnodes.h:258
TupleTableSlot * resultslot
Definition: execnodes.h:97
ExprState * qual
Definition: execnodes.h:1147
ExprContext * ps_ExprContext
Definition: execnodes.h:1165
ProjectionInfo * ps_ProjInfo
Definition: execnodes.h:1166
ExprState pi_state
Definition: execnodes.h:365
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:454
#define TupIsNull(slot)
Definition: tuptable.h:306

References ExprContext::ecxt_scantuple, ExecClearTuple(), ExecProject(), ExecQual(), ExecScanFetch(), InstrCountFiltered1, ProjectionInfo::pi_state, ScanState::ps, PlanState::ps_ExprContext, PlanState::ps_ProjInfo, PlanState::qual, ResetExprContext, ExprState::resultslot, and TupIsNull.

Referenced by ExecBitmapHeapScan(), ExecCteScan(), ExecForeignScan(), ExecFunctionScan(), ExecIndexOnlyScan(), ExecIndexScan(), ExecNamedTuplestoreScan(), ExecSampleScan(), ExecSeqScan(), ExecSubqueryScan(), ExecTableFuncScan(), ExecTidRangeScan(), ExecTidScan(), ExecValuesScan(), and ExecWorkTableScan().

◆ ExecScanFetch()

static TupleTableSlot * ExecScanFetch ( ScanState node,
ExecScanAccessMtd  accessMtd,
ExecScanRecheckMtd  recheckMtd 
)
inlinestatic

Definition at line 34 of file execScan.c.

37{
38 EState *estate = node->ps.state;
39
41
42 if (estate->es_epq_active != NULL)
43 {
44 EPQState *epqstate = estate->es_epq_active;
45
46 /*
47 * We are inside an EvalPlanQual recheck. Return the test tuple if
48 * one is available, after rechecking any access-method-specific
49 * conditions.
50 */
51 Index scanrelid = ((Scan *) node->ps.plan)->scanrelid;
52
53 if (scanrelid == 0)
54 {
55 /*
56 * This is a ForeignScan or CustomScan which has pushed down a
57 * join to the remote side. The recheck method is responsible not
58 * only for rechecking the scan/join quals but also for storing
59 * the correct tuple in the slot.
60 */
61
62 TupleTableSlot *slot = node->ss_ScanTupleSlot;
63
64 if (!(*recheckMtd) (node, slot))
65 ExecClearTuple(slot); /* would not be returned by scan */
66 return slot;
67 }
68 else if (epqstate->relsubs_done[scanrelid - 1])
69 {
70 /*
71 * Return empty slot, as either there is no EPQ tuple for this rel
72 * or we already returned it.
73 */
74
75 TupleTableSlot *slot = node->ss_ScanTupleSlot;
76
77 return ExecClearTuple(slot);
78 }
79 else if (epqstate->relsubs_slot[scanrelid - 1] != NULL)
80 {
81 /*
82 * Return replacement tuple provided by the EPQ caller.
83 */
84
85 TupleTableSlot *slot = epqstate->relsubs_slot[scanrelid - 1];
86
87 Assert(epqstate->relsubs_rowmark[scanrelid - 1] == NULL);
88
89 /* Mark to remember that we shouldn't return it again */
90 epqstate->relsubs_done[scanrelid - 1] = true;
91
92 /* Return empty slot if we haven't got a test tuple */
93 if (TupIsNull(slot))
94 return NULL;
95
96 /* Check if it meets the access-method conditions */
97 if (!(*recheckMtd) (node, slot))
98 return ExecClearTuple(slot); /* would not be returned by
99 * scan */
100 return slot;
101 }
102 else if (epqstate->relsubs_rowmark[scanrelid - 1] != NULL)
103 {
104 /*
105 * Fetch and return replacement tuple using a non-locking rowmark.
106 */
107
108 TupleTableSlot *slot = node->ss_ScanTupleSlot;
109
110 /* Mark to remember that we shouldn't return more */
111 epqstate->relsubs_done[scanrelid - 1] = true;
112
113 if (!EvalPlanQualFetchRowMark(epqstate, scanrelid, slot))
114 return NULL;
115
116 /* Return empty slot if we haven't got a test tuple */
117 if (TupIsNull(slot))
118 return NULL;
119
120 /* Check if it meets the access-method conditions */
121 if (!(*recheckMtd) (node, slot))
122 return ExecClearTuple(slot); /* would not be returned by
123 * scan */
124 return slot;
125 }
126 }
127
128 /*
129 * Run the node-type-specific access method function to get the next tuple
130 */
131 return (*accessMtd) (node);
132}
#define Assert(condition)
Definition: c.h:812
unsigned int Index
Definition: c.h:568
bool EvalPlanQualFetchRowMark(EPQState *epqstate, Index rti, TupleTableSlot *slot)
Definition: execMain.c:2635
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:122
ExecAuxRowMark ** relsubs_rowmark
Definition: execnodes.h:1301
TupleTableSlot ** relsubs_slot
Definition: execnodes.h:1273
bool * relsubs_done
Definition: execnodes.h:1308
struct EPQState * es_epq_active
Definition: execnodes.h:707
EState * state
Definition: execnodes.h:1128

References Assert, CHECK_FOR_INTERRUPTS, EState::es_epq_active, EvalPlanQualFetchRowMark(), ExecClearTuple(), PlanState::plan, ScanState::ps, EPQState::relsubs_done, EPQState::relsubs_rowmark, EPQState::relsubs_slot, ScanState::ss_ScanTupleSlot, PlanState::state, and TupIsNull.

Referenced by ExecScan().

◆ ExecScanReScan()

void ExecScanReScan ( ScanState node)

Definition at line 297 of file execScan.c.

298{
299 EState *estate = node->ps.state;
300
301 /*
302 * We must clear the scan tuple so that observers (e.g., execCurrent.c)
303 * can tell that this plan node is not positioned on a tuple.
304 */
306
307 /*
308 * Rescan EvalPlanQual tuple(s) if we're inside an EvalPlanQual recheck.
309 * But don't lose the "blocked" status of blocked target relations.
310 */
311 if (estate->es_epq_active != NULL)
312 {
313 EPQState *epqstate = estate->es_epq_active;
314 Index scanrelid = ((Scan *) node->ps.plan)->scanrelid;
315
316 if (scanrelid > 0)
317 epqstate->relsubs_done[scanrelid - 1] =
318 epqstate->relsubs_blocked[scanrelid - 1];
319 else
320 {
321 Bitmapset *relids;
322 int rtindex = -1;
323
324 /*
325 * If an FDW or custom scan provider has replaced the join with a
326 * scan, there are multiple RTIs; reset the epqScanDone flag for
327 * all of them.
328 */
329 if (IsA(node->ps.plan, ForeignScan))
330 relids = ((ForeignScan *) node->ps.plan)->fs_base_relids;
331 else if (IsA(node->ps.plan, CustomScan))
332 relids = ((CustomScan *) node->ps.plan)->custom_relids;
333 else
334 elog(ERROR, "unexpected scan node: %d",
335 (int) nodeTag(node->ps.plan));
336
337 while ((rtindex = bms_next_member(relids, rtindex)) >= 0)
338 {
339 Assert(rtindex > 0);
340 epqstate->relsubs_done[rtindex - 1] =
341 epqstate->relsubs_blocked[rtindex - 1];
342 }
343 }
344 }
345}
int bms_next_member(const Bitmapset *a, int prevbit)
Definition: bitmapset.c:1306
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
#define IsA(nodeptr, _type_)
Definition: nodes.h:158
#define nodeTag(nodeptr)
Definition: nodes.h:133
bool * relsubs_blocked
Definition: execnodes.h:1317

References Assert, bms_next_member(), elog, ERROR, EState::es_epq_active, ExecClearTuple(), IsA, nodeTag, PlanState::plan, ScanState::ps, EPQState::relsubs_blocked, EPQState::relsubs_done, ScanState::ss_ScanTupleSlot, and PlanState::state.

Referenced by ExecReScanBitmapHeapScan(), ExecReScanCteScan(), ExecReScanForeignScan(), ExecReScanFunctionScan(), ExecReScanIndexOnlyScan(), ExecReScanIndexScan(), ExecReScanNamedTuplestoreScan(), ExecReScanSampleScan(), ExecReScanSeqScan(), ExecReScanSubqueryScan(), ExecReScanTableFuncScan(), ExecReScanTidRangeScan(), ExecReScanTidScan(), ExecReScanValuesScan(), and ExecReScanWorkTableScan().