1/*-------------------------------------------------------------------------
4 * Routines to support bitmapped scans of relations
6 * NOTE: it is critical that this plan type only be used with MVCC-compliant
7 * snapshots (ie, regular snapshots, not SnapshotAny or one of the other
8 * special snapshots). The reason is that since index and heap scans are
9 * decoupled, there can be no assurance that the index tuple prompting a
10 * visit to a particular heap TID still exists when the visit is made.
11 * Therefore the tuple might not exist anymore either (which is OK because
12 * heap_fetch will cope) --- but worse, the tuple slot could have been
13 * re-used for a newer tuple. With an MVCC snapshot the newer tuple is
14 * certain to fail the time qual and so it will not be mistakenly returned,
15 * but with anything else we might return a tuple that doesn't meet the
16 * required index qual conditions.
19 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
20 * Portions Copyright (c) 1994, Regents of the University of California
24 * src/backend/executor/nodeBitmapHeapscan.c
26 *-------------------------------------------------------------------------
30 * ExecBitmapHeapScan scans a relation using bitmap info
31 * ExecBitmapHeapNext workhorse for above
32 * ExecInitBitmapHeapScan creates and initializes state info.
33 * ExecReScanBitmapHeapScan prepares to rescan the plan.
34 * ExecEndBitmapHeapScan releases all storage.
58 * Do the underlying index scan, build the bitmap, set up the parallel state
59 * needed for parallel workers to iterate through the bitmap, and set up the
60 * underlying table scan descriptor.
74 elog(
ERROR,
"unrecognized result from subplan");
79 * The leader will immediately come out of the function, but others
80 * will be blocked until leader populates the TBM and wakes them up.
84 elog(
ERROR,
"unrecognized result from subplan");
87 * Prepare to iterate over the TBM. This will return the dsa_pointer
88 * of the iterator state which will be used by multiple processes to
93 /* We have initialized the shared state so wake up others. */
103 * If this is the first scan of the underlying table, create the table
104 * scan descriptor and begin the scan.
119/* ----------------------------------------------------------------
122 * Retrieve next tuple from the BitmapHeapScan node's currentRelation
123 * ----------------------------------------------------------------
132 * If we haven't yet performed the underlying index scan, do it, and begin
133 * the iteration over the bitmap.
144 * Continuing in previously obtained page.
149 * If we are using lossy info, we have to recheck the qual conditions
157 /* Fails recheck, so drop it and loop back for another */
164 /* OK to return this tuple */
169 * if we get here it means we are at the end of the scan..
175 * BitmapDoneInitializingSharedState - Shared state is initialized
177 * By this time the leader has already populated the TBM and initialized the
178 * shared state so wake up other processes.
190 * BitmapHeapRecheck -- access method routine to recheck a tuple in EvalPlanQual
198 * extract necessary information from index scan node
202 /* Does the tuple meet the original qual conditions? */
207/* ----------------------------------------------------------------
208 * ExecBitmapHeapScan(node)
209 * ----------------------------------------------------------------
221/* ----------------------------------------------------------------
222 * ExecReScanBitmapHeapScan(node)
223 * ----------------------------------------------------------------
235 * End iteration on iterators saved in scan descriptor if they have
236 * not already been cleaned up.
241 /* rescan to release any page pin */
245 /* release bitmaps and buffers if any */
255 * if chgParam of subnode is not null then plan will be re-scanned by
256 * first ExecProcNode.
262/* ----------------------------------------------------------------
263 * ExecEndBitmapHeapScan
264 * ----------------------------------------------------------------
272 * When ending a parallel worker, copy the statistics gathered by the
273 * worker back into shared memory so that it can be picked up by the main
274 * process to report in EXPLAIN ANALYZE.
280 Assert(ParallelWorkerNumber <= node->sinstrument->num_workers);
284 * Here we accumulate the stats rather than performing memcpy on
285 * node->stats into si. When a Gather/GatherMerge node finishes it
286 * will perform planner shutdown on the workers. On rescan it will
287 * spin up new workers which will have a new BitmapHeapScanState and
295 * extract information from the node
300 * close down subplans
307 * End iteration on iterators saved in scan descriptor if they have
308 * not already been cleaned up.
320 * release bitmaps and buffers if any
326/* ----------------------------------------------------------------
327 * ExecInitBitmapHeapScan
329 * Initializes the scan's state information.
330 * ----------------------------------------------------------------
338 /* check for unsupported flags */
342 * Assert caller didn't ask for an unsafe snapshot --- see comments at
348 * create state structure
355 scanstate->
tbm = NULL;
357 /* Zero the statistics counters */
365 * Miscellaneous initialization
367 * create expression context for node
372 * open the scan relation
377 * initialize child nodes
382 * get the scan type from the relation descriptor.
389 * Initialize result type and projection.
395 * initialize child expressions
411 * BitmapShouldInitializeSharedState
413 * The first process to come here and see the state to the BM_INITIAL
414 * will become the leader for the parallel bitmap scan and will be
415 * responsible for populating the TIDBitmap. The other processes will
416 * be blocked by the condition variable until the leader wakes them up.
432 /* Exit if bitmap is done, or if we're the leader. */
436 /* Wait for the leader to wake us up. */
445/* ----------------------------------------------------------------
446 * ExecBitmapHeapEstimate
448 * Compute the amount of space we'll need in the parallel
449 * query DSM, and inform pcxt->estimator about our needs.
450 * ----------------------------------------------------------------
460 /* account for instrumentation, if required */
471/* ----------------------------------------------------------------
472 * ExecBitmapHeapInitializeDSM
474 * Set up a parallel bitmap heap scan descriptor.
475 * ----------------------------------------------------------------
487 /* If there's no DSA, there are no workers; initialize nothing. */
506 /* Initialize the mutex */
516 /* ensure any unfilled slots will contain zeroes */
526/* ----------------------------------------------------------------
527 * ExecBitmapHeapReInitializeDSM
529 * Reset shared state before beginning a fresh scan.
530 * ----------------------------------------------------------------
539 /* If there's no DSA, there are no workers; do nothing. */
551/* ----------------------------------------------------------------
552 * ExecBitmapHeapInitializeWorker
554 * Copy relevant information from TOC into planstate.
555 * ----------------------------------------------------------------
574/* ----------------------------------------------------------------
575 * ExecBitmapHeapRetrieveInstrumentation
577 * Transfer bitmap heap scan statistics from DSM to private memory.
578 * ----------------------------------------------------------------
586 if (sinstrument == NULL)
bool ConditionVariableCancelSleep(void)
void ConditionVariableBroadcast(ConditionVariable *cv)
void ConditionVariableInit(ConditionVariable *cv)
void ConditionVariableSleep(ConditionVariable *cv, uint32 wait_event_info)
#define InvalidDsaPointer
#define DsaPointerIsValid(x)
void ExecReScan(PlanState *node)
ExprState * ExecInitQual(List *qual, PlanState *parent)
Node * MultiExecProcNode(PlanState *node)
void ExecEndNode(PlanState *node)
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
TupleTableSlot * ExecScan(ScanState *node, ExecScanAccessMtd accessMtd, ExecScanRecheckMtd recheckMtd)
void ExecAssignScanProjectionInfo(ScanState *node)
void ExecScanReScan(ScanState *node)
void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
void ExecInitResultTypeTL(PlanState *planstate)
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Relation ExecOpenScanRelation(EState *estate, Index scanrelid, int eflags)
#define outerPlanState(node)
#define InstrCountFiltered2(node, delta)
struct BitmapHeapScanInstrumentation BitmapHeapScanInstrumentation
#define EXEC_FLAG_BACKWARD
bool(* ExecScanRecheckMtd)(ScanState *node, TupleTableSlot *slot)
static bool ExecQualAndReset(ExprState *state, ExprContext *econtext)
TupleTableSlot *(* ExecScanAccessMtd)(ScanState *node)
Assert(PointerIsAligned(start, uint64))
#define IsParallelWorker()
#define CHECK_FOR_INTERRUPTS()
void ExecEndBitmapHeapScan(BitmapHeapScanState *node)
void ExecBitmapHeapInitializeWorker(BitmapHeapScanState *node, ParallelWorkerContext *pwcxt)
void ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
void ExecBitmapHeapEstimate(BitmapHeapScanState *node, ParallelContext *pcxt)
void ExecBitmapHeapRetrieveInstrumentation(BitmapHeapScanState *node)
void ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node, ParallelContext *pcxt)
static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate)
void ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node, ParallelContext *pcxt)
static TupleTableSlot * ExecBitmapHeapScan(PlanState *pstate)
BitmapHeapScanState * ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
static TupleTableSlot * BitmapHeapNext(BitmapHeapScanState *node)
static void BitmapTableScanSetup(BitmapHeapScanState *node)
static void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
static bool BitmapHeapRecheck(BitmapHeapScanState *node, TupleTableSlot *slot)
#define IsA(nodeptr, _type_)
#define castNode(_type_, nodeptr)
#define RelationGetDescr(relation)
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)
Size add_size(Size s1, Size s2)
Size mul_size(Size s1, Size s2)
#define IsMVCCSnapshot(snapshot)
#define SpinLockInit(lock)
#define SpinLockRelease(lock)
#define SpinLockAcquire(lock)
ParallelBitmapHeapState * pstate
ExprState * bitmapqualorig
BitmapHeapScanInstrumentation stats
SharedBitmapHeapInstrumentation * sinstrument
struct dsa_area * es_query_dsa
TupleTableSlot * ecxt_scantuple
shm_toc_estimator estimator
Instrumentation * instrument
ExprContext * ps_ExprContext
ExecProcNodeMtd ExecProcNode
Relation ss_currentRelation
TupleTableSlot * ss_ScanTupleSlot
struct TableScanDescData * ss_currentScanDesc
BitmapHeapScanInstrumentation sinstrument[FLEXIBLE_ARRAY_MEMBER]
TBMIterator rs_tbmiterator
union TableScanDescData::@50 st
const TupleTableSlotOps * table_slot_callbacks(Relation relation)
static void table_endscan(TableScanDesc scan)
static bool table_scan_bitmap_next_tuple(TableScanDesc scan, TupleTableSlot *slot, bool *recheck, uint64 *lossy_pages, uint64 *exact_pages)
static void table_rescan(TableScanDesc scan, ScanKeyData *key)
static TableScanDesc table_beginscan_bm(Relation rel, Snapshot snapshot, int nkeys, ScanKeyData *key)
void tbm_free(TIDBitmap *tbm)
void tbm_end_iterate(TBMIterator *iterator)
dsa_pointer tbm_prepare_shared_iterate(TIDBitmap *tbm)
void tbm_free_shared_area(dsa_area *dsa, dsa_pointer dp)
TBMIterator tbm_begin_iterate(TIDBitmap *tbm, dsa_area *dsa, dsa_pointer dsp)
static bool tbm_exhausted(TBMIterator *iterator)
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)