Add helper functions to simplify heapgettup code
authorDavid Rowley <drowley@postgresql.org>
Thu, 2 Feb 2023 23:38:42 +0000 (12:38 +1300)
committerDavid Rowley <drowley@postgresql.org>
Thu, 2 Feb 2023 23:38:42 +0000 (12:38 +1300)
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

src/backend/access/heap/heapam.c

index ec6b7962c50f848c2aac41495d1a3ff482fc7db0..57ff13ee8df41fd872cab6deee292be857076ce5 100644 (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)
                {