diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/access/heap/heapam_handler.c | 28 | ||||
-rw-r--r-- | src/test/regress/expected/bitmapops.out | 14 | ||||
-rw-r--r-- | src/test/regress/sql/bitmapops.sql | 10 |
3 files changed, 41 insertions, 11 deletions
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c index 4da4dc84580..24d3765aa20 100644 --- a/src/backend/access/heap/heapam_handler.c +++ b/src/backend/access/heap/heapam_handler.c @@ -2147,6 +2147,19 @@ heapam_scan_bitmap_next_tuple(TableScanDesc scan, */ ExecStoreAllNullTuple(slot); bscan->rs_empty_tuples_pending--; + + /* + * We do not recheck all NULL tuples. Because the streaming read + * API only yields TBMIterateResults for blocks actually fetched + * from the heap, we must unset `recheck` ourselves here to ensure + * correct results. + * + * Our read stream callback accrues a count of empty tuples to + * emit and then emits them after emitting tuples from the next + * fetched block. If no blocks need fetching, we'll emit the + * accrued count at the end of the scan. + */ + *recheck = false; return true; } @@ -2510,13 +2523,14 @@ BitmapHeapScanNextBlock(TableScanDesc scan, } /* - * Bitmap is exhausted. Time to emit empty tuples if relevant. We emit - * all empty tuples at the end instead of emitting them per block we - * skip fetching. This is necessary because the streaming read API - * will only return TBMIterateResults for blocks actually fetched. - * When we skip fetching a block, we keep track of how many empty - * tuples to emit at the end of the BitmapHeapScan. We do not recheck - * all NULL tuples. + * The bitmap is exhausted. Now emit any remaining empty tuples. The + * read stream API only returns TBMIterateResults for blocks actually + * fetched from the heap. Our callback will accrue a count of empty + * tuples to emit for all blocks we skipped fetching. So, if we skip + * fetching heap blocks at the end of the relation (or no heap blocks + * are fetched) we need to ensure we emit empty tuples before ending + * the scan. We don't recheck empty tuples so ensure `recheck` is + * unset. */ *recheck = false; return bscan->rs_empty_tuples_pending > 0; diff --git a/src/test/regress/expected/bitmapops.out b/src/test/regress/expected/bitmapops.out index 3570973e3ca..64068e0469c 100644 --- a/src/test/regress/expected/bitmapops.out +++ b/src/test/regress/expected/bitmapops.out @@ -8,7 +8,7 @@ -- there's a maximum number of a,b combinations in the table. -- That allows us to test all the different combinations of -- lossy and non-lossy pages with the minimum amount of data -CREATE TABLE bmscantest (a int, b int, t text); +CREATE TABLE bmscantest (a int, b int, t text) WITH (autovacuum_enabled = false); INSERT INTO bmscantest SELECT (r%53), (r%59), 'foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo' FROM generate_series(1,70000) r; @@ -20,7 +20,17 @@ set enable_indexscan=false; set enable_seqscan=false; -- Lower work_mem to trigger use of lossy bitmaps set work_mem = 64; --- Test bitmap-and. +-- Test bitmap-and without the skip fetch optimization. +SELECT count(*) FROM bmscantest WHERE a = 1 AND b = 1; + count +------- + 23 +(1 row) + +-- Test that we return correct results when using the skip fetch optimization +-- VACUUM FREEZE will set all the pages in the relation all-visible, enabling +-- the optimization. +VACUUM (FREEZE) bmscantest; SELECT count(*) FROM bmscantest WHERE a = 1 AND b = 1; count ------- diff --git a/src/test/regress/sql/bitmapops.sql b/src/test/regress/sql/bitmapops.sql index 498f4721b51..1b175f6ff96 100644 --- a/src/test/regress/sql/bitmapops.sql +++ b/src/test/regress/sql/bitmapops.sql @@ -12,7 +12,7 @@ -- That allows us to test all the different combinations of -- lossy and non-lossy pages with the minimum amount of data -CREATE TABLE bmscantest (a int, b int, t text); +CREATE TABLE bmscantest (a int, b int, t text) WITH (autovacuum_enabled = false); INSERT INTO bmscantest SELECT (r%53), (r%59), 'foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo' @@ -29,8 +29,14 @@ set enable_seqscan=false; -- Lower work_mem to trigger use of lossy bitmaps set work_mem = 64; +-- Test bitmap-and without the skip fetch optimization. +SELECT count(*) FROM bmscantest WHERE a = 1 AND b = 1; + +-- Test that we return correct results when using the skip fetch optimization +-- VACUUM FREEZE will set all the pages in the relation all-visible, enabling +-- the optimization. +VACUUM (FREEZE) bmscantest; --- Test bitmap-and. SELECT count(*) FROM bmscantest WHERE a = 1 AND b = 1; -- Test bitmap-or. |