@@ -567,7 +567,7 @@ heapgettup_start_page(HeapScanDesc scan, ScanDirection dir, int *linesleft,
567
567
568
568
TestForOldSnapshot (scan -> rs_base .rs_snapshot , scan -> rs_base .rs_rd , page );
569
569
570
- * linesleft = PageGetMaxOffsetNumber (( Page ) page ) - FirstOffsetNumber + 1 ;
570
+ * linesleft = PageGetMaxOffsetNumber (page ) - FirstOffsetNumber + 1 ;
571
571
572
572
if (ScanDirectionIsForward (dir ))
573
573
* lineoff = FirstOffsetNumber ;
@@ -732,34 +732,17 @@ heapgettup(HeapScanDesc scan,
732
732
ScanKey key )
733
733
{
734
734
HeapTuple tuple = & (scan -> rs_ctup );
735
- bool backward = ScanDirectionIsBackward (dir );
736
735
BlockNumber block ;
737
736
Page page ;
738
737
OffsetNumber lineoff ;
739
738
int linesleft ;
740
- ItemId lpp ;
741
739
742
740
if (unlikely (!scan -> rs_inited ))
743
741
{
744
742
block = heapgettup_initial_block (scan , dir );
745
-
746
- /*
747
- * Check if we have reached the end of the scan already. This could
748
- * happen if the table is empty or if the parallel workers have
749
- * already finished the scan before we did anything ourselves
750
- */
751
- if (block == InvalidBlockNumber )
752
- {
753
- Assert (!BufferIsValid (scan -> rs_cbuf ));
754
- tuple -> t_data = NULL ;
755
- return ;
756
- }
743
+ /* ensure rs_cbuf is invalid when we get InvalidBlockNumber */
744
+ Assert (block != InvalidBlockNumber || !BufferIsValid (scan -> rs_cbuf ));
757
745
scan -> rs_inited = true;
758
-
759
- heapgetpage ((TableScanDesc ) scan , block );
760
-
761
- LockBuffer (scan -> rs_cbuf , BUFFER_LOCK_SHARE );
762
- page = heapgettup_start_page (scan , dir , & linesleft , & lineoff );
763
746
}
764
747
else
765
748
{
@@ -768,69 +751,60 @@ heapgettup(HeapScanDesc scan,
768
751
769
752
LockBuffer (scan -> rs_cbuf , BUFFER_LOCK_SHARE );
770
753
page = heapgettup_continue_page (scan , dir , & linesleft , & lineoff );
754
+ goto continue_page ;
771
755
}
772
756
773
757
/*
774
758
* advance the scan until we find a qualifying tuple or run out of stuff
775
759
* to scan
776
760
*/
777
- lpp = PageGetItemId (page , lineoff );
778
- for (;;)
761
+ while (block != InvalidBlockNumber )
779
762
{
763
+ heapgetpage ((TableScanDesc ) scan , block );
764
+ LockBuffer (scan -> rs_cbuf , BUFFER_LOCK_SHARE );
765
+ page = heapgettup_start_page (scan , dir , & linesleft , & lineoff );
766
+ continue_page :
767
+
780
768
/*
781
769
* Only continue scanning the page while we have lines left.
782
770
*
783
771
* Note that this protects us from accessing line pointers past
784
772
* PageGetMaxOffsetNumber(); both for forward scans when we resume the
785
773
* table scan, and for when we start scanning a new page.
786
774
*/
787
- while ( linesleft > 0 )
775
+ for (; linesleft > 0 ; linesleft -- , lineoff += dir )
788
776
{
789
- if (ItemIdIsNormal (lpp ))
790
- {
791
- bool valid ;
777
+ bool visible ;
778
+ ItemId lpp = PageGetItemId (page , lineoff );
792
779
793
- tuple -> t_data = (HeapTupleHeader ) PageGetItem (page , lpp );
794
- tuple -> t_len = ItemIdGetLength (lpp );
795
- ItemPointerSet (& (tuple -> t_self ), block , lineoff );
780
+ if (!ItemIdIsNormal (lpp ))
781
+ continue ;
796
782
797
- /*
798
- * if current tuple qualifies, return it.
799
- */
800
- valid = HeapTupleSatisfiesVisibility (tuple ,
801
- scan -> rs_base .rs_snapshot ,
802
- scan -> rs_cbuf );
783
+ tuple -> t_data = (HeapTupleHeader ) PageGetItem (page , lpp );
784
+ tuple -> t_len = ItemIdGetLength (lpp );
785
+ ItemPointerSet (& (tuple -> t_self ), block , lineoff );
803
786
804
- HeapCheckForSerializableConflictOut ( valid , scan -> rs_base . rs_rd ,
805
- tuple , scan -> rs_cbuf ,
806
- scan -> rs_base . rs_snapshot );
787
+ visible = HeapTupleSatisfiesVisibility ( tuple ,
788
+ scan -> rs_base . rs_snapshot ,
789
+ scan -> rs_cbuf );
807
790
808
- if ( valid && key != NULL )
809
- valid = HeapKeyTest ( tuple , RelationGetDescr ( scan -> rs_base . rs_rd ) ,
810
- nkeys , key );
791
+ HeapCheckForSerializableConflictOut ( visible , scan -> rs_base . rs_rd ,
792
+ tuple , scan -> rs_cbuf ,
793
+ scan -> rs_base . rs_snapshot );
811
794
812
- if (valid )
813
- {
814
- LockBuffer (scan -> rs_cbuf , BUFFER_LOCK_UNLOCK );
815
- scan -> rs_coffset = lineoff ;
816
- return ;
817
- }
818
- }
795
+ /* skip tuples not visible to this snapshot */
796
+ if (!visible )
797
+ continue ;
819
798
820
- /*
821
- * otherwise move to the next item on the page
822
- */
823
- -- linesleft ;
824
- if (backward )
825
- {
826
- -- lpp ; /* move back in this page's ItemId array */
827
- -- lineoff ;
828
- }
829
- else
830
- {
831
- ++ lpp ; /* move forward in this page's ItemId array */
832
- ++ lineoff ;
833
- }
799
+ /* skip any tuples that don't match the scan key */
800
+ if (key != NULL &&
801
+ !HeapKeyTest (tuple , RelationGetDescr (scan -> rs_base .rs_rd ),
802
+ nkeys , key ))
803
+ continue ;
804
+
805
+ LockBuffer (scan -> rs_cbuf , BUFFER_LOCK_UNLOCK );
806
+ scan -> rs_coffset = lineoff ;
807
+ return ;
834
808
}
835
809
836
810
/*
@@ -841,40 +815,16 @@ heapgettup(HeapScanDesc scan,
841
815
842
816
/* get the BlockNumber to scan next */
843
817
block = heapgettup_advance_block (scan , block , dir );
818
+ }
844
819
845
- /*
846
- * return NULL if we've exhausted all the pages
847
- */
848
- if (block == InvalidBlockNumber )
849
- {
850
- if (BufferIsValid (scan -> rs_cbuf ))
851
- ReleaseBuffer (scan -> rs_cbuf );
852
- scan -> rs_cbuf = InvalidBuffer ;
853
- scan -> rs_cblock = InvalidBlockNumber ;
854
- tuple -> t_data = NULL ;
855
- scan -> rs_inited = false;
856
- return ;
857
- }
858
-
859
- heapgetpage ((TableScanDesc ) scan , block );
860
-
861
- LockBuffer (scan -> rs_cbuf , BUFFER_LOCK_SHARE );
820
+ /* end of scan */
821
+ if (BufferIsValid (scan -> rs_cbuf ))
822
+ ReleaseBuffer (scan -> rs_cbuf );
862
823
863
- page = BufferGetPage (scan -> rs_cbuf );
864
- TestForOldSnapshot (scan -> rs_base .rs_snapshot , scan -> rs_base .rs_rd ,
865
- page );
866
- linesleft = PageGetMaxOffsetNumber (page );
867
- if (backward )
868
- {
869
- lineoff = linesleft ;
870
- lpp = PageGetItemId (page , linesleft );
871
- }
872
- else
873
- {
874
- lineoff = FirstOffsetNumber ;
875
- lpp = PageGetItemId (page , FirstOffsetNumber );
876
- }
877
- }
824
+ scan -> rs_cbuf = InvalidBuffer ;
825
+ scan -> rs_cblock = InvalidBlockNumber ;
826
+ tuple -> t_data = NULL ;
827
+ scan -> rs_inited = false;
878
828
}
879
829
880
830
/* ----------------
@@ -897,35 +847,16 @@ heapgettup_pagemode(HeapScanDesc scan,
897
847
ScanKey key )
898
848
{
899
849
HeapTuple tuple = & (scan -> rs_ctup );
900
- bool backward = ScanDirectionIsBackward (dir );
901
850
BlockNumber block ;
902
851
Page page ;
903
852
int lineindex ;
904
- OffsetNumber lineoff ;
905
853
int linesleft ;
906
- ItemId lpp ;
907
854
908
855
if (unlikely (!scan -> rs_inited ))
909
856
{
910
857
block = heapgettup_initial_block (scan , dir );
911
-
912
- /*
913
- * Check if we have reached the end of the scan already. This could
914
- * happen if the table is empty or if the other workers in a parallel
915
- * scan have already finished the scan.
916
- */
917
- if (block == InvalidBlockNumber )
918
- {
919
- Assert (!BufferIsValid (scan -> rs_cbuf ));
920
- tuple -> t_data = NULL ;
921
- return ;
922
- }
923
-
924
- heapgetpage ((TableScanDesc ) scan , block );
925
- page = BufferGetPage (scan -> rs_cbuf );
926
- TestForOldSnapshot (scan -> rs_base .rs_snapshot , scan -> rs_base .rs_rd , page );
927
- linesleft = scan -> rs_ntuples ;
928
- lineindex = ScanDirectionIsForward (dir ) ? 0 : linesleft - 1 ;
858
+ /* ensure rs_cbuf is invalid when we get InvalidBlockNumber */
859
+ Assert (block != InvalidBlockNumber || !BufferIsValid (scan -> rs_cbuf ));
929
860
scan -> rs_inited = true;
930
861
}
931
862
else
@@ -940,16 +871,31 @@ heapgettup_pagemode(HeapScanDesc scan,
940
871
linesleft = scan -> rs_ntuples - lineindex ;
941
872
else
942
873
linesleft = scan -> rs_cindex ;
874
+ /* lineindex now references the next or previous visible tid */
875
+
876
+ goto continue_page ;
943
877
}
944
878
945
879
/*
946
880
* advance the scan until we find a qualifying tuple or run out of stuff
947
881
* to scan
948
882
*/
949
- for (;; )
883
+ while ( block != InvalidBlockNumber )
950
884
{
951
- while (linesleft > 0 )
885
+ heapgetpage ((TableScanDesc ) scan , block );
886
+ page = BufferGetPage (scan -> rs_cbuf );
887
+ TestForOldSnapshot (scan -> rs_base .rs_snapshot , scan -> rs_base .rs_rd , page );
888
+ linesleft = scan -> rs_ntuples ;
889
+ lineindex = ScanDirectionIsForward (dir ) ? 0 : linesleft - 1 ;
890
+
891
+ /* lineindex now references the next or previous visible tid */
892
+ continue_page :
893
+
894
+ for (; linesleft > 0 ; linesleft -- , lineindex += dir )
952
895
{
896
+ ItemId lpp ;
897
+ OffsetNumber lineoff ;
898
+
953
899
lineoff = scan -> rs_vistuples [lineindex ];
954
900
lpp = PageGetItemId (page , lineoff );
955
901
Assert (ItemIdIsNormal (lpp ));
@@ -958,64 +904,27 @@ heapgettup_pagemode(HeapScanDesc scan,
958
904
tuple -> t_len = ItemIdGetLength (lpp );
959
905
ItemPointerSet (& (tuple -> t_self ), block , lineoff );
960
906
961
- /*
962
- * if current tuple qualifies, return it.
963
- */
964
- if (key != NULL )
965
- {
966
- bool valid ;
967
-
968
- valid = HeapKeyTest (tuple , RelationGetDescr (scan -> rs_base .rs_rd ),
969
- nkeys , key );
970
- if (valid )
971
- {
972
- scan -> rs_cindex = lineindex ;
973
- return ;
974
- }
975
- }
976
- else
977
- {
978
- scan -> rs_cindex = lineindex ;
979
- return ;
980
- }
907
+ /* skip any tuples that don't match the scan key */
908
+ if (key != NULL &&
909
+ !HeapKeyTest (tuple , RelationGetDescr (scan -> rs_base .rs_rd ),
910
+ nkeys , key ))
911
+ continue ;
981
912
982
- /*
983
- * otherwise move to the next item on the page
984
- */
985
- -- linesleft ;
986
- if (backward )
987
- -- lineindex ;
988
- else
989
- ++ lineindex ;
913
+ scan -> rs_cindex = lineindex ;
914
+ return ;
990
915
}
991
916
992
917
/* get the BlockNumber to scan next */
993
918
block = heapgettup_advance_block (scan , block , dir );
994
-
995
- /*
996
- * return NULL if we've exhausted all the pages
997
- */
998
- if (block == InvalidBlockNumber )
999
- {
1000
- if (BufferIsValid (scan -> rs_cbuf ))
1001
- ReleaseBuffer (scan -> rs_cbuf );
1002
- scan -> rs_cbuf = InvalidBuffer ;
1003
- scan -> rs_cblock = InvalidBlockNumber ;
1004
- tuple -> t_data = NULL ;
1005
- scan -> rs_inited = false;
1006
- return ;
1007
- }
1008
-
1009
- heapgetpage ((TableScanDesc ) scan , block );
1010
-
1011
- page = BufferGetPage (scan -> rs_cbuf );
1012
- TestForOldSnapshot (scan -> rs_base .rs_snapshot , scan -> rs_base .rs_rd , page );
1013
- linesleft = scan -> rs_ntuples ;
1014
- if (backward )
1015
- lineindex = linesleft - 1 ;
1016
- else
1017
- lineindex = 0 ;
1018
919
}
920
+
921
+ /* end of scan */
922
+ if (BufferIsValid (scan -> rs_cbuf ))
923
+ ReleaseBuffer (scan -> rs_cbuf );
924
+ scan -> rs_cbuf = InvalidBuffer ;
925
+ scan -> rs_cblock = InvalidBlockNumber ;
926
+ tuple -> t_data = NULL ;
927
+ scan -> rs_inited = false;
1019
928
}
1020
929
1021
930
0 commit comments