PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
nodeBitmapHeapscan.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * nodeBitmapHeapscan.c
4 * Routines to support bitmapped scans of relations
5 *
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.
17 *
18 *
19 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
20 * Portions Copyright (c) 1994, Regents of the University of California
21 *
22 *
23 * IDENTIFICATION
24 * src/backend/executor/nodeBitmapHeapscan.c
25 *
26 *-------------------------------------------------------------------------
27 */
28/*
29 * INTERFACE ROUTINES
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.
35 */
36#include "postgres.h"
37
38#include <math.h>
39
40#include "access/relscan.h"
41#include "access/tableam.h"
43#include "executor/executor.h"
45#include "miscadmin.h"
46#include "pgstat.h"
47#include "storage/bufmgr.h"
48#include "utils/rel.h"
49#include "utils/spccache.h"
50
55
56
57/*
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.
61 */
62static void
64{
65 TBMIterator tbmiterator = {0};
66 ParallelBitmapHeapState *pstate = node->pstate;
67 dsa_area *dsa = node->ss.ps.state->es_query_dsa;
68
69 if (!pstate)
70 {
72
73 if (!node->tbm || !IsA(node->tbm, TIDBitmap))
74 elog(ERROR, "unrecognized result from subplan");
75 }
76 else if (BitmapShouldInitializeSharedState(pstate))
77 {
78 /*
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.
81 */
83 if (!node->tbm || !IsA(node->tbm, TIDBitmap))
84 elog(ERROR, "unrecognized result from subplan");
85
86 /*
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
89 * iterate jointly.
90 */
92
93 /* We have initialized the shared state so wake up others. */
95 }
96
97 tbmiterator = tbm_begin_iterate(node->tbm, dsa,
98 pstate ?
99 pstate->tbmiterator :
101
102 /*
103 * If this is the first scan of the underlying table, create the table
104 * scan descriptor and begin the scan.
105 */
106 if (!node->ss.ss_currentScanDesc)
107 {
108 node->ss.ss_currentScanDesc =
110 node->ss.ps.state->es_snapshot,
111 0,
112 NULL);
113 }
114
115 node->ss.ss_currentScanDesc->st.rs_tbmiterator = tbmiterator;
116 node->initialized = true;
117}
118
119/* ----------------------------------------------------------------
120 * BitmapHeapNext
121 *
122 * Retrieve next tuple from the BitmapHeapScan node's currentRelation
123 * ----------------------------------------------------------------
124 */
125static TupleTableSlot *
127{
128 ExprContext *econtext = node->ss.ps.ps_ExprContext;
129 TupleTableSlot *slot = node->ss.ss_ScanTupleSlot;
130
131 /*
132 * If we haven't yet performed the underlying index scan, do it, and begin
133 * the iteration over the bitmap.
134 */
135 if (!node->initialized)
137
139 slot, &node->recheck,
140 &node->stats.lossy_pages,
141 &node->stats.exact_pages))
142 {
143 /*
144 * Continuing in previously obtained page.
145 */
147
148 /*
149 * If we are using lossy info, we have to recheck the qual conditions
150 * at every tuple.
151 */
152 if (node->recheck)
153 {
154 econtext->ecxt_scantuple = slot;
155 if (!ExecQualAndReset(node->bitmapqualorig, econtext))
156 {
157 /* Fails recheck, so drop it and loop back for another */
158 InstrCountFiltered2(node, 1);
159 ExecClearTuple(slot);
160 continue;
161 }
162 }
163
164 /* OK to return this tuple */
165 return slot;
166 }
167
168 /*
169 * if we get here it means we are at the end of the scan..
170 */
171 return ExecClearTuple(slot);
172}
173
174/*
175 * BitmapDoneInitializingSharedState - Shared state is initialized
176 *
177 * By this time the leader has already populated the TBM and initialized the
178 * shared state so wake up other processes.
179 */
180static inline void
182{
183 SpinLockAcquire(&pstate->mutex);
184 pstate->state = BM_FINISHED;
185 SpinLockRelease(&pstate->mutex);
187}
188
189/*
190 * BitmapHeapRecheck -- access method routine to recheck a tuple in EvalPlanQual
191 */
192static bool
194{
195 ExprContext *econtext;
196
197 /*
198 * extract necessary information from index scan node
199 */
200 econtext = node->ss.ps.ps_ExprContext;
201
202 /* Does the tuple meet the original qual conditions? */
203 econtext->ecxt_scantuple = slot;
204 return ExecQualAndReset(node->bitmapqualorig, econtext);
205}
206
207/* ----------------------------------------------------------------
208 * ExecBitmapHeapScan(node)
209 * ----------------------------------------------------------------
210 */
211static TupleTableSlot *
213{
215
216 return ExecScan(&node->ss,
219}
220
221/* ----------------------------------------------------------------
222 * ExecReScanBitmapHeapScan(node)
223 * ----------------------------------------------------------------
224 */
225void
227{
229
231
232 if (scan)
233 {
234 /*
235 * End iteration on iterators saved in scan descriptor if they have
236 * not already been cleaned up.
237 */
238 if (!tbm_exhausted(&scan->st.rs_tbmiterator))
240
241 /* rescan to release any page pin */
243 }
244
245 /* release bitmaps and buffers if any */
246 if (node->tbm)
247 tbm_free(node->tbm);
248 node->tbm = NULL;
249 node->initialized = false;
250 node->recheck = true;
251
252 ExecScanReScan(&node->ss);
253
254 /*
255 * if chgParam of subnode is not null then plan will be re-scanned by
256 * first ExecProcNode.
257 */
258 if (outerPlan->chgParam == NULL)
260}
261
262/* ----------------------------------------------------------------
263 * ExecEndBitmapHeapScan
264 * ----------------------------------------------------------------
265 */
266void
268{
269 TableScanDesc scanDesc;
270
271 /*
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.
275 */
276 if (node->sinstrument != NULL && IsParallelWorker())
277 {
279
280 Assert(ParallelWorkerNumber <= node->sinstrument->num_workers);
282
283 /*
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
288 * zeroed stats.
289 */
290 si->exact_pages += node->stats.exact_pages;
291 si->lossy_pages += node->stats.lossy_pages;
292 }
293
294 /*
295 * extract information from the node
296 */
297 scanDesc = node->ss.ss_currentScanDesc;
298
299 /*
300 * close down subplans
301 */
303
304 if (scanDesc)
305 {
306 /*
307 * End iteration on iterators saved in scan descriptor if they have
308 * not already been cleaned up.
309 */
310 if (!tbm_exhausted(&scanDesc->st.rs_tbmiterator))
312
313 /*
314 * close table scan
315 */
316 table_endscan(scanDesc);
317 }
318
319 /*
320 * release bitmaps and buffers if any
321 */
322 if (node->tbm)
323 tbm_free(node->tbm);
324}
325
326/* ----------------------------------------------------------------
327 * ExecInitBitmapHeapScan
328 *
329 * Initializes the scan's state information.
330 * ----------------------------------------------------------------
331 */
334{
335 BitmapHeapScanState *scanstate;
336 Relation currentRelation;
337
338 /* check for unsupported flags */
340
341 /*
342 * Assert caller didn't ask for an unsafe snapshot --- see comments at
343 * head of file.
344 */
346
347 /*
348 * create state structure
349 */
350 scanstate = makeNode(BitmapHeapScanState);
351 scanstate->ss.ps.plan = (Plan *) node;
352 scanstate->ss.ps.state = estate;
354
355 scanstate->tbm = NULL;
356
357 /* Zero the statistics counters */
358 memset(&scanstate->stats, 0, sizeof(BitmapHeapScanInstrumentation));
359
360 scanstate->initialized = false;
361 scanstate->pstate = NULL;
362 scanstate->recheck = true;
363
364 /*
365 * Miscellaneous initialization
366 *
367 * create expression context for node
368 */
369 ExecAssignExprContext(estate, &scanstate->ss.ps);
370
371 /*
372 * open the scan relation
373 */
374 currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
375
376 /*
377 * initialize child nodes
378 */
379 outerPlanState(scanstate) = ExecInitNode(outerPlan(node), estate, eflags);
380
381 /*
382 * get the scan type from the relation descriptor.
383 */
384 ExecInitScanTupleSlot(estate, &scanstate->ss,
385 RelationGetDescr(currentRelation),
386 table_slot_callbacks(currentRelation));
387
388 /*
389 * Initialize result type and projection.
390 */
391 ExecInitResultTypeTL(&scanstate->ss.ps);
392 ExecAssignScanProjectionInfo(&scanstate->ss);
393
394 /*
395 * initialize child expressions
396 */
397 scanstate->ss.ps.qual =
398 ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
399 scanstate->bitmapqualorig =
400 ExecInitQual(node->bitmapqualorig, (PlanState *) scanstate);
401
402 scanstate->ss.ss_currentRelation = currentRelation;
403
404 /*
405 * all done.
406 */
407 return scanstate;
408}
409
410/*----------------
411 * BitmapShouldInitializeSharedState
412 *
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.
417 * ---------------
418 */
419static bool
421{
423
424 while (1)
425 {
426 SpinLockAcquire(&pstate->mutex);
427 state = pstate->state;
428 if (pstate->state == BM_INITIAL)
429 pstate->state = BM_INPROGRESS;
430 SpinLockRelease(&pstate->mutex);
431
432 /* Exit if bitmap is done, or if we're the leader. */
433 if (state != BM_INPROGRESS)
434 break;
435
436 /* Wait for the leader to wake us up. */
437 ConditionVariableSleep(&pstate->cv, WAIT_EVENT_PARALLEL_BITMAP_SCAN);
438 }
439
441
442 return (state == BM_INITIAL);
443}
444
445/* ----------------------------------------------------------------
446 * ExecBitmapHeapEstimate
447 *
448 * Compute the amount of space we'll need in the parallel
449 * query DSM, and inform pcxt->estimator about our needs.
450 * ----------------------------------------------------------------
451 */
452void
454 ParallelContext *pcxt)
455{
456 Size size;
457
458 size = MAXALIGN(sizeof(ParallelBitmapHeapState));
459
460 /* account for instrumentation, if required */
461 if (node->ss.ps.instrument && pcxt->nworkers > 0)
462 {
463 size = add_size(size, offsetof(SharedBitmapHeapInstrumentation, sinstrument));
464 size = add_size(size, mul_size(pcxt->nworkers, sizeof(BitmapHeapScanInstrumentation)));
465 }
466
467 shm_toc_estimate_chunk(&pcxt->estimator, size);
469}
470
471/* ----------------------------------------------------------------
472 * ExecBitmapHeapInitializeDSM
473 *
474 * Set up a parallel bitmap heap scan descriptor.
475 * ----------------------------------------------------------------
476 */
477void
479 ParallelContext *pcxt)
480{
482 SharedBitmapHeapInstrumentation *sinstrument = NULL;
483 dsa_area *dsa = node->ss.ps.state->es_query_dsa;
484 char *ptr;
485 Size size;
486
487 /* If there's no DSA, there are no workers; initialize nothing. */
488 if (dsa == NULL)
489 return;
490
491 size = MAXALIGN(sizeof(ParallelBitmapHeapState));
492 if (node->ss.ps.instrument && pcxt->nworkers > 0)
493 {
494 size = add_size(size, offsetof(SharedBitmapHeapInstrumentation, sinstrument));
495 size = add_size(size, mul_size(pcxt->nworkers, sizeof(BitmapHeapScanInstrumentation)));
496 }
497
498 ptr = shm_toc_allocate(pcxt->toc, size);
499 pstate = (ParallelBitmapHeapState *) ptr;
500 ptr += MAXALIGN(sizeof(ParallelBitmapHeapState));
501 if (node->ss.ps.instrument && pcxt->nworkers > 0)
502 sinstrument = (SharedBitmapHeapInstrumentation *) ptr;
503
504 pstate->tbmiterator = 0;
505
506 /* Initialize the mutex */
507 SpinLockInit(&pstate->mutex);
508 pstate->state = BM_INITIAL;
509
510 ConditionVariableInit(&pstate->cv);
511
512 if (sinstrument)
513 {
514 sinstrument->num_workers = pcxt->nworkers;
515
516 /* ensure any unfilled slots will contain zeroes */
517 memset(sinstrument->sinstrument, 0,
519 }
520
521 shm_toc_insert(pcxt->toc, node->ss.ps.plan->plan_node_id, pstate);
522 node->pstate = pstate;
523 node->sinstrument = sinstrument;
524}
525
526/* ----------------------------------------------------------------
527 * ExecBitmapHeapReInitializeDSM
528 *
529 * Reset shared state before beginning a fresh scan.
530 * ----------------------------------------------------------------
531 */
532void
534 ParallelContext *pcxt)
535{
536 ParallelBitmapHeapState *pstate = node->pstate;
537 dsa_area *dsa = node->ss.ps.state->es_query_dsa;
538
539 /* If there's no DSA, there are no workers; do nothing. */
540 if (dsa == NULL)
541 return;
542
543 pstate->state = BM_INITIAL;
544
545 if (DsaPointerIsValid(pstate->tbmiterator))
546 tbm_free_shared_area(dsa, pstate->tbmiterator);
547
549}
550
551/* ----------------------------------------------------------------
552 * ExecBitmapHeapInitializeWorker
553 *
554 * Copy relevant information from TOC into planstate.
555 * ----------------------------------------------------------------
556 */
557void
560{
561 char *ptr;
562
563 Assert(node->ss.ps.state->es_query_dsa != NULL);
564
565 ptr = shm_toc_lookup(pwcxt->toc, node->ss.ps.plan->plan_node_id, false);
566
567 node->pstate = (ParallelBitmapHeapState *) ptr;
568 ptr += MAXALIGN(sizeof(ParallelBitmapHeapState));
569
570 if (node->ss.ps.instrument)
572}
573
574/* ----------------------------------------------------------------
575 * ExecBitmapHeapRetrieveInstrumentation
576 *
577 * Transfer bitmap heap scan statistics from DSM to private memory.
578 * ----------------------------------------------------------------
579 */
580void
582{
583 SharedBitmapHeapInstrumentation *sinstrument = node->sinstrument;
584 Size size;
585
586 if (sinstrument == NULL)
587 return;
588
589 size = offsetof(SharedBitmapHeapInstrumentation, sinstrument)
590 + sinstrument->num_workers * sizeof(BitmapHeapScanInstrumentation);
591
592 node->sinstrument = palloc(size);
593 memcpy(node->sinstrument, sinstrument, size);
594}
int ParallelWorkerNumber
Definition: parallel.c:115
#define MAXALIGN(LEN)
Definition: c.h:782
size_t Size
Definition: c.h:576
bool ConditionVariableCancelSleep(void)
void ConditionVariableBroadcast(ConditionVariable *cv)
void ConditionVariableInit(ConditionVariable *cv)
void ConditionVariableSleep(ConditionVariable *cv, uint32 wait_event_info)
#define InvalidDsaPointer
Definition: dsa.h:78
#define DsaPointerIsValid(x)
Definition: dsa.h:106
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:226
void ExecReScan(PlanState *node)
Definition: execAmi.c:77
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition: execExpr.c:229
Node * MultiExecProcNode(PlanState *node)
Definition: execProcnode.c:507
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:562
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
Definition: execProcnode.c:142
TupleTableSlot * ExecScan(ScanState *node, ExecScanAccessMtd accessMtd, ExecScanRecheckMtd recheckMtd)
Definition: execScan.c:47
void ExecAssignScanProjectionInfo(ScanState *node)
Definition: execScan.c:81
void ExecScanReScan(ScanState *node)
Definition: execScan.c:108
void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:2000
void ExecInitResultTypeTL(PlanState *planstate)
Definition: execTuples.c:1944
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition: execUtils.c:486
Relation ExecOpenScanRelation(EState *estate, Index scanrelid, int eflags)
Definition: execUtils.c:743
#define outerPlanState(node)
Definition: execnodes.h:1255
#define InstrCountFiltered2(node, delta)
Definition: execnodes.h:1268
SharedBitmapState
Definition: execnodes.h:1840
@ BM_INITIAL
Definition: execnodes.h:1841
@ BM_FINISHED
Definition: execnodes.h:1843
@ BM_INPROGRESS
Definition: execnodes.h:1842
struct BitmapHeapScanInstrumentation BitmapHeapScanInstrumentation
#define EXEC_FLAG_BACKWARD
Definition: executor.h:69
bool(* ExecScanRecheckMtd)(ScanState *node, TupleTableSlot *slot)
Definition: executor.h:602
static bool ExecQualAndReset(ExprState *state, ExprContext *econtext)
Definition: executor.h:568
TupleTableSlot *(* ExecScanAccessMtd)(ScanState *node)
Definition: executor.h:601
#define EXEC_FLAG_MARK
Definition: executor.h:70
Assert(PointerIsAligned(start, uint64))
#define IsParallelWorker()
Definition: parallel.h:60
void * palloc(Size size)
Definition: mcxt.c:1940
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:123
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_)
Definition: nodes.h:164
#define makeNode(_type_)
Definition: nodes.h:161
#define castNode(_type_, nodeptr)
Definition: nodes.h:182
#define outerPlan(node)
Definition: plannodes.h:241
#define RelationGetDescr(relation)
Definition: rel.h:542
void * shm_toc_allocate(shm_toc *toc, Size nbytes)
Definition: shm_toc.c:88
void shm_toc_insert(shm_toc *toc, uint64 key, void *address)
Definition: shm_toc.c:171
void * shm_toc_lookup(shm_toc *toc, uint64 key, bool noError)
Definition: shm_toc.c:232
#define shm_toc_estimate_chunk(e, sz)
Definition: shm_toc.h:51
#define shm_toc_estimate_keys(e, cnt)
Definition: shm_toc.h:53
Size add_size(Size s1, Size s2)
Definition: shmem.c:493
Size mul_size(Size s1, Size s2)
Definition: shmem.c:510
#define IsMVCCSnapshot(snapshot)
Definition: snapmgr.h:55
#define SpinLockInit(lock)
Definition: spin.h:57
#define SpinLockRelease(lock)
Definition: spin.h:61
#define SpinLockAcquire(lock)
Definition: spin.h:59
ParallelBitmapHeapState * pstate
Definition: execnodes.h:1895
ExprState * bitmapqualorig
Definition: execnodes.h:1891
BitmapHeapScanInstrumentation stats
Definition: execnodes.h:1893
SharedBitmapHeapInstrumentation * sinstrument
Definition: execnodes.h:1896
TIDBitmap * tbm
Definition: execnodes.h:1892
List * bitmapqualorig
Definition: plannodes.h:653
struct dsa_area * es_query_dsa
Definition: execnodes.h:751
Snapshot es_snapshot
Definition: execnodes.h:657
TupleTableSlot * ecxt_scantuple
Definition: execnodes.h:268
SharedBitmapState state
Definition: execnodes.h:1858
dsa_pointer tbmiterator
Definition: execnodes.h:1856
ConditionVariable cv
Definition: execnodes.h:1859
shm_toc_estimator estimator
Definition: parallel.h:41
shm_toc * toc
Definition: parallel.h:44
Instrumentation * instrument
Definition: execnodes.h:1169
ExprState * qual
Definition: execnodes.h:1180
Plan * plan
Definition: execnodes.h:1159
EState * state
Definition: execnodes.h:1161
ExprContext * ps_ExprContext
Definition: execnodes.h:1198
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:1165
int plan_node_id
Definition: plannodes.h:207
Relation ss_currentRelation
Definition: execnodes.h:1616
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1618
PlanState ps
Definition: execnodes.h:1615
struct TableScanDescData * ss_currentScanDesc
Definition: execnodes.h:1617
Index scanrelid
Definition: plannodes.h:483
BitmapHeapScanInstrumentation sinstrument[FLEXIBLE_ARRAY_MEMBER]
Definition: execnodes.h:1873
TBMIterator rs_tbmiterator
Definition: relscan.h:47
union TableScanDescData::@49 st
Definition: dsa.c:348
Definition: regguts.h:323
const TupleTableSlotOps * table_slot_callbacks(Relation relation)
Definition: tableam.c:59
static void table_endscan(TableScanDesc scan)
Definition: tableam.h:979
static TableScanDesc table_beginscan_bm(Relation rel, Snapshot snapshot, int nkeys, struct ScanKeyData *key)
Definition: tableam.h:915
static bool table_scan_bitmap_next_tuple(TableScanDesc scan, TupleTableSlot *slot, bool *recheck, uint64 *lossy_pages, uint64 *exact_pages)
Definition: tableam.h:1925
static void table_rescan(TableScanDesc scan, struct ScanKeyData *key)
Definition: tableam.h:988
void tbm_free(TIDBitmap *tbm)
Definition: tidbitmap.c:311
void tbm_end_iterate(TBMIterator *iterator)
Definition: tidbitmap.c:1597
dsa_pointer tbm_prepare_shared_iterate(TIDBitmap *tbm)
Definition: tidbitmap.c:754
void tbm_free_shared_area(dsa_area *dsa, dsa_pointer dp)
Definition: tidbitmap.c:330
TBMIterator tbm_begin_iterate(TIDBitmap *tbm, dsa_area *dsa, dsa_pointer dsp)
Definition: tidbitmap.c:1574
static bool tbm_exhausted(TBMIterator *iterator)
Definition: tidbitmap.h:119
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:458