diff --git a/contrib/btree_gist/expected/inet.out b/contrib/btree_gist/expected/inet.out index 721a78e701..905f55d740 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 328846c0a3..08952f2c44 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 2952bfb7c2..47a01b3ad0 100644 --- a/src/backend/optimizer/path/indxpath.c +++ b/src/backend/optimizer/path/indxpath.c @@ -1791,6 +1791,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; @@ -1830,7 +1831,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++) { @@ -1847,13 +1852,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; }