@@ -620,6 +620,91 @@ heapgettup_continue_page(HeapScanDesc scan, ScanDirection dir, int *linesleft,
620
620
return page ;
621
621
}
622
622
623
+ /*
624
+ * heapgettup_advance_block - helper for heapgettup() and heapgettup_pagemode()
625
+ *
626
+ * Given the current block number, the scan direction, and various information
627
+ * contained in the scan descriptor, calculate the BlockNumber to scan next
628
+ * and return it. If there are no further blocks to scan, return
629
+ * InvalidBlockNumber to indicate this fact to the caller.
630
+ *
631
+ * This should not be called to determine the initial block number -- only for
632
+ * subsequent blocks.
633
+ *
634
+ * This also adjusts rs_numblocks when a limit has been imposed by
635
+ * heap_setscanlimits().
636
+ */
637
+ static inline BlockNumber
638
+ heapgettup_advance_block (HeapScanDesc scan , BlockNumber block , ScanDirection dir )
639
+ {
640
+ if (ScanDirectionIsForward (dir ))
641
+ {
642
+ if (scan -> rs_base .rs_parallel == NULL )
643
+ {
644
+ block ++ ;
645
+
646
+ /* wrap back to the start of the heap */
647
+ if (block >= scan -> rs_nblocks )
648
+ block = 0 ;
649
+
650
+ /* we're done if we're back at where we started */
651
+ if (block == scan -> rs_startblock )
652
+ return InvalidBlockNumber ;
653
+
654
+ /* check if the limit imposed by heap_setscanlimits() is met */
655
+ if (scan -> rs_numblocks != InvalidBlockNumber )
656
+ {
657
+ if (-- scan -> rs_numblocks == 0 )
658
+ return InvalidBlockNumber ;
659
+ }
660
+
661
+ /*
662
+ * Report our new scan position for synchronization purposes. We
663
+ * don't do that when moving backwards, however. That would just
664
+ * mess up any other forward-moving scanners.
665
+ *
666
+ * Note: we do this before checking for end of scan so that the
667
+ * final state of the position hint is back at the start of the
668
+ * rel. That's not strictly necessary, but otherwise when you run
669
+ * the same query multiple times the starting position would shift
670
+ * a little bit backwards on every invocation, which is confusing.
671
+ * We don't guarantee any specific ordering in general, though.
672
+ */
673
+ if (scan -> rs_base .rs_flags & SO_ALLOW_SYNC )
674
+ ss_report_location (scan -> rs_base .rs_rd , block );
675
+
676
+ return block ;
677
+ }
678
+ else
679
+ {
680
+ return table_block_parallelscan_nextpage (scan -> rs_base .rs_rd ,
681
+ scan -> rs_parallelworkerdata , (ParallelBlockTableScanDesc )
682
+ scan -> rs_base .rs_parallel );
683
+ }
684
+ }
685
+ else
686
+ {
687
+ /* we're done if the last block is the start position */
688
+ if (block == scan -> rs_startblock )
689
+ return InvalidBlockNumber ;
690
+
691
+ /* check if the limit imposed by heap_setscanlimits() is met */
692
+ if (scan -> rs_numblocks != InvalidBlockNumber )
693
+ {
694
+ if (-- scan -> rs_numblocks == 0 )
695
+ return InvalidBlockNumber ;
696
+ }
697
+
698
+ /* wrap to the end of the heap when the last page was page 0 */
699
+ if (block == 0 )
700
+ block = scan -> rs_nblocks ;
701
+
702
+ block -- ;
703
+
704
+ return block ;
705
+ }
706
+ }
707
+
623
708
/* ----------------
624
709
* heapgettup - fetch next heap tuple
625
710
*
@@ -649,7 +734,6 @@ heapgettup(HeapScanDesc scan,
649
734
HeapTuple tuple = & (scan -> rs_ctup );
650
735
bool backward = ScanDirectionIsBackward (dir );
651
736
BlockNumber block ;
652
- bool finished ;
653
737
Page page ;
654
738
OffsetNumber lineoff ;
655
739
int linesleft ;
@@ -755,56 +839,13 @@ heapgettup(HeapScanDesc scan,
755
839
*/
756
840
LockBuffer (scan -> rs_cbuf , BUFFER_LOCK_UNLOCK );
757
841
758
- /*
759
- * advance to next/prior page and detect end of scan
760
- */
761
- if (backward )
762
- {
763
- finished = (block == scan -> rs_startblock ) ||
764
- (scan -> rs_numblocks != InvalidBlockNumber ? -- scan -> rs_numblocks == 0 : false);
765
- if (block == 0 )
766
- block = scan -> rs_nblocks ;
767
- block -- ;
768
- }
769
- else if (scan -> rs_base .rs_parallel != NULL )
770
- {
771
- ParallelBlockTableScanDesc pbscan =
772
- (ParallelBlockTableScanDesc ) scan -> rs_base .rs_parallel ;
773
- ParallelBlockTableScanWorker pbscanwork =
774
- scan -> rs_parallelworkerdata ;
775
-
776
- block = table_block_parallelscan_nextpage (scan -> rs_base .rs_rd ,
777
- pbscanwork , pbscan );
778
- finished = (block == InvalidBlockNumber );
779
- }
780
- else
781
- {
782
- block ++ ;
783
- if (block >= scan -> rs_nblocks )
784
- block = 0 ;
785
- finished = (block == scan -> rs_startblock ) ||
786
- (scan -> rs_numblocks != InvalidBlockNumber ? -- scan -> rs_numblocks == 0 : false);
787
-
788
- /*
789
- * Report our new scan position for synchronization purposes. We
790
- * don't do that when moving backwards, however. That would just
791
- * mess up any other forward-moving scanners.
792
- *
793
- * Note: we do this before checking for end of scan so that the
794
- * final state of the position hint is back at the start of the
795
- * rel. That's not strictly necessary, but otherwise when you run
796
- * the same query multiple times the starting position would shift
797
- * a little bit backwards on every invocation, which is confusing.
798
- * We don't guarantee any specific ordering in general, though.
799
- */
800
- if (scan -> rs_base .rs_flags & SO_ALLOW_SYNC )
801
- ss_report_location (scan -> rs_base .rs_rd , block );
802
- }
842
+ /* get the BlockNumber to scan next */
843
+ block = heapgettup_advance_block (scan , block , dir );
803
844
804
845
/*
805
846
* return NULL if we've exhausted all the pages
806
847
*/
807
- if (finished )
848
+ if (block == InvalidBlockNumber )
808
849
{
809
850
if (BufferIsValid (scan -> rs_cbuf ))
810
851
ReleaseBuffer (scan -> rs_cbuf );
@@ -858,7 +899,6 @@ heapgettup_pagemode(HeapScanDesc scan,
858
899
HeapTuple tuple = & (scan -> rs_ctup );
859
900
bool backward = ScanDirectionIsBackward (dir );
860
901
BlockNumber block ;
861
- bool finished ;
862
902
Page page ;
863
903
int lineindex ;
864
904
OffsetNumber lineoff ;
@@ -949,57 +989,13 @@ heapgettup_pagemode(HeapScanDesc scan,
949
989
++ lineindex ;
950
990
}
951
991
952
- /*
953
- * if we get here, it means we've exhausted the items on this page and
954
- * it's time to move to the next.
955
- */
956
- if (backward )
957
- {
958
- finished = (block == scan -> rs_startblock ) ||
959
- (scan -> rs_numblocks != InvalidBlockNumber ? -- scan -> rs_numblocks == 0 : false);
960
- if (block == 0 )
961
- block = scan -> rs_nblocks ;
962
- block -- ;
963
- }
964
- else if (scan -> rs_base .rs_parallel != NULL )
965
- {
966
- ParallelBlockTableScanDesc pbscan =
967
- (ParallelBlockTableScanDesc ) scan -> rs_base .rs_parallel ;
968
- ParallelBlockTableScanWorker pbscanwork =
969
- scan -> rs_parallelworkerdata ;
970
-
971
- block = table_block_parallelscan_nextpage (scan -> rs_base .rs_rd ,
972
- pbscanwork , pbscan );
973
- finished = (block == InvalidBlockNumber );
974
- }
975
- else
976
- {
977
- block ++ ;
978
- if (block >= scan -> rs_nblocks )
979
- block = 0 ;
980
- finished = (block == scan -> rs_startblock ) ||
981
- (scan -> rs_numblocks != InvalidBlockNumber ? -- scan -> rs_numblocks == 0 : false);
982
-
983
- /*
984
- * Report our new scan position for synchronization purposes. We
985
- * don't do that when moving backwards, however. That would just
986
- * mess up any other forward-moving scanners.
987
- *
988
- * Note: we do this before checking for end of scan so that the
989
- * final state of the position hint is back at the start of the
990
- * rel. That's not strictly necessary, but otherwise when you run
991
- * the same query multiple times the starting position would shift
992
- * a little bit backwards on every invocation, which is confusing.
993
- * We don't guarantee any specific ordering in general, though.
994
- */
995
- if (scan -> rs_base .rs_flags & SO_ALLOW_SYNC )
996
- ss_report_location (scan -> rs_base .rs_rd , block );
997
- }
992
+ /* get the BlockNumber to scan next */
993
+ block = heapgettup_advance_block (scan , block , dir );
998
994
999
995
/*
1000
996
* return NULL if we've exhausted all the pages
1001
997
*/
1002
- if (finished )
998
+ if (block == InvalidBlockNumber )
1003
999
{
1004
1000
if (BufferIsValid (scan -> rs_cbuf ))
1005
1001
ReleaseBuffer (scan -> rs_cbuf );
0 commit comments