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-2018, 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 "executor/execdebug.h"
32 #include "executor/nodeSeqscan.h"
33 #include "utils/rel.h"
34 
35 static TupleTableSlot *SeqNext(SeqScanState *node);
36 
37 /* ----------------------------------------------------------------
38  * Scan Support
39  * ----------------------------------------------------------------
40  */
41 
42 /* ----------------------------------------------------------------
43  * SeqNext
44  *
45  * This is a workhorse for ExecSeqScan
46  * ----------------------------------------------------------------
47  */
48 static TupleTableSlot *
50 {
51  HeapTuple tuple;
52  HeapScanDesc scandesc;
53  EState *estate;
54  ScanDirection direction;
55  TupleTableSlot *slot;
56 
57  /*
58  * get information from the estate and scan state
59  */
60  scandesc = node->ss.ss_currentScanDesc;
61  estate = node->ss.ps.state;
62  direction = estate->es_direction;
63  slot = node->ss.ss_ScanTupleSlot;
64 
65  if (scandesc == NULL)
66  {
67  /*
68  * We reach here if the scan is not parallel, or if we're executing a
69  * scan that was intended to be parallel serially.
70  */
71  scandesc = heap_beginscan(node->ss.ss_currentRelation,
72  estate->es_snapshot,
73  0, NULL);
74  node->ss.ss_currentScanDesc = scandesc;
75  }
76 
77  /*
78  * get the next tuple from the table
79  */
80  tuple = heap_getnext(scandesc, direction);
81 
82  /*
83  * save the tuple and the buffer returned to us by the access methods in
84  * our scan tuple slot and return the slot. Note: we pass 'false' because
85  * tuples returned by heap_getnext() are pointers onto disk pages and were
86  * not created with palloc() and so should not be pfree()'d. Note also
87  * that ExecStoreTuple will increment the refcount of the buffer; the
88  * refcount will not be dropped until the tuple table slot is cleared.
89  */
90  if (tuple)
91  ExecStoreTuple(tuple, /* tuple to store */
92  slot, /* slot to store in */
93  scandesc->rs_cbuf, /* buffer associated with this
94  * tuple */
95  false); /* don't pfree this pointer */
96  else
97  ExecClearTuple(slot);
98 
99  return slot;
100 }
101 
102 /*
103  * SeqRecheck -- access method routine to recheck a tuple in EvalPlanQual
104  */
105 static bool
107 {
108  /*
109  * Note that unlike IndexScan, SeqScan never use keys in heap_beginscan
110  * (and this is very bad) - so, here we do not check are keys ok or not.
111  */
112  return true;
113 }
114 
115 /* ----------------------------------------------------------------
116  * ExecSeqScan(node)
117  *
118  * Scans the relation sequentially and returns the next qualifying
119  * tuple.
120  * We call the ExecScan() routine and pass it the appropriate
121  * access method functions.
122  * ----------------------------------------------------------------
123  */
124 static TupleTableSlot *
126 {
127  SeqScanState *node = castNode(SeqScanState, pstate);
128 
129  return ExecScan(&node->ss,
132 }
133 
134 
135 /* ----------------------------------------------------------------
136  * ExecInitSeqScan
137  * ----------------------------------------------------------------
138  */
139 SeqScanState *
140 ExecInitSeqScan(SeqScan *node, EState *estate, int eflags)
141 {
142  SeqScanState *scanstate;
143 
144  /*
145  * Once upon a time it was possible to have an outerPlan of a SeqScan, but
146  * not any more.
147  */
148  Assert(outerPlan(node) == NULL);
149  Assert(innerPlan(node) == NULL);
150 
151  /*
152  * create state structure
153  */
154  scanstate = makeNode(SeqScanState);
155  scanstate->ss.ps.plan = (Plan *) node;
156  scanstate->ss.ps.state = estate;
157  scanstate->ss.ps.ExecProcNode = ExecSeqScan;
158 
159  /*
160  * Miscellaneous initialization
161  *
162  * create expression context for node
163  */
164  ExecAssignExprContext(estate, &scanstate->ss.ps);
165 
166  /*
167  * Initialize scan relation.
168  *
169  * Get the relation object id from the relid'th entry in the range table,
170  * open that relation and acquire appropriate lock on it.
171  */
172  scanstate->ss.ss_currentRelation =
173  ExecOpenScanRelation(estate,
174  node->scanrelid,
175  eflags);
176 
177  /* and create slot with the appropriate rowtype */
178  ExecInitScanTupleSlot(estate, &scanstate->ss,
180 
181  /*
182  * Initialize result slot, type and projection.
183  */
184  ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps);
185  ExecAssignScanProjectionInfo(&scanstate->ss);
186 
187  /*
188  * initialize child expressions
189  */
190  scanstate->ss.ps.qual =
191  ExecInitQual(node->plan.qual, (PlanState *) scanstate);
192 
193  return scanstate;
194 }
195 
196 /* ----------------------------------------------------------------
197  * ExecEndSeqScan
198  *
199  * frees any storage allocated through C routines.
200  * ----------------------------------------------------------------
201  */
202 void
204 {
205  Relation relation;
206  HeapScanDesc scanDesc;
207 
208  /*
209  * get information from node
210  */
211  relation = node->ss.ss_currentRelation;
212  scanDesc = node->ss.ss_currentScanDesc;
213 
214  /*
215  * Free the exprcontext
216  */
217  ExecFreeExprContext(&node->ss.ps);
218 
219  /*
220  * clean out the tuple table
221  */
224 
225  /*
226  * close heap scan
227  */
228  if (scanDesc != NULL)
229  heap_endscan(scanDesc);
230 
231  /*
232  * close the heap relation.
233  */
234  ExecCloseScanRelation(relation);
235 }
236 
237 /* ----------------------------------------------------------------
238  * Join Support
239  * ----------------------------------------------------------------
240  */
241 
242 /* ----------------------------------------------------------------
243  * ExecReScanSeqScan
244  *
245  * Rescans the relation.
246  * ----------------------------------------------------------------
247  */
248 void
250 {
251  HeapScanDesc scan;
252 
253  scan = node->ss.ss_currentScanDesc;
254 
255  if (scan != NULL)
256  heap_rescan(scan, /* scan desc */
257  NULL); /* new scan keys */
258 
259  ExecScanReScan((ScanState *) node);
260 }
261 
262 /* ----------------------------------------------------------------
263  * Parallel Scan Support
264  * ----------------------------------------------------------------
265  */
266 
267 /* ----------------------------------------------------------------
268  * ExecSeqScanEstimate
269  *
270  * Compute the amount of space we'll need in the parallel
271  * query DSM, and inform pcxt->estimator about our needs.
272  * ----------------------------------------------------------------
273  */
274 void
276  ParallelContext *pcxt)
277 {
278  EState *estate = node->ss.ps.state;
279 
282  shm_toc_estimate_keys(&pcxt->estimator, 1);
283 }
284 
285 /* ----------------------------------------------------------------
286  * ExecSeqScanInitializeDSM
287  *
288  * Set up a parallel heap scan descriptor.
289  * ----------------------------------------------------------------
290  */
291 void
293  ParallelContext *pcxt)
294 {
295  EState *estate = node->ss.ps.state;
296  ParallelHeapScanDesc pscan;
297 
298  pscan = shm_toc_allocate(pcxt->toc, node->pscan_len);
300  node->ss.ss_currentRelation,
301  estate->es_snapshot);
302  shm_toc_insert(pcxt->toc, node->ss.ps.plan->plan_node_id, pscan);
303  node->ss.ss_currentScanDesc =
305 }
306 
307 /* ----------------------------------------------------------------
308  * ExecSeqScanReInitializeDSM
309  *
310  * Reset shared state before beginning a fresh scan.
311  * ----------------------------------------------------------------
312  */
313 void
315  ParallelContext *pcxt)
316 {
317  HeapScanDesc scan = node->ss.ss_currentScanDesc;
318 
320 }
321 
322 /* ----------------------------------------------------------------
323  * ExecSeqScanInitializeWorker
324  *
325  * Copy relevant information from TOC into planstate.
326  * ----------------------------------------------------------------
327  */
328 void
330  ParallelWorkerContext *pwcxt)
331 {
332  ParallelHeapScanDesc pscan;
333 
334  pscan = shm_toc_lookup(pwcxt->toc, node->ss.ps.plan->plan_node_id, false);
335  node->ss.ss_currentScanDesc =
337 }
TupleTableSlot * ExecStoreTuple(HeapTuple tuple, TupleTableSlot *slot, Buffer buffer, bool shouldFree)
Definition: execTuples.c:356
List * qual
Definition: plannodes.h:147
Plan plan
Definition: plannodes.h:342
void heap_endscan(HeapScanDesc scan)
Definition: heapam.c:1572
Index scanrelid
Definition: plannodes.h:343
#define RelationGetDescr(relation)
Definition: rel.h:433
#define castNode(_type_, nodeptr)
Definition: nodes.h:586
TupleTableSlot * ExecScan(ScanState *node, ExecScanAccessMtd accessMtd, ExecScanRecheckMtd recheckMtd)
Definition: execScan.c:121
shm_toc_estimator estimator
Definition: parallel.h:41
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:475
int plan_node_id
Definition: plannodes.h:145
Snapshot es_snapshot
Definition: execnodes.h:478
ScanState ss
Definition: execnodes.h:1204
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1195
Relation ss_currentRelation
Definition: execnodes.h:1193
EState * state
Definition: execnodes.h:914
#define shm_toc_estimate_chunk(e, sz)
Definition: shm_toc.h:51
static TupleTableSlot * SeqNext(SeqScanState *node)
Definition: nodeSeqscan.c:49
void ExecFreeExprContext(PlanState *planstate)
Definition: execUtils.c:566
Size pscan_len
Definition: execnodes.h:1205
ScanDirection es_direction
Definition: execnodes.h:477
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition: execExpr.c:205
PlanState ps
Definition: execnodes.h:1192
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:946
void ExecSeqScanInitializeDSM(SeqScanState *node, ParallelContext *pcxt)
Definition: nodeSeqscan.c:292
static TupleTableSlot * ExecSeqScan(PlanState *pstate)
Definition: nodeSeqscan.c:125
void ExecAssignScanProjectionInfo(ScanState *node)
Definition: execScan.c:235
Relation ExecOpenScanRelation(EState *estate, Index scanrelid, int eflags)
Definition: execUtils.c:643
#define innerPlan(node)
Definition: plannodes.h:175
ParallelHeapScanDesc rs_parallel
Definition: relscan.h:74
ScanDirection
Definition: sdir.h:22
void heap_rescan(HeapScanDesc scan, ScanKey key)
Definition: heapam.c:1528
void ExecEndSeqScan(SeqScanState *node)
Definition: nodeSeqscan.c:203
#define outerPlan(node)
Definition: plannodes.h:176
bool(* ExecScanRecheckMtd)(ScanState *node, TupleTableSlot *slot)
Definition: executor.h:422
void heap_parallelscan_initialize(ParallelHeapScanDesc target, Relation relation, Snapshot snapshot)
Definition: heapam.c:1622
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:918
HeapTuple heap_getnext(HeapScanDesc scan, ScanDirection direction)
Definition: heapam.c:1835
void ExecInitResultTupleSlotTL(EState *estate, PlanState *planstate)
Definition: execTuples.c:890
Plan * plan
Definition: execnodes.h:912
Buffer rs_cbuf
Definition: relscan.h:72
#define makeNode(_type_)
Definition: nodes.h:565
#define Assert(condition)
Definition: c.h:699
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition: execUtils.c:428
void ExecSeqScanEstimate(SeqScanState *node, ParallelContext *pcxt)
Definition: nodeSeqscan.c:275
#define shm_toc_estimate_keys(e, cnt)
Definition: shm_toc.h:53
void ExecCloseScanRelation(Relation scanrel)
Definition: execUtils.c:701
void * shm_toc_allocate(shm_toc *toc, Size nbytes)
Definition: shm_toc.c:88
ExprState * qual
Definition: execnodes.h:930
static bool SeqRecheck(SeqScanState *node, TupleTableSlot *slot)
Definition: nodeSeqscan.c:106
HeapScanDesc ss_currentScanDesc
Definition: execnodes.h:1194
void ExecSeqScanReInitializeDSM(SeqScanState *node, ParallelContext *pcxt)
Definition: nodeSeqscan.c:314
void shm_toc_insert(shm_toc *toc, uint64 key, void *address)
Definition: shm_toc.c:171
SeqScanState * ExecInitSeqScan(SeqScan *node, EState *estate, int eflags)
Definition: nodeSeqscan.c:140
void ExecScanReScan(ScanState *node)
Definition: execScan.c:262
void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate, TupleDesc tupledesc)
Definition: execTuples.c:915
Size heap_parallelscan_estimate(Snapshot snapshot)
Definition: heapam.c:1607
void heap_parallelscan_reinitialize(ParallelHeapScanDesc parallel_scan)
Definition: heapam.c:1654
TupleTableSlot *(* ExecScanAccessMtd)(ScanState *node)
Definition: executor.h:421
void ExecSeqScanInitializeWorker(SeqScanState *node, ParallelWorkerContext *pwcxt)
Definition: nodeSeqscan.c:329
HeapScanDesc heap_beginscan_parallel(Relation relation, ParallelHeapScanDesc parallel_scan)
Definition: heapam.c:1666
HeapScanDesc heap_beginscan(Relation relation, Snapshot snapshot, int nkeys, ScanKey key)
Definition: heapam.c:1404
void * shm_toc_lookup(shm_toc *toc, uint64 key, bool noError)
Definition: shm_toc.c:232
shm_toc * toc
Definition: parallel.h:44
void ExecReScanSeqScan(SeqScanState *node)
Definition: nodeSeqscan.c:249