Skip to content

Commit 51bce3c

Browse files
committed
MDEV-28882: Assertion `tmp >= 0' failed in best_access_path
Histogram_json_hb::range_selectivity() may return small negative numbers due to rounding errors in the histogram. Make sure the returned value is non-negative. Add an assert to catch negative values that are not small. (attempt #2)
1 parent 54ac356 commit 51bce3c

File tree

3 files changed

+67
-1
lines changed

3 files changed

+67
-1
lines changed

mysql-test/main/statistics_json.result

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8322,3 +8322,34 @@ histogram
83228322
]
83238323
}
83248324
drop table t1;
8325+
#
8326+
# MDEV-28882: Assertion `tmp >= 0' failed in best_access_path
8327+
#
8328+
CREATE TABLE t1 (a varchar(1));
8329+
INSERT INTO t1 VALUES ('o'),('s'),('j'),('s'),('y'),('s'),('l'),
8330+
('q'),('x'),('m'),('t'),('d'),('v'),('j'),('p'),('t'),('b'),('q');
8331+
set histogram_type=json_hb;
8332+
analyze table t1 persistent for all;
8333+
Table Op Msg_type Msg_text
8334+
test.t1 analyze status Engine-independent statistics collected
8335+
test.t1 analyze status OK
8336+
# filtered must not be negative:
8337+
explain format=json select * from t1 where a > 'y';
8338+
EXPLAIN
8339+
{
8340+
"query_block": {
8341+
"select_id": 1,
8342+
"nested_loop": [
8343+
{
8344+
"table": {
8345+
"table_name": "t1",
8346+
"access_type": "ALL",
8347+
"rows": 18,
8348+
"filtered": 5.555555344,
8349+
"attached_condition": "t1.a > 'y'"
8350+
}
8351+
}
8352+
]
8353+
}
8354+
}
8355+
drop table t1;

mysql-test/main/statistics_json.test

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,3 +460,19 @@ from mysql.column_stats where table_name='t1' and db_name=database();
460460

461461
drop table t1;
462462

463+
--echo #
464+
--echo # MDEV-28882: Assertion `tmp >= 0' failed in best_access_path
465+
--echo #
466+
467+
CREATE TABLE t1 (a varchar(1));
468+
469+
INSERT INTO t1 VALUES ('o'),('s'),('j'),('s'),('y'),('s'),('l'),
470+
('q'),('x'),('m'),('t'),('d'),('v'),('j'),('p'),('t'),('b'),('q');
471+
472+
set histogram_type=json_hb;
473+
analyze table t1 persistent for all;
474+
--echo # filtered must not be negative:
475+
explain format=json select * from t1 where a > 'y';
476+
477+
drop table t1;
478+

sql/opt_histogram_json.cc

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -959,9 +959,16 @@ std::string& Histogram_json_hb::get_end_value(int idx)
959959
@param field The table field histogram is for. We don't care about the
960960
field's current value, we only need its virtual functions to
961961
perform various operations
962-
963962
@param min_endp Left endpoint, or NULL if there is none
964963
@param max_endp Right endpoint, or NULL if there is none
964+
@param avg_sel Average selectivity of "field=const" equality for this field
965+
966+
@return
967+
Range selectivity: a number between 0.0 and 1.0.
968+
969+
@note
970+
This may return 0.0. Adjustments to avoid multiply-by-zero meltdown are
971+
made elsewhere.
965972
*/
966973

967974
double Histogram_json_hb::range_selectivity(Field *field, key_range *min_endp,
@@ -1062,6 +1069,18 @@ double Histogram_json_hb::range_selectivity(Field *field, key_range *min_endp,
10621069
else
10631070
max= 1.0;
10641071

1072+
if (min > max)
1073+
{
1074+
/*
1075+
This can happen due to rounding errors.
1076+
1077+
What is the acceptable error size? Json_writer::add_double() uses
1078+
%.11lg format. This gives 9 digits after the dot. A histogram may have
1079+
hundreds of buckets, let's multiply the error by 1000. 9-3=6
1080+
*/
1081+
DBUG_ASSERT(max < min + 1e-6);
1082+
max= min;
1083+
}
10651084
return max - min;
10661085
}
10671086

0 commit comments

Comments
 (0)