diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index 7fab15db3d6..5b9f3a2670e 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -899,7 +899,11 @@ heapgettup_advance_block(HeapScanDesc scan, BlockNumber block, ScanDirection dir /* check if the limit imposed by heap_setscanlimits() is met */ if (scan->rs_numblocks != InvalidBlockNumber) { - if (--scan->rs_numblocks == 0) + BlockNumber endblock; + + endblock = (scan->rs_startblock + scan->rs_numblocks) % + scan->rs_nblocks; + if (block == endblock) return InvalidBlockNumber; } @@ -907,17 +911,15 @@ heapgettup_advance_block(HeapScanDesc scan, BlockNumber block, ScanDirection dir } else { - /* we're done if the last block is the start position */ + /* + * We're done if the last block is the start position. No need to + * check if rs_numblocks was set by heap_setscanlimits() as that only + * changes the end block. The start block is the same with or without + * scan limits. + */ if (block == scan->rs_startblock) return InvalidBlockNumber; - /* check if the limit imposed by heap_setscanlimits() is met */ - if (scan->rs_numblocks != InvalidBlockNumber) - { - if (--scan->rs_numblocks == 0) - return InvalidBlockNumber; - } - /* wrap to the end of the heap when the last page was page 0 */ if (block == 0) block = scan->rs_nblocks; diff --git a/src/test/regress/expected/tidrangescan.out b/src/test/regress/expected/tidrangescan.out index 721f3b94e04..3ccef0fd0c2 100644 --- a/src/test/regress/expected/tidrangescan.out +++ b/src/test/regress/expected/tidrangescan.out @@ -295,6 +295,32 @@ FETCH LAST c; (0,10) (1 row) +COMMIT; +-- Ensure TID Range Scans with scrollable cursors count blocks correctly. +BEGIN; +DECLARE c SCROLL CURSOR FOR SELECT ctid FROM tidrangescan WHERE ctid >= '(0,1)' AND ctid <= '(2,10)'; +MOVE FORWARD 25 c; +MOVE BACKWARD 4 c; +FETCH BACKWARD 1 c; + ctid +-------- + (1,10) +(1 row) + +MOVE BACKWARD ALL c; +FETCH FORWARD 1 c; + ctid +------- + (0,1) +(1 row) + +MOVE FORWARD ALL c; +FETCH BACKWARD 1 c; + ctid +-------- + (2,10) +(1 row) + COMMIT; DROP TABLE tidrangescan; RESET enable_seqscan; diff --git a/src/test/regress/sql/tidrangescan.sql b/src/test/regress/sql/tidrangescan.sql index ac09ebb6262..e367292e885 100644 --- a/src/test/regress/sql/tidrangescan.sql +++ b/src/test/regress/sql/tidrangescan.sql @@ -96,6 +96,18 @@ FETCH FIRST c; FETCH LAST c; COMMIT; +-- Ensure TID Range Scans with scrollable cursors count blocks correctly. +BEGIN; +DECLARE c SCROLL CURSOR FOR SELECT ctid FROM tidrangescan WHERE ctid >= '(0,1)' AND ctid <= '(2,10)'; +MOVE FORWARD 25 c; +MOVE BACKWARD 4 c; +FETCH BACKWARD 1 c; +MOVE BACKWARD ALL c; +FETCH FORWARD 1 c; +MOVE FORWARD ALL c; +FETCH BACKWARD 1 c; +COMMIT; + DROP TABLE tidrangescan; RESET enable_seqscan;