Skip to content

Commit 8ca6d49

Browse files
committed
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
1 parent f9bc34f commit 8ca6d49

File tree

1 file changed

+83
-35
lines changed

1 file changed

+83
-35
lines changed

src/backend/access/heap/heapam.c

Lines changed: 83 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,82 @@ heapgettup_initial_block(HeapScanDesc scan, ScanDirection dir)
544544
}
545545
}
546546

547+
548+
/*
549+
* heapgettup_start_page - helper function for heapgettup()
550+
*
551+
* Return the next page to scan based on the scan->rs_cbuf and set *linesleft
552+
* to the number of tuples on this page. Also set *lineoff to the first
553+
* offset to scan with forward scans getting the first offset and backward
554+
* getting the final offset on the page.
555+
*/
556+
static Page
557+
heapgettup_start_page(HeapScanDesc scan, ScanDirection dir, int *linesleft,
558+
OffsetNumber *lineoff)
559+
{
560+
Page page;
561+
562+
Assert(scan->rs_inited);
563+
Assert(BufferIsValid(scan->rs_cbuf));
564+
565+
/* Caller is responsible for ensuring buffer is locked if needed */
566+
page = BufferGetPage(scan->rs_cbuf);
567+
568+
TestForOldSnapshot(scan->rs_base.rs_snapshot, scan->rs_base.rs_rd, page);
569+
570+
*linesleft = PageGetMaxOffsetNumber((Page) page) - FirstOffsetNumber + 1;
571+
572+
if (ScanDirectionIsForward(dir))
573+
*lineoff = FirstOffsetNumber;
574+
else
575+
*lineoff = (OffsetNumber) (*linesleft);
576+
577+
/* lineoff now references the physically previous or next tid */
578+
return page;
579+
}
580+
581+
582+
/*
583+
* heapgettup_continue_page - helper function for heapgettup()
584+
*
585+
* Return the next page to scan based on the scan->rs_cbuf and set *linesleft
586+
* to the number of tuples left to scan on this page. Also set *lineoff to
587+
* the next offset to scan according to the ScanDirection in 'dir'.
588+
*/
589+
static inline Page
590+
heapgettup_continue_page(HeapScanDesc scan, ScanDirection dir, int *linesleft,
591+
OffsetNumber *lineoff)
592+
{
593+
Page page;
594+
595+
Assert(scan->rs_inited);
596+
Assert(BufferIsValid(scan->rs_cbuf));
597+
598+
/* Caller is responsible for ensuring buffer is locked if needed */
599+
page = BufferGetPage(scan->rs_cbuf);
600+
601+
TestForOldSnapshot(scan->rs_base.rs_snapshot, scan->rs_base.rs_rd, page);
602+
603+
if (ScanDirectionIsForward(dir))
604+
{
605+
*lineoff = OffsetNumberNext(scan->rs_coffset);
606+
*linesleft = PageGetMaxOffsetNumber(page) - (*lineoff) + 1;
607+
}
608+
else
609+
{
610+
/*
611+
* The previous returned tuple may have been vacuumed since the
612+
* previous scan when we use a non-MVCC snapshot, so we must
613+
* re-establish the lineoff <= PageGetMaxOffsetNumber(page) invariant
614+
*/
615+
*lineoff = Min(PageGetMaxOffsetNumber(page), OffsetNumberPrev(scan->rs_coffset));
616+
*linesleft = *lineoff;
617+
}
618+
619+
/* lineoff now references the physically previous or next tid */
620+
return page;
621+
}
622+
547623
/* ----------------
548624
* heapgettup - fetch next heap tuple
549625
*
@@ -571,7 +647,6 @@ heapgettup(HeapScanDesc scan,
571647
ScanKey key)
572648
{
573649
HeapTuple tuple = &(scan->rs_ctup);
574-
Snapshot snapshot = scan->rs_base.rs_snapshot;
575650
bool backward = ScanDirectionIsBackward(dir);
576651
BlockNumber block;
577652
bool finished;
@@ -595,48 +670,20 @@ heapgettup(HeapScanDesc scan,
595670
tuple->t_data = NULL;
596671
return;
597672
}
673+
scan->rs_inited = true;
598674

599675
heapgetpage((TableScanDesc) scan, block);
600676

601677
LockBuffer(scan->rs_cbuf, BUFFER_LOCK_SHARE);
602-
page = BufferGetPage(scan->rs_cbuf);
603-
TestForOldSnapshot(snapshot, scan->rs_base.rs_rd, page);
604-
605-
linesleft = PageGetMaxOffsetNumber(page) - FirstOffsetNumber + 1;
606-
607-
if (ScanDirectionIsForward(dir))
608-
lineoff = FirstOffsetNumber; /* first offnum */
609-
else
610-
lineoff = (OffsetNumber) linesleft;
611-
612-
scan->rs_inited = true;
678+
page = heapgettup_start_page(scan, dir, &linesleft, &lineoff);
613679
}
614680
else
615681
{
616682
/* continue from previously returned page/tuple */
617683
block = scan->rs_cblock;
618684

619685
LockBuffer(scan->rs_cbuf, BUFFER_LOCK_SHARE);
620-
page = BufferGetPage(scan->rs_cbuf);
621-
TestForOldSnapshot(snapshot, scan->rs_base.rs_rd, page);
622-
623-
if (ScanDirectionIsForward(dir))
624-
{
625-
lineoff = OffsetNumberNext(scan->rs_coffset);
626-
linesleft = PageGetMaxOffsetNumber(page) - lineoff + 1;
627-
}
628-
else
629-
{
630-
/*
631-
* The previous returned tuple may have been vacuumed since the
632-
* previous scan when we use a non-MVCC snapshot, so we must
633-
* re-establish the lineoff <= PageGetMaxOffsetNumber(page)
634-
* invariant
635-
*/
636-
lineoff = Min(PageGetMaxOffsetNumber(page),
637-
OffsetNumberPrev(scan->rs_coffset));
638-
linesleft = lineoff;
639-
}
686+
page = heapgettup_continue_page(scan, dir, &linesleft, &lineoff);
640687
}
641688

642689
/*
@@ -667,12 +714,12 @@ heapgettup(HeapScanDesc scan,
667714
* if current tuple qualifies, return it.
668715
*/
669716
valid = HeapTupleSatisfiesVisibility(tuple,
670-
snapshot,
717+
scan->rs_base.rs_snapshot,
671718
scan->rs_cbuf);
672719

673720
HeapCheckForSerializableConflictOut(valid, scan->rs_base.rs_rd,
674721
tuple, scan->rs_cbuf,
675-
snapshot);
722+
scan->rs_base.rs_snapshot);
676723

677724
if (valid && key != NULL)
678725
valid = HeapKeyTest(tuple, RelationGetDescr(scan->rs_base.rs_rd),
@@ -773,7 +820,8 @@ heapgettup(HeapScanDesc scan,
773820
LockBuffer(scan->rs_cbuf, BUFFER_LOCK_SHARE);
774821

775822
page = BufferGetPage(scan->rs_cbuf);
776-
TestForOldSnapshot(snapshot, scan->rs_base.rs_rd, page);
823+
TestForOldSnapshot(scan->rs_base.rs_snapshot, scan->rs_base.rs_rd,
824+
page);
777825
linesleft = PageGetMaxOffsetNumber(page);
778826
if (backward)
779827
{

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy