diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c index a7cbaf1660e..928c94cab6a 100644 --- a/src/backend/executor/nodeBitmapHeapscan.c +++ b/src/backend/executor/nodeBitmapHeapscan.c @@ -572,9 +572,11 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node) if (scan) { /* - * End iteration on iterators saved in scan descriptor. + * End iteration on iterators saved in scan descriptor if they have + * not already been cleaned up. */ - tbm_end_iterate(&scan->st.rs_tbmiterator); + if (!tbm_exhausted(&scan->st.rs_tbmiterator)) + tbm_end_iterate(&scan->st.rs_tbmiterator); /* rescan to release any page pin */ table_rescan(node->ss.ss_currentScanDesc, NULL); @@ -654,9 +656,11 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node) if (scanDesc) { /* - * End iteration on iterators saved in scan descriptor. + * End iteration on iterators saved in scan descriptor if they have + * not already been cleaned up. */ - tbm_end_iterate(&scanDesc->st.rs_tbmiterator); + if (!tbm_exhausted(&scanDesc->st.rs_tbmiterator)) + tbm_end_iterate(&scanDesc->st.rs_tbmiterator); /* * close table scan diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c index 687d6f17636..63316d5d655 100644 --- a/src/backend/nodes/tidbitmap.c +++ b/src/backend/nodes/tidbitmap.c @@ -1594,7 +1594,7 @@ tbm_begin_iterate(TIDBitmap *tbm, dsa_area *dsa, dsa_pointer dsp) void tbm_end_iterate(TBMIterator *iterator) { - Assert(iterator); + Assert(iterator && !tbm_exhausted(iterator)); if (iterator->shared) tbm_end_shared_iterate(iterator->i.shared_iterator); diff --git a/src/test/regress/expected/join.out b/src/test/regress/expected/join.out index 55d44a9bcee..0c9b312eafd 100644 --- a/src/test/regress/expected/join.out +++ b/src/test/regress/expected/join.out @@ -8182,3 +8182,38 @@ SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS RESET enable_indexonlyscan; RESET enable_seqscan; +-- Test BitmapHeapScan with a rescan releases resources correctly +SET enable_seqscan = off; +SET enable_indexscan = off; +CREATE TEMP TABLE rescan_bhs (a INT); +INSERT INTO rescan_bhs VALUES (1), (2); +CREATE INDEX ON rescan_bhs (a); +EXPLAIN (COSTS OFF) +SELECT * FROM rescan_bhs t1 LEFT JOIN rescan_bhs t2 ON t1.a IN + (SELECT a FROM rescan_bhs t3 WHERE t2.a > 1); + QUERY PLAN +----------------------------------------------------------- + Nested Loop Left Join + Join Filter: (ANY (t1.a = (SubPlan 1).col1)) + -> Bitmap Heap Scan on rescan_bhs t1 + -> Bitmap Index Scan on rescan_bhs_a_idx + -> Materialize + -> Bitmap Heap Scan on rescan_bhs t2 + -> Bitmap Index Scan on rescan_bhs_a_idx + SubPlan 1 + -> Result + One-Time Filter: (t2.a > 1) + -> Bitmap Heap Scan on rescan_bhs t3 + -> Bitmap Index Scan on rescan_bhs_a_idx +(12 rows) + +SELECT * FROM rescan_bhs t1 LEFT JOIN rescan_bhs t2 ON t1.a IN + (SELECT a FROM rescan_bhs t3 WHERE t2.a > 1); + a | a +---+--- + 1 | 2 + 2 | 2 +(2 rows) + +RESET enable_seqscan; +RESET enable_indexscan; diff --git a/src/test/regress/sql/join.sql b/src/test/regress/sql/join.sql index d6f49f281b7..8cfc1053cb7 100644 --- a/src/test/regress/sql/join.sql +++ b/src/test/regress/sql/join.sql @@ -3016,3 +3016,20 @@ SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS RESET enable_indexonlyscan; RESET enable_seqscan; + +-- Test BitmapHeapScan with a rescan releases resources correctly +SET enable_seqscan = off; +SET enable_indexscan = off; + +CREATE TEMP TABLE rescan_bhs (a INT); +INSERT INTO rescan_bhs VALUES (1), (2); +CREATE INDEX ON rescan_bhs (a); + +EXPLAIN (COSTS OFF) +SELECT * FROM rescan_bhs t1 LEFT JOIN rescan_bhs t2 ON t1.a IN + (SELECT a FROM rescan_bhs t3 WHERE t2.a > 1); +SELECT * FROM rescan_bhs t1 LEFT JOIN rescan_bhs t2 ON t1.a IN + (SELECT a FROM rescan_bhs t3 WHERE t2.a > 1); + +RESET enable_seqscan; +RESET enable_indexscan;