PostgreSQL Source Code git master
Loading...
Searching...
No Matches
nodeSeqscan.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * nodeSeqscan.c
4 * Support routines for sequential scans of relations.
5 *
6 * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
8 *
9 *
10 * IDENTIFICATION
11 * src/backend/executor/nodeSeqscan.c
12 *
13 *-------------------------------------------------------------------------
14 */
15/*
16 * INTERFACE ROUTINES
17 * ExecSeqScan sequentially scans a relation.
18 * ExecSeqNext retrieve next tuple in sequential order.
19 * ExecInitSeqScan creates and initializes a seqscan node.
20 * ExecEndSeqScan releases any storage allocated.
21 * ExecReScanSeqScan rescans the relation
22 *
23 * ExecSeqScanEstimate estimates DSM space needed for parallel scan
24 * ExecSeqScanInitializeDSM initialize DSM for parallel scan
25 * ExecSeqScanReInitializeDSM reinitialize DSM for fresh parallel scan
26 * ExecSeqScanInitializeWorker attach to DSM info in parallel worker
27 */
28#include "postgres.h"
29
30#include "access/relscan.h"
31#include "access/tableam.h"
32#include "executor/execScan.h"
33#include "executor/executor.h"
35#include "utils/rel.h"
36
38
39/* ----------------------------------------------------------------
40 * Scan Support
41 * ----------------------------------------------------------------
42 */
43
44/* ----------------------------------------------------------------
45 * SeqNext
46 *
47 * This is a workhorse for ExecSeqScan
48 * ----------------------------------------------------------------
49 */
52{
53 TableScanDesc scandesc;
54 EState *estate;
55 ScanDirection direction;
56 TupleTableSlot *slot;
57
58 /*
59 * get information from the estate and scan state
60 */
61 scandesc = node->ss.ss_currentScanDesc;
62 estate = node->ss.ps.state;
63 direction = estate->es_direction;
64 slot = node->ss.ss_ScanTupleSlot;
65
66 if (scandesc == NULL)
67 {
68 /*
69 * We reach here if the scan is not parallel, or if we're serially
70 * executing a scan that was planned to be parallel.
71 */
72 scandesc = table_beginscan(node->ss.ss_currentRelation,
73 estate->es_snapshot,
74 0, NULL);
75 node->ss.ss_currentScanDesc = scandesc;
76 }
77
78 /*
79 * get the next tuple from the table
80 */
81 if (table_scan_getnextslot(scandesc, direction, slot))
82 return slot;
83 return NULL;
84}
85
86/*
87 * SeqRecheck -- access method routine to recheck a tuple in EvalPlanQual
88 */
91{
92 /*
93 * Note that unlike IndexScan, SeqScan never use keys in heap_beginscan
94 * (and this is very bad) - so, here we do not check are keys ok or not.
95 */
96 return true;
97}
98
99/* ----------------------------------------------------------------
100 * ExecSeqScan(node)
101 *
102 * Scans the relation sequentially and returns the next qualifying
103 * tuple. This variant is used when there is no es_epq_active, no qual
104 * and no projection. Passing const-NULLs for these to ExecScanExtended
105 * allows the compiler to eliminate the additional code that would
106 * ordinarily be required for the evaluation of these.
107 * ----------------------------------------------------------------
108 */
109static TupleTableSlot *
111{
112 SeqScanState *node = castNode(SeqScanState, pstate);
113
114 Assert(pstate->state->es_epq_active == NULL);
115 Assert(pstate->qual == NULL);
116 Assert(pstate->ps_ProjInfo == NULL);
117
118 return ExecScanExtended(&node->ss,
121 NULL,
122 NULL,
123 NULL);
124}
125
126/*
127 * Variant of ExecSeqScan() but when qual evaluation is required.
128 */
129static TupleTableSlot *
131{
132 SeqScanState *node = castNode(SeqScanState, pstate);
133
134 /*
135 * Use pg_assume() for != NULL tests to make the compiler realize no
136 * runtime check for the field is needed in ExecScanExtended().
137 */
138 Assert(pstate->state->es_epq_active == NULL);
139 pg_assume(pstate->qual != NULL);
140 Assert(pstate->ps_ProjInfo == NULL);
141
142 return ExecScanExtended(&node->ss,
145 NULL,
146 pstate->qual,
147 NULL);
148}
149
150/*
151 * Variant of ExecSeqScan() but when projection is required.
152 */
153static TupleTableSlot *
155{
156 SeqScanState *node = castNode(SeqScanState, pstate);
157
158 Assert(pstate->state->es_epq_active == NULL);
159 Assert(pstate->qual == NULL);
160 pg_assume(pstate->ps_ProjInfo != NULL);
161
162 return ExecScanExtended(&node->ss,
165 NULL,
166 NULL,
167 pstate->ps_ProjInfo);
168}
169
170/*
171 * Variant of ExecSeqScan() but when qual evaluation and projection are
172 * required.
173 */
174static TupleTableSlot *
176{
177 SeqScanState *node = castNode(SeqScanState, pstate);
178
179 Assert(pstate->state->es_epq_active == NULL);
180 pg_assume(pstate->qual != NULL);
181 pg_assume(pstate->ps_ProjInfo != NULL);
182
183 return ExecScanExtended(&node->ss,
186 NULL,
187 pstate->qual,
188 pstate->ps_ProjInfo);
189}
190
191/*
192 * Variant of ExecSeqScan for when EPQ evaluation is required. We don't
193 * bother adding variants of this for with/without qual and projection as
194 * EPQ doesn't seem as exciting a case to optimize for.
195 */
196static TupleTableSlot *
198{
199 SeqScanState *node = castNode(SeqScanState, pstate);
200
201 return ExecScan(&node->ss,
204}
205
206/* ----------------------------------------------------------------
207 * ExecInitSeqScan
208 * ----------------------------------------------------------------
209 */
211ExecInitSeqScan(SeqScan *node, EState *estate, int eflags)
212{
214
215 /*
216 * Once upon a time it was possible to have an outerPlan of a SeqScan, but
217 * not any more.
218 */
219 Assert(outerPlan(node) == NULL);
220 Assert(innerPlan(node) == NULL);
221
222 /*
223 * create state structure
224 */
226 scanstate->ss.ps.plan = (Plan *) node;
227 scanstate->ss.ps.state = estate;
228
229 /*
230 * Miscellaneous initialization
231 *
232 * create expression context for node
233 */
234 ExecAssignExprContext(estate, &scanstate->ss.ps);
235
236 /*
237 * open the scan relation
238 */
239 scanstate->ss.ss_currentRelation =
241 node->scan.scanrelid,
242 eflags);
243
244 /* and create slot with the appropriate rowtype */
245 ExecInitScanTupleSlot(estate, &scanstate->ss,
246 RelationGetDescr(scanstate->ss.ss_currentRelation),
247 table_slot_callbacks(scanstate->ss.ss_currentRelation));
248
249 /*
250 * Initialize result type and projection.
251 */
254
255 /*
256 * initialize child expressions
257 */
258 scanstate->ss.ps.qual =
259 ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
260
261 /*
262 * When EvalPlanQual() is not in use, assign ExecProcNode for this node
263 * based on the presence of qual and projection. Each ExecSeqScan*()
264 * variant is optimized for the specific combination of these conditions.
265 */
266 if (scanstate->ss.ps.state->es_epq_active != NULL)
267 scanstate->ss.ps.ExecProcNode = ExecSeqScanEPQ;
268 else if (scanstate->ss.ps.qual == NULL)
269 {
270 if (scanstate->ss.ps.ps_ProjInfo == NULL)
271 scanstate->ss.ps.ExecProcNode = ExecSeqScan;
272 else
273 scanstate->ss.ps.ExecProcNode = ExecSeqScanWithProject;
274 }
275 else
276 {
277 if (scanstate->ss.ps.ps_ProjInfo == NULL)
278 scanstate->ss.ps.ExecProcNode = ExecSeqScanWithQual;
279 else
280 scanstate->ss.ps.ExecProcNode = ExecSeqScanWithQualProject;
281 }
282
283 return scanstate;
284}
285
286/* ----------------------------------------------------------------
287 * ExecEndSeqScan
288 *
289 * frees any storage allocated through C routines.
290 * ----------------------------------------------------------------
291 */
292void
294{
296
297 /*
298 * get information from node
299 */
301
302 /*
303 * close heap scan
304 */
305 if (scanDesc != NULL)
307}
308
309/* ----------------------------------------------------------------
310 * Join Support
311 * ----------------------------------------------------------------
312 */
313
314/* ----------------------------------------------------------------
315 * ExecReScanSeqScan
316 *
317 * Rescans the relation.
318 * ----------------------------------------------------------------
319 */
320void
322{
323 TableScanDesc scan;
324
325 scan = node->ss.ss_currentScanDesc;
326
327 if (scan != NULL)
328 table_rescan(scan, /* scan desc */
329 NULL); /* new scan keys */
330
331 ExecScanReScan((ScanState *) node);
332}
333
334/* ----------------------------------------------------------------
335 * Parallel Scan Support
336 * ----------------------------------------------------------------
337 */
338
339/* ----------------------------------------------------------------
340 * ExecSeqScanEstimate
341 *
342 * Compute the amount of space we'll need in the parallel
343 * query DSM, and inform pcxt->estimator about our needs.
344 * ----------------------------------------------------------------
345 */
346void
348 ParallelContext *pcxt)
349{
350 EState *estate = node->ss.ps.state;
351
353 estate->es_snapshot);
356}
357
358/* ----------------------------------------------------------------
359 * ExecSeqScanInitializeDSM
360 *
361 * Set up a parallel heap scan descriptor.
362 * ----------------------------------------------------------------
363 */
364void
379
380/* ----------------------------------------------------------------
381 * ExecSeqScanReInitializeDSM
382 *
383 * Reset shared state before beginning a fresh scan.
384 * ----------------------------------------------------------------
385 */
386void
395
396/* ----------------------------------------------------------------
397 * ExecSeqScanInitializeWorker
398 *
399 * Copy relevant information from TOC into planstate.
400 * ----------------------------------------------------------------
401 */
402void
#define Assert(condition)
Definition c.h:873
#define pg_attribute_always_inline
Definition c.h:279
#define pg_assume(expr)
Definition c.h:397
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition execExpr.c:229
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
static pg_attribute_always_inline TupleTableSlot * ExecScanExtended(ScanState *node, ExecScanAccessMtd accessMtd, ExecScanRecheckMtd recheckMtd, EPQState *epqstate, ExprState *qual, ProjectionInfo *projInfo)
Definition execScan.h:160
void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
void ExecInitResultTypeTL(PlanState *planstate)
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition execUtils.c:485
Relation ExecOpenScanRelation(EState *estate, Index scanrelid, int eflags)
Definition execUtils.c:742
bool(* ExecScanRecheckMtd)(ScanState *node, TupleTableSlot *slot)
Definition executor.h:580
TupleTableSlot *(* ExecScanAccessMtd)(ScanState *node)
Definition executor.h:579
static TupleTableSlot * ExecSeqScanWithQual(PlanState *pstate)
void ExecSeqScanReInitializeDSM(SeqScanState *node, ParallelContext *pcxt)
void ExecSeqScanInitializeWorker(SeqScanState *node, ParallelWorkerContext *pwcxt)
static pg_attribute_always_inline bool SeqRecheck(SeqScanState *node, TupleTableSlot *slot)
Definition nodeSeqscan.c:90
void ExecEndSeqScan(SeqScanState *node)
static TupleTableSlot * ExecSeqScanWithQualProject(PlanState *pstate)
static TupleTableSlot * ExecSeqScan(PlanState *pstate)
SeqScanState * ExecInitSeqScan(SeqScan *node, EState *estate, int eflags)
void ExecSeqScanInitializeDSM(SeqScanState *node, ParallelContext *pcxt)
static TupleTableSlot * ExecSeqScanEPQ(PlanState *pstate)
static TupleTableSlot * ExecSeqScanWithProject(PlanState *pstate)
void ExecSeqScanEstimate(SeqScanState *node, ParallelContext *pcxt)
static TupleTableSlot * SeqNext(SeqScanState *node)
Definition nodeSeqscan.c:51
void ExecReScanSeqScan(SeqScanState *node)
#define makeNode(_type_)
Definition nodes.h:161
#define castNode(_type_, nodeptr)
Definition nodes.h:182
#define innerPlan(node)
Definition plannodes.h:260
#define outerPlan(node)
Definition plannodes.h:261
static int fb(int x)
#define RelationGetDescr(relation)
Definition rel.h:540
ScanDirection
Definition sdir.h:25
void * shm_toc_allocate(shm_toc *toc, Size nbytes)
Definition shm_toc.c:88
void shm_toc_insert(shm_toc *toc, uint64 key, void *address)
Definition shm_toc.c:171
void * shm_toc_lookup(shm_toc *toc, uint64 key, bool noError)
Definition shm_toc.c:232
#define shm_toc_estimate_chunk(e, sz)
Definition shm_toc.h:51
#define shm_toc_estimate_keys(e, cnt)
Definition shm_toc.h:53
ScanDirection es_direction
Definition execnodes.h:661
struct EPQState * es_epq_active
Definition execnodes.h:744
Snapshot es_snapshot
Definition execnodes.h:662
shm_toc_estimator estimator
Definition parallel.h:41
shm_toc * toc
Definition parallel.h:44
ExprState * qual
Definition execnodes.h:1188
Plan * plan
Definition execnodes.h:1167
EState * state
Definition execnodes.h:1169
ProjectionInfo * ps_ProjInfo
Definition execnodes.h:1207
int plan_node_id
Definition plannodes.h:227
Relation ss_currentRelation
Definition execnodes.h:1624
TupleTableSlot * ss_ScanTupleSlot
Definition execnodes.h:1626
PlanState ps
Definition execnodes.h:1623
struct TableScanDescData * ss_currentScanDesc
Definition execnodes.h:1625
Index scanrelid
Definition plannodes.h:523
ScanState ss
Definition execnodes.h:1635
Scan scan
Definition plannodes.h:532
struct ParallelTableScanDescData * rs_parallel
Definition relscan.h:65
TableScanDesc table_beginscan_parallel(Relation relation, ParallelTableScanDesc pscan)
Definition tableam.c:166
Size table_parallelscan_estimate(Relation rel, Snapshot snapshot)
Definition tableam.c:131
void table_parallelscan_initialize(Relation rel, ParallelTableScanDesc pscan, Snapshot snapshot)
Definition tableam.c:146
const TupleTableSlotOps * table_slot_callbacks(Relation relation)
Definition tableam.c:59
static void table_endscan(TableScanDesc scan)
Definition tableam.h:1005
static void table_rescan(TableScanDesc scan, ScanKeyData *key)
Definition tableam.h:1014
static bool table_scan_getnextslot(TableScanDesc sscan, ScanDirection direction, TupleTableSlot *slot)
Definition tableam.h:1040
static TableScanDesc table_beginscan(Relation rel, Snapshot snapshot, int nkeys, ScanKeyData *key)
Definition tableam.h:897
static void table_parallelscan_reinitialize(Relation rel, ParallelTableScanDesc pscan)
Definition tableam.h:1161