@@ -544,6 +544,82 @@ heapgettup_initial_block(HeapScanDesc scan, ScanDirection dir)
544
544
}
545
545
}
546
546
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
+
547
623
/* ----------------
548
624
* heapgettup - fetch next heap tuple
549
625
*
@@ -571,7 +647,6 @@ heapgettup(HeapScanDesc scan,
571
647
ScanKey key )
572
648
{
573
649
HeapTuple tuple = & (scan -> rs_ctup );
574
- Snapshot snapshot = scan -> rs_base .rs_snapshot ;
575
650
bool backward = ScanDirectionIsBackward (dir );
576
651
BlockNumber block ;
577
652
bool finished ;
@@ -595,48 +670,20 @@ heapgettup(HeapScanDesc scan,
595
670
tuple -> t_data = NULL ;
596
671
return ;
597
672
}
673
+ scan -> rs_inited = true;
598
674
599
675
heapgetpage ((TableScanDesc ) scan , block );
600
676
601
677
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 );
613
679
}
614
680
else
615
681
{
616
682
/* continue from previously returned page/tuple */
617
683
block = scan -> rs_cblock ;
618
684
619
685
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 );
640
687
}
641
688
642
689
/*
@@ -667,12 +714,12 @@ heapgettup(HeapScanDesc scan,
667
714
* if current tuple qualifies, return it.
668
715
*/
669
716
valid = HeapTupleSatisfiesVisibility (tuple ,
670
- snapshot ,
717
+ scan -> rs_base . rs_snapshot ,
671
718
scan -> rs_cbuf );
672
719
673
720
HeapCheckForSerializableConflictOut (valid , scan -> rs_base .rs_rd ,
674
721
tuple , scan -> rs_cbuf ,
675
- snapshot );
722
+ scan -> rs_base . rs_snapshot );
676
723
677
724
if (valid && key != NULL )
678
725
valid = HeapKeyTest (tuple , RelationGetDescr (scan -> rs_base .rs_rd ),
@@ -773,7 +820,8 @@ heapgettup(HeapScanDesc scan,
773
820
LockBuffer (scan -> rs_cbuf , BUFFER_LOCK_SHARE );
774
821
775
822
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 );
777
825
linesleft = PageGetMaxOffsetNumber (page );
778
826
if (backward )
779
827
{
0 commit comments