]> granicus.if.org Git - postgresql/blob - src/backend/executor/nodeBitmapIndexscan.c
Re-run pgindent, fixing a problem where comment lines after a blank
[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.11 2005/11/22 18:17:10 momjian 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 now.
58          */
59         if (node->biss_RuntimeKeyInfo && !node->biss_RuntimeKeysReady)
60                 ExecReScan((PlanState *) node, NULL);
61
62         /*
63          * Prepare the result bitmap.  Normally we just create a new one to pass
64          * back; however, our parent node is allowed to store a pre-made one into
65          * node->biss_result, in which case we just OR our tuple IDs into the
66          * existing bitmap.  (This saves needing explicit UNION steps.)
67          */
68         if (node->biss_result)
69         {
70                 tbm = node->biss_result;
71                 node->biss_result = NULL;               /* reset for next time */
72         }
73         else
74         {
75                 /* XXX should we use less than work_mem for this? */
76                 tbm = tbm_create(work_mem * 1024L);
77         }
78
79         /*
80          * Get TIDs from index and insert into bitmap
81          */
82         for (;;)
83         {
84                 bool            more = index_getmulti(scandesc, tids, MAX_TIDS, &ntids);
85
86                 if (ntids > 0)
87                 {
88                         tbm_add_tuples(tbm, tids, ntids);
89                         nTuples += ntids;
90                 }
91
92                 if (!more)
93                         break;
94
95                 CHECK_FOR_INTERRUPTS();
96         }
97
98         /* must provide our own instrumentation support */
99         if (node->ss.ps.instrument)
100                 InstrStopNodeMulti(node->ss.ps.instrument, nTuples);
101
102         return (Node *) tbm;
103 }
104
105 /* ----------------------------------------------------------------
106  *              ExecBitmapIndexReScan(node)
107  *
108  *              Recalculates the value of the scan keys whose value depends on
109  *              information known at runtime and rescans the indexed relation.
110  * ----------------------------------------------------------------
111  */
112 void
113 ExecBitmapIndexReScan(BitmapIndexScanState *node, ExprContext *exprCtxt)
114 {
115         ExprContext *econtext;
116         ExprState **runtimeKeyInfo;
117
118         econtext = node->biss_RuntimeContext;           /* context for runtime keys */
119         runtimeKeyInfo = node->biss_RuntimeKeyInfo;
120
121         if (econtext)
122         {
123                 /*
124                  * If we are being passed an outer tuple, save it for runtime key
125                  * calc.
126                  */
127                 if (exprCtxt != NULL)
128                         econtext->ecxt_outertuple = exprCtxt->ecxt_outertuple;
129
130                 /*
131                  * Reset the runtime-key context so we don't leak memory as each outer
132                  * tuple is scanned.  Note this assumes that we will recalculate *all*
133                  * runtime keys on each call.
134                  */
135                 ResetExprContext(econtext);
136         }
137
138         /*
139          * If we are doing runtime key calculations (ie, the index keys depend on
140          * data from an outer scan), compute the new key values
141          */
142         if (runtimeKeyInfo)
143         {
144                 ExecIndexEvalRuntimeKeys(econtext,
145                                                                  runtimeKeyInfo,
146                                                                  node->biss_ScanKeys,
147                                                                  node->biss_NumScanKeys);
148                 node->biss_RuntimeKeysReady = true;
149         }
150
151         /* reset index scan */
152         index_rescan(node->biss_ScanDesc, node->biss_ScanKeys);
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);
177 #endif
178
179         /*
180          * close the index relation
181          */
182         index_endscan(indexScanDesc);
183         index_close(indexRelationDesc);
184 }
185
186 /* ----------------------------------------------------------------
187  *              ExecInitBitmapIndexScan
188  *
189  *              Initializes the index scan's state information.
190  * ----------------------------------------------------------------
191  */
192 BitmapIndexScanState *
193 ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate)
194 {
195         BitmapIndexScanState *indexstate;
196         ScanKey         scanKeys;
197         int                     numScanKeys;
198         ExprState **runtimeKeyInfo;
199         bool            have_runtime_keys;
200
201         /*
202          * create state structure
203          */
204         indexstate = makeNode(BitmapIndexScanState);
205         indexstate->ss.ps.plan = (Plan *) node;
206         indexstate->ss.ps.state = estate;
207
208         /* normally we don't make the result bitmap till runtime */
209         indexstate->biss_result = NULL;
210
211         /*
212          * Miscellaneous initialization
213          *
214          * We do not need a standard exprcontext for this node, though we may
215          * decide below to create a runtime-key exprcontext
216          */
217
218         /*
219          * initialize child expressions
220          *
221          * We don't need to initialize targetlist or qual since neither are used.
222          *
223          * Note: we don't initialize all of the indexqual expression, only the
224          * sub-parts corresponding to runtime keys (see below).
225          */
226
227 #define BITMAPINDEXSCAN_NSLOTS 0
228
229         /*
230          * Initialize index-specific scan state
231          */
232         indexstate->biss_RuntimeKeysReady = false;
233
234         CXT1_printf("ExecInitBitmapIndexScan: context is %d\n", CurrentMemoryContext);
235
236         /*
237          * build the index scan keys from the index qualification
238          */
239         have_runtime_keys =
240                 ExecIndexBuildScanKeys((PlanState *) indexstate,
241                                                            node->indexqual,
242                                                            node->indexstrategy,
243                                                            node->indexsubtype,
244                                                            &runtimeKeyInfo,
245                                                            &scanKeys,
246                                                            &numScanKeys);
247
248         indexstate->biss_RuntimeKeyInfo = runtimeKeyInfo;
249         indexstate->biss_ScanKeys = scanKeys;
250         indexstate->biss_NumScanKeys = numScanKeys;
251
252         /*
253          * If we have runtime keys, we need an ExprContext to evaluate them. We
254          * could just create a "standard" plan node exprcontext, but to keep the
255          * code looking similar to nodeIndexscan.c, it seems better to stick with
256          * the approach of using a separate ExprContext.
257          */
258         if (have_runtime_keys)
259         {
260                 ExprContext *stdecontext = indexstate->ss.ps.ps_ExprContext;
261
262                 ExecAssignExprContext(estate, &indexstate->ss.ps);
263                 indexstate->biss_RuntimeContext = indexstate->ss.ps.ps_ExprContext;
264                 indexstate->ss.ps.ps_ExprContext = stdecontext;
265         }
266         else
267         {
268                 indexstate->biss_RuntimeContext = NULL;
269         }
270
271         /*
272          * We do not open or lock the base relation here.  We assume that an
273          * ancestor BitmapHeapScan node is holding AccessShareLock on the heap
274          * relation throughout the execution of the plan tree.
275          */
276
277         indexstate->ss.ss_currentRelation = NULL;
278         indexstate->ss.ss_currentScanDesc = NULL;
279
280         /*
281          * open the index relation and initialize relation and scan descriptors.
282          * Note we acquire no locks here; the index machinery does its own locks
283          * and unlocks.
284          */
285         indexstate->biss_RelationDesc = index_open(node->indexid);
286         indexstate->biss_ScanDesc =
287                 index_beginscan_multi(indexstate->biss_RelationDesc,
288                                                           estate->es_snapshot,
289                                                           numScanKeys,
290                                                           scanKeys);
291
292         /*
293          * all done.
294          */
295         return indexstate;
296 }
297
298 int
299 ExecCountSlotsBitmapIndexScan(BitmapIndexScan *node)
300 {
301         return ExecCountSlotsNode(outerPlan((Plan *) node)) +
302                 ExecCountSlotsNode(innerPlan((Plan *) node)) + BITMAPINDEXSCAN_NSLOTS;
303 }