PostgreSQL Source Code git master
nodeBitmapIndexscan.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * nodeBitmapIndexscan.c
4 * Routines to support bitmapped index scans of relations
5 *
6 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
8 *
9 *
10 * IDENTIFICATION
11 * src/backend/executor/nodeBitmapIndexscan.c
12 *
13 *-------------------------------------------------------------------------
14 */
15/*
16 * INTERFACE ROUTINES
17 * MultiExecBitmapIndexScan scans a relation using index.
18 * ExecInitBitmapIndexScan creates and initializes state info.
19 * ExecReScanBitmapIndexScan prepares to rescan the plan.
20 * ExecEndBitmapIndexScan releases all storage.
21 */
22#include "postgres.h"
23
24#include "access/genam.h"
25#include "executor/executor.h"
28#include "miscadmin.h"
29
30
31/* ----------------------------------------------------------------
32 * ExecBitmapIndexScan
33 *
34 * stub for pro forma compliance
35 * ----------------------------------------------------------------
36 */
37static TupleTableSlot *
39{
40 elog(ERROR, "BitmapIndexScan node does not support ExecProcNode call convention");
41 return NULL;
42}
43
44/* ----------------------------------------------------------------
45 * MultiExecBitmapIndexScan(node)
46 * ----------------------------------------------------------------
47 */
48Node *
50{
51 TIDBitmap *tbm;
52 IndexScanDesc scandesc;
53 double nTuples = 0;
54 bool doscan;
55
56 /* must provide our own instrumentation support */
57 if (node->ss.ps.instrument)
59
60 /*
61 * extract necessary information from index scan node
62 */
63 scandesc = node->biss_ScanDesc;
64
65 /*
66 * If we have runtime keys and they've not already been set up, do it now.
67 * Array keys are also treated as runtime keys; note that if ExecReScan
68 * returns with biss_RuntimeKeysReady still false, then there is an empty
69 * array key so we should do nothing.
70 */
71 if (!node->biss_RuntimeKeysReady &&
72 (node->biss_NumRuntimeKeys != 0 || node->biss_NumArrayKeys != 0))
73 {
74 ExecReScan((PlanState *) node);
75 doscan = node->biss_RuntimeKeysReady;
76 }
77 else
78 doscan = true;
79
80 /*
81 * Prepare the result bitmap. Normally we just create a new one to pass
82 * back; however, our parent node is allowed to store a pre-made one into
83 * node->biss_result, in which case we just OR our tuple IDs into the
84 * existing bitmap. (This saves needing explicit UNION steps.)
85 */
86 if (node->biss_result)
87 {
88 tbm = node->biss_result;
89 node->biss_result = NULL; /* reset for next time */
90 }
91 else
92 {
93 /* XXX should we use less than work_mem for this? */
94 tbm = tbm_create(work_mem * 1024L,
95 ((BitmapIndexScan *) node->ss.ps.plan)->isshared ?
96 node->ss.ps.state->es_query_dsa : NULL);
97 }
98
99 /*
100 * Get TIDs from index and insert into bitmap
101 */
102 while (doscan)
103 {
104 nTuples += (double) index_getbitmap(scandesc, tbm);
105
107
109 node->biss_NumArrayKeys);
110 if (doscan) /* reset index scan */
112 node->biss_ScanKeys, node->biss_NumScanKeys,
113 NULL, 0);
114 }
115
116 /* must provide our own instrumentation support */
117 if (node->ss.ps.instrument)
118 InstrStopNode(node->ss.ps.instrument, nTuples);
119
120 return (Node *) tbm;
121}
122
123/* ----------------------------------------------------------------
124 * ExecReScanBitmapIndexScan(node)
125 *
126 * Recalculates the values of any scan keys whose value depends on
127 * information known at runtime, then rescans the indexed relation.
128 * ----------------------------------------------------------------
129 */
130void
132{
133 ExprContext *econtext = node->biss_RuntimeContext;
134
135 /*
136 * Reset the runtime-key context so we don't leak memory as each outer
137 * tuple is scanned. Note this assumes that we will recalculate *all*
138 * runtime keys on each call.
139 */
140 if (econtext)
141 ResetExprContext(econtext);
142
143 /*
144 * If we are doing runtime key calculations (ie, any of the index key
145 * values weren't simple Consts), compute the new key values.
146 *
147 * Array keys are also treated as runtime keys; note that if we return
148 * with biss_RuntimeKeysReady still false, then there is an empty array
149 * key so no index scan is needed.
150 */
151 if (node->biss_NumRuntimeKeys != 0)
153 node->biss_RuntimeKeys,
154 node->biss_NumRuntimeKeys);
155 if (node->biss_NumArrayKeys != 0)
157 ExecIndexEvalArrayKeys(econtext,
158 node->biss_ArrayKeys,
159 node->biss_NumArrayKeys);
160 else
161 node->biss_RuntimeKeysReady = true;
162
163 /* reset index scan */
164 if (node->biss_RuntimeKeysReady)
166 node->biss_ScanKeys, node->biss_NumScanKeys,
167 NULL, 0);
168}
169
170/* ----------------------------------------------------------------
171 * ExecEndBitmapIndexScan
172 * ----------------------------------------------------------------
173 */
174void
176{
177 Relation indexRelationDesc;
178 IndexScanDesc indexScanDesc;
179
180 /*
181 * extract information from the node
182 */
183 indexRelationDesc = node->biss_RelationDesc;
184 indexScanDesc = node->biss_ScanDesc;
185
186 /*
187 * close the index relation (no-op if we didn't open it)
188 */
189 if (indexScanDesc)
190 index_endscan(indexScanDesc);
191 if (indexRelationDesc)
192 index_close(indexRelationDesc, NoLock);
193}
194
195/* ----------------------------------------------------------------
196 * ExecInitBitmapIndexScan
197 *
198 * Initializes the index scan's state information.
199 * ----------------------------------------------------------------
200 */
203{
204 BitmapIndexScanState *indexstate;
205 LOCKMODE lockmode;
206
207 /* check for unsupported flags */
209
210 /*
211 * create state structure
212 */
213 indexstate = makeNode(BitmapIndexScanState);
214 indexstate->ss.ps.plan = (Plan *) node;
215 indexstate->ss.ps.state = estate;
217
218 /* normally we don't make the result bitmap till runtime */
219 indexstate->biss_result = NULL;
220
221 /*
222 * We do not open or lock the base relation here. We assume that an
223 * ancestor BitmapHeapScan node is holding AccessShareLock (or better) on
224 * the heap relation throughout the execution of the plan tree.
225 */
226
227 indexstate->ss.ss_currentRelation = NULL;
228 indexstate->ss.ss_currentScanDesc = NULL;
229
230 /*
231 * Miscellaneous initialization
232 *
233 * We do not need a standard exprcontext for this node, though we may
234 * decide below to create a runtime-key exprcontext
235 */
236
237 /*
238 * initialize child expressions
239 *
240 * We don't need to initialize targetlist or qual since neither are used.
241 *
242 * Note: we don't initialize all of the indexqual expression, only the
243 * sub-parts corresponding to runtime keys (see below).
244 */
245
246 /*
247 * If we are just doing EXPLAIN (ie, aren't going to run the plan), stop
248 * here. This allows an index-advisor plugin to EXPLAIN a plan containing
249 * references to nonexistent indexes.
250 */
251 if (eflags & EXEC_FLAG_EXPLAIN_ONLY)
252 return indexstate;
253
254 /* Open the index relation. */
255 lockmode = exec_rt_fetch(node->scan.scanrelid, estate)->rellockmode;
256 indexstate->biss_RelationDesc = index_open(node->indexid, lockmode);
257
258 /*
259 * Initialize index-specific scan state
260 */
261 indexstate->biss_RuntimeKeysReady = false;
262 indexstate->biss_RuntimeKeys = NULL;
263 indexstate->biss_NumRuntimeKeys = 0;
264
265 /*
266 * build the index scan keys from the index qualification
267 */
268 ExecIndexBuildScanKeys((PlanState *) indexstate,
269 indexstate->biss_RelationDesc,
270 node->indexqual,
271 false,
272 &indexstate->biss_ScanKeys,
273 &indexstate->biss_NumScanKeys,
274 &indexstate->biss_RuntimeKeys,
275 &indexstate->biss_NumRuntimeKeys,
276 &indexstate->biss_ArrayKeys,
277 &indexstate->biss_NumArrayKeys);
278
279 /*
280 * If we have runtime keys or array keys, we need an ExprContext to
281 * evaluate them. We could just create a "standard" plan node exprcontext,
282 * but to keep the code looking similar to nodeIndexscan.c, it seems
283 * better to stick with the approach of using a separate ExprContext.
284 */
285 if (indexstate->biss_NumRuntimeKeys != 0 ||
286 indexstate->biss_NumArrayKeys != 0)
287 {
288 ExprContext *stdecontext = indexstate->ss.ps.ps_ExprContext;
289
290 ExecAssignExprContext(estate, &indexstate->ss.ps);
291 indexstate->biss_RuntimeContext = indexstate->ss.ps.ps_ExprContext;
292 indexstate->ss.ps.ps_ExprContext = stdecontext;
293 }
294 else
295 {
296 indexstate->biss_RuntimeContext = NULL;
297 }
298
299 /*
300 * Initialize scan descriptor.
301 */
302 indexstate->biss_ScanDesc =
304 estate->es_snapshot,
305 indexstate->biss_NumScanKeys);
306
307 /*
308 * If no run-time keys to calculate, go ahead and pass the scankeys to the
309 * index AM.
310 */
311 if (indexstate->biss_NumRuntimeKeys == 0 &&
312 indexstate->biss_NumArrayKeys == 0)
313 index_rescan(indexstate->biss_ScanDesc,
314 indexstate->biss_ScanKeys, indexstate->biss_NumScanKeys,
315 NULL, 0);
316
317 /*
318 * all done.
319 */
320 return indexstate;
321}
#define Assert(condition)
Definition: c.h:815
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
void ExecReScan(PlanState *node)
Definition: execAmi.c:76
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition: execUtils.c:485
#define EXEC_FLAG_BACKWARD
Definition: executor.h:68
static RangeTblEntry * exec_rt_fetch(Index rti, EState *estate)
Definition: executor.h:603
#define ResetExprContext(econtext)
Definition: executor.h:557
#define EXEC_FLAG_EXPLAIN_ONLY
Definition: executor.h:65
#define EXEC_FLAG_MARK
Definition: executor.h:69
int work_mem
Definition: globals.c:130
IndexScanDesc index_beginscan_bitmap(Relation indexRelation, Snapshot snapshot, int nkeys)
Definition: indexam.c:287
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:177
void index_endscan(IndexScanDesc scan)
Definition: indexam.c:378
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition: indexam.c:133
int64 index_getbitmap(IndexScanDesc scan, TIDBitmap *bitmap)
Definition: indexam.c:720
void index_rescan(IndexScanDesc scan, ScanKey keys, int nkeys, ScanKey orderbys, int norderbys)
Definition: indexam.c:352
void InstrStartNode(Instrumentation *instr)
Definition: instrument.c:68
void InstrStopNode(Instrumentation *instr, double nTuples)
Definition: instrument.c:84
int LOCKMODE
Definition: lockdefs.h:26
#define NoLock
Definition: lockdefs.h:34
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:122
Node * MultiExecBitmapIndexScan(BitmapIndexScanState *node)
void ExecEndBitmapIndexScan(BitmapIndexScanState *node)
BitmapIndexScanState * ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate, int eflags)
void ExecReScanBitmapIndexScan(BitmapIndexScanState *node)
static TupleTableSlot * ExecBitmapIndexScan(PlanState *pstate)
void ExecIndexBuildScanKeys(PlanState *planstate, Relation index, List *quals, bool isorderby, ScanKey *scanKeys, int *numScanKeys, IndexRuntimeKeyInfo **runtimeKeys, int *numRuntimeKeys, IndexArrayKeyInfo **arrayKeys, int *numArrayKeys)
bool ExecIndexEvalArrayKeys(ExprContext *econtext, IndexArrayKeyInfo *arrayKeys, int numArrayKeys)
void ExecIndexEvalRuntimeKeys(ExprContext *econtext, IndexRuntimeKeyInfo *runtimeKeys, int numRuntimeKeys)
bool ExecIndexAdvanceArrayKeys(IndexArrayKeyInfo *arrayKeys, int numArrayKeys)
#define makeNode(_type_)
Definition: nodes.h:155
ExprContext * biss_RuntimeContext
Definition: execnodes.h:1769
IndexArrayKeyInfo * biss_ArrayKeys
Definition: execnodes.h:1766
IndexRuntimeKeyInfo * biss_RuntimeKeys
Definition: execnodes.h:1764
TIDBitmap * biss_result
Definition: execnodes.h:1761
struct ScanKeyData * biss_ScanKeys
Definition: execnodes.h:1762
struct IndexScanDescData * biss_ScanDesc
Definition: execnodes.h:1771
Relation biss_RelationDesc
Definition: execnodes.h:1770
List * indexqual
Definition: plannodes.h:528
struct dsa_area * es_query_dsa
Definition: execnodes.h:733
Snapshot es_snapshot
Definition: execnodes.h:648
Definition: nodes.h:129
Instrumentation * instrument
Definition: execnodes.h:1151
Plan * plan
Definition: execnodes.h:1141
EState * state
Definition: execnodes.h:1143
ExprContext * ps_ExprContext
Definition: execnodes.h:1180
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:1147
Relation ss_currentRelation
Definition: execnodes.h:1589
PlanState ps
Definition: execnodes.h:1588
struct TableScanDescData * ss_currentScanDesc
Definition: execnodes.h:1590
Index scanrelid
Definition: plannodes.h:392
TIDBitmap * tbm_create(long maxbytes, dsa_area *dsa)
Definition: tidbitmap.c:266