diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index bf2b9b19e7..6524fc44a5 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -360,14 +360,13 @@ heap_setscanlimits(TableScanDesc sscan, BlockNumber startBlk, BlockNumber numBlk } /* - * heapbuildvis - Utility function for heap scans. + * heap_page_prep - Prepare the current scan page to be scanned in pagemode * - * Given a page residing in a buffer saved in the scan descriptor, prune the - * page and determine which of its tuples are all visible, saving their offsets - * in an array in the scan descriptor. + * Preparation currently consists of 1. prune the scan's rs_cbuf page, and 2. + * fill the rs_vistuples array with the OffsetNumbers of visible tuples. */ void -heapbuildvis(TableScanDesc sscan) +heap_page_prep(TableScanDesc sscan) { HeapScanDesc scan = (HeapScanDesc) sscan; Buffer buffer = scan->rs_cbuf; @@ -381,6 +380,8 @@ heapbuildvis(TableScanDesc sscan) Assert(BufferGetBlockNumber(buffer) == block); + /* ensure we're not accidentally being used when not in pagemode */ + Assert(scan->rs_base.rs_flags & SO_ALLOW_PAGEMODE); snapshot = scan->rs_base.rs_snapshot; /* @@ -454,10 +455,10 @@ heapbuildvis(TableScanDesc sscan) } /* - * heapfetchbuf - subroutine for heapgettup() + * heapfetchbuf - read and pin the given MAIN_FORKNUM block number. * - * This routine reads the specified block of the relation into a buffer and - * returns with that pinned buffer saved in the scan descriptor. + * Read the specified block of the scan relation into a buffer and pin that + * buffer before saving it in the scan descriptor. */ static inline void heapfetchbuf(HeapScanDesc scan, BlockNumber block) @@ -878,8 +879,11 @@ heapgettup_pagemode(HeapScanDesc scan, */ while (block != InvalidBlockNumber) { + /* read the page */ heapfetchbuf(scan, block); - heapbuildvis((TableScanDesc) scan); + + /* prune the page and determine visible tuple offsets */ + heap_page_prep((TableScanDesc) scan); page = BufferGetPage(scan->rs_cbuf); linesleft = scan->rs_ntuples; lineindex = ScanDirectionIsForward(dir) ? 0 : linesleft - 1; diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c index f4f670e9b2..a4451c24b4 100644 --- a/src/backend/access/heap/heapam_handler.c +++ b/src/backend/access/heap/heapam_handler.c @@ -2352,6 +2352,7 @@ heapam_scan_sample_next_block(TableScanDesc scan, SampleScanState *scanstate) if (hscan->rs_nblocks == 0) return false; + /* release previous scan buffer, if any */ if (BufferIsValid(hscan->rs_cbuf)) { ReleaseBuffer(hscan->rs_cbuf); @@ -2403,7 +2404,7 @@ heapam_scan_sample_next_block(TableScanDesc scan, SampleScanState *scanstate) hscan->rs_cblock = blockno; - if (!BlockNumberIsValid(hscan->rs_cblock)) + if (!BlockNumberIsValid(blockno)) { hscan->rs_inited = false; return false; @@ -2412,22 +2413,19 @@ heapam_scan_sample_next_block(TableScanDesc scan, SampleScanState *scanstate) Assert(hscan->rs_cblock < hscan->rs_nblocks); /* - * We may scan multiple pages before finding tuples to yield or finishing - * the scan. Since we want to check for interrupts at least once per page, - * do so here. + * Be sure to check for interrupts at least once per page. Checks at + * higher code levels won't be able to stop a sample scan that encounters + * many pages' worth of consecutive dead tuples. */ CHECK_FOR_INTERRUPTS(); /* Read page using selected strategy */ hscan->rs_cbuf = ReadBufferExtended(hscan->rs_base.rs_rd, MAIN_FORKNUM, - hscan->rs_cblock, RBM_NORMAL, hscan->rs_strategy); + blockno, RBM_NORMAL, hscan->rs_strategy); - /* - * If pagemode is allowed, prune the page and build an array of visible - * tuple offsets. - */ + /* in pagemode, prune the page and determine visible tuple offsets */ if (hscan->rs_base.rs_flags & SO_ALLOW_PAGEMODE) - heapbuildvis(scan); + heap_page_prep(scan); hscan->rs_inited = true; return true; @@ -2590,7 +2588,7 @@ SampleHeapTupleVisible(TableScanDesc scan, Buffer buffer, if (scan->rs_flags & SO_ALLOW_PAGEMODE) { /* - * In pageatatime mode, heapgetpage() already did visibility checks, + * In pageatatime mode, heap_page_prep() already did visibility checks, * so just look at the info it left in rs_vistuples[]. * * We use a binary search over the known-sorted array. Note: we could diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h index 4d324c78e5..e8a211cf1b 100644 --- a/src/include/access/heapam.h +++ b/src/include/access/heapam.h @@ -267,7 +267,7 @@ extern TableScanDesc heap_beginscan(Relation relation, Snapshot snapshot, uint32 flags); extern void heap_setscanlimits(TableScanDesc sscan, BlockNumber startBlk, BlockNumber numBlks); -extern void heapbuildvis(TableScanDesc sscan); +extern void heap_page_prep(TableScanDesc sscan); extern void heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params, bool allow_strat, bool allow_sync, bool allow_pagemode); extern void heap_endscan(TableScanDesc sscan);