From c0d7155fb0af55295b3bcd598c083b4690c538dd Mon Sep 17 00:00:00 2001 From: Melanie Plageman Date: Tue, 10 Jan 2023 14:06:56 -0500 Subject: [PATCH v7 4/6] Add heapgettup() helpers Add heapgettup_start_page() and heapgettup_continue_page(), helper functions for heapgettup(). --- src/backend/access/heap/heapam.c | 110 ++++++++++++++++++++++--------- 1 file changed, 79 insertions(+), 31 deletions(-) diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index 4e238d9558..223bb1d5d3 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -545,6 +545,83 @@ heapgettup_initial_block(HeapScanDesc scan, ScanDirection dir) return scan->rs_nblocks - 1; } + +/* + * heapgettup_start_page - helper for heapgettup() + * + * Given a scan descriptor with a valid buffer referenced in rs_cbuf containing + * a block which we have yet to scan, set our lineoff at the tuple we will + * start with and our linesleft to the number of tuples in the page. Return the + * page associated with that buffer. + */ +static inline Page +heapgettup_start_page(HeapScanDesc scan, ScanDirection dir, int *linesleft, + OffsetNumber *lineoff) +{ + Page page; + + Assert(scan->rs_inited); + Assert(BufferIsValid(scan->rs_cbuf)); + + /* Caller is responsible for ensuring buffer is locked if needed */ + page = BufferGetPage(scan->rs_cbuf); + + TestForOldSnapshot(scan->rs_base.rs_snapshot, scan->rs_base.rs_rd, page); + + *linesleft = PageGetMaxOffsetNumber((Page) page) - FirstOffsetNumber + 1; + + if (ScanDirectionIsForward(dir)) + *lineoff = FirstOffsetNumber; + else + *lineoff = (OffsetNumber) (*linesleft); + + /* lineoff now references the physically previous or next tid */ + return page; +} + + +/* + * heapgettup_continue_page - helper for heapgettup() + * + * Given a scan descriptor with a valid buffer referenced in rs_cbuf containing + * a block from which we have already fetched some tuples, set the lineoff to + * the start of the next tuple to fetch and update linesleft. Return the page + * associated with that buffer. + */ +static inline Page +heapgettup_continue_page(HeapScanDesc scan, ScanDirection dir, int *linesleft, + OffsetNumber *lineoff) +{ + Page page; + + Assert(scan->rs_inited); + Assert(BufferIsValid(scan->rs_cbuf)); + + /* Caller is responsible for ensuring buffer is locked if needed */ + page = BufferGetPage(scan->rs_cbuf); + + TestForOldSnapshot(scan->rs_base.rs_snapshot, scan->rs_base.rs_rd, page); + + if (ScanDirectionIsForward(dir)) + { + *lineoff = OffsetNumberNext(scan->rs_cindex); + *linesleft = PageGetMaxOffsetNumber(page) - (*lineoff) + 1; + } + else + { + /* + * The previous returned tuple may have been vacuumed since the + * previous scan when we use a non-MVCC snapshot, so we must + * re-establish the lineoff <= PageGetMaxOffsetNumber(page) invariant + */ + *lineoff = Min(PageGetMaxOffsetNumber(page), OffsetNumberPrev(scan->rs_cindex)); + *linesleft = *lineoff; + } + + /* lineoff now references the physically previous or next tid */ + return page; +} + /* ---------------- * heapgettup - fetch next heap tuple * @@ -605,43 +682,14 @@ heapgettup(HeapScanDesc scan, heapgetpage((TableScanDesc) scan, block); LockBuffer(scan->rs_cbuf, BUFFER_LOCK_SHARE); - page = BufferGetPage(scan->rs_cbuf); - TestForOldSnapshot(scan->rs_base.rs_snapshot, scan->rs_base.rs_rd, - page); - - linesleft = PageGetMaxOffsetNumber(page) - FirstOffsetNumber + 1; - - if (ScanDirectionIsForward(dir)) - lineoff = FirstOffsetNumber; - else - lineoff = (OffsetNumber) linesleft; + page = heapgettup_start_page(scan, dir, &linesleft, &lineoff); } else { block = scan->rs_cblock; LockBuffer(scan->rs_cbuf, BUFFER_LOCK_SHARE); - page = BufferGetPage(scan->rs_cbuf); - TestForOldSnapshot(scan->rs_base.rs_snapshot, scan->rs_base.rs_rd, page); - - if (ScanDirectionIsForward(dir)) - { - lineoff = OffsetNumberNext(scan->rs_cindex); - linesleft = PageGetMaxOffsetNumber(page) - lineoff + 1; - } - else - { - /* - * The previous returned tuple may have been vacuumed since the - * previous scan when we use a non-MVCC snapshot, so we must - * re-establish the lineoff <= PageGetMaxOffsetNumber(page) - * invariant - */ - lineoff = - Min(PageGetMaxOffsetNumber(page), - OffsetNumberPrev(scan->rs_cindex)); - linesleft = lineoff; - } + page = heapgettup_continue_page(scan, dir, &linesleft, &lineoff); } -- 2.37.2