]> granicus.if.org Git - postgresql/blob - src/backend/executor/nodeBitmapIndexscan.c
Update misleading comment about the use of lanpltrusted ... it is
[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.8 2005/05/05 03:37:23 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
31
32 /* ----------------------------------------------------------------
33  *              MultiExecBitmapIndexScan(node)
34  * ----------------------------------------------------------------
35  */
36 Node *
37 MultiExecBitmapIndexScan(BitmapIndexScanState *node)
38 {
39 #define MAX_TIDS        1024
40         TIDBitmap  *tbm;
41         IndexScanDesc scandesc;
42         ItemPointerData tids[MAX_TIDS];
43         int32           ntids;
44         double          nTuples = 0;
45
46         /* must provide our own instrumentation support */
47         if (node->ss.ps.instrument)
48                 InstrStartNode(node->ss.ps.instrument);
49
50         /*
51          * extract necessary information from index scan node
52          */
53         scandesc = node->biss_ScanDesc;
54
55         /*
56          * If we have runtime keys and they've not already been set up, do it
57          * 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
65          * into node->biss_result, in which case we just OR our tuple IDs into
66          * the 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
119                                                                                                  * keys */
120         runtimeKeyInfo = node->biss_RuntimeKeyInfo;
121
122         if (econtext)
123         {
124                 /*
125                  * If we are being passed an outer tuple, save it for runtime key
126                  * calc.
127                  */
128                 if (exprCtxt != NULL)
129                         econtext->ecxt_outertuple = exprCtxt->ecxt_outertuple;
130
131                 /*
132                  * Reset the runtime-key context so we don't leak memory as each
133                  * outer tuple is scanned.      Note this assumes that we will
134                  * recalculate *all* runtime keys on each call.
135                  */
136                 ResetExprContext(econtext);
137         }
138
139         /*
140          * If we are doing runtime key calculations (ie, the index keys depend
141          * on data from an outer scan), compute the new key values
142          */
143         if (runtimeKeyInfo)
144         {
145                 ExecIndexEvalRuntimeKeys(econtext,
146                                                                  runtimeKeyInfo,
147                                                                  node->biss_ScanKeys,
148                                                                  node->biss_NumScanKeys);
149                 node->biss_RuntimeKeysReady = true;
150         }
151
152         /* reset index scan */
153         index_rescan(node->biss_ScanDesc, node->biss_ScanKeys);
154 }
155
156 /* ----------------------------------------------------------------
157  *              ExecEndBitmapIndexScan
158  * ----------------------------------------------------------------
159  */
160 void
161 ExecEndBitmapIndexScan(BitmapIndexScanState *node)
162 {
163         Relation        indexRelationDesc;
164         IndexScanDesc indexScanDesc;
165
166         /*
167          * extract information from the node
168          */
169         indexRelationDesc = node->biss_RelationDesc;
170         indexScanDesc = node->biss_ScanDesc;
171
172         /*
173          * Free the exprcontext ... now dead code, see ExecFreeExprContext
174          */
175 #ifdef NOT_USED
176         if (node->biss_RuntimeContext)
177                 FreeExprContext(node->biss_RuntimeContext);
178 #endif
179
180         /*
181          * close the index relation
182          */
183         index_endscan(indexScanDesc);
184         index_close(indexRelationDesc);
185 }
186
187 /* ----------------------------------------------------------------
188  *              ExecInitBitmapIndexScan
189  *
190  *              Initializes the index scan's state information.
191  * ----------------------------------------------------------------
192  */
193 BitmapIndexScanState *
194 ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate)
195 {
196         BitmapIndexScanState *indexstate;
197         ScanKey         scanKeys;
198         int                     numScanKeys;
199         ExprState **runtimeKeyInfo;
200         bool            have_runtime_keys;
201
202         /*
203          * create state structure
204          */
205         indexstate = makeNode(BitmapIndexScanState);
206         indexstate->ss.ps.plan = (Plan *) node;
207         indexstate->ss.ps.state = estate;
208
209         /* normally we don't make the result bitmap till runtime */
210         indexstate->biss_result = NULL;
211
212         /*
213          * Miscellaneous initialization
214          *
215          * We do not need a standard exprcontext for this node, though we may
216          * decide below to create a runtime-key exprcontext
217          */
218
219         /*
220          * initialize child expressions
221          *
222          * We don't need to initialize targetlist or qual since neither are used.
223          *
224          * Note: we don't initialize all of the indexqual expression, only the
225          * sub-parts corresponding to runtime keys (see below).
226          */
227
228 #define BITMAPINDEXSCAN_NSLOTS 0
229
230         /*
231          * Initialize index-specific scan state
232          */
233         indexstate->biss_RuntimeKeysReady = false;
234
235         CXT1_printf("ExecInitBitmapIndexScan: context is %d\n", CurrentMemoryContext);
236
237         /*
238          * build the index scan keys from the index qualification
239          */
240         have_runtime_keys =
241                 ExecIndexBuildScanKeys((PlanState *) indexstate,
242                                                            node->indexqual,
243                                                            node->indexstrategy,
244                                                            node->indexsubtype,
245                                                            &runtimeKeyInfo,
246                                                            &scanKeys,
247                                                            &numScanKeys);
248
249         indexstate->biss_RuntimeKeyInfo = runtimeKeyInfo;
250         indexstate->biss_ScanKeys = scanKeys;
251         indexstate->biss_NumScanKeys = numScanKeys;
252
253         /*
254          * If we have runtime keys, we need an ExprContext to evaluate them.
255          * We could just create a "standard" plan node exprcontext, but to
256          * keep the code looking similar to nodeIndexscan.c, it seems better
257          * to stick with the approach of using a separate ExprContext.
258          */
259         if (have_runtime_keys)
260         {
261                 ExprContext *stdecontext = indexstate->ss.ps.ps_ExprContext;
262
263                 ExecAssignExprContext(estate, &indexstate->ss.ps);
264                 indexstate->biss_RuntimeContext = indexstate->ss.ps.ps_ExprContext;
265                 indexstate->ss.ps.ps_ExprContext = stdecontext;
266         }
267         else
268         {
269                 indexstate->biss_RuntimeContext = NULL;
270         }
271
272         /*
273          * We do not open or lock the base relation here.  We assume that an
274          * ancestor BitmapHeapScan node is holding AccessShareLock on the
275          * heap relation throughout the execution of the plan tree.
276          */
277
278         indexstate->ss.ss_currentRelation = NULL;
279         indexstate->ss.ss_currentScanDesc = NULL;
280
281         /*
282          * open the index relation and initialize relation and scan
283          * descriptors.  Note we acquire no locks here; the index machinery
284          * does its own locks and unlocks.
285          */
286         indexstate->biss_RelationDesc = index_open(node->indexid);
287         indexstate->biss_ScanDesc =
288                 index_beginscan_multi(indexstate->biss_RelationDesc,
289                                                           estate->es_snapshot,
290                                                           numScanKeys,
291                                                           scanKeys);
292
293         /*
294          * all done.
295          */
296         return indexstate;
297 }
298
299 int
300 ExecCountSlotsBitmapIndexScan(BitmapIndexScan *node)
301 {
302         return ExecCountSlotsNode(outerPlan((Plan *) node)) +
303                 ExecCountSlotsNode(innerPlan((Plan *) node)) + BITMAPINDEXSCAN_NSLOTS;
304 }