diff --git a/src/backend/utils/adt/rangetypes_selfuncs.c b/src/backend/utils/adt/rangetypes_selfuncs.c index a4d7a7ab42..607385bf44 100644 --- a/src/backend/utils/adt/rangetypes_selfuncs.c +++ b/src/backend/utils/adt/rangetypes_selfuncs.c @@ -1063,10 +1063,11 @@ calc_hist_selectivity_contained(TypeCacheEntry *typcache, /* * Subtract from bin_width the portion of this bin that we want to - * ignore. + * ignore, if current bin has finite upper bound. */ - bin_width -= get_position(typcache, lower, &hist_lower[i], - &hist_lower[i + 1]); + if (i + 1 != hist_nvalues) + bin_width -= get_position(typcache, lower, &hist_lower[i], + &hist_lower[i + 1]); if (bin_width < 0.0) bin_width = 0.0; final_bin = true; diff --git a/src/test/regress/expected/rangetypes.out b/src/test/regress/expected/rangetypes.out index 5ed6ae47ec..8427418bb5 100644 --- a/src/test/regress/expected/rangetypes.out +++ b/src/test/regress/expected/rangetypes.out @@ -1434,3 +1434,16 @@ create function table_fail(i anyelement) returns table(i anyelement, r anyrange) as $$ select $1, '[1,10]' $$ language sql; ERROR: cannot determine result data type DETAIL: A function returning "anyrange" must have at least one "anyrange" argument. +-- Corner case with selectivity of range operators, per bug #16122. +CREATE TABLE rangetab (a numrange); +INSERT INTO rangetab +SELECT ('['|| (45.0 - a::numeric/10000000) || ',' || + (45.1 + a::numeric/10000000) || ')')::numrange + FROM generate_series(1,1000) as a; +ANALYZE rangetab; +SELECT a FROM rangetab WHERE a <@ '[89.9999998611111,90.0000001388889)'; + a +--- +(0 rows) + +DROP TABLE rangetab; diff --git a/src/test/regress/sql/rangetypes.sql b/src/test/regress/sql/rangetypes.sql index 2d0ec8964e..d045cb7650 100644 --- a/src/test/regress/sql/rangetypes.sql +++ b/src/test/regress/sql/rangetypes.sql @@ -510,3 +510,13 @@ create function inoutparam_fail(inout i anyelement, out r anyrange) --should fail create function table_fail(i anyelement) returns table(i anyelement, r anyrange) as $$ select $1, '[1,10]' $$ language sql; + +-- Corner case with selectivity of range operators, per bug #16122. +CREATE TABLE rangetab (a numrange); +INSERT INTO rangetab +SELECT ('['|| (45.0 - a::numeric/10000000) || ',' || + (45.1 + a::numeric/10000000) || ')')::numrange + FROM generate_series(1,1000) as a; +ANALYZE rangetab; +SELECT a FROM rangetab WHERE a <@ '[89.9999998611111,90.0000001388889)'; +DROP TABLE rangetab;