]> granicus.if.org Git - postgresql/blob - src/backend/executor/nodeBitmapIndexscan.c
For some reason access/tupmacs.h has been #including utils/memutils.h,
[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-2005, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        $PostgreSQL: pgsql/src/backend/executor/nodeBitmapIndexscan.c,v 1.9 2005/05/06 17:24:54 tgl Exp $
12  *
13  *-------------------------------------------------------------------------
14  */
15 /*
16  * INTERFACE ROUTINES
17  *              MultiExecBitmapIndexScan        scans a relation using index.
18  *              ExecInitBitmapIndexScan         creates and initializes state info.
19  *              ExecBitmapIndexReScan           prepares to rescan the plan.
20  *              ExecEndBitmapIndexScan          releases all storage.
21  */
22 #include "postgres.h"
23
24 #include "access/genam.h"
25 #include "executor/execdebug.h"
26 #include "executor/instrument.h"
27 #include "executor/nodeBitmapIndexscan.h"
28 #include "executor/nodeIndexscan.h"
29 #include "miscadmin.h"
30 #include "utils/memutils.h"
31
32
33 /* ----------------------------------------------------------------
34  *              MultiExecBitmapIndexScan(node)
35  * ----------------------------------------------------------------
36  */
37 Node *
38 MultiExecBitmapIndexScan(BitmapIndexScanState *node)
39 {
40 #define MAX_TIDS        1024
41         TIDBitmap  *tbm;
42         IndexScanDesc scandesc;
43         ItemPointerData tids[MAX_TIDS];
44         int32           ntids;
45         double          nTuples = 0;
46
47         /* must provide our own instrumentation support */
48         if (node->ss.ps.instrument)
49                 InstrStartNode(node->ss.ps.instrument);
50
51         /*
52          * extract necessary information from index scan node
53          */
54         scandesc = node->biss_ScanDesc;
55
56         /*
57          * If we have runtime keys and they've not already been set up, do it
58          * now.
59          */
60         if (node->biss_RuntimeKeyInfo && !node->biss_RuntimeKeysReady)
61                 ExecReScan((PlanState *) node, NULL);
62
63         /*
64          * Prepare the result bitmap.  Normally we just create a new one to pass
65          * back; however, our parent node is allowed to store a pre-made one
66          * into node->biss_result, in which case we just OR our tuple IDs into
67          * the existing bitmap.  (This saves needing explicit UNION steps.)
68          */
69         if (node->biss_result)
70         {
71                 tbm = node->biss_result;
72                 node->biss_result = NULL;               /* reset for next time */
73         }
74         else
75         {
76                 /* XXX should we use less than work_mem for this? */
77                 tbm = tbm_create(work_mem * 1024L);
78         }
79
80         /*
81          * Get TIDs from index and insert into bitmap
82          */
83         for (;;)
84         {
85                 bool    more = index_getmulti(scandesc, tids, MAX_TIDS, &ntids);
86
87                 if (ntids > 0)
88                 {
89                         tbm_add_tuples(tbm, tids, ntids);
90                         nTuples += ntids;
91                 }
92
93                 if (!more)
94                         break;
95
96                 CHECK_FOR_INTERRUPTS();
97         }
98
99         /* must provide our own instrumentation support */
100         if (node->ss.ps.instrument)
101                 InstrStopNodeMulti(node->ss.ps.instrument, nTuples);
102
103         return (Node *) tbm;
104 }
105
106 /* ----------------------------------------------------------------
107  *              ExecBitmapIndexReScan(node)
108  *
109  *              Recalculates the value of the scan keys whose value depends on
110  *              information known at runtime and rescans the indexed relation.
111  * ----------------------------------------------------------------
112  */
113 void
114 ExecBitmapIndexReScan(BitmapIndexScanState *node, ExprContext *exprCtxt)
115 {
116         ExprContext *econtext;
117         ExprState **runtimeKeyInfo;
118
119         econtext = node->biss_RuntimeContext;           /* context for runtime
120                                                                                                  * keys */
121         runtimeKeyInfo = node->biss_RuntimeKeyInfo;
122
123         if (econtext)
124         {
125                 /*
126                  * If we are being passed an outer tuple, save it for runtime key
127                  * calc.
128                  */
129                 if (exprCtxt != NULL)
130                         econtext->ecxt_outertuple = exprCtxt->ecxt_outertuple;
131
132                 /*
133                  * Reset the runtime-key context so we don't leak memory as each
134                  * outer tuple is scanned.      Note this assumes that we will
135                  * recalculate *all* runtime keys on each call.
136                  */
137                 ResetExprContext(econtext);
138         }
139
140         /*
141          * If we are doing runtime key calculations (ie, the index keys depend
142          * on data from an outer scan), compute the new key values
143          */
144         if (runtimeKeyInfo)
145         {
146                 ExecIndexEvalRuntimeKeys(econtext,
147                                                                  runtimeKeyInfo,
148                                                                  node->biss_ScanKeys,
149                                                                  node->biss_NumScanKeys);
150                 node->biss_RuntimeKeysReady = true;
151         }
152
153         /* reset index scan */
154         index_rescan(node->biss_ScanDesc, node->biss_ScanKeys);
155 }
156
157 /* ----------------------------------------------------------------
158  *              ExecEndBitmapIndexScan
159  * ----------------------------------------------------------------
160  */
161 void
162 ExecEndBitmapIndexScan(BitmapIndexScanState *node)
163 {
164         Relation        indexRelationDesc;
165         IndexScanDesc indexScanDesc;
166
167         /*
168          * extract information from the node
169          */
170         indexRelationDesc = node->biss_RelationDesc;
171         indexScanDesc = node->biss_ScanDesc;
172
173         /*
174          * Free the exprcontext ... now dead code, see ExecFreeExprContext
175          */
176 #ifdef NOT_USED
177         if (node->biss_RuntimeContext)
178                 FreeExprContext(node->biss_RuntimeContext);
179 #endif
180
181         /*
182          * close the index relation
183          */
184         index_endscan(indexScanDesc);
185         index_close(indexRelationDesc);
186 }
187
188 /* ----------------------------------------------------------------
189  *              ExecInitBitmapIndexScan
190  *
191  *              Initializes the index scan's state information.
192  * ----------------------------------------------------------------
193  */
194 BitmapIndexScanState *
195 ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate)
196 {
197         BitmapIndexScanState *indexstate;
198         ScanKey         scanKeys;
199         int                     numScanKeys;
200         ExprState **runtimeKeyInfo;
201         bool            have_runtime_keys;
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 #define BITMAPINDEXSCAN_NSLOTS 0
230
231         /*
232          * Initialize index-specific scan state
233          */
234         indexstate->biss_RuntimeKeysReady = false;
235
236         CXT1_printf("ExecInitBitmapIndexScan: context is %d\n", CurrentMemoryContext);
237
238         /*
239          * build the index scan keys from the index qualification
240          */
241         have_runtime_keys =
242                 ExecIndexBuildScanKeys((PlanState *) indexstate,
243                                                            node->indexqual,
244                                                            node->indexstrategy,
245                                                            node->indexsubtype,
246                                                            &runtimeKeyInfo,
247                                                            &scanKeys,
248                                                            &numScanKeys);
249
250         indexstate->biss_RuntimeKeyInfo = runtimeKeyInfo;
251         indexstate->biss_ScanKeys = scanKeys;
252         indexstate->biss_NumScanKeys = numScanKeys;
253
254         /*
255          * If we have runtime keys, we need an ExprContext to evaluate them.
256          * We could just create a "standard" plan node exprcontext, but to
257          * keep the code looking similar to nodeIndexscan.c, it seems better
258          * to stick with the approach of using a separate ExprContext.
259          */
260         if (have_runtime_keys)
261         {
262                 ExprContext *stdecontext = indexstate->ss.ps.ps_ExprContext;
263
264                 ExecAssignExprContext(estate, &indexstate->ss.ps);
265                 indexstate->biss_RuntimeContext = indexstate->ss.ps.ps_ExprContext;
266                 indexstate->ss.ps.ps_ExprContext = stdecontext;
267         }
268         else
269         {
270                 indexstate->biss_RuntimeContext = NULL;
271         }
272
273         /*
274          * We do not open or lock the base relation here.  We assume that an
275          * ancestor BitmapHeapScan node is holding AccessShareLock on the
276          * heap relation throughout the execution of the plan tree.
277          */
278
279         indexstate->ss.ss_currentRelation = NULL;
280         indexstate->ss.ss_currentScanDesc = NULL;
281
282         /*
283          * open the index relation and initialize relation and scan
284          * descriptors.  Note we acquire no locks here; the index machinery
285          * does its own locks and unlocks.
286          */
287         indexstate->biss_RelationDesc = index_open(node->indexid);
288         indexstate->biss_ScanDesc =
289                 index_beginscan_multi(indexstate->biss_RelationDesc,
290                                                           estate->es_snapshot,
291                                                           numScanKeys,
292                                                           scanKeys);
293
294         /*
295          * all done.
296          */
297         return indexstate;
298 }
299
300 int
301 ExecCountSlotsBitmapIndexScan(BitmapIndexScan *node)
302 {
303         return ExecCountSlotsNode(outerPlan((Plan *) node)) +
304                 ExecCountSlotsNode(innerPlan((Plan *) node)) + BITMAPINDEXSCAN_NSLOTS;
305 }