1 /*-------------------------------------------------------------------------
3 * nodeBitmapIndexscan.c
4 * Routines to support bitmapped index scans of relations
6 * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * $PostgreSQL: pgsql/src/backend/executor/nodeBitmapIndexscan.c,v 1.11 2005/11/22 18:17:10 momjian Exp $
13 *-------------------------------------------------------------------------
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.
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"
33 /* ----------------------------------------------------------------
34 * MultiExecBitmapIndexScan(node)
35 * ----------------------------------------------------------------
38 MultiExecBitmapIndexScan(BitmapIndexScanState *node)
42 IndexScanDesc scandesc;
43 ItemPointerData tids[MAX_TIDS];
47 /* must provide our own instrumentation support */
48 if (node->ss.ps.instrument)
49 InstrStartNode(node->ss.ps.instrument);
52 * extract necessary information from index scan node
54 scandesc = node->biss_ScanDesc;
57 * If we have runtime keys and they've not already been set up, do it now.
59 if (node->biss_RuntimeKeyInfo && !node->biss_RuntimeKeysReady)
60 ExecReScan((PlanState *) node, NULL);
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.)
68 if (node->biss_result)
70 tbm = node->biss_result;
71 node->biss_result = NULL; /* reset for next time */
75 /* XXX should we use less than work_mem for this? */
76 tbm = tbm_create(work_mem * 1024L);
80 * Get TIDs from index and insert into bitmap
84 bool more = index_getmulti(scandesc, tids, MAX_TIDS, &ntids);
88 tbm_add_tuples(tbm, tids, ntids);
95 CHECK_FOR_INTERRUPTS();
98 /* must provide our own instrumentation support */
99 if (node->ss.ps.instrument)
100 InstrStopNodeMulti(node->ss.ps.instrument, nTuples);
105 /* ----------------------------------------------------------------
106 * ExecBitmapIndexReScan(node)
108 * Recalculates the value of the scan keys whose value depends on
109 * information known at runtime and rescans the indexed relation.
110 * ----------------------------------------------------------------
113 ExecBitmapIndexReScan(BitmapIndexScanState *node, ExprContext *exprCtxt)
115 ExprContext *econtext;
116 ExprState **runtimeKeyInfo;
118 econtext = node->biss_RuntimeContext; /* context for runtime keys */
119 runtimeKeyInfo = node->biss_RuntimeKeyInfo;
124 * If we are being passed an outer tuple, save it for runtime key
127 if (exprCtxt != NULL)
128 econtext->ecxt_outertuple = exprCtxt->ecxt_outertuple;
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.
135 ResetExprContext(econtext);
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
144 ExecIndexEvalRuntimeKeys(econtext,
147 node->biss_NumScanKeys);
148 node->biss_RuntimeKeysReady = true;
151 /* reset index scan */
152 index_rescan(node->biss_ScanDesc, node->biss_ScanKeys);
155 /* ----------------------------------------------------------------
156 * ExecEndBitmapIndexScan
157 * ----------------------------------------------------------------
160 ExecEndBitmapIndexScan(BitmapIndexScanState *node)
162 Relation indexRelationDesc;
163 IndexScanDesc indexScanDesc;
166 * extract information from the node
168 indexRelationDesc = node->biss_RelationDesc;
169 indexScanDesc = node->biss_ScanDesc;
172 * Free the exprcontext ... now dead code, see ExecFreeExprContext
175 if (node->biss_RuntimeContext)
176 FreeExprContext(node->biss_RuntimeContext);
180 * close the index relation
182 index_endscan(indexScanDesc);
183 index_close(indexRelationDesc);
186 /* ----------------------------------------------------------------
187 * ExecInitBitmapIndexScan
189 * Initializes the index scan's state information.
190 * ----------------------------------------------------------------
192 BitmapIndexScanState *
193 ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate)
195 BitmapIndexScanState *indexstate;
198 ExprState **runtimeKeyInfo;
199 bool have_runtime_keys;
202 * create state structure
204 indexstate = makeNode(BitmapIndexScanState);
205 indexstate->ss.ps.plan = (Plan *) node;
206 indexstate->ss.ps.state = estate;
208 /* normally we don't make the result bitmap till runtime */
209 indexstate->biss_result = NULL;
212 * Miscellaneous initialization
214 * We do not need a standard exprcontext for this node, though we may
215 * decide below to create a runtime-key exprcontext
219 * initialize child expressions
221 * We don't need to initialize targetlist or qual since neither are used.
223 * Note: we don't initialize all of the indexqual expression, only the
224 * sub-parts corresponding to runtime keys (see below).
227 #define BITMAPINDEXSCAN_NSLOTS 0
230 * Initialize index-specific scan state
232 indexstate->biss_RuntimeKeysReady = false;
234 CXT1_printf("ExecInitBitmapIndexScan: context is %d\n", CurrentMemoryContext);
237 * build the index scan keys from the index qualification
240 ExecIndexBuildScanKeys((PlanState *) indexstate,
248 indexstate->biss_RuntimeKeyInfo = runtimeKeyInfo;
249 indexstate->biss_ScanKeys = scanKeys;
250 indexstate->biss_NumScanKeys = numScanKeys;
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.
258 if (have_runtime_keys)
260 ExprContext *stdecontext = indexstate->ss.ps.ps_ExprContext;
262 ExecAssignExprContext(estate, &indexstate->ss.ps);
263 indexstate->biss_RuntimeContext = indexstate->ss.ps.ps_ExprContext;
264 indexstate->ss.ps.ps_ExprContext = stdecontext;
268 indexstate->biss_RuntimeContext = NULL;
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.
277 indexstate->ss.ss_currentRelation = NULL;
278 indexstate->ss.ss_currentScanDesc = NULL;
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
285 indexstate->biss_RelationDesc = index_open(node->indexid);
286 indexstate->biss_ScanDesc =
287 index_beginscan_multi(indexstate->biss_RelationDesc,
299 ExecCountSlotsBitmapIndexScan(BitmapIndexScan *node)
301 return ExecCountSlotsNode(outerPlan((Plan *) node)) +
302 ExecCountSlotsNode(innerPlan((Plan *) node)) + BITMAPINDEXSCAN_NSLOTS;