@@ -576,101 +576,67 @@ heapgettup(HeapScanDesc scan,
576576 BlockNumber block ;
577577 bool finished ;
578578 Page page ;
579- int lines ;
580579 OffsetNumber lineoff ;
581580 int linesleft ;
582581 ItemId lpp ;
583582
584- /*
585- * calculate next starting lineoff, given scan direction
586- */
587- if (ScanDirectionIsForward (dir ))
583+ if (unlikely (!scan -> rs_inited ))
588584 {
589- if (!scan -> rs_inited )
590- {
591- block = heapgettup_initial_block (scan , dir );
585+ block = heapgettup_initial_block (scan , dir );
592586
593- /*
594- * Check if we have reached the end of the scan already. This
595- * could happen if the table is empty or if the parallel workers
596- * have already finished the scan before we did anything ourselves
597- */
598- if (block == InvalidBlockNumber )
599- {
600- Assert (!BufferIsValid (scan -> rs_cbuf ));
601- tuple -> t_data = NULL ;
602- return ;
603- }
604- heapgetpage ((TableScanDesc ) scan , block );
605- lineoff = FirstOffsetNumber ; /* first offnum */
606- scan -> rs_inited = true;
607- }
608- else
587+ /*
588+ * Check if we have reached the end of the scan already. This could
589+ * happen if the table is empty or if the parallel workers have
590+ * already finished the scan before we did anything ourselves
591+ */
592+ if (block == InvalidBlockNumber )
609593 {
610- /* continue from previously returned page/tuple */
611- block = scan -> rs_cblock ; /* current page */
612- lineoff = /* next offnum */
613- OffsetNumberNext (ItemPointerGetOffsetNumber (& (tuple -> t_self )));
594+ Assert (!BufferIsValid (scan -> rs_cbuf ));
595+ tuple -> t_data = NULL ;
596+ return ;
614597 }
615598
616- LockBuffer ( scan -> rs_cbuf , BUFFER_LOCK_SHARE );
599+ heapgetpage (( TableScanDesc ) scan , block );
617600
601+ LockBuffer (scan -> rs_cbuf , BUFFER_LOCK_SHARE );
618602 page = BufferGetPage (scan -> rs_cbuf );
619603 TestForOldSnapshot (snapshot , scan -> rs_base .rs_rd , page );
620- lines = PageGetMaxOffsetNumber (page );
621- /* block and lineoff now reference the physically next tid */
622604
623- linesleft = lines - lineoff + 1 ;
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;
624613 }
625614 else
626615 {
627- if (!scan -> rs_inited )
628- {
629- block = heapgettup_initial_block (scan , dir );
630-
631- /*
632- * Check if we have reached the end of the scan already. This
633- * could happen if the table is empty.
634- */
635- if (block == InvalidBlockNumber )
636- {
637- Assert (!BufferIsValid (scan -> rs_cbuf ));
638- tuple -> t_data = NULL ;
639- return ;
640- }
616+ /* continue from previously returned page/tuple */
617+ block = scan -> rs_cblock ;
641618
642- heapgetpage ((TableScanDesc ) scan , block );
643- LockBuffer (scan -> rs_cbuf , BUFFER_LOCK_SHARE );
619+ LockBuffer (scan -> rs_cbuf , BUFFER_LOCK_SHARE );
620+ page = BufferGetPage (scan -> rs_cbuf );
621+ TestForOldSnapshot (snapshot , scan -> rs_base .rs_rd , page );
644622
645- page = BufferGetPage (scan -> rs_cbuf );
646- TestForOldSnapshot (snapshot , scan -> rs_base .rs_rd , page );
647- lines = PageGetMaxOffsetNumber (page );
648- lineoff = lines ; /* final offnum */
649- scan -> rs_inited = true;
623+ if (ScanDirectionIsForward (dir ))
624+ {
625+ lineoff = OffsetNumberNext (scan -> rs_coffset );
626+ linesleft = PageGetMaxOffsetNumber (page ) - lineoff + 1 ;
650627 }
651628 else
652629 {
653- /* continue from previously returned page/tuple */
654- block = scan -> rs_cblock ; /* current page */
655- LockBuffer (scan -> rs_cbuf , BUFFER_LOCK_SHARE );
656-
657- page = BufferGetPage (scan -> rs_cbuf );
658- TestForOldSnapshot (snapshot , scan -> rs_base .rs_rd , page );
659- lines = PageGetMaxOffsetNumber (page );
660-
661630 /*
662631 * The previous returned tuple may have been vacuumed since the
663632 * previous scan when we use a non-MVCC snapshot, so we must
664633 * re-establish the lineoff <= PageGetMaxOffsetNumber(page)
665634 * invariant
666635 */
667- lineoff = /* previous offnum */
668- Min ( lines ,
669- OffsetNumberPrev ( ItemPointerGetOffsetNumber ( & ( tuple -> t_self )))) ;
636+ lineoff = Min ( PageGetMaxOffsetNumber ( page ),
637+ OffsetNumberPrev ( scan -> rs_coffset ));
638+ linesleft = lineoff ;
670639 }
671- /* block and lineoff now reference the physically previous tid */
672-
673- linesleft = lineoff ;
674640 }
675641
676642 /*
@@ -715,6 +681,7 @@ heapgettup(HeapScanDesc scan,
715681 if (valid )
716682 {
717683 LockBuffer (scan -> rs_cbuf , BUFFER_LOCK_UNLOCK );
684+ scan -> rs_coffset = lineoff ;
718685 return ;
719686 }
720687 }
@@ -807,12 +774,11 @@ heapgettup(HeapScanDesc scan,
807774
808775 page = BufferGetPage (scan -> rs_cbuf );
809776 TestForOldSnapshot (snapshot , scan -> rs_base .rs_rd , page );
810- lines = PageGetMaxOffsetNumber (page );
811- linesleft = lines ;
777+ linesleft = PageGetMaxOffsetNumber (page );
812778 if (backward )
813779 {
814- lineoff = lines ;
815- lpp = PageGetItemId (page , lines );
780+ lineoff = linesleft ;
781+ lpp = PageGetItemId (page , linesleft );
816782 }
817783 else
818784 {
@@ -846,87 +812,46 @@ heapgettup_pagemode(HeapScanDesc scan,
846812 BlockNumber block ;
847813 bool finished ;
848814 Page page ;
849- int lines ;
850815 int lineindex ;
851816 OffsetNumber lineoff ;
852817 int linesleft ;
853818 ItemId lpp ;
854819
855- /*
856- * calculate next starting lineindex, given scan direction
857- */
858- if (ScanDirectionIsForward (dir ))
820+ if (unlikely (!scan -> rs_inited ))
859821 {
860- if (!scan -> rs_inited )
861- {
862- block = heapgettup_initial_block (scan , dir );
822+ block = heapgettup_initial_block (scan , dir );
863823
864- /*
865- * Check if we have reached the end of the scan already. This
866- * could happen if the table is empty or if the parallel workers
867- * have already finished the scan before we did anything ourselves
868- */
869- if (block == InvalidBlockNumber )
870- {
871- Assert (!BufferIsValid (scan -> rs_cbuf ));
872- tuple -> t_data = NULL ;
873- return ;
874- }
875- heapgetpage ((TableScanDesc ) scan , block );
876- lineindex = 0 ;
877- scan -> rs_inited = true;
878- }
879- else
824+ /*
825+ * Check if we have reached the end of the scan already. This could
826+ * happen if the table is empty or if the other workers in a parallel
827+ * scan have already finished the scan.
828+ */
829+ if (block == InvalidBlockNumber )
880830 {
881- /* continue from previously returned page/tuple */
882- block = scan -> rs_cblock ; /* current page */
883- lineindex = scan -> rs_cindex + 1 ;
831+ Assert (! BufferIsValid ( scan -> rs_cbuf ));
832+ tuple -> t_data = NULL ;
833+ return ;
884834 }
885835
836+ heapgetpage ((TableScanDesc ) scan , block );
886837 page = BufferGetPage (scan -> rs_cbuf );
887838 TestForOldSnapshot (scan -> rs_base .rs_snapshot , scan -> rs_base .rs_rd , page );
888- lines = scan -> rs_ntuples ;
889- /* block and lineindex now reference the next visible tid */
890-
891- linesleft = lines - lineindex ;
839+ linesleft = scan -> rs_ntuples ;
840+ lineindex = ScanDirectionIsForward (dir ) ? 0 : linesleft - 1 ;
841+ scan -> rs_inited = true;
892842 }
893843 else
894844 {
895- if (!scan -> rs_inited )
896- {
897- block = heapgettup_initial_block (scan , dir );
898-
899- /*
900- * Check if we have reached the end of the scan already. This
901- * could happen if the table is empty.
902- */
903- if (block == InvalidBlockNumber )
904- {
905- Assert (!BufferIsValid (scan -> rs_cbuf ));
906- tuple -> t_data = NULL ;
907- return ;
908- }
845+ /* continue from previously returned page/tuple */
846+ block = scan -> rs_cblock ; /* current page */
847+ page = BufferGetPage (scan -> rs_cbuf );
848+ TestForOldSnapshot (scan -> rs_base .rs_snapshot , scan -> rs_base .rs_rd , page );
909849
910- heapgetpage ((TableScanDesc ) scan , block );
911- page = BufferGetPage (scan -> rs_cbuf );
912- TestForOldSnapshot (scan -> rs_base .rs_snapshot , scan -> rs_base .rs_rd , page );
913- lines = scan -> rs_ntuples ;
914- lineindex = lines - 1 ;
915- scan -> rs_inited = true;
916- }
850+ lineindex = scan -> rs_cindex + dir ;
851+ if (ScanDirectionIsForward (dir ))
852+ linesleft = scan -> rs_ntuples - lineindex ;
917853 else
918- {
919- /* continue from previously returned page/tuple */
920- block = scan -> rs_cblock ; /* current page */
921-
922- page = BufferGetPage (scan -> rs_cbuf );
923- TestForOldSnapshot (scan -> rs_base .rs_snapshot , scan -> rs_base .rs_rd , page );
924- lines = scan -> rs_ntuples ;
925- lineindex = scan -> rs_cindex - 1 ;
926- }
927- /* block and lineindex now reference the previous visible tid */
928-
929- linesleft = lineindex + 1 ;
854+ linesleft = scan -> rs_cindex ;
930855 }
931856
932857 /*
@@ -1041,10 +966,9 @@ heapgettup_pagemode(HeapScanDesc scan,
1041966
1042967 page = BufferGetPage (scan -> rs_cbuf );
1043968 TestForOldSnapshot (scan -> rs_base .rs_snapshot , scan -> rs_base .rs_rd , page );
1044- lines = scan -> rs_ntuples ;
1045- linesleft = lines ;
969+ linesleft = scan -> rs_ntuples ;
1046970 if (backward )
1047- lineindex = lines - 1 ;
971+ lineindex = linesleft - 1 ;
1048972 else
1049973 lineindex = 0 ;
1050974 }
0 commit comments