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-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  * 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 void InitScanRelation(SeqScanState *node, EState *estate, int eflags);
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 *
51 {
52  HeapTuple tuple;
53  HeapScanDesc 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 executing a
70  * scan that was intended to be parallel serially.
71  */
72  scandesc = heap_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  tuple = heap_getnext(scandesc, direction);
82 
83  /*
84  * save the tuple and the buffer returned to us by the access methods in
85  * our scan tuple slot and return the slot. Note: we pass 'false' because
86  * tuples returned by heap_getnext() are pointers onto disk pages and were
87  * not created with palloc() and so should not be pfree()'d. Note also
88  * that ExecStoreTuple will increment the refcount of the buffer; the
89  * refcount will not be dropped until the tuple table slot is cleared.
90  */
91  if (tuple)
92  ExecStoreTuple(tuple, /* tuple to store */
93  slot, /* slot to store in */
94  scandesc->rs_cbuf, /* buffer associated with this
95  * tuple */
96  false); /* don't pfree this pointer */
97  else
98  ExecClearTuple(slot);
99 
100  return slot;
101 }
102 
103 /*
104  * SeqRecheck -- access method routine to recheck a tuple in EvalPlanQual
105  */
106 static bool
108 {
109  /*
110  * Note that unlike IndexScan, SeqScan never use keys in heap_beginscan
111  * (and this is very bad) - so, here we do not check are keys ok or not.
112  */
113  return true;
114 }
115 
116 /* ----------------------------------------------------------------
117  * ExecSeqScan(node)
118  *
119  * Scans the relation sequentially and returns the next qualifying
120  * tuple.
121  * We call the ExecScan() routine and pass it the appropriate
122  * access method functions.
123  * ----------------------------------------------------------------
124  */
125 static TupleTableSlot *
127 {
128  SeqScanState *node = castNode(SeqScanState, pstate);
129 
130  return ExecScan(&node->ss,
133 }
134 
135 /* ----------------------------------------------------------------
136  * InitScanRelation
137  *
138  * Set up to access the scan relation.
139  * ----------------------------------------------------------------
140  */
141 static void
142 InitScanRelation(SeqScanState *node, EState *estate, int eflags)
143 {
144  Relation currentRelation;
145 
146  /*
147  * get the relation object id from the relid'th entry in the range table,
148  * open that relation and acquire appropriate lock on it.
149  */
150  currentRelation = ExecOpenScanRelation(estate,
151  ((SeqScan *) node->ss.ps.plan)->scanrelid,
152  eflags);
153 
154  node->ss.ss_currentRelation = currentRelation;
155 
156  /* and report the scan tuple slot's rowtype */
157  ExecAssignScanType(&node->ss, RelationGetDescr(currentRelation));
158 }
159 
160 
161 /* ----------------------------------------------------------------
162  * ExecInitSeqScan
163  * ----------------------------------------------------------------
164  */
165 SeqScanState *
166 ExecInitSeqScan(SeqScan *node, EState *estate, int eflags)
167 {
168  SeqScanState *scanstate;
169 
170  /*
171  * Once upon a time it was possible to have an outerPlan of a SeqScan, but
172  * not any more.
173  */
174  Assert(outerPlan(node) == NULL);
175  Assert(innerPlan(node) == NULL);
176 
177  /*
178  * create state structure
179  */
180  scanstate = makeNode(SeqScanState);
181  scanstate->ss.ps.plan = (Plan *) node;
182  scanstate->ss.ps.state = estate;
183  scanstate->ss.ps.ExecProcNode = ExecSeqScan;
184 
185  /*
186  * Miscellaneous initialization
187  *
188  * create expression context for node
189  */
190  ExecAssignExprContext(estate, &scanstate->ss.ps);
191 
192  /*
193  * initialize child expressions
194  */
195  scanstate->ss.ps.qual =
196  ExecInitQual(node->plan.qual, (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  * Compute the amount of space we'll need in the parallel
293  * query DSM, and inform pcxt->estimator about our needs.
294  * ----------------------------------------------------------------
295  */
296 void
298  ParallelContext *pcxt)
299 {
300  EState *estate = node->ss.ps.state;
301 
304  shm_toc_estimate_keys(&pcxt->estimator, 1);
305 }
306 
307 /* ----------------------------------------------------------------
308  * ExecSeqScanInitializeDSM
309  *
310  * Set up a parallel heap scan descriptor.
311  * ----------------------------------------------------------------
312  */
313 void
315  ParallelContext *pcxt)
316 {
317  EState *estate = node->ss.ps.state;
318  ParallelHeapScanDesc pscan;
319 
320  pscan = shm_toc_allocate(pcxt->toc, node->pscan_len);
322  node->ss.ss_currentRelation,
323  estate->es_snapshot);
324  shm_toc_insert(pcxt->toc, node->ss.ps.plan->plan_node_id, pscan);
325  node->ss.ss_currentScanDesc =
327 }
328 
329 /* ----------------------------------------------------------------
330  * ExecSeqScanReInitializeDSM
331  *
332  * Reset shared state before beginning a fresh scan.
333  * ----------------------------------------------------------------
334  */
335 void
337  ParallelContext *pcxt)
338 {
339  HeapScanDesc scan = node->ss.ss_currentScanDesc;
340 
342 }
343 
344 /* ----------------------------------------------------------------
345  * ExecSeqScanInitializeWorker
346  *
347  * Copy relevant information from TOC into planstate.
348  * ----------------------------------------------------------------
349  */
350 void
352  ParallelWorkerContext *pwcxt)
353 {
354  ParallelHeapScanDesc pscan;
355 
356  pscan = shm_toc_lookup(pwcxt->toc, node->ss.ps.plan->plan_node_id, false);
357  node->ss.ss_currentScanDesc =
359 }
TupleTableSlot * ExecStoreTuple(HeapTuple tuple, TupleTableSlot *slot, Buffer buffer, bool shouldFree)
Definition: execTuples.c:320
List * qual
Definition: plannodes.h:145
Plan plan
Definition: plannodes.h:329
void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate)
Definition: execTuples.c:842
void heap_endscan(HeapScanDesc scan)
Definition: heapam.c:1565
#define RelationGetDescr(relation)
Definition: rel.h:437
#define castNode(_type_, nodeptr)
Definition: nodes.h:581
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:439
int plan_node_id
Definition: plannodes.h:143
static void InitScanRelation(SeqScanState *node, EState *estate, int eflags)
Definition: nodeSeqscan.c:142
Snapshot es_snapshot
Definition: execnodes.h:430
ScanState ss
Definition: execnodes.h:1125
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1116
Relation ss_currentRelation
Definition: execnodes.h:1114
EState * state
Definition: execnodes.h:852
#define shm_toc_estimate_chunk(e, sz)
Definition: shm_toc.h:51
static TupleTableSlot * SeqNext(SeqScanState *node)
Definition: nodeSeqscan.c:50
void ExecFreeExprContext(PlanState *planstate)
Definition: execUtils.c:603
Size pscan_len
Definition: execnodes.h:1126
ScanDirection es_direction
Definition: execnodes.h:429
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition: execExpr.c:160
void ExecAssignResultTypeFromTL(PlanState *planstate)
Definition: execUtils.c:448
PlanState ps
Definition: execnodes.h:1113
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:883
void ExecSeqScanInitializeDSM(SeqScanState *node, ParallelContext *pcxt)
Definition: nodeSeqscan.c:314
static TupleTableSlot * ExecSeqScan(PlanState *pstate)
Definition: nodeSeqscan.c:126
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:690
#define innerPlan(node)
Definition: plannodes.h:173
ParallelHeapScanDesc rs_parallel
Definition: relscan.h:73
ScanDirection
Definition: sdir.h:22
void heap_rescan(HeapScanDesc scan, ScanKey key)
Definition: heapam.c:1521
void ExecEndSeqScan(SeqScanState *node)
Definition: nodeSeqscan.c:225
#define outerPlan(node)
Definition: plannodes.h:174
bool(* ExecScanRecheckMtd)(ScanState *node, TupleTableSlot *slot)
Definition: executor.h:402
void heap_parallelscan_initialize(ParallelHeapScanDesc target, Relation relation, Snapshot snapshot)
Definition: heapam.c:1615
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:856
HeapTuple heap_getnext(HeapScanDesc scan, ScanDirection direction)
Definition: heapam.c:1808
Plan * plan
Definition: execnodes.h:850
Buffer rs_cbuf
Definition: relscan.h:71
#define makeNode(_type_)
Definition: nodes.h:560
#define Assert(condition)
Definition: c.h:680
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition: execUtils.c:426
void ExecSeqScanEstimate(SeqScanState *node, ParallelContext *pcxt)
Definition: nodeSeqscan.c:297
#define shm_toc_estimate_keys(e, cnt)
Definition: shm_toc.h:53
void ExecCloseScanRelation(Relation scanrel)
Definition: execUtils.c:748
void * shm_toc_allocate(shm_toc *toc, Size nbytes)
Definition: shm_toc.c:88
ExprState * qual
Definition: execnodes.h:868
static bool SeqRecheck(SeqScanState *node, TupleTableSlot *slot)
Definition: nodeSeqscan.c:107
HeapScanDesc ss_currentScanDesc
Definition: execnodes.h:1115
void ExecSeqScanReInitializeDSM(SeqScanState *node, ParallelContext *pcxt)
Definition: nodeSeqscan.c:336
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:166
void ExecScanReScan(ScanState *node)
Definition: execScan.c:262
void ExecAssignScanType(ScanState *scanstate, TupleDesc tupDesc)
Definition: execUtils.c:627
Size heap_parallelscan_estimate(Snapshot snapshot)
Definition: heapam.c:1600
void heap_parallelscan_reinitialize(ParallelHeapScanDesc parallel_scan)
Definition: heapam.c:1638
TupleTableSlot *(* ExecScanAccessMtd)(ScanState *node)
Definition: executor.h:401
void ExecSeqScanInitializeWorker(SeqScanState *node, ParallelWorkerContext *pwcxt)
Definition: nodeSeqscan.c:351
HeapScanDesc heap_beginscan_parallel(Relation relation, ParallelHeapScanDesc parallel_scan)
Definition: heapam.c:1650
HeapScanDesc heap_beginscan(Relation relation, Snapshot snapshot, int nkeys, ScanKey key)
Definition: heapam.c:1397
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:271