@@ -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