]> granicus.if.org Git - postgresql/blob - src/backend/executor/nodeSamplescan.c
pgindent run for 9.5
[postgresql] / src / backend / executor / nodeSamplescan.c
1 /*-------------------------------------------------------------------------
2  *
3  * nodeSamplescan.c
4  *        Support routines for sample scans of relations (table sampling).
5  *
6  * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        src/backend/executor/nodeSamplescan.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16
17 #include "access/tablesample.h"
18 #include "executor/executor.h"
19 #include "executor/nodeSamplescan.h"
20 #include "miscadmin.h"
21 #include "parser/parsetree.h"
22 #include "pgstat.h"
23 #include "storage/bufmgr.h"
24 #include "storage/predicate.h"
25 #include "utils/rel.h"
26 #include "utils/syscache.h"
27 #include "utils/tqual.h"
28
29 static void InitScanRelation(SampleScanState *node, EState *estate,
30                                  int eflags, TableSampleClause *tablesample);
31 static TupleTableSlot *SampleNext(SampleScanState *node);
32
33
34 /* ----------------------------------------------------------------
35  *                                              Scan Support
36  * ----------------------------------------------------------------
37  */
38
39 /* ----------------------------------------------------------------
40  *              SampleNext
41  *
42  *              This is a workhorse for ExecSampleScan
43  * ----------------------------------------------------------------
44  */
45 static TupleTableSlot *
46 SampleNext(SampleScanState *node)
47 {
48         TupleTableSlot *slot;
49         TableSampleDesc *tsdesc;
50         HeapTuple       tuple;
51
52         /*
53          * get information from the scan state
54          */
55         slot = node->ss.ss_ScanTupleSlot;
56         tsdesc = node->tsdesc;
57
58         tuple = tablesample_getnext(tsdesc);
59
60         if (tuple)
61                 ExecStoreTuple(tuple,   /* tuple to store */
62                                            slot,        /* slot to store in */
63                                            tsdesc->heapScan->rs_cbuf,           /* buffer associated
64                                                                                                                  * with this tuple */
65                                            false);      /* don't pfree this pointer */
66         else
67                 ExecClearTuple(slot);
68
69         return slot;
70 }
71
72 /*
73  * SampleRecheck -- access method routine to recheck a tuple in EvalPlanQual
74  */
75 static bool
76 SampleRecheck(SampleScanState *node, TupleTableSlot *slot)
77 {
78         /* No need to recheck for SampleScan */
79         return true;
80 }
81
82 /* ----------------------------------------------------------------
83  *              ExecSampleScan(node)
84  *
85  *              Scans the relation using the sampling method and returns
86  *              the next qualifying tuple.
87  *              We call the ExecScan() routine and pass it the appropriate
88  *              access method functions.
89  * ----------------------------------------------------------------
90  */
91 TupleTableSlot *
92 ExecSampleScan(SampleScanState *node)
93 {
94         return ExecScan((ScanState *) node,
95                                         (ExecScanAccessMtd) SampleNext,
96                                         (ExecScanRecheckMtd) SampleRecheck);
97 }
98
99 /* ----------------------------------------------------------------
100  *              InitScanRelation
101  *
102  *              Set up to access the scan relation.
103  * ----------------------------------------------------------------
104  */
105 static void
106 InitScanRelation(SampleScanState *node, EState *estate, int eflags,
107                                  TableSampleClause *tablesample)
108 {
109         Relation        currentRelation;
110
111         /*
112          * get the relation object id from the relid'th entry in the range table,
113          * open that relation and acquire appropriate lock on it.
114          */
115         currentRelation = ExecOpenScanRelation(estate,
116                                                                 ((SampleScan *) node->ss.ps.plan)->scanrelid,
117                                                                                    eflags);
118
119         node->ss.ss_currentRelation = currentRelation;
120
121         /*
122          * Even though we aren't going to do a conventional seqscan, it is useful
123          * to create a HeapScanDesc --- many of the fields in it are usable.
124          */
125         node->ss.ss_currentScanDesc =
126                 heap_beginscan_sampling(currentRelation, estate->es_snapshot, 0, NULL,
127                                                                 tablesample->tsmseqscan,
128                                                                 tablesample->tsmpagemode);
129
130         /* and report the scan tuple slot's rowtype */
131         ExecAssignScanType(&node->ss, RelationGetDescr(currentRelation));
132 }
133
134
135 /* ----------------------------------------------------------------
136  *              ExecInitSampleScan
137  * ----------------------------------------------------------------
138  */
139 SampleScanState *
140 ExecInitSampleScan(SampleScan *node, EState *estate, int eflags)
141 {
142         SampleScanState *scanstate;
143         RangeTblEntry *rte = rt_fetch(node->scanrelid,
144                                                                   estate->es_range_table);
145
146         Assert(outerPlan(node) == NULL);
147         Assert(innerPlan(node) == NULL);
148         Assert(rte->tablesample != NULL);
149
150         /*
151          * create state structure
152          */
153         scanstate = makeNode(SampleScanState);
154         scanstate->ss.ps.plan = (Plan *) node;
155         scanstate->ss.ps.state = estate;
156
157         /*
158          * Miscellaneous initialization
159          *
160          * create expression context for node
161          */
162         ExecAssignExprContext(estate, &scanstate->ss.ps);
163
164         /*
165          * initialize child expressions
166          */
167         scanstate->ss.ps.targetlist = (List *)
168                 ExecInitExpr((Expr *) node->plan.targetlist,
169                                          (PlanState *) scanstate);
170         scanstate->ss.ps.qual = (List *)
171                 ExecInitExpr((Expr *) node->plan.qual,
172                                          (PlanState *) scanstate);
173
174         /*
175          * tuple table initialization
176          */
177         ExecInitResultTupleSlot(estate, &scanstate->ss.ps);
178         ExecInitScanTupleSlot(estate, &scanstate->ss);
179
180         /*
181          * initialize scan relation
182          */
183         InitScanRelation(scanstate, estate, eflags, rte->tablesample);
184
185         scanstate->ss.ps.ps_TupFromTlist = false;
186
187         /*
188          * Initialize result tuple type and projection info.
189          */
190         ExecAssignResultTypeFromTL(&scanstate->ss.ps);
191         ExecAssignScanProjectionInfo(&scanstate->ss);
192
193         scanstate->tsdesc = tablesample_init(scanstate, rte->tablesample);
194
195         return scanstate;
196 }
197
198 /* ----------------------------------------------------------------
199  *              ExecEndSampleScan
200  *
201  *              frees any storage allocated through C routines.
202  * ----------------------------------------------------------------
203  */
204 void
205 ExecEndSampleScan(SampleScanState *node)
206 {
207         /*
208          * Tell sampling function that we finished the scan.
209          */
210         tablesample_end(node->tsdesc);
211
212         /*
213          * Free the exprcontext
214          */
215         ExecFreeExprContext(&node->ss.ps);
216
217         /*
218          * clean out the tuple table
219          */
220         ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
221         ExecClearTuple(node->ss.ss_ScanTupleSlot);
222
223         /*
224          * close heap scan
225          */
226         heap_endscan(node->ss.ss_currentScanDesc);
227
228         /*
229          * close the heap relation.
230          */
231         ExecCloseScanRelation(node->ss.ss_currentRelation);
232 }
233
234 /* ----------------------------------------------------------------
235  *                                              Join Support
236  * ----------------------------------------------------------------
237  */
238
239 /* ----------------------------------------------------------------
240  *              ExecReScanSampleScan
241  *
242  *              Rescans the relation.
243  *
244  * ----------------------------------------------------------------
245  */
246 void
247 ExecReScanSampleScan(SampleScanState *node)
248 {
249         heap_rescan(node->ss.ss_currentScanDesc, NULL);
250
251         /*
252          * Tell sampling function to reset its state for rescan.
253          */
254         tablesample_reset(node->tsdesc);
255
256         ExecScanReScan(&node->ss);
257 }