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.9 2005/05/06 17:24:54 tgl 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
60 if (node->biss_RuntimeKeyInfo && !node->biss_RuntimeKeysReady)
61 ExecReScan((PlanState *) node, NULL);
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.)
69 if (node->biss_result)
71 tbm = node->biss_result;
72 node->biss_result = NULL; /* reset for next time */
76 /* XXX should we use less than work_mem for this? */
77 tbm = tbm_create(work_mem * 1024L);
81 * Get TIDs from index and insert into bitmap
85 bool more = index_getmulti(scandesc, tids, MAX_TIDS, &ntids);
89 tbm_add_tuples(tbm, tids, ntids);
96 CHECK_FOR_INTERRUPTS();
99 /* must provide our own instrumentation support */
100 if (node->ss.ps.instrument)
101 InstrStopNodeMulti(node->ss.ps.instrument, nTuples);
106 /* ----------------------------------------------------------------
107 * ExecBitmapIndexReScan(node)
109 * Recalculates the value of the scan keys whose value depends on
110 * information known at runtime and rescans the indexed relation.
111 * ----------------------------------------------------------------
114 ExecBitmapIndexReScan(BitmapIndexScanState *node, ExprContext *exprCtxt)
116 ExprContext *econtext;
117 ExprState **runtimeKeyInfo;
119 econtext = node->biss_RuntimeContext; /* context for runtime
121 runtimeKeyInfo = node->biss_RuntimeKeyInfo;
126 * If we are being passed an outer tuple, save it for runtime key
129 if (exprCtxt != NULL)
130 econtext->ecxt_outertuple = exprCtxt->ecxt_outertuple;
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.
137 ResetExprContext(econtext);
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
146 ExecIndexEvalRuntimeKeys(econtext,
149 node->biss_NumScanKeys);
150 node->biss_RuntimeKeysReady = true;
153 /* reset index scan */
154 index_rescan(node->biss_ScanDesc, node->biss_ScanKeys);
157 /* ----------------------------------------------------------------
158 * ExecEndBitmapIndexScan
159 * ----------------------------------------------------------------
162 ExecEndBitmapIndexScan(BitmapIndexScanState *node)
164 Relation indexRelationDesc;
165 IndexScanDesc indexScanDesc;
168 * extract information from the node
170 indexRelationDesc = node->biss_RelationDesc;
171 indexScanDesc = node->biss_ScanDesc;
174 * Free the exprcontext ... now dead code, see ExecFreeExprContext
177 if (node->biss_RuntimeContext)
178 FreeExprContext(node->biss_RuntimeContext);
182 * close the index relation
184 index_endscan(indexScanDesc);
185 index_close(indexRelationDesc);
188 /* ----------------------------------------------------------------
189 * ExecInitBitmapIndexScan
191 * Initializes the index scan's state information.
192 * ----------------------------------------------------------------
194 BitmapIndexScanState *
195 ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate)
197 BitmapIndexScanState *indexstate;
200 ExprState **runtimeKeyInfo;
201 bool have_runtime_keys;
204 * create state structure
206 indexstate = makeNode(BitmapIndexScanState);
207 indexstate->ss.ps.plan = (Plan *) node;
208 indexstate->ss.ps.state = estate;
210 /* normally we don't make the result bitmap till runtime */
211 indexstate->biss_result = NULL;
214 * Miscellaneous initialization
216 * We do not need a standard exprcontext for this node, though we may
217 * decide below to create a runtime-key exprcontext
221 * initialize child expressions
223 * We don't need to initialize targetlist or qual since neither are used.
225 * Note: we don't initialize all of the indexqual expression, only the
226 * sub-parts corresponding to runtime keys (see below).
229 #define BITMAPINDEXSCAN_NSLOTS 0
232 * Initialize index-specific scan state
234 indexstate->biss_RuntimeKeysReady = false;
236 CXT1_printf("ExecInitBitmapIndexScan: context is %d\n", CurrentMemoryContext);
239 * build the index scan keys from the index qualification
242 ExecIndexBuildScanKeys((PlanState *) indexstate,
250 indexstate->biss_RuntimeKeyInfo = runtimeKeyInfo;
251 indexstate->biss_ScanKeys = scanKeys;
252 indexstate->biss_NumScanKeys = numScanKeys;
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.
260 if (have_runtime_keys)
262 ExprContext *stdecontext = indexstate->ss.ps.ps_ExprContext;
264 ExecAssignExprContext(estate, &indexstate->ss.ps);
265 indexstate->biss_RuntimeContext = indexstate->ss.ps.ps_ExprContext;
266 indexstate->ss.ps.ps_ExprContext = stdecontext;
270 indexstate->biss_RuntimeContext = NULL;
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.
279 indexstate->ss.ss_currentRelation = NULL;
280 indexstate->ss.ss_currentScanDesc = NULL;
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.
287 indexstate->biss_RelationDesc = index_open(node->indexid);
288 indexstate->biss_ScanDesc =
289 index_beginscan_multi(indexstate->biss_RelationDesc,
301 ExecCountSlotsBitmapIndexScan(BitmapIndexScan *node)
303 return ExecCountSlotsNode(outerPlan((Plan *) node)) +
304 ExecCountSlotsNode(innerPlan((Plan *) node)) + BITMAPINDEXSCAN_NSLOTS;