@@ -83,6 +83,11 @@ static Bitmapset *HeapDetermineColumnsInfo(Relation relation,
8383static bool heap_acquire_tuplock (Relation relation , ItemPointer tid ,
8484 LockTupleMode mode , LockWaitPolicy wait_policy ,
8585 bool * have_tuple_lock );
86+ static inline BlockNumber heapgettup_advance_block (HeapScanDesc scan ,
87+ BlockNumber block ,
88+ ScanDirection dir );
89+ static pg_noinline BlockNumber heapgettup_initial_block (HeapScanDesc scan ,
90+ ScanDirection dir );
8691static void compute_new_xmax_infomask (TransactionId xmax , uint16 old_infomask ,
8792 uint16 old_infomask2 , TransactionId add_to_xmax ,
8893 LockTupleMode mode , bool is_update ,
@@ -455,16 +460,14 @@ heap_prepare_pagescan(TableScanDesc sscan)
455460}
456461
457462/*
458- * heapfetchbuf - read and pin the given MAIN_FORKNUM block number .
463+ * heap_fetch_next_buffer - read and pin the next block from MAIN_FORKNUM .
459464 *
460- * Read the specified block of the scan relation into a buffer and pin that
461- * buffer before saving it in the scan descriptor.
465+ * Read the next block of the scan relation into a buffer and pin that buffer
466+ * before saving it in the scan descriptor.
462467 */
463468static inline void
464- heapfetchbuf (HeapScanDesc scan , BlockNumber block )
469+ heap_fetch_next_buffer (HeapScanDesc scan , ScanDirection dir )
465470{
466- Assert (block < scan -> rs_nblocks );
467-
468471 /* release previous scan buffer, if any */
469472 if (BufferIsValid (scan -> rs_cbuf ))
470473 {
@@ -479,10 +482,25 @@ heapfetchbuf(HeapScanDesc scan, BlockNumber block)
479482 */
480483 CHECK_FOR_INTERRUPTS ();
481484
482- /* read page using selected strategy */
483- scan -> rs_cbuf = ReadBufferExtended (scan -> rs_base .rs_rd , MAIN_FORKNUM , block ,
484- RBM_NORMAL , scan -> rs_strategy );
485- scan -> rs_cblock = block ;
485+ if (unlikely (!scan -> rs_inited ))
486+ {
487+ scan -> rs_cblock = heapgettup_initial_block (scan , dir );
488+
489+ /* ensure rs_cbuf is invalid when we get InvalidBlockNumber */
490+ Assert (scan -> rs_cblock != InvalidBlockNumber ||
491+ !BufferIsValid (scan -> rs_cbuf ));
492+
493+ scan -> rs_inited = true;
494+ }
495+ else
496+ scan -> rs_cblock = heapgettup_advance_block (scan , scan -> rs_cblock ,
497+ dir );
498+
499+ /* read block if valid */
500+ if (BlockNumberIsValid (scan -> rs_cblock ))
501+ scan -> rs_cbuf = ReadBufferExtended (scan -> rs_base .rs_rd , MAIN_FORKNUM ,
502+ scan -> rs_cblock , RBM_NORMAL ,
503+ scan -> rs_strategy );
486504}
487505
488506/*
@@ -492,7 +510,7 @@ heapfetchbuf(HeapScanDesc scan, BlockNumber block)
492510 * occur with empty tables and in parallel scans when parallel workers get all
493511 * of the pages before we can get a chance to get our first page.
494512 */
495- static BlockNumber
513+ static pg_noinline BlockNumber
496514heapgettup_initial_block (HeapScanDesc scan , ScanDirection dir )
497515{
498516 Assert (!scan -> rs_inited );
@@ -619,7 +637,7 @@ heapgettup_continue_page(HeapScanDesc scan, ScanDirection dir, int *linesleft,
619637}
620638
621639/*
622- * heapgettup_advance_block - helper for heapgettup() and heapgettup_pagemode ()
640+ * heapgettup_advance_block - helper for heap_fetch_next_buffer ()
623641 *
624642 * Given the current block number, the scan direction, and various information
625643 * contained in the scan descriptor, calculate the BlockNumber to scan next
@@ -730,23 +748,13 @@ heapgettup(HeapScanDesc scan,
730748 ScanKey key )
731749{
732750 HeapTuple tuple = & (scan -> rs_ctup );
733- BlockNumber block ;
734751 Page page ;
735752 OffsetNumber lineoff ;
736753 int linesleft ;
737754
738- if (unlikely (!scan -> rs_inited ))
739- {
740- block = heapgettup_initial_block (scan , dir );
741- /* ensure rs_cbuf is invalid when we get InvalidBlockNumber */
742- Assert (block != InvalidBlockNumber || !BufferIsValid (scan -> rs_cbuf ));
743- scan -> rs_inited = true;
744- }
745- else
755+ if (likely (scan -> rs_inited ))
746756 {
747757 /* continue from previously returned page/tuple */
748- block = scan -> rs_cblock ;
749-
750758 LockBuffer (scan -> rs_cbuf , BUFFER_LOCK_SHARE );
751759 page = heapgettup_continue_page (scan , dir , & linesleft , & lineoff );
752760 goto continue_page ;
@@ -756,9 +764,16 @@ heapgettup(HeapScanDesc scan,
756764 * advance the scan until we find a qualifying tuple or run out of stuff
757765 * to scan
758766 */
759- while (block != InvalidBlockNumber )
767+ while (true )
760768 {
761- heapfetchbuf (scan , block );
769+ heap_fetch_next_buffer (scan , dir );
770+
771+ /* did we run out of blocks to scan? */
772+ if (!BufferIsValid (scan -> rs_cbuf ))
773+ break ;
774+
775+ Assert (BufferGetBlockNumber (scan -> rs_cbuf ) == scan -> rs_cblock );
776+
762777 LockBuffer (scan -> rs_cbuf , BUFFER_LOCK_SHARE );
763778 page = heapgettup_start_page (scan , dir , & linesleft , & lineoff );
764779continue_page :
@@ -780,7 +795,7 @@ heapgettup(HeapScanDesc scan,
780795
781796 tuple -> t_data = (HeapTupleHeader ) PageGetItem (page , lpp );
782797 tuple -> t_len = ItemIdGetLength (lpp );
783- ItemPointerSet (& (tuple -> t_self ), block , lineoff );
798+ ItemPointerSet (& (tuple -> t_self ), scan -> rs_cblock , lineoff );
784799
785800 visible = HeapTupleSatisfiesVisibility (tuple ,
786801 scan -> rs_base .rs_snapshot ,
@@ -810,9 +825,6 @@ heapgettup(HeapScanDesc scan,
810825 * it's time to move to the next.
811826 */
812827 LockBuffer (scan -> rs_cbuf , BUFFER_LOCK_UNLOCK );
813-
814- /* get the BlockNumber to scan next */
815- block = heapgettup_advance_block (scan , block , dir );
816828 }
817829
818830 /* end of scan */
@@ -832,9 +844,9 @@ heapgettup(HeapScanDesc scan,
832844 *
833845 * The internal logic is much the same as heapgettup's too, but there are some
834846 * differences: we do not take the buffer content lock (that only needs to
835- * happen inside heapgetpage ), and we iterate through just the tuples listed
836- * in rs_vistuples[] rather than all tuples on the page. Notice that
837- * lineindex is 0-based, where the corresponding loop variable lineoff in
847+ * happen inside heap_prepare_pagescan ), and we iterate through just the
848+ * tuples listed in rs_vistuples[] rather than all tuples on the page. Notice
849+ * that lineindex is 0-based, where the corresponding loop variable lineoff in
838850 * heapgettup is 1-based.
839851 * ----------------
840852 */
@@ -845,22 +857,13 @@ heapgettup_pagemode(HeapScanDesc scan,
845857 ScanKey key )
846858{
847859 HeapTuple tuple = & (scan -> rs_ctup );
848- BlockNumber block ;
849860 Page page ;
850861 int lineindex ;
851862 int linesleft ;
852863
853- if (unlikely (!scan -> rs_inited ))
854- {
855- block = heapgettup_initial_block (scan , dir );
856- /* ensure rs_cbuf is invalid when we get InvalidBlockNumber */
857- Assert (block != InvalidBlockNumber || !BufferIsValid (scan -> rs_cbuf ));
858- scan -> rs_inited = true;
859- }
860- else
864+ if (likely (scan -> rs_inited ))
861865 {
862866 /* continue from previously returned page/tuple */
863- block = scan -> rs_cblock ; /* current page */
864867 page = BufferGetPage (scan -> rs_cbuf );
865868
866869 lineindex = scan -> rs_cindex + dir ;
@@ -877,10 +880,15 @@ heapgettup_pagemode(HeapScanDesc scan,
877880 * advance the scan until we find a qualifying tuple or run out of stuff
878881 * to scan
879882 */
880- while (block != InvalidBlockNumber )
883+ while (true )
881884 {
882- /* read the page */
883- heapfetchbuf (scan , block );
885+ heap_fetch_next_buffer (scan , dir );
886+
887+ /* did we run out of blocks to scan? */
888+ if (!BufferIsValid (scan -> rs_cbuf ))
889+ break ;
890+
891+ Assert (BufferGetBlockNumber (scan -> rs_cbuf ) == scan -> rs_cblock );
884892
885893 /* prune the page and determine visible tuple offsets */
886894 heap_prepare_pagescan ((TableScanDesc ) scan );
@@ -902,7 +910,7 @@ heapgettup_pagemode(HeapScanDesc scan,
902910
903911 tuple -> t_data = (HeapTupleHeader ) PageGetItem (page , lpp );
904912 tuple -> t_len = ItemIdGetLength (lpp );
905- ItemPointerSet (& (tuple -> t_self ), block , lineoff );
913+ ItemPointerSet (& (tuple -> t_self ), scan -> rs_cblock , lineoff );
906914
907915 /* skip any tuples that don't match the scan key */
908916 if (key != NULL &&
@@ -913,9 +921,6 @@ heapgettup_pagemode(HeapScanDesc scan,
913921 scan -> rs_cindex = lineindex ;
914922 return ;
915923 }
916-
917- /* get the BlockNumber to scan next */
918- block = heapgettup_advance_block (scan , block , dir );
919924 }
920925
921926 /* end of scan */
0 commit comments