aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--contrib/btree_gist/expected/inet.out39
-rw-r--r--contrib/btree_gist/sql/inet.sql18
-rw-r--r--src/backend/optimizer/path/indxpath.c15
3 files changed, 71 insertions, 1 deletions
diff --git a/contrib/btree_gist/expected/inet.out b/contrib/btree_gist/expected/inet.out
index 721a78e701b..905f55d740b 100644
--- a/contrib/btree_gist/expected/inet.out
+++ b/contrib/btree_gist/expected/inet.out
@@ -64,3 +64,42 @@ SELECT count(*) FROM inettmp WHERE a > '89.225.196.191'::inet;
386
(1 row)
+VACUUM inettmp;
+-- gist_inet_ops lacks a fetch function, so this should not be index-only scan
+EXPLAIN (COSTS OFF)
+SELECT count(*) FROM inettmp WHERE a = '89.225.196.191'::inet;
+ QUERY PLAN
+--------------------------------------------------------
+ Aggregate
+ -> Bitmap Heap Scan on inettmp
+ Recheck Cond: (a = '89.225.196.191'::inet)
+ -> Bitmap Index Scan on inetidx
+ Index Cond: (a = '89.225.196.191'::inet)
+(5 rows)
+
+SELECT count(*) FROM inettmp WHERE a = '89.225.196.191'::inet;
+ count
+-------
+ 1
+(1 row)
+
+DROP INDEX inetidx;
+CREATE INDEX ON inettmp USING gist (a gist_inet_ops, a inet_ops);
+-- likewise here (checks for core planner bug)
+EXPLAIN (COSTS OFF)
+SELECT count(*) FROM inettmp WHERE a = '89.225.196.191'::inet;
+ QUERY PLAN
+--------------------------------------------------------
+ Aggregate
+ -> Bitmap Heap Scan on inettmp
+ Recheck Cond: (a = '89.225.196.191'::inet)
+ -> Bitmap Index Scan on inettmp_a_a1_idx
+ Index Cond: (a = '89.225.196.191'::inet)
+(5 rows)
+
+SELECT count(*) FROM inettmp WHERE a = '89.225.196.191'::inet;
+ count
+-------
+ 1
+(1 row)
+
diff --git a/contrib/btree_gist/sql/inet.sql b/contrib/btree_gist/sql/inet.sql
index 328846c0a38..08952f2c449 100644
--- a/contrib/btree_gist/sql/inet.sql
+++ b/contrib/btree_gist/sql/inet.sql
@@ -29,3 +29,21 @@ SELECT count(*) FROM inettmp WHERE a = '89.225.196.191'::inet;
SELECT count(*) FROM inettmp WHERE a >= '89.225.196.191'::inet;
SELECT count(*) FROM inettmp WHERE a > '89.225.196.191'::inet;
+
+VACUUM inettmp;
+
+-- gist_inet_ops lacks a fetch function, so this should not be index-only scan
+EXPLAIN (COSTS OFF)
+SELECT count(*) FROM inettmp WHERE a = '89.225.196.191'::inet;
+
+SELECT count(*) FROM inettmp WHERE a = '89.225.196.191'::inet;
+
+DROP INDEX inetidx;
+
+CREATE INDEX ON inettmp USING gist (a gist_inet_ops, a inet_ops);
+
+-- likewise here (checks for core planner bug)
+EXPLAIN (COSTS OFF)
+SELECT count(*) FROM inettmp WHERE a = '89.225.196.191'::inet;
+
+SELECT count(*) FROM inettmp WHERE a = '89.225.196.191'::inet;
diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c
index f35380391ad..035f82f05d9 100644
--- a/src/backend/optimizer/path/indxpath.c
+++ b/src/backend/optimizer/path/indxpath.c
@@ -1866,6 +1866,7 @@ check_index_only(RelOptInfo *rel, IndexOptInfo *index)
bool result;
Bitmapset *attrs_used = NULL;
Bitmapset *index_canreturn_attrs = NULL;
+ Bitmapset *index_cannotreturn_attrs = NULL;
ListCell *lc;
int i;
@@ -1905,7 +1906,11 @@ check_index_only(RelOptInfo *rel, IndexOptInfo *index)
/*
* Construct a bitmapset of columns that the index can return back in an
- * index-only scan.
+ * index-only scan. If there are multiple index columns containing the
+ * same attribute, all of them must be capable of returning the value,
+ * since we might recheck operators on any of them. (Potentially we could
+ * be smarter about that, but it's such a weird situation that it doesn't
+ * seem worth spending a lot of sweat on.)
*/
for (i = 0; i < index->ncolumns; i++)
{
@@ -1922,13 +1927,21 @@ check_index_only(RelOptInfo *rel, IndexOptInfo *index)
index_canreturn_attrs =
bms_add_member(index_canreturn_attrs,
attno - FirstLowInvalidHeapAttributeNumber);
+ else
+ index_cannotreturn_attrs =
+ bms_add_member(index_cannotreturn_attrs,
+ attno - FirstLowInvalidHeapAttributeNumber);
}
+ index_canreturn_attrs = bms_del_members(index_canreturn_attrs,
+ index_cannotreturn_attrs);
+
/* Do we have all the necessary attributes? */
result = bms_is_subset(attrs_used, index_canreturn_attrs);
bms_free(attrs_used);
bms_free(index_canreturn_attrs);
+ bms_free(index_cannotreturn_attrs);
return result;
}