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)
        {