1/*-------------------------------------------------------------------------
3 * nodeBitmapIndexscan.c
4 * Routines to support bitmapped index scans of relations
6 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * src/backend/executor/nodeBitmapIndexscan.c
13 *-------------------------------------------------------------------------
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.
31/* ----------------------------------------------------------------
34 * stub for pro forma compliance
35 * ----------------------------------------------------------------
40 elog(
ERROR,
"BitmapIndexScan node does not support ExecProcNode call convention");
44/* ----------------------------------------------------------------
45 * MultiExecBitmapIndexScan(node)
46 * ----------------------------------------------------------------
56 /* must provide our own instrumentation support */
61 * extract necessary information from index scan node
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.
75 doscan = node->biss_RuntimeKeysReady;
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.)
93 /* XXX should we use less than work_mem for this? */
100 * Get TIDs from index and insert into bitmap
110 if (doscan)
/* reset index scan */
116 /* must provide our own instrumentation support */
123/* ----------------------------------------------------------------
124 * ExecReScanBitmapIndexScan(node)
126 * Recalculates the values of any scan keys whose value depends on
127 * information known at runtime, then rescans the indexed relation.
128 * ----------------------------------------------------------------
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.
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.
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.
163 /* reset index scan */
170/* ----------------------------------------------------------------
171 * ExecEndBitmapIndexScan
172 * ----------------------------------------------------------------
181 * extract information from the node
187 * When ending a parallel worker, copy the statistics gathered by the
188 * worker back into shared memory so that it can be picked up by the main
189 * process to report in EXPLAIN ANALYZE
195 Assert(ParallelWorkerNumber <= node->biss_SharedInfo->num_workers);
199 * We have to accumulate the stats rather than performing a memcpy.
200 * When a Gather/GatherMerge node finishes it will perform planner
201 * shutdown on the workers. On rescan it will spin up new workers
202 * which will have a new BitmapIndexScanState and zeroed stats.
208 * close the index relation (no-op if we didn't open it)
212 if (indexRelationDesc)
216/* ----------------------------------------------------------------
217 * ExecInitBitmapIndexScan
219 * Initializes the index scan's state information.
220 * ----------------------------------------------------------------
228 /* check for unsupported flags */
232 * create state structure
239 /* normally we don't make the result bitmap till runtime */
243 * We do not open or lock the base relation here. We assume that an
244 * ancestor BitmapHeapScan node is holding AccessShareLock (or better) on
245 * the heap relation throughout the execution of the plan tree.
252 * Miscellaneous initialization
254 * We do not need a standard exprcontext for this node, though we may
255 * decide below to create a runtime-key exprcontext
259 * initialize child expressions
261 * We don't need to initialize targetlist or qual since neither are used.
263 * Note: we don't initialize all of the indexqual expression, only the
264 * sub-parts corresponding to runtime keys (see below).
268 * If we are just doing EXPLAIN (ie, aren't going to run the plan), stop
269 * here. This allows an index-advisor plugin to EXPLAIN a plan containing
270 * references to nonexistent indexes.
275 /* Open the index relation. */
280 * Initialize index-specific scan state
287 * build the index scan keys from the index qualification
301 * If we have runtime keys or array keys, we need an ExprContext to
302 * evaluate them. We could just create a "standard" plan node exprcontext,
303 * but to keep the code looking similar to nodeIndexscan.c, it seems
304 * better to stick with the approach of using a separate ExprContext.
321 * Initialize scan descriptor.
330 * If no run-time keys to calculate, go ahead and pass the scankeys to the
345/* ----------------------------------------------------------------
346 * ExecBitmapIndexScanEstimate
348 * Compute the amount of space we'll need in the parallel
349 * query DSM, and inform pcxt->estimator about our needs.
350 * ----------------------------------------------------------------
358 * Parallel bitmap index scans are not supported, but we still need to
359 * store the scan's instrumentation in DSM during parallel query
370/* ----------------------------------------------------------------
371 * ExecBitmapIndexScanInitializeDSM
373 * Set up bitmap index scan shared instrumentation.
374 * ----------------------------------------------------------------
382 /* don't need this if not instrumenting or no workers */
394 /* Each per-worker area must start out as zeroes */
399/* ----------------------------------------------------------------
400 * ExecBitmapIndexScanInitializeWorker
402 * Copy relevant information from TOC into planstate.
403 * ----------------------------------------------------------------
409 /* don't need this if not instrumenting */
417/* ----------------------------------------------------------------
418 * ExecBitmapIndexScanRetrieveInstrumentation
420 * Transfer bitmap index scan statistics from DSM to private memory.
421 * ----------------------------------------------------------------
429 if (SharedInfo == NULL)
432 /* Create a copy of SharedInfo in backend-local memory */
void ExecReScan(PlanState *node)
void ExecAssignExprContext(EState *estate, PlanState *planstate)
#define EXEC_FLAG_BACKWARD
static RangeTblEntry * exec_rt_fetch(Index rti, EState *estate)
#define ResetExprContext(econtext)
#define EXEC_FLAG_EXPLAIN_ONLY
struct IndexScanInstrumentation IndexScanInstrumentation
Assert(PointerIsAligned(start, uint64))
#define IsParallelWorker()
void index_close(Relation relation, LOCKMODE lockmode)
void index_endscan(IndexScanDesc scan)
IndexScanDesc index_beginscan_bitmap(Relation indexRelation, Snapshot snapshot, IndexScanInstrumentation *instrument, int nkeys)
Relation index_open(Oid relationId, LOCKMODE lockmode)
int64 index_getbitmap(IndexScanDesc scan, TIDBitmap *bitmap)
void index_rescan(IndexScanDesc scan, ScanKey keys, int nkeys, ScanKey orderbys, int norderbys)
void InstrStartNode(Instrumentation *instr)
void InstrStopNode(Instrumentation *instr, double nTuples)
#define CHECK_FOR_INTERRUPTS()
void ExecBitmapIndexScanEstimate(BitmapIndexScanState *node, ParallelContext *pcxt)
Node * MultiExecBitmapIndexScan(BitmapIndexScanState *node)
void ExecEndBitmapIndexScan(BitmapIndexScanState *node)
void ExecBitmapIndexScanInitializeDSM(BitmapIndexScanState *node, ParallelContext *pcxt)
BitmapIndexScanState * ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate, int eflags)
void ExecReScanBitmapIndexScan(BitmapIndexScanState *node)
void ExecBitmapIndexScanRetrieveInstrumentation(BitmapIndexScanState *node)
static TupleTableSlot * ExecBitmapIndexScan(PlanState *pstate)
void ExecBitmapIndexScanInitializeWorker(BitmapIndexScanState *node, ParallelWorkerContext *pwcxt)
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)
void * shm_toc_allocate(shm_toc *toc, Size nbytes)
void shm_toc_insert(shm_toc *toc, uint64 key, void *address)
void * shm_toc_lookup(shm_toc *toc, uint64 key, bool noError)
#define shm_toc_estimate_chunk(e, sz)
#define shm_toc_estimate_keys(e, cnt)
bool biss_RuntimeKeysReady
ExprContext * biss_RuntimeContext
IndexArrayKeyInfo * biss_ArrayKeys
ScanKeyData * biss_ScanKeys
IndexRuntimeKeyInfo * biss_RuntimeKeys
SharedIndexScanInstrumentation * biss_SharedInfo
struct IndexScanDescData * biss_ScanDesc
Relation biss_RelationDesc
IndexScanInstrumentation biss_Instrument
struct dsa_area * es_query_dsa
shm_toc_estimator estimator
Instrumentation * instrument
ExprContext * ps_ExprContext
ExecProcNodeMtd ExecProcNode
Relation ss_currentRelation
struct TableScanDescData * ss_currentScanDesc
IndexScanInstrumentation winstrument[FLEXIBLE_ARRAY_MEMBER]
TIDBitmap * tbm_create(Size maxbytes, dsa_area *dsa)