aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/heap/heapam.c9
-rw-r--r--src/test/regress/expected/join.out36
-rw-r--r--src/test/regress/sql/join.sql24
3 files changed, 66 insertions, 3 deletions
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 4be0dee4de0..82bb9cb33b6 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -1184,7 +1184,12 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
scan->rs_vmbuffer = InvalidBuffer;
}
- Assert(scan->rs_empty_tuples_pending == 0);
+ /*
+ * Reset rs_empty_tuples_pending, a field only used by bitmap heap scan,
+ * to avoid incorrectly emitting NULL-filled tuples from a previous scan
+ * on rescan.
+ */
+ scan->rs_empty_tuples_pending = 0;
/*
* The read stream is reset on rescan. This must be done before
@@ -1216,8 +1221,6 @@ heap_endscan(TableScanDesc sscan)
if (BufferIsValid(scan->rs_vmbuffer))
ReleaseBuffer(scan->rs_vmbuffer);
- Assert(scan->rs_empty_tuples_pending == 0);
-
/*
* Must free the read stream before freeing the BufferAccessStrategy.
*/
diff --git a/src/test/regress/expected/join.out b/src/test/regress/expected/join.out
index 0246d56aea9..6b16c3a6769 100644
--- a/src/test/regress/expected/join.out
+++ b/src/test/regress/expected/join.out
@@ -7924,3 +7924,39 @@ where exists (select 1 from j3
(13 rows)
drop table j3;
+-- Exercise the "skip fetch" Bitmap Heap Scan optimization when candidate
+-- tuples are discarded. This may occur when:
+-- 1. A join doesn't require all inner tuples to be scanned for each outer
+-- tuple, and
+-- 2. The inner side is scanned using a bitmap heap scan, and
+-- 3. The bitmap heap scan is eligible for the "skip fetch" optimization.
+-- This optimization is usable when no data from the underlying table is
+-- needed. Use a temp table so it is only visible to this backend and
+-- vacuum may reliably mark all blocks in the table all visible in the
+-- visibility map.
+CREATE TEMP TABLE skip_fetch (a INT, b INT) WITH (fillfactor=10);
+INSERT INTO skip_fetch SELECT i % 3, i FROM generate_series(0,30) i;
+CREATE INDEX ON skip_fetch(a);
+VACUUM (ANALYZE) skip_fetch;
+SET enable_indexonlyscan = off;
+SET enable_seqscan = off;
+EXPLAIN (COSTS OFF)
+SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS NULL;
+ QUERY PLAN
+---------------------------------------------------------
+ Nested Loop Anti Join
+ -> Seq Scan on skip_fetch t1
+ -> Materialize
+ -> Bitmap Heap Scan on skip_fetch t2
+ Recheck Cond: (a = 1)
+ -> Bitmap Index Scan on skip_fetch_a_idx
+ Index Cond: (a = 1)
+(7 rows)
+
+SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS NULL;
+ a
+---
+(0 rows)
+
+RESET enable_indexonlyscan;
+RESET enable_seqscan;
diff --git a/src/test/regress/sql/join.sql b/src/test/regress/sql/join.sql
index 923e7c5549a..8bfe3b7ba67 100644
--- a/src/test/regress/sql/join.sql
+++ b/src/test/regress/sql/join.sql
@@ -2904,3 +2904,27 @@ where exists (select 1 from j3
and t1.unique1 < 1;
drop table j3;
+
+-- Exercise the "skip fetch" Bitmap Heap Scan optimization when candidate
+-- tuples are discarded. This may occur when:
+-- 1. A join doesn't require all inner tuples to be scanned for each outer
+-- tuple, and
+-- 2. The inner side is scanned using a bitmap heap scan, and
+-- 3. The bitmap heap scan is eligible for the "skip fetch" optimization.
+-- This optimization is usable when no data from the underlying table is
+-- needed. Use a temp table so it is only visible to this backend and
+-- vacuum may reliably mark all blocks in the table all visible in the
+-- visibility map.
+CREATE TEMP TABLE skip_fetch (a INT, b INT) WITH (fillfactor=10);
+INSERT INTO skip_fetch SELECT i % 3, i FROM generate_series(0,30) i;
+CREATE INDEX ON skip_fetch(a);
+VACUUM (ANALYZE) skip_fetch;
+
+SET enable_indexonlyscan = off;
+SET enable_seqscan = off;
+EXPLAIN (COSTS OFF)
+SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS NULL;
+SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS NULL;
+
+RESET enable_indexonlyscan;
+RESET enable_seqscan;