PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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-2017, 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  * ExecSeqScanInitializeWorker attach to DSM info in parallel worker
26  */
27 #include "postgres.h"
28 
29 #include "access/relscan.h"
30 #include "executor/execdebug.h"
31 #include "executor/nodeSeqscan.h"
32 #include "utils/rel.h"
33 
34 static void InitScanRelation(SeqScanState *node, EState *estate, int eflags);
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  */
126 {
127  return ExecScan((ScanState *) node,
130 }
131 
132 /* ----------------------------------------------------------------
133  * InitScanRelation
134  *
135  * Set up to access the scan relation.
136  * ----------------------------------------------------------------
137  */
138 static void
139 InitScanRelation(SeqScanState *node, EState *estate, int eflags)
140 {
141  Relation currentRelation;
142 
143  /*
144  * get the relation object id from the relid'th entry in the range table,
145  * open that relation and acquire appropriate lock on it.
146  */
147  currentRelation = ExecOpenScanRelation(estate,
148  ((SeqScan *) node->ss.ps.plan)->scanrelid,
149  eflags);
150 
151  node->ss.ss_currentRelation = currentRelation;
152 
153  /* and report the scan tuple slot's rowtype */
154  ExecAssignScanType(&node->ss, RelationGetDescr(currentRelation));
155 }
156 
157 
158 /* ----------------------------------------------------------------
159  * ExecInitSeqScan
160  * ----------------------------------------------------------------
161  */
162 SeqScanState *
163 ExecInitSeqScan(SeqScan *node, EState *estate, int eflags)
164 {
165  SeqScanState *scanstate;
166 
167  /*
168  * Once upon a time it was possible to have an outerPlan of a SeqScan, but
169  * not any more.
170  */
171  Assert(outerPlan(node) == NULL);
172  Assert(innerPlan(node) == NULL);
173 
174  /*
175  * create state structure
176  */
177  scanstate = makeNode(SeqScanState);
178  scanstate->ss.ps.plan = (Plan *) node;
179  scanstate->ss.ps.state = estate;
180 
181  /*
182  * Miscellaneous initialization
183  *
184  * create expression context for node
185  */
186  ExecAssignExprContext(estate, &scanstate->ss.ps);
187 
188  /*
189  * initialize child expressions
190  */
191  scanstate->ss.ps.targetlist = (List *)
192  ExecInitExpr((Expr *) node->plan.targetlist,
193  (PlanState *) scanstate);
194  scanstate->ss.ps.qual = (List *)
195  ExecInitExpr((Expr *) node->plan.qual,
196  (PlanState *) scanstate);
197 
198  /*
199  * tuple table initialization
200  */
201  ExecInitResultTupleSlot(estate, &scanstate->ss.ps);
202  ExecInitScanTupleSlot(estate, &scanstate->ss);
203 
204  /*
205  * initialize scan relation
206  */
207  InitScanRelation(scanstate, estate, eflags);
208 
209  /*
210  * Initialize result tuple type and projection info.
211  */
212  ExecAssignResultTypeFromTL(&scanstate->ss.ps);
213  ExecAssignScanProjectionInfo(&scanstate->ss);
214 
215  return scanstate;
216 }
217 
218 /* ----------------------------------------------------------------
219  * ExecEndSeqScan
220  *
221  * frees any storage allocated through C routines.
222  * ----------------------------------------------------------------
223  */
224 void
226 {
227  Relation relation;
228  HeapScanDesc scanDesc;
229 
230  /*
231  * get information from node
232  */
233  relation = node->ss.ss_currentRelation;
234  scanDesc = node->ss.ss_currentScanDesc;
235 
236  /*
237  * Free the exprcontext
238  */
239  ExecFreeExprContext(&node->ss.ps);
240 
241  /*
242  * clean out the tuple table
243  */
246 
247  /*
248  * close heap scan
249  */
250  if (scanDesc != NULL)
251  heap_endscan(scanDesc);
252 
253  /*
254  * close the heap relation.
255  */
256  ExecCloseScanRelation(relation);
257 }
258 
259 /* ----------------------------------------------------------------
260  * Join Support
261  * ----------------------------------------------------------------
262  */
263 
264 /* ----------------------------------------------------------------
265  * ExecReScanSeqScan
266  *
267  * Rescans the relation.
268  * ----------------------------------------------------------------
269  */
270 void
272 {
273  HeapScanDesc scan;
274 
275  scan = node->ss.ss_currentScanDesc;
276 
277  if (scan != NULL)
278  heap_rescan(scan, /* scan desc */
279  NULL); /* new scan keys */
280 
281  ExecScanReScan((ScanState *) node);
282 }
283 
284 /* ----------------------------------------------------------------
285  * Parallel Scan Support
286  * ----------------------------------------------------------------
287  */
288 
289 /* ----------------------------------------------------------------
290  * ExecSeqScanEstimate
291  *
292  * estimates the space required to serialize seqscan node.
293  * ----------------------------------------------------------------
294  */
295 void
297  ParallelContext *pcxt)
298 {
299  EState *estate = node->ss.ps.state;
300 
303  shm_toc_estimate_keys(&pcxt->estimator, 1);
304 }
305 
306 /* ----------------------------------------------------------------
307  * ExecSeqScanInitializeDSM
308  *
309  * Set up a parallel heap scan descriptor.
310  * ----------------------------------------------------------------
311  */
312 void
314  ParallelContext *pcxt)
315 {
316  EState *estate = node->ss.ps.state;
317  ParallelHeapScanDesc pscan;
318 
319  pscan = shm_toc_allocate(pcxt->toc, node->pscan_len);
321  node->ss.ss_currentRelation,
322  estate->es_snapshot);
323  shm_toc_insert(pcxt->toc, node->ss.ps.plan->plan_node_id, pscan);
324  node->ss.ss_currentScanDesc =
326 }
327 
328 /* ----------------------------------------------------------------
329  * ExecSeqScanInitializeWorker
330  *
331  * Copy relevant information from TOC into planstate.
332  * ----------------------------------------------------------------
333  */
334 void
336 {
337  ParallelHeapScanDesc pscan;
338 
339  pscan = shm_toc_lookup(toc, node->ss.ps.plan->plan_node_id);
340  node->ss.ss_currentScanDesc =
342 }
void ExecSeqScanInitializeWorker(SeqScanState *node, shm_toc *toc)
Definition: nodeSeqscan.c:335
TupleTableSlot * ExecStoreTuple(HeapTuple tuple, TupleTableSlot *slot, Buffer buffer, bool shouldFree)
Definition: execTuples.c:320
List * qual
Definition: plannodes.h:133
Plan plan
Definition: plannodes.h:315
void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate)
Definition: execTuples.c:842
void heap_endscan(HeapScanDesc scan)
Definition: heapam.c:1581
#define RelationGetDescr(relation)
Definition: rel.h:425
TupleTableSlot * ExecScan(ScanState *node, ExecScanAccessMtd accessMtd, ExecScanRecheckMtd recheckMtd)
Definition: execScan.c:121
shm_toc_estimator estimator
Definition: parallel.h:42
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:439
int plan_node_id
Definition: plannodes.h:131
List * qual
Definition: execnodes.h:1064
static void InitScanRelation(SeqScanState *node, EState *estate, int eflags)
Definition: nodeSeqscan.c:139
List * targetlist
Definition: execnodes.h:1063
Snapshot es_snapshot
Definition: execnodes.h:372
ScanState ss
Definition: execnodes.h:1302
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1293
Relation ss_currentRelation
Definition: execnodes.h:1291
EState * state
Definition: execnodes.h:1051
#define shm_toc_estimate_chunk(e, sz)
Definition: shm_toc.h:49
static TupleTableSlot * SeqNext(SeqScanState *node)
Definition: nodeSeqscan.c:49
void ExecFreeExprContext(PlanState *planstate)
Definition: execUtils.c:686
Size pscan_len
Definition: execnodes.h:1303
ScanDirection es_direction
Definition: execnodes.h:371
void ExecAssignResultTypeFromTL(PlanState *planstate)
Definition: execUtils.c:431
TupleTableSlot *(* ExecScanAccessMtd)(ScanState *node)
Definition: executor.h:272
PlanState ps
Definition: execnodes.h:1290
bool(* ExecScanRecheckMtd)(ScanState *node, TupleTableSlot *slot)
Definition: executor.h:273
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:1079
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execQual.c:4267
void ExecSeqScanInitializeDSM(SeqScanState *node, ParallelContext *pcxt)
Definition: nodeSeqscan.c:313
void ExecAssignScanProjectionInfo(ScanState *node)
Definition: execScan.c:235
void ExecInitResultTupleSlot(EState *estate, PlanState *planstate)
Definition: execTuples.c:832
Relation ExecOpenScanRelation(EState *estate, Index scanrelid, int eflags)
Definition: execUtils.c:773
#define innerPlan(node)
Definition: plannodes.h:161
void * shm_toc_lookup(shm_toc *toc, uint64 key)
Definition: shm_toc.c:218
ScanDirection
Definition: sdir.h:22
void heap_rescan(HeapScanDesc scan, ScanKey key)
Definition: heapam.c:1518
void ExecEndSeqScan(SeqScanState *node)
Definition: nodeSeqscan.c:225
#define outerPlan(node)
Definition: plannodes.h:162
void heap_parallelscan_initialize(ParallelHeapScanDesc target, Relation relation, Snapshot snapshot)
Definition: heapam.c:1631
HeapTuple heap_getnext(HeapScanDesc scan, ScanDirection direction)
Definition: heapam.c:1797
Plan * plan
Definition: execnodes.h:1049
Buffer rs_cbuf
Definition: relscan.h:70
#define makeNode(_type_)
Definition: nodes.h:568
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition: execUtils.c:409
void ExecSeqScanEstimate(SeqScanState *node, ParallelContext *pcxt)
Definition: nodeSeqscan.c:296
#define shm_toc_estimate_keys(e, cnt)
Definition: shm_toc.h:52
void ExecCloseScanRelation(Relation scanrel)
Definition: execUtils.c:831
void * shm_toc_allocate(shm_toc *toc, Size nbytes)
Definition: shm_toc.c:83
List * targetlist
Definition: plannodes.h:132
TupleTableSlot * ExecSeqScan(SeqScanState *node)
Definition: nodeSeqscan.c:125
static bool SeqRecheck(SeqScanState *node, TupleTableSlot *slot)
Definition: nodeSeqscan.c:106
HeapScanDesc ss_currentScanDesc
Definition: execnodes.h:1292
void shm_toc_insert(shm_toc *toc, uint64 key, void *address)
Definition: shm_toc.c:161
SeqScanState * ExecInitSeqScan(SeqScan *node, EState *estate, int eflags)
Definition: nodeSeqscan.c:163
void ExecScanReScan(ScanState *node)
Definition: execScan.c:327
void ExecAssignScanType(ScanState *scanstate, TupleDesc tupDesc)
Definition: execUtils.c:710
Size heap_parallelscan_estimate(Snapshot snapshot)
Definition: heapam.c:1616
Definition: pg_list.h:45
HeapScanDesc heap_beginscan_parallel(Relation relation, ParallelHeapScanDesc parallel_scan)
Definition: heapam.c:1653
HeapScanDesc heap_beginscan(Relation relation, Snapshot snapshot, int nkeys, ScanKey key)
Definition: heapam.c:1394
shm_toc * toc
Definition: parallel.h:45
void ExecReScanSeqScan(SeqScanState *node)
Definition: nodeSeqscan.c:271