PostgreSQL Source Code git master
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-2025, 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 */
50static TupleTableSlot *
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 */
89static bool
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_eqp_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 Assert(pstate->state->es_epq_active == NULL);
135 Assert(pstate->qual != NULL);
136 Assert(pstate->ps_ProjInfo == NULL);
137
138 return ExecScanExtended(&node->ss,
141 NULL,
142 pstate->qual,
143 NULL);
144}
145
146/*
147 * Variant of ExecSeqScan() but when projection is required.
148 */
149static TupleTableSlot *
151{
152 SeqScanState *node = castNode(SeqScanState, pstate);
153
154 Assert(pstate->state->es_epq_active == NULL);
155 Assert(pstate->qual == NULL);
156 Assert(pstate->ps_ProjInfo != NULL);
157
158 return ExecScanExtended(&node->ss,
161 NULL,
162 NULL,
163 pstate->ps_ProjInfo);
164}
165
166/*
167 * Variant of ExecSeqScan() but when qual evaluation and projection are
168 * required.
169 */
170static TupleTableSlot *
172{
173 SeqScanState *node = castNode(SeqScanState, pstate);
174
175 Assert(pstate->state->es_epq_active == NULL);
176 Assert(pstate->qual != NULL);
177 Assert(pstate->ps_ProjInfo != NULL);
178
179 return ExecScanExtended(&node->ss,
182 NULL,
183 pstate->qual,
184 pstate->ps_ProjInfo);
185}
186
187/*
188 * Variant of ExecSeqScan for when EPQ evaluation is required. We don't
189 * bother adding variants of this for with/without qual and projection as
190 * EPQ doesn't seem as exciting a case to optimize for.
191 */
192static TupleTableSlot *
194{
195 SeqScanState *node = castNode(SeqScanState, pstate);
196
197 return ExecScan(&node->ss,
200}
201
202/* ----------------------------------------------------------------
203 * ExecInitSeqScan
204 * ----------------------------------------------------------------
205 */
207ExecInitSeqScan(SeqScan *node, EState *estate, int eflags)
208{
209 SeqScanState *scanstate;
210
211 /*
212 * Once upon a time it was possible to have an outerPlan of a SeqScan, but
213 * not any more.
214 */
215 Assert(outerPlan(node) == NULL);
216 Assert(innerPlan(node) == NULL);
217
218 /*
219 * create state structure
220 */
221 scanstate = makeNode(SeqScanState);
222 scanstate->ss.ps.plan = (Plan *) node;
223 scanstate->ss.ps.state = estate;
224
225 /*
226 * Miscellaneous initialization
227 *
228 * create expression context for node
229 */
230 ExecAssignExprContext(estate, &scanstate->ss.ps);
231
232 /*
233 * open the scan relation
234 */
235 scanstate->ss.ss_currentRelation =
237 node->scan.scanrelid,
238 eflags);
239
240 /* and create slot with the appropriate rowtype */
241 ExecInitScanTupleSlot(estate, &scanstate->ss,
244
245 /*
246 * Initialize result type and projection.
247 */
248 ExecInitResultTypeTL(&scanstate->ss.ps);
249 ExecAssignScanProjectionInfo(&scanstate->ss);
250
251 /*
252 * initialize child expressions
253 */
254 scanstate->ss.ps.qual =
255 ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
256
257 /*
258 * When EvalPlanQual() is not in use, assign ExecProcNode for this node
259 * based on the presence of qual and projection. Each ExecSeqScan*()
260 * variant is optimized for the specific combination of these conditions.
261 */
262 if (scanstate->ss.ps.state->es_epq_active != NULL)
263 scanstate->ss.ps.ExecProcNode = ExecSeqScanEPQ;
264 else if (scanstate->ss.ps.qual == NULL)
265 {
266 if (scanstate->ss.ps.ps_ProjInfo == NULL)
267 scanstate->ss.ps.ExecProcNode = ExecSeqScan;
268 else
270 }
271 else
272 {
273 if (scanstate->ss.ps.ps_ProjInfo == NULL)
275 else
277 }
278
279 return scanstate;
280}
281
282/* ----------------------------------------------------------------
283 * ExecEndSeqScan
284 *
285 * frees any storage allocated through C routines.
286 * ----------------------------------------------------------------
287 */
288void
290{
291 TableScanDesc scanDesc;
292
293 /*
294 * get information from node
295 */
296 scanDesc = node->ss.ss_currentScanDesc;
297
298 /*
299 * close heap scan
300 */
301 if (scanDesc != NULL)
302 table_endscan(scanDesc);
303}
304
305/* ----------------------------------------------------------------
306 * Join Support
307 * ----------------------------------------------------------------
308 */
309
310/* ----------------------------------------------------------------
311 * ExecReScanSeqScan
312 *
313 * Rescans the relation.
314 * ----------------------------------------------------------------
315 */
316void
318{
319 TableScanDesc scan;
320
321 scan = node->ss.ss_currentScanDesc;
322
323 if (scan != NULL)
324 table_rescan(scan, /* scan desc */
325 NULL); /* new scan keys */
326
327 ExecScanReScan((ScanState *) node);
328}
329
330/* ----------------------------------------------------------------
331 * Parallel Scan Support
332 * ----------------------------------------------------------------
333 */
334
335/* ----------------------------------------------------------------
336 * ExecSeqScanEstimate
337 *
338 * Compute the amount of space we'll need in the parallel
339 * query DSM, and inform pcxt->estimator about our needs.
340 * ----------------------------------------------------------------
341 */
342void
344 ParallelContext *pcxt)
345{
346 EState *estate = node->ss.ps.state;
347
349 estate->es_snapshot);
352}
353
354/* ----------------------------------------------------------------
355 * ExecSeqScanInitializeDSM
356 *
357 * Set up a parallel heap scan descriptor.
358 * ----------------------------------------------------------------
359 */
360void
362 ParallelContext *pcxt)
363{
364 EState *estate = node->ss.ps.state;
366
367 pscan = shm_toc_allocate(pcxt->toc, node->pscan_len);
369 pscan,
370 estate->es_snapshot);
371 shm_toc_insert(pcxt->toc, node->ss.ps.plan->plan_node_id, pscan);
372 node->ss.ss_currentScanDesc =
374}
375
376/* ----------------------------------------------------------------
377 * ExecSeqScanReInitializeDSM
378 *
379 * Reset shared state before beginning a fresh scan.
380 * ----------------------------------------------------------------
381 */
382void
384 ParallelContext *pcxt)
385{
387
388 pscan = node->ss.ss_currentScanDesc->rs_parallel;
390}
391
392/* ----------------------------------------------------------------
393 * ExecSeqScanInitializeWorker
394 *
395 * Copy relevant information from TOC into planstate.
396 * ----------------------------------------------------------------
397 */
398void
401{
403
404 pscan = shm_toc_lookup(pwcxt->toc, node->ss.ps.plan->plan_node_id, false);
405 node->ss.ss_currentScanDesc =
407}
#define Assert(condition)
Definition: c.h:815
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:152
void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1998
void ExecInitResultTypeTL(PlanState *planstate)
Definition: execTuples.c:1942
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition: execUtils.c:486
Relation ExecOpenScanRelation(EState *estate, Index scanrelid, int eflags)
Definition: execUtils.c:743
bool(* ExecScanRecheckMtd)(ScanState *node, TupleTableSlot *slot)
Definition: executor.h:487
TupleTableSlot *(* ExecScanAccessMtd)(ScanState *node)
Definition: executor.h:486
static TupleTableSlot * ExecSeqScanWithQual(PlanState *pstate)
Definition: nodeSeqscan.c:130
void ExecSeqScanReInitializeDSM(SeqScanState *node, ParallelContext *pcxt)
Definition: nodeSeqscan.c:383
void ExecSeqScanInitializeWorker(SeqScanState *node, ParallelWorkerContext *pwcxt)
Definition: nodeSeqscan.c:399
void ExecEndSeqScan(SeqScanState *node)
Definition: nodeSeqscan.c:289
static TupleTableSlot * ExecSeqScanWithQualProject(PlanState *pstate)
Definition: nodeSeqscan.c:171
static TupleTableSlot * ExecSeqScan(PlanState *pstate)
Definition: nodeSeqscan.c:110
SeqScanState * ExecInitSeqScan(SeqScan *node, EState *estate, int eflags)
Definition: nodeSeqscan.c:207
void ExecSeqScanInitializeDSM(SeqScanState *node, ParallelContext *pcxt)
Definition: nodeSeqscan.c:361
static TupleTableSlot * ExecSeqScanEPQ(PlanState *pstate)
Definition: nodeSeqscan.c:193
static bool SeqRecheck(SeqScanState *node, TupleTableSlot *slot)
Definition: nodeSeqscan.c:90
static TupleTableSlot * ExecSeqScanWithProject(PlanState *pstate)
Definition: nodeSeqscan.c:150
void ExecSeqScanEstimate(SeqScanState *node, ParallelContext *pcxt)
Definition: nodeSeqscan.c:343
static TupleTableSlot * SeqNext(SeqScanState *node)
Definition: nodeSeqscan.c:51
void ExecReScanSeqScan(SeqScanState *node)
Definition: nodeSeqscan.c:317
#define makeNode(_type_)
Definition: nodes.h:155
#define castNode(_type_, nodeptr)
Definition: nodes.h:176
#define innerPlan(node)
Definition: plannodes.h:230
#define outerPlan(node)
Definition: plannodes.h:231
#define RelationGetDescr(relation)
Definition: rel.h:538
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:649
struct EPQState * es_epq_active
Definition: execnodes.h:732
Snapshot es_snapshot
Definition: execnodes.h:650
shm_toc_estimator estimator
Definition: parallel.h:41
shm_toc * toc
Definition: parallel.h:44
ExprState * qual
Definition: execnodes.h:1171
Plan * plan
Definition: execnodes.h:1150
EState * state
Definition: execnodes.h:1152
ProjectionInfo * ps_ProjInfo
Definition: execnodes.h:1190
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:1156
int plan_node_id
Definition: plannodes.h:197
Relation ss_currentRelation
Definition: execnodes.h:1604
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1606
PlanState ps
Definition: execnodes.h:1603
struct TableScanDescData * ss_currentScanDesc
Definition: execnodes.h:1605
Index scanrelid
Definition: plannodes.h:473
ScanState ss
Definition: execnodes.h:1615
Size pscan_len
Definition: execnodes.h:1616
Scan scan
Definition: plannodes.h:482
struct ParallelTableScanDescData * rs_parallel
Definition: relscan.h:66
TableScanDesc table_beginscan_parallel(Relation relation, ParallelTableScanDesc pscan)
Definition: tableam.c:165
Size table_parallelscan_estimate(Relation rel, Snapshot snapshot)
Definition: tableam.c:130
void table_parallelscan_initialize(Relation rel, ParallelTableScanDesc pscan, Snapshot snapshot)
Definition: tableam.c:145
const TupleTableSlotOps * table_slot_callbacks(Relation relation)
Definition: tableam.c:58
static TableScanDesc table_beginscan(Relation rel, Snapshot snapshot, int nkeys, struct ScanKeyData *key)
Definition: tableam.h:913
static void table_endscan(TableScanDesc scan)
Definition: tableam.h:1025
static void table_rescan(TableScanDesc scan, struct ScanKeyData *key)
Definition: tableam.h:1034
static bool table_scan_getnextslot(TableScanDesc sscan, ScanDirection direction, TupleTableSlot *slot)
Definition: tableam.h:1061
static void table_parallelscan_reinitialize(Relation rel, ParallelTableScanDesc pscan)
Definition: tableam.h:1180