1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-09 22:41:56 +03:00

Fixes for multirange selectivity estimation

* Fix enumeration of the multirange operators in calc_multirangesel() and
   calc_multirangesel() switches.
 * Add more regression tests for matching to empty ranges/multiranges.

Reported-by: Alexander Lakhin
Discussion: https://postgr.es/m/c5269c65-f967-77c5-ff7c-15e621c47f6a%40gmail.com
Author: Alexander Korotkov
Backpatch-through: 14, where multiranges were introduced
This commit is contained in:
Alexander Korotkov
2021-06-29 23:18:09 +03:00
parent b71a9cb31e
commit 178ec460db
3 changed files with 272 additions and 13 deletions

View File

@ -347,16 +347,15 @@ calc_multirangesel(TypeCacheEntry *typcache, VariableStatData *vardata,
switch (operator)
{
/* these return false if either argument is empty */
case OID_RANGE_OVERLAPS_MULTIRANGE_OP:
case OID_MULTIRANGE_OVERLAPS_RANGE_OP:
case OID_MULTIRANGE_OVERLAPS_MULTIRANGE_OP:
case OID_RANGE_OVERLAPS_LEFT_MULTIRANGE_OP:
case OID_MULTIRANGE_OVERLAPS_LEFT_RANGE_OP:
case OID_MULTIRANGE_OVERLAPS_LEFT_MULTIRANGE_OP:
case OID_RANGE_OVERLAPS_RIGHT_MULTIRANGE_OP:
case OID_MULTIRANGE_OVERLAPS_RIGHT_RANGE_OP:
case OID_MULTIRANGE_OVERLAPS_RIGHT_MULTIRANGE_OP:
case OID_MULTIRANGE_LEFT_RANGE_OP:
case OID_MULTIRANGE_LEFT_MULTIRANGE_OP:
case OID_MULTIRANGE_RIGHT_RANGE_OP:
case OID_MULTIRANGE_RIGHT_MULTIRANGE_OP:
/* nothing is less than an empty multirange */
case OID_MULTIRANGE_LESS_OP:
@ -367,7 +366,7 @@ calc_multirangesel(TypeCacheEntry *typcache, VariableStatData *vardata,
* only empty multiranges can be contained by an empty
* multirange
*/
case OID_MULTIRANGE_RANGE_CONTAINED_OP:
case OID_RANGE_MULTIRANGE_CONTAINED_OP:
case OID_MULTIRANGE_MULTIRANGE_CONTAINED_OP:
/* only empty ranges are <= an empty multirange */
case OID_MULTIRANGE_LESS_EQUAL_OP:
@ -388,8 +387,18 @@ calc_multirangesel(TypeCacheEntry *typcache, VariableStatData *vardata,
break;
/* an element cannot be empty */
case OID_MULTIRANGE_ELEM_CONTAINED_OP:
case OID_MULTIRANGE_CONTAINS_ELEM_OP:
/* filtered out by multirangesel() */
case OID_RANGE_OVERLAPS_MULTIRANGE_OP:
case OID_RANGE_OVERLAPS_LEFT_MULTIRANGE_OP:
case OID_RANGE_OVERLAPS_RIGHT_MULTIRANGE_OP:
case OID_RANGE_LEFT_MULTIRANGE_OP:
case OID_RANGE_RIGHT_MULTIRANGE_OP:
case OID_RANGE_CONTAINS_MULTIRANGE_OP:
case OID_MULTIRANGE_ELEM_CONTAINED_OP:
case OID_MULTIRANGE_RANGE_CONTAINED_OP:
default:
elog(ERROR, "unexpected operator %u", operator);
selec = 0.0; /* keep compiler quiet */
@ -416,8 +425,7 @@ calc_multirangesel(TypeCacheEntry *typcache, VariableStatData *vardata,
* calculations, realizing that the histogram covers only the
* non-null, non-empty values.
*/
if (operator == OID_MULTIRANGE_ELEM_CONTAINED_OP ||
operator == OID_MULTIRANGE_RANGE_CONTAINED_OP ||
if (operator == OID_RANGE_MULTIRANGE_CONTAINED_OP ||
operator == OID_MULTIRANGE_MULTIRANGE_CONTAINED_OP)
{
/* empty is contained by anything non-empty */
@ -575,7 +583,6 @@ calc_hist_selectivity(TypeCacheEntry *typcache, VariableStatData *vardata,
hist_lower, nhist, true);
break;
case OID_RANGE_LEFT_MULTIRANGE_OP:
case OID_MULTIRANGE_LEFT_RANGE_OP:
case OID_MULTIRANGE_LEFT_MULTIRANGE_OP:
/* var << const when upper(var) < lower(const) */
@ -584,7 +591,6 @@ calc_hist_selectivity(TypeCacheEntry *typcache, VariableStatData *vardata,
hist_upper, nhist, false);
break;
case OID_RANGE_RIGHT_MULTIRANGE_OP:
case OID_MULTIRANGE_RIGHT_RANGE_OP:
case OID_MULTIRANGE_RIGHT_MULTIRANGE_OP:
/* var >> const when lower(var) > upper(const) */
@ -593,7 +599,6 @@ calc_hist_selectivity(TypeCacheEntry *typcache, VariableStatData *vardata,
hist_lower, nhist, true);
break;
case OID_RANGE_OVERLAPS_RIGHT_MULTIRANGE_OP:
case OID_MULTIRANGE_OVERLAPS_RIGHT_RANGE_OP:
case OID_MULTIRANGE_OVERLAPS_RIGHT_MULTIRANGE_OP:
/* compare lower bounds */
@ -602,7 +607,6 @@ calc_hist_selectivity(TypeCacheEntry *typcache, VariableStatData *vardata,
hist_lower, nhist, false);
break;
case OID_RANGE_OVERLAPS_LEFT_MULTIRANGE_OP:
case OID_MULTIRANGE_OVERLAPS_LEFT_RANGE_OP:
case OID_MULTIRANGE_OVERLAPS_LEFT_MULTIRANGE_OP:
/* compare upper bounds */
@ -611,7 +615,6 @@ calc_hist_selectivity(TypeCacheEntry *typcache, VariableStatData *vardata,
hist_upper, nhist, true);
break;
case OID_RANGE_OVERLAPS_MULTIRANGE_OP:
case OID_MULTIRANGE_OVERLAPS_RANGE_OP:
case OID_MULTIRANGE_OVERLAPS_MULTIRANGE_OP:
case OID_MULTIRANGE_CONTAINS_ELEM_OP:
@ -647,7 +650,6 @@ calc_hist_selectivity(TypeCacheEntry *typcache, VariableStatData *vardata,
lslot.values, lslot.nvalues);
break;
case OID_MULTIRANGE_RANGE_CONTAINED_OP:
case OID_MULTIRANGE_MULTIRANGE_CONTAINED_OP:
case OID_RANGE_MULTIRANGE_CONTAINED_OP:
if (const_lower.infinite)
@ -675,6 +677,16 @@ calc_hist_selectivity(TypeCacheEntry *typcache, VariableStatData *vardata,
}
break;
/* filtered out by multirangesel() */
case OID_RANGE_OVERLAPS_MULTIRANGE_OP:
case OID_RANGE_OVERLAPS_LEFT_MULTIRANGE_OP:
case OID_RANGE_OVERLAPS_RIGHT_MULTIRANGE_OP:
case OID_RANGE_LEFT_MULTIRANGE_OP:
case OID_RANGE_RIGHT_MULTIRANGE_OP:
case OID_RANGE_CONTAINS_MULTIRANGE_OP:
case OID_MULTIRANGE_ELEM_CONTAINED_OP:
case OID_MULTIRANGE_RANGE_CONTAINED_OP:
default:
elog(ERROR, "unknown multirange operator %u", operator);
hist_selec = -1.0; /* keep compiler quiet */