Add helper functions to simplify heapgettup code

Here we add heapgettup_start_page() and heapgettup_continue_page() to
simplify the code in the heapgettup() function.

Author: Melanie Plageman
Reviewed-by: David Rowley
Discussion: https://postgr.es/m/CAAKRu_bvkhka0CZQun28KTqhuUh5ZqY=_T8QEqZqOL02rpi2bw@mail.gmail.com
This commit is contained in:
David Rowley 2023-02-03 12:38:42 +13:00
parent f9bc34fcb6
commit 8ca6d49f63
1 changed files with 83 additions and 35 deletions

View File

@ -544,6 +544,82 @@ heapgettup_initial_block(HeapScanDesc scan, ScanDirection dir)
}
}
/*
* heapgettup_start_page - helper function for heapgettup()
*
* Return the next page to scan based on the scan->rs_cbuf and set *linesleft
* to the number of tuples on this page. Also set *lineoff to the first
* offset to scan with forward scans getting the first offset and backward
* getting the final offset on the page.
*/
static 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 function for heapgettup()
*
* Return the next page to scan based on the scan->rs_cbuf and set *linesleft
* to the number of tuples left to scan on this page. Also set *lineoff to
* the next offset to scan according to the ScanDirection in 'dir'.
*/
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_coffset);
*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_coffset));
*linesleft = *lineoff;
}
/* lineoff now references the physically previous or next tid */
return page;
}
/* ----------------
* heapgettup - fetch next heap tuple
*
@ -571,7 +647,6 @@ heapgettup(HeapScanDesc scan,
ScanKey key)
{
HeapTuple tuple = &(scan->rs_ctup);
Snapshot snapshot = scan->rs_base.rs_snapshot;
bool backward = ScanDirectionIsBackward(dir);
BlockNumber block;
bool finished;
@ -595,21 +670,12 @@ heapgettup(HeapScanDesc scan,
tuple->t_data = NULL;
return;
}
scan->rs_inited = true;
heapgetpage((TableScanDesc) scan, block);
LockBuffer(scan->rs_cbuf, BUFFER_LOCK_SHARE);
page = BufferGetPage(scan->rs_cbuf);
TestForOldSnapshot(snapshot, scan->rs_base.rs_rd, page);
linesleft = PageGetMaxOffsetNumber(page) - FirstOffsetNumber + 1;
if (ScanDirectionIsForward(dir))
lineoff = FirstOffsetNumber; /* first offnum */
else
lineoff = (OffsetNumber) linesleft;
scan->rs_inited = true;
page = heapgettup_start_page(scan, dir, &linesleft, &lineoff);
}
else
{
@ -617,26 +683,7 @@ heapgettup(HeapScanDesc scan,
block = scan->rs_cblock;
LockBuffer(scan->rs_cbuf, BUFFER_LOCK_SHARE);
page = BufferGetPage(scan->rs_cbuf);
TestForOldSnapshot(snapshot, scan->rs_base.rs_rd, page);
if (ScanDirectionIsForward(dir))
{
lineoff = OffsetNumberNext(scan->rs_coffset);
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_coffset));
linesleft = lineoff;
}
page = heapgettup_continue_page(scan, dir, &linesleft, &lineoff);
}
/*
@ -667,12 +714,12 @@ heapgettup(HeapScanDesc scan,
* if current tuple qualifies, return it.
*/
valid = HeapTupleSatisfiesVisibility(tuple,
snapshot,
scan->rs_base.rs_snapshot,
scan->rs_cbuf);
HeapCheckForSerializableConflictOut(valid, scan->rs_base.rs_rd,
tuple, scan->rs_cbuf,
snapshot);
scan->rs_base.rs_snapshot);
if (valid && key != NULL)
valid = HeapKeyTest(tuple, RelationGetDescr(scan->rs_base.rs_rd),
@ -773,7 +820,8 @@ heapgettup(HeapScanDesc scan,
LockBuffer(scan->rs_cbuf, BUFFER_LOCK_SHARE);
page = BufferGetPage(scan->rs_cbuf);
TestForOldSnapshot(snapshot, scan->rs_base.rs_rd, page);
TestForOldSnapshot(scan->rs_base.rs_snapshot, scan->rs_base.rs_rd,
page);
linesleft = PageGetMaxOffsetNumber(page);
if (backward)
{