From 926fe578495242fe2b400c2f7a4310c12a24459f Mon Sep 17 00:00:00 2001
From: Justin Pryzby <pryzbyj@telsasoft.com>
Date: Thu, 2 Jul 2020 18:46:48 -0500
Subject: [PATCH 2/2] Avoid index scan inconsistent with partition constraint

---
 src/backend/optimizer/path/indxpath.c      |  5 +++++
 src/test/regress/expected/create_index.out | 25 ++++++++++++++++++++++
 src/test/regress/sql/create_index.sql      | 10 +++++++++
 3 files changed, 40 insertions(+)

diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c
index 2a50272da6..c103496bfc 100644
--- a/src/backend/optimizer/path/indxpath.c
+++ b/src/backend/optimizer/path/indxpath.c
@@ -1315,6 +1315,11 @@ generate_bitmap_or_paths(PlannerInfo *root, RelOptInfo *rel,
 				Assert(!restriction_is_or_clause(rinfo));
 				orargs = list_make1(rinfo);
 
+				/* Avoid scanning indexes using a scan condition which is
+				 * inconsistent with the partition constraint */
+				if (predicate_refuted_by(rel->partition_qual, orargs, false))
+					continue;
+
 				indlist = build_paths_for_OR(root, rel,
 											 orargs,
 											 all_clauses);
diff --git a/src/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out
index e3e6634d7e..1a976ad211 100644
--- a/src/test/regress/expected/create_index.out
+++ b/src/test/regress/expected/create_index.out
@@ -1843,6 +1843,31 @@ SELECT count(*) FROM tenk1
     10
 (1 row)
 
+-- Check that indexes are not scanned for "arms" of an OR with a scan condition inconsistent with the partition constraint
+CREATE TABLE bitmapor (i int, j int) PARTITION BY RANGE(i);
+CREATE TABLE bitmapor1 PARTITION OF bitmapor FOR VALUES FROM (0) TO (10);
+CREATE TABLE bitmapor2 PARTITION OF bitmapor FOR VALUES FROM (10) TO (20);
+INSERT INTO bitmapor SELECT i%20, i%2 FROM generate_series(1,55555)i;
+VACUUM ANALYZE bitmapor;
+CREATE INDEX ON bitmapor(i);
+EXPLAIN (COSTS OFF) SELECT * FROM bitmapor WHERE (i=1 OR i=2 OR i=11);
+                       QUERY PLAN                       
+--------------------------------------------------------
+ Append
+   ->  Bitmap Heap Scan on bitmapor1 bitmapor_1
+         Recheck Cond: ((i = 1) OR (i = 2))
+         ->  BitmapOr
+               ->  Bitmap Index Scan on bitmapor1_i_idx
+                     Index Cond: (i = 1)
+               ->  Bitmap Index Scan on bitmapor1_i_idx
+                     Index Cond: (i = 2)
+   ->  Bitmap Heap Scan on bitmapor2 bitmapor_2
+         Recheck Cond: (i = 11)
+         ->  Bitmap Index Scan on bitmapor2_i_idx
+               Index Cond: (i = 11)
+(12 rows)
+
+DROP TABLE bitmapor;
 --
 -- Check behavior with duplicate index column contents
 --
diff --git a/src/test/regress/sql/create_index.sql b/src/test/regress/sql/create_index.sql
index f3667bacdc..dd1de8ee1d 100644
--- a/src/test/regress/sql/create_index.sql
+++ b/src/test/regress/sql/create_index.sql
@@ -703,6 +703,16 @@ SELECT count(*) FROM tenk1
 SELECT count(*) FROM tenk1
   WHERE hundred = 42 AND (thousand = 42 OR thousand = 99);
 
+-- Check that indexes are not scanned for "arms" of an OR with a scan condition inconsistent with the partition constraint
+CREATE TABLE bitmapor (i int, j int) PARTITION BY RANGE(i);
+CREATE TABLE bitmapor1 PARTITION OF bitmapor FOR VALUES FROM (0) TO (10);
+CREATE TABLE bitmapor2 PARTITION OF bitmapor FOR VALUES FROM (10) TO (20);
+INSERT INTO bitmapor SELECT i%20, i%2 FROM generate_series(1,55555)i;
+VACUUM ANALYZE bitmapor;
+CREATE INDEX ON bitmapor(i);
+EXPLAIN (COSTS OFF) SELECT * FROM bitmapor WHERE (i=1 OR i=2 OR i=11);
+DROP TABLE bitmapor;
+
 --
 -- Check behavior with duplicate index column contents
 --
-- 
2.17.0

