diff --git a/mysql-test/r/selectivity_innodb.result b/mysql-test/r/selectivity_innodb.result index 96eedc0b415..0dc678f0c0d 100644 --- a/mysql-test/r/selectivity_innodb.result +++ b/mysql-test/r/selectivity_innodb.result @@ -1358,6 +1358,8 @@ set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivit DROP TABLE t1,t2; set use_stat_tables=@save_use_stat_tables; set optimizer_switch=@save_optimizer_switch_for_selectivity_test; +set @tmp_ust= @@use_stat_tables; +set @tmp_oucs= @@optimizer_use_condition_selectivity; # # MDEV-6808: MariaDB 10.0.13 crash with optimizer_use_condition_selectivity > 1 # @@ -1393,4 +1395,22 @@ t2.subject_type in ('user') repost_id subject_type subject_id object_type object_id is_private event_id DROP TABLE t1, t2; set optimizer_use_condition_selectivity=@tmp_mdev6808; +# +# MDEV-6442: Assertion `join->best_read < double(...)' failed with optimizer_use_condition_selectivity >=3, ... +# +SET use_stat_tables = PREFERABLY; +SET optimizer_use_condition_selectivity = 3; +CREATE TABLE t1 ( a VARCHAR(3), b VARCHAR(8), KEY (a,b) ) ENGINE=InnoDB; +INSERT INTO t1 VALUES ('USA','Chinese'),('USA','English'); +CREATE TABLE t2 (i INT) ENGINE=InnoDB; +SELECT * FROM t1, t2 WHERE ( 't', 'o' ) IN ( +SELECT t1_2.b, t1_1.a FROM t1 AS t1_1 STRAIGHT_JOIN t1 AS t1_2 ON ( t1_2.a = t1_1.b ) +); +a b i +DROP TABLE t1,t2; +# +# End of 10.0 tests +# +set use_stat_tables= @tmp_ust; +set optimizer_use_condition_selectivity= @tmp_oucs; SET SESSION STORAGE_ENGINE=DEFAULT; diff --git a/mysql-test/t/selectivity_innodb.test b/mysql-test/t/selectivity_innodb.test index 6996a6dd7ed..60b0da0d5d1 100644 --- a/mysql-test/t/selectivity_innodb.test +++ b/mysql-test/t/selectivity_innodb.test @@ -8,6 +8,9 @@ set optimizer_switch='extended_keys=on'; --source selectivity.test set optimizer_switch=@save_optimizer_switch_for_selectivity_test; +set @tmp_ust= @@use_stat_tables; +set @tmp_oucs= @@optimizer_use_condition_selectivity; + --echo # --echo # MDEV-6808: MariaDB 10.0.13 crash with optimizer_use_condition_selectivity > 1 @@ -46,4 +49,26 @@ WHERE DROP TABLE t1, t2; set optimizer_use_condition_selectivity=@tmp_mdev6808; +--echo # +--echo # MDEV-6442: Assertion `join->best_read < double(...)' failed with optimizer_use_condition_selectivity >=3, ... +--echo # +SET use_stat_tables = PREFERABLY; +SET optimizer_use_condition_selectivity = 3; + +CREATE TABLE t1 ( a VARCHAR(3), b VARCHAR(8), KEY (a,b) ) ENGINE=InnoDB; +INSERT INTO t1 VALUES ('USA','Chinese'),('USA','English'); + +CREATE TABLE t2 (i INT) ENGINE=InnoDB; + +SELECT * FROM t1, t2 WHERE ( 't', 'o' ) IN ( + SELECT t1_2.b, t1_1.a FROM t1 AS t1_1 STRAIGHT_JOIN t1 AS t1_2 ON ( t1_2.a = t1_1.b ) +); +DROP TABLE t1,t2; + +--echo # +--echo # End of 10.0 tests +--echo # + +set use_stat_tables= @tmp_ust; +set optimizer_use_condition_selectivity= @tmp_oucs; SET SESSION STORAGE_ENGINE=DEFAULT; diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc index bf79747f9a0..e1b197f4a63 100644 --- a/sql/sql_statistics.cc +++ b/sql/sql_statistics.cc @@ -3502,7 +3502,7 @@ double get_column_range_cardinality(Field *field, !(range_flag & NEAR_MIN); if (col_non_nulls < 1) - res= 0; + res= 0; /* this is likely wrong, see MDEV-6843 */ else if (min_endp && max_endp && min_endp->length == max_endp->length && !memcmp(min_endp->key, max_endp->key, min_endp->length)) { @@ -3515,6 +3515,15 @@ double get_column_range_cardinality(Field *field, { double avg_frequency= col_stats->get_avg_frequency(); res= avg_frequency; + /* + psergey-todo: what does check for min_value, max_value mean? + min/max_value are set to NULL in alloc_statistics_for_table() and + alloc_statistics_for_table_share(). Both functions will immediately + call create_min_max_statistical_fields_for_table and + create_min_max_statistical_fields_for_table_share() respectively, + which will set min/max_value to be valid pointers, unless OOM + occurs. + */ if (avg_frequency > 1.0 + 0.000001 && col_stats->min_value && col_stats->max_value) { @@ -3530,6 +3539,11 @@ double get_column_range_cardinality(Field *field, avg_frequency / col_non_nulls); } } + else if (avg_frequency == 0.0) + { + /* This actually means there is no statistics data */ + res= tab_records; + } } } else diff --git a/sql/sql_statistics.h b/sql/sql_statistics.h index c399951b828..46e5cef22d1 100644 --- a/sql/sql_statistics.h +++ b/sql/sql_statistics.h @@ -280,7 +280,14 @@ public: }; -/* Statistical data on a column */ +/* + Statistical data on a column + + Note: objects of this class may be "empty", where they have almost all fields + as zeros, for example, get_avg_frequency() will return 0. + + objects are allocated in alloc_statistics_for_table[_share]. +*/ class Column_statistics { @@ -296,7 +303,8 @@ public: are available for the column */ uint32 column_stat_nulls; - + + /* For the below two, see comments in get_column_range_cardinality() */ /* Minimum value for the column */ Field *min_value; /* Maximum value for the column */