]> granicus.if.org Git - postgresql/blob - src/backend/executor/nodeBitmapIndexscan.c
Update copyrights for 2013
[postgresql] / src / backend / executor / nodeBitmapIndexscan.c
1 /*-------------------------------------------------------------------------
2  *
3  * nodeBitmapIndexscan.c
4  *        Routines to support bitmapped index scans of relations
5  *
6  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        src/backend/executor/nodeBitmapIndexscan.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 /*
16  * INTERFACE ROUTINES
17  *              MultiExecBitmapIndexScan        scans a relation using index.
18  *              ExecInitBitmapIndexScan         creates and initializes state info.
19  *              ExecReScanBitmapIndexScan       prepares to rescan the plan.
20  *              ExecEndBitmapIndexScan          releases all storage.
21  */
22 #include "postgres.h"
23
24 #include "executor/execdebug.h"
25 #include "executor/nodeBitmapIndexscan.h"
26 #include "executor/nodeIndexscan.h"
27 #include "miscadmin.h"
28 #include "utils/memutils.h"
29
30
31 /* ----------------------------------------------------------------
32  *              MultiExecBitmapIndexScan(node)
33  * ----------------------------------------------------------------
34  */
35 Node *
36 MultiExecBitmapIndexScan(BitmapIndexScanState *node)
37 {
38         TIDBitmap  *tbm;
39         IndexScanDesc scandesc;
40         double          nTuples = 0;
41         bool            doscan;
42
43         /* must provide our own instrumentation support */
44         if (node->ss.ps.instrument)
45                 InstrStartNode(node->ss.ps.instrument);
46
47         /*
48          * extract necessary information from index scan node
49          */
50         scandesc = node->biss_ScanDesc;
51
52         /*
53          * If we have runtime keys and they've not already been set up, do it now.
54          * Array keys are also treated as runtime keys; note that if ExecReScan
55          * returns with biss_RuntimeKeysReady still false, then there is an empty
56          * array key so we should do nothing.
57          */
58         if (!node->biss_RuntimeKeysReady &&
59                 (node->biss_NumRuntimeKeys != 0 || node->biss_NumArrayKeys != 0))
60         {
61                 ExecReScan((PlanState *) node);
62                 doscan = node->biss_RuntimeKeysReady;
63         }
64         else
65                 doscan = true;
66
67         /*
68          * Prepare the result bitmap.  Normally we just create a new one to pass
69          * back; however, our parent node is allowed to store a pre-made one into
70          * node->biss_result, in which case we just OR our tuple IDs into the
71          * existing bitmap.  (This saves needing explicit UNION steps.)
72          */
73         if (node->biss_result)
74         {
75                 tbm = node->biss_result;
76                 node->biss_result = NULL;               /* reset for next time */
77         }
78         else
79         {
80                 /* XXX should we use less than work_mem for this? */
81                 tbm = tbm_create(work_mem * 1024L);
82         }
83
84         /*
85          * Get TIDs from index and insert into bitmap
86          */
87         while (doscan)
88         {
89                 nTuples += (double) index_getbitmap(scandesc, tbm);
90
91                 CHECK_FOR_INTERRUPTS();
92
93                 doscan = ExecIndexAdvanceArrayKeys(node->biss_ArrayKeys,
94                                                                                    node->biss_NumArrayKeys);
95                 if (doscan)                             /* reset index scan */
96                         index_rescan(node->biss_ScanDesc,
97                                                  node->biss_ScanKeys, node->biss_NumScanKeys,
98                                                  NULL, 0);
99         }
100
101         /* must provide our own instrumentation support */
102         if (node->ss.ps.instrument)
103                 InstrStopNode(node->ss.ps.instrument, nTuples);
104
105         return (Node *) tbm;
106 }
107
108 /* ----------------------------------------------------------------
109  *              ExecReScanBitmapIndexScan(node)
110  *
111  *              Recalculates the values of any scan keys whose value depends on
112  *              information known at runtime, then rescans the indexed relation.
113  * ----------------------------------------------------------------
114  */
115 void
116 ExecReScanBitmapIndexScan(BitmapIndexScanState *node)
117 {
118         ExprContext *econtext = node->biss_RuntimeContext;
119
120         /*
121          * Reset the runtime-key context so we don't leak memory as each outer
122          * tuple is scanned.  Note this assumes that we will recalculate *all*
123          * runtime keys on each call.
124          */
125         if (econtext)
126                 ResetExprContext(econtext);
127
128         /*
129          * If we are doing runtime key calculations (ie, any of the index key
130          * values weren't simple Consts), compute the new key values.
131          *
132          * Array keys are also treated as runtime keys; note that if we return
133          * with biss_RuntimeKeysReady still false, then there is an empty array
134          * key so no index scan is needed.
135          */
136         if (node->biss_NumRuntimeKeys != 0)
137                 ExecIndexEvalRuntimeKeys(econtext,
138                                                                  node->biss_RuntimeKeys,
139                                                                  node->biss_NumRuntimeKeys);
140         if (node->biss_NumArrayKeys != 0)
141                 node->biss_RuntimeKeysReady =
142                         ExecIndexEvalArrayKeys(econtext,
143                                                                    node->biss_ArrayKeys,
144                                                                    node->biss_NumArrayKeys);
145         else
146                 node->biss_RuntimeKeysReady = true;
147
148         /* reset index scan */
149         if (node->biss_RuntimeKeysReady)
150                 index_rescan(node->biss_ScanDesc,
151                                          node->biss_ScanKeys, node->biss_NumScanKeys,
152                                          NULL, 0);
153 }
154
155 /* ----------------------------------------------------------------
156  *              ExecEndBitmapIndexScan
157  * ----------------------------------------------------------------
158  */
159 void
160 ExecEndBitmapIndexScan(BitmapIndexScanState *node)
161 {
162         Relation        indexRelationDesc;
163         IndexScanDesc indexScanDesc;
164
165         /*
166          * extract information from the node
167          */
168         indexRelationDesc = node->biss_RelationDesc;
169         indexScanDesc = node->biss_ScanDesc;
170
171         /*
172          * Free the exprcontext ... now dead code, see ExecFreeExprContext
173          */
174 #ifdef NOT_USED
175         if (node->biss_RuntimeContext)
176                 FreeExprContext(node->biss_RuntimeContext, true);
177 #endif
178
179         /*
180          * close the index relation (no-op if we didn't open it)
181          */
182         if (indexScanDesc)
183                 index_endscan(indexScanDesc);
184         if (indexRelationDesc)
185                 index_close(indexRelationDesc, NoLock);
186 }
187
188 /* ----------------------------------------------------------------
189  *              ExecInitBitmapIndexScan
190  *
191  *              Initializes the index scan's state information.
192  * ----------------------------------------------------------------
193  */
194 BitmapIndexScanState *
195 ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate, int eflags)
196 {
197         BitmapIndexScanState *indexstate;
198         bool            relistarget;
199
200         /* check for unsupported flags */
201         Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
202
203         /*
204          * create state structure
205          */
206         indexstate = makeNode(BitmapIndexScanState);
207         indexstate->ss.ps.plan = (Plan *) node;
208         indexstate->ss.ps.state = estate;
209
210         /* normally we don't make the result bitmap till runtime */
211         indexstate->biss_result = NULL;
212
213         /*
214          * Miscellaneous initialization
215          *
216          * We do not need a standard exprcontext for this node, though we may
217          * decide below to create a runtime-key exprcontext
218          */
219
220         /*
221          * initialize child expressions
222          *
223          * We don't need to initialize targetlist or qual since neither are used.
224          *
225          * Note: we don't initialize all of the indexqual expression, only the
226          * sub-parts corresponding to runtime keys (see below).
227          */
228
229         /*
230          * We do not open or lock the base relation here.  We assume that an
231          * ancestor BitmapHeapScan node is holding AccessShareLock (or better) on
232          * the heap relation throughout the execution of the plan tree.
233          */
234
235         indexstate->ss.ss_currentRelation = NULL;
236         indexstate->ss.ss_currentScanDesc = NULL;
237
238         /*
239          * If we are just doing EXPLAIN (ie, aren't going to run the plan), stop
240          * here.  This allows an index-advisor plugin to EXPLAIN a plan containing
241          * references to nonexistent indexes.
242          */
243         if (eflags & EXEC_FLAG_EXPLAIN_ONLY)
244                 return indexstate;
245
246         /*
247          * Open the index relation.
248          *
249          * If the parent table is one of the target relations of the query, then
250          * InitPlan already opened and write-locked the index, so we can avoid
251          * taking another lock here.  Otherwise we need a normal reader's lock.
252          */
253         relistarget = ExecRelationIsTargetRelation(estate, node->scan.scanrelid);
254         indexstate->biss_RelationDesc = index_open(node->indexid,
255                                                                          relistarget ? NoLock : AccessShareLock);
256
257         /*
258          * Initialize index-specific scan state
259          */
260         indexstate->biss_RuntimeKeysReady = false;
261         indexstate->biss_RuntimeKeys = NULL;
262         indexstate->biss_NumRuntimeKeys = 0;
263
264         /*
265          * build the index scan keys from the index qualification
266          */
267         ExecIndexBuildScanKeys((PlanState *) indexstate,
268                                                    indexstate->biss_RelationDesc,
269                                                    node->indexqual,
270                                                    false,
271                                                    &indexstate->biss_ScanKeys,
272                                                    &indexstate->biss_NumScanKeys,
273                                                    &indexstate->biss_RuntimeKeys,
274                                                    &indexstate->biss_NumRuntimeKeys,
275                                                    &indexstate->biss_ArrayKeys,
276                                                    &indexstate->biss_NumArrayKeys);
277
278         /*
279          * If we have runtime keys or array keys, we need an ExprContext to
280          * evaluate them. We could just create a "standard" plan node exprcontext,
281          * but to keep the code looking similar to nodeIndexscan.c, it seems
282          * better to stick with the approach of using a separate ExprContext.
283          */
284         if (indexstate->biss_NumRuntimeKeys != 0 ||
285                 indexstate->biss_NumArrayKeys != 0)
286         {
287                 ExprContext *stdecontext = indexstate->ss.ps.ps_ExprContext;
288
289                 ExecAssignExprContext(estate, &indexstate->ss.ps);
290                 indexstate->biss_RuntimeContext = indexstate->ss.ps.ps_ExprContext;
291                 indexstate->ss.ps.ps_ExprContext = stdecontext;
292         }
293         else
294         {
295                 indexstate->biss_RuntimeContext = NULL;
296         }
297
298         /*
299          * Initialize scan descriptor.
300          */
301         indexstate->biss_ScanDesc =
302                 index_beginscan_bitmap(indexstate->biss_RelationDesc,
303                                                            estate->es_snapshot,
304                                                            indexstate->biss_NumScanKeys);
305
306         /*
307          * If no run-time keys to calculate, go ahead and pass the scankeys to the
308          * index AM.
309          */
310         if (indexstate->biss_NumRuntimeKeys == 0 &&
311                 indexstate->biss_NumArrayKeys == 0)
312                 index_rescan(indexstate->biss_ScanDesc,
313                                          indexstate->biss_ScanKeys, indexstate->biss_NumScanKeys,
314                                          NULL, 0);
315
316         /*
317          * all done.
318          */
319         return indexstate;
320 }