Age Owner TLA Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * nodeSeqscan.c
4 : * Support routines for sequential scans of relations.
5 : *
6 : * Portions Copyright (c) 1996-2023, 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/execdebug.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 *
7184 bruce 50 CBC 37554361 : 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 : */
2706 rhaas 60 37554361 : scandesc = node->ss.ss_currentScanDesc;
61 37554361 : estate = node->ss.ps.state;
9345 bruce 62 37554361 : direction = estate->es_direction;
2706 rhaas 63 37554361 : slot = node->ss.ss_ScanTupleSlot;
64 :
65 37554361 : 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 : */
1490 andres 71 76850 : scandesc = table_beginscan(node->ss.ss_currentRelation,
72 : estate->es_snapshot,
73 : 0, NULL);
2706 rhaas 74 76850 : node->ss.ss_currentScanDesc = scandesc;
75 : }
76 :
77 : /*
78 : * get the next tuple from the table
79 : */
1490 andres 80 37554361 : if (table_scan_getnextslot(scandesc, direction, slot))
81 37104995 : return slot;
82 449356 : return NULL;
83 : }
84 :
85 : /*
86 : * SeqRecheck -- access method routine to recheck a tuple in EvalPlanQual
87 : */
88 : static bool
4913 tgl 89 79 : 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 79 : 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 *
2092 andres 108 24410430 : ExecSeqScan(PlanState *pstate)
109 : {
110 24410430 : SeqScanState *node = castNode(SeqScanState, pstate);
111 :
112 24410430 : return ExecScan(&node->ss,
113 : (ExecScanAccessMtd) SeqNext,
114 : (ExecScanRecheckMtd) SeqRecheck);
115 : }
116 :
117 :
118 : /* ----------------------------------------------------------------
119 : * ExecInitSeqScan
120 : * ----------------------------------------------------------------
121 : */
122 : SeqScanState *
6249 tgl 123 93563 : 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 : */
7430 131 93563 : Assert(outerPlan(node) == NULL);
132 93563 : Assert(innerPlan(node) == NULL);
133 :
134 : /*
135 : * create state structure
136 : */
137 93563 : scanstate = makeNode(SeqScanState);
2706 rhaas 138 93563 : scanstate->ss.ps.plan = (Plan *) node;
139 93563 : scanstate->ss.ps.state = estate;
2092 andres 140 93563 : scanstate->ss.ps.ExecProcNode = ExecSeqScan;
141 :
142 : /*
143 : * Miscellaneous initialization
144 : *
145 : * create expression context for node
146 : */
2706 rhaas 147 93563 : ExecAssignExprContext(estate, &scanstate->ss.ps);
148 :
149 : /*
150 : * open the scan relation
151 : */
1878 andres 152 93557 : scanstate->ss.ss_currentRelation =
153 93563 : ExecOpenScanRelation(estate,
154 : node->scan.scanrelid,
155 : eflags);
156 :
157 : /* and create slot with the appropriate rowtype */
158 93557 : ExecInitScanTupleSlot(estate, &scanstate->ss,
1606 159 93557 : RelationGetDescr(scanstate->ss.ss_currentRelation),
160 : table_slot_callbacks(scanstate->ss.ss_currentRelation));
161 :
162 : /*
163 : * Initialize result type and projection.
164 : */
1612 165 93557 : ExecInitResultTypeTL(&scanstate->ss.ps);
1878 166 93557 : ExecAssignScanProjectionInfo(&scanstate->ss);
167 :
168 : /*
169 : * initialize child expressions
170 : */
171 93557 : scanstate->ss.ps.qual =
609 peter 172 93557 : ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
173 :
7430 tgl 174 93557 : return scanstate;
175 : }
176 :
177 : /* ----------------------------------------------------------------
178 : * ExecEndSeqScan
179 : *
180 : * frees any storage allocated through C routines.
181 : * ----------------------------------------------------------------
182 : */
183 : void
7184 bruce 184 92458 : ExecEndSeqScan(SeqScanState *node)
185 : {
186 : TableScanDesc scanDesc;
187 :
188 : /*
189 : * get information from node
190 : */
2706 rhaas 191 92458 : scanDesc = node->ss.ss_currentScanDesc;
192 :
193 : /*
194 : * Free the exprcontext
195 : */
196 92458 : ExecFreeExprContext(&node->ss.ps);
197 :
198 : /*
199 : * clean out the tuple table
200 : */
1612 andres 201 92458 : if (node->ss.ps.ps_ResultTupleSlot)
202 51088 : ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
2706 rhaas 203 92458 : ExecClearTuple(node->ss.ss_ScanTupleSlot);
204 :
205 : /*
206 : * close heap scan
207 : */
208 92458 : if (scanDesc != NULL)
1490 andres 209 77714 : table_endscan(scanDesc);
9770 scrappy 210 92458 : }
211 :
212 : /* ----------------------------------------------------------------
213 : * Join Support
214 : * ----------------------------------------------------------------
215 : */
216 :
217 : /* ----------------------------------------------------------------
218 : * ExecReScanSeqScan
219 : *
220 : * Rescans the relation.
221 : * ----------------------------------------------------------------
222 : */
223 : void
4654 tgl 224 387654 : ExecReScanSeqScan(SeqScanState *node)
225 : {
226 : TableScanDesc scan;
227 :
2706 rhaas 228 387654 : scan = node->ss.ss_currentScanDesc;
229 :
230 387654 : if (scan != NULL)
1418 tgl 231 379034 : table_rescan(scan, /* scan desc */
232 : NULL); /* new scan keys */
233 :
4913 234 387654 : ExecScanReScan((ScanState *) node);
9770 scrappy 235 387654 : }
236 :
237 : /* ----------------------------------------------------------------
238 : * Parallel Scan Support
239 : * ----------------------------------------------------------------
240 : */
241 :
242 : /* ----------------------------------------------------------------
243 : * ExecSeqScanEstimate
244 : *
245 : * Compute the amount of space we'll need in the parallel
246 : * query DSM, and inform pcxt->estimator about our needs.
247 : * ----------------------------------------------------------------
248 : */
249 : void
2706 rhaas 250 441 : ExecSeqScanEstimate(SeqScanState *node,
251 : ParallelContext *pcxt)
252 : {
253 441 : EState *estate = node->ss.ps.state;
254 :
1490 andres 255 441 : node->pscan_len = table_parallelscan_estimate(node->ss.ss_currentRelation,
256 : estate->es_snapshot);
2706 rhaas 257 441 : shm_toc_estimate_chunk(&pcxt->estimator, node->pscan_len);
258 441 : shm_toc_estimate_keys(&pcxt->estimator, 1);
259 441 : }
260 :
261 : /* ----------------------------------------------------------------
262 : * ExecSeqScanInitializeDSM
263 : *
264 : * Set up a parallel heap scan descriptor.
265 : * ----------------------------------------------------------------
266 : */
267 : void
268 441 : ExecSeqScanInitializeDSM(SeqScanState *node,
269 : ParallelContext *pcxt)
270 : {
271 441 : EState *estate = node->ss.ps.state;
272 : ParallelTableScanDesc pscan;
273 :
274 441 : pscan = shm_toc_allocate(pcxt->toc, node->pscan_len);
1490 andres 275 441 : table_parallelscan_initialize(node->ss.ss_currentRelation,
276 : pscan,
277 : estate->es_snapshot);
2706 rhaas 278 441 : shm_toc_insert(pcxt->toc, node->ss.ps.plan->plan_node_id, pscan);
279 441 : node->ss.ss_currentScanDesc =
1490 andres 280 441 : table_beginscan_parallel(node->ss.ss_currentRelation, pscan);
2706 rhaas 281 441 : }
282 :
283 : /* ----------------------------------------------------------------
284 : * ExecSeqScanReInitializeDSM
285 : *
286 : * Reset shared state before beginning a fresh scan.
287 : * ----------------------------------------------------------------
288 : */
289 : void
2048 tgl 290 114 : ExecSeqScanReInitializeDSM(SeqScanState *node,
291 : ParallelContext *pcxt)
292 : {
293 : ParallelTableScanDesc pscan;
294 :
1490 andres 295 114 : pscan = node->ss.ss_currentScanDesc->rs_parallel;
296 114 : table_parallelscan_reinitialize(node->ss.ss_currentRelation, pscan);
2048 tgl 297 114 : }
298 :
299 : /* ----------------------------------------------------------------
300 : * ExecSeqScanInitializeWorker
301 : *
302 : * Copy relevant information from TOC into planstate.
303 : * ----------------------------------------------------------------
304 : */
305 : void
1970 andres 306 1312 : ExecSeqScanInitializeWorker(SeqScanState *node,
307 : ParallelWorkerContext *pwcxt)
308 : {
309 : ParallelTableScanDesc pscan;
310 :
311 1312 : pscan = shm_toc_lookup(pwcxt->toc, node->ss.ps.plan->plan_node_id, false);
2706 rhaas 312 1312 : node->ss.ss_currentScanDesc =
1490 andres 313 1312 : table_beginscan_parallel(node->ss.ss_currentRelation, pscan);
2706 rhaas 314 1312 : }
|