Age Owner Branch data TLA Line data Source code
1 : : /*-------------------------------------------------------------------------
2 : : *
3 : : * nodeSeqscan.c
4 : : * Support routines for sequential scans of relations.
5 : : *
6 : : * Portions Copyright (c) 1996-2024, 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/executor.h"
33 : : #include "executor/nodeSeqscan.h"
34 : : #include "utils/rel.h"
35 : :
36 : : static TupleTableSlot *SeqNext(SeqScanState *node);
37 : :
38 : : /* ----------------------------------------------------------------
39 : : * Scan Support
40 : : * ----------------------------------------------------------------
41 : : */
42 : :
43 : : /* ----------------------------------------------------------------
44 : : * SeqNext
45 : : *
46 : : * This is a workhorse for ExecSeqScan
47 : : * ----------------------------------------------------------------
48 : : */
49 : : static TupleTableSlot *
7555 bruce@momjian.us 50 :CBC 34269891 : SeqNext(SeqScanState *node)
51 : : {
52 : : TableScanDesc scandesc;
53 : : EState *estate;
54 : : ScanDirection direction;
55 : : TupleTableSlot *slot;
56 : :
57 : : /*
58 : : * get information from the estate and scan state
59 : : */
3077 rhaas@postgresql.org 60 : 34269891 : scandesc = node->ss.ss_currentScanDesc;
61 : 34269891 : estate = node->ss.ps.state;
9716 bruce@momjian.us 62 : 34269891 : direction = estate->es_direction;
3077 rhaas@postgresql.org 63 : 34269891 : slot = node->ss.ss_ScanTupleSlot;
64 : :
65 [ + + ]: 34269891 : if (scandesc == NULL)
66 : : {
67 : : /*
68 : : * We reach here if the scan is not parallel, or if we're serially
69 : : * executing a scan that was planned to be parallel.
70 : : */
1861 andres@anarazel.de 71 : 78765 : scandesc = table_beginscan(node->ss.ss_currentRelation,
72 : : estate->es_snapshot,
73 : : 0, NULL);
3077 rhaas@postgresql.org 74 : 78765 : node->ss.ss_currentScanDesc = scandesc;
75 : : }
76 : :
77 : : /*
78 : : * get the next tuple from the table
79 : : */
1861 andres@anarazel.de 80 [ + + ]: 34269891 : if (table_scan_getnextslot(scandesc, direction, slot))
81 : 33700866 : return slot;
82 : 569017 : return NULL;
83 : : }
84 : :
85 : : /*
86 : : * SeqRecheck -- access method routine to recheck a tuple in EvalPlanQual
87 : : */
88 : : static bool
5284 tgl@sss.pgh.pa.us 89 : 120 : SeqRecheck(SeqScanState *node, TupleTableSlot *slot)
90 : : {
91 : : /*
92 : : * Note that unlike IndexScan, SeqScan never use keys in heap_beginscan
93 : : * (and this is very bad) - so, here we do not check are keys ok or not.
94 : : */
95 : 120 : return true;
96 : : }
97 : :
98 : : /* ----------------------------------------------------------------
99 : : * ExecSeqScan(node)
100 : : *
101 : : * Scans the relation sequentially and returns the next qualifying
102 : : * tuple.
103 : : * We call the ExecScan() routine and pass it the appropriate
104 : : * access method functions.
105 : : * ----------------------------------------------------------------
106 : : */
107 : : static TupleTableSlot *
2463 andres@anarazel.de 108 : 23550196 : ExecSeqScan(PlanState *pstate)
109 : : {
110 : 23550196 : SeqScanState *node = castNode(SeqScanState, pstate);
111 : :
112 : 23550196 : return ExecScan(&node->ss,
113 : : (ExecScanAccessMtd) SeqNext,
114 : : (ExecScanRecheckMtd) SeqRecheck);
115 : : }
116 : :
117 : :
118 : : /* ----------------------------------------------------------------
119 : : * ExecInitSeqScan
120 : : * ----------------------------------------------------------------
121 : : */
122 : : SeqScanState *
6620 tgl@sss.pgh.pa.us 123 : 98160 : ExecInitSeqScan(SeqScan *node, EState *estate, int eflags)
124 : : {
125 : : SeqScanState *scanstate;
126 : :
127 : : /*
128 : : * Once upon a time it was possible to have an outerPlan of a SeqScan, but
129 : : * not any more.
130 : : */
7801 131 [ - + ]: 98160 : Assert(outerPlan(node) == NULL);
132 [ - + ]: 98160 : Assert(innerPlan(node) == NULL);
133 : :
134 : : /*
135 : : * create state structure
136 : : */
137 : 98160 : scanstate = makeNode(SeqScanState);
3077 rhaas@postgresql.org 138 : 98160 : scanstate->ss.ps.plan = (Plan *) node;
139 : 98160 : scanstate->ss.ps.state = estate;
2463 andres@anarazel.de 140 : 98160 : scanstate->ss.ps.ExecProcNode = ExecSeqScan;
141 : :
142 : : /*
143 : : * Miscellaneous initialization
144 : : *
145 : : * create expression context for node
146 : : */
3077 rhaas@postgresql.org 147 : 98160 : ExecAssignExprContext(estate, &scanstate->ss.ps);
148 : :
149 : : /*
150 : : * open the scan relation
151 : : */
2249 andres@anarazel.de 152 : 98154 : scanstate->ss.ss_currentRelation =
153 : 98160 : ExecOpenScanRelation(estate,
154 : : node->scan.scanrelid,
155 : : eflags);
156 : :
157 : : /* and create slot with the appropriate rowtype */
158 : 98154 : ExecInitScanTupleSlot(estate, &scanstate->ss,
1977 159 : 98154 : RelationGetDescr(scanstate->ss.ss_currentRelation),
160 : : table_slot_callbacks(scanstate->ss.ss_currentRelation));
161 : :
162 : : /*
163 : : * Initialize result type and projection.
164 : : */
1983 165 : 98154 : ExecInitResultTypeTL(&scanstate->ss.ps);
2249 166 : 98154 : ExecAssignScanProjectionInfo(&scanstate->ss);
167 : :
168 : : /*
169 : : * initialize child expressions
170 : : */
171 : 98154 : scanstate->ss.ps.qual =
980 peter@eisentraut.org 172 : 98154 : ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
173 : :
7801 tgl@sss.pgh.pa.us 174 : 98154 : return scanstate;
175 : : }
176 : :
177 : : /* ----------------------------------------------------------------
178 : : * ExecEndSeqScan
179 : : *
180 : : * frees any storage allocated through C routines.
181 : : * ----------------------------------------------------------------
182 : : */
183 : : void
7555 bruce@momjian.us 184 : 96962 : ExecEndSeqScan(SeqScanState *node)
185 : : {
186 : : TableScanDesc scanDesc;
187 : :
188 : : /*
189 : : * get information from node
190 : : */
3077 rhaas@postgresql.org 191 : 96962 : scanDesc = node->ss.ss_currentScanDesc;
192 : :
193 : : /*
194 : : * close heap scan
195 : : */
196 [ + + ]: 96962 : if (scanDesc != NULL)
1861 andres@anarazel.de 197 : 79583 : table_endscan(scanDesc);
10141 scrappy@hub.org 198 : 96962 : }
199 : :
200 : : /* ----------------------------------------------------------------
201 : : * Join Support
202 : : * ----------------------------------------------------------------
203 : : */
204 : :
205 : : /* ----------------------------------------------------------------
206 : : * ExecReScanSeqScan
207 : : *
208 : : * Rescans the relation.
209 : : * ----------------------------------------------------------------
210 : : */
211 : : void
5025 tgl@sss.pgh.pa.us 212 : 507215 : ExecReScanSeqScan(SeqScanState *node)
213 : : {
214 : : TableScanDesc scan;
215 : :
3077 rhaas@postgresql.org 216 : 507215 : scan = node->ss.ss_currentScanDesc;
217 : :
218 [ + + ]: 507215 : if (scan != NULL)
1789 tgl@sss.pgh.pa.us 219 : 497309 : table_rescan(scan, /* scan desc */
220 : : NULL); /* new scan keys */
221 : :
5284 222 : 507215 : ExecScanReScan((ScanState *) node);
10141 scrappy@hub.org 223 : 507215 : }
224 : :
225 : : /* ----------------------------------------------------------------
226 : : * Parallel Scan Support
227 : : * ----------------------------------------------------------------
228 : : */
229 : :
230 : : /* ----------------------------------------------------------------
231 : : * ExecSeqScanEstimate
232 : : *
233 : : * Compute the amount of space we'll need in the parallel
234 : : * query DSM, and inform pcxt->estimator about our needs.
235 : : * ----------------------------------------------------------------
236 : : */
237 : : void
3077 rhaas@postgresql.org 238 : 450 : ExecSeqScanEstimate(SeqScanState *node,
239 : : ParallelContext *pcxt)
240 : : {
241 : 450 : EState *estate = node->ss.ps.state;
242 : :
1861 andres@anarazel.de 243 : 450 : node->pscan_len = table_parallelscan_estimate(node->ss.ss_currentRelation,
244 : : estate->es_snapshot);
3077 rhaas@postgresql.org 245 : 450 : shm_toc_estimate_chunk(&pcxt->estimator, node->pscan_len);
246 : 450 : shm_toc_estimate_keys(&pcxt->estimator, 1);
247 : 450 : }
248 : :
249 : : /* ----------------------------------------------------------------
250 : : * ExecSeqScanInitializeDSM
251 : : *
252 : : * Set up a parallel heap scan descriptor.
253 : : * ----------------------------------------------------------------
254 : : */
255 : : void
256 : 450 : ExecSeqScanInitializeDSM(SeqScanState *node,
257 : : ParallelContext *pcxt)
258 : : {
259 : 450 : EState *estate = node->ss.ps.state;
260 : : ParallelTableScanDesc pscan;
261 : :
262 : 450 : pscan = shm_toc_allocate(pcxt->toc, node->pscan_len);
1861 andres@anarazel.de 263 : 450 : table_parallelscan_initialize(node->ss.ss_currentRelation,
264 : : pscan,
265 : : estate->es_snapshot);
3077 rhaas@postgresql.org 266 : 450 : shm_toc_insert(pcxt->toc, node->ss.ps.plan->plan_node_id, pscan);
267 : 450 : node->ss.ss_currentScanDesc =
1861 andres@anarazel.de 268 : 450 : table_beginscan_parallel(node->ss.ss_currentRelation, pscan);
3077 rhaas@postgresql.org 269 : 450 : }
270 : :
271 : : /* ----------------------------------------------------------------
272 : : * ExecSeqScanReInitializeDSM
273 : : *
274 : : * Reset shared state before beginning a fresh scan.
275 : : * ----------------------------------------------------------------
276 : : */
277 : : void
2419 tgl@sss.pgh.pa.us 278 : 114 : ExecSeqScanReInitializeDSM(SeqScanState *node,
279 : : ParallelContext *pcxt)
280 : : {
281 : : ParallelTableScanDesc pscan;
282 : :
1861 andres@anarazel.de 283 : 114 : pscan = node->ss.ss_currentScanDesc->rs_parallel;
284 : 114 : table_parallelscan_reinitialize(node->ss.ss_currentRelation, pscan);
2419 tgl@sss.pgh.pa.us 285 : 114 : }
286 : :
287 : : /* ----------------------------------------------------------------
288 : : * ExecSeqScanInitializeWorker
289 : : *
290 : : * Copy relevant information from TOC into planstate.
291 : : * ----------------------------------------------------------------
292 : : */
293 : : void
2341 andres@anarazel.de 294 : 1333 : ExecSeqScanInitializeWorker(SeqScanState *node,
295 : : ParallelWorkerContext *pwcxt)
296 : : {
297 : : ParallelTableScanDesc pscan;
298 : :
299 : 1333 : pscan = shm_toc_lookup(pwcxt->toc, node->ss.ps.plan->plan_node_id, false);
3077 rhaas@postgresql.org 300 : 1333 : node->ss.ss_currentScanDesc =
1861 andres@anarazel.de 301 : 1333 : table_beginscan_parallel(node->ss.ss_currentRelation, pscan);
3077 rhaas@postgresql.org 302 : 1333 : }
|