diff --git a/mysql-test/suite/innodb/r/innodb_stats_fetch.result b/mysql-test/suite/innodb/r/innodb_stats_fetch.result index cb205b1827b..d2fce6301d3 100644 --- a/mysql-test/suite/innodb/r/innodb_stats_fetch.result +++ b/mysql-test/suite/innodb/r/innodb_stats_fetch.result @@ -181,3 +181,13 @@ ALTER TABLE mysql.innodb_table_stats FORCE, LOCK=NONE; ERROR 0A000: LOCK=NONE is not supported. Reason: innodb_table_stats. Try LOCK=SHARED ALTER TABLE mysql.innodb_index_stats FORCE, LOCK=NONE; ERROR 0A000: LOCK=NONE is not supported. Reason: innodb_index_stats. Try LOCK=SHARED +# +# MDEV-34474 InnoDB: Failing assertion: stat_n_leaf_pages > 0 +# in ha_innobase::estimate_rows_upper_bound +# +CREATE TABLE t (c1 INT,c2 INT, +INDEX(c1))STATS_PERSISTENT=1 ENGINE=INNODB; +UPDATE mysql.innodb_index_stats SET stat_value=0 WHERE database_name like "test" and table_name like 't'; +UPDATE mysql.innodb_table_stats SET clustered_index_size= 0, sum_of_other_index_sizes=0 WHERE database_name like "test" and table_name like 't'; +UPDATE t SET c1=+1 ORDER BY c2; +DROP TABLE t; diff --git a/mysql-test/suite/innodb/t/innodb_stats_fetch.test b/mysql-test/suite/innodb/t/innodb_stats_fetch.test index d02cd3b8959..031144d82bc 100644 --- a/mysql-test/suite/innodb/t/innodb_stats_fetch.test +++ b/mysql-test/suite/innodb/t/innodb_stats_fetch.test @@ -104,3 +104,15 @@ DROP TABLE t1; ALTER TABLE mysql.innodb_table_stats FORCE, LOCK=NONE; --error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON ALTER TABLE mysql.innodb_index_stats FORCE, LOCK=NONE; + +--echo # +--echo # MDEV-34474 InnoDB: Failing assertion: stat_n_leaf_pages > 0 +--echo # in ha_innobase::estimate_rows_upper_bound +--echo # + +CREATE TABLE t (c1 INT,c2 INT, + INDEX(c1))STATS_PERSISTENT=1 ENGINE=INNODB; +UPDATE mysql.innodb_index_stats SET stat_value=0 WHERE database_name like "test" and table_name like 't'; +UPDATE mysql.innodb_table_stats SET clustered_index_size= 0, sum_of_other_index_sizes=0 WHERE database_name like "test" and table_name like 't'; +UPDATE t SET c1=+1 ORDER BY c2; +DROP TABLE t; diff --git a/storage/innobase/dict/dict0stats.cc b/storage/innobase/dict/dict0stats.cc index 3d931c4a490..580aeaeae6a 100644 --- a/storage/innobase/dict/dict0stats.cc +++ b/storage/innobase/dict/dict0stats.cc @@ -3503,25 +3503,34 @@ dict_stats_fetch_table_stats_step( break; case 1: /* mysql.innodb_table_stats.clustered_index_size */ - + { ut_a(dtype_get_mtype(type) == DATA_INT); ut_a(len == 8); table->stat_clustered_index_size - = (ulint) mach_read_from_8(data); - + = std::max(mach_read_from_8(data), 1); break; + } case 2: /* mysql.innodb_table_stats.sum_of_other_index_sizes */ - + { ut_a(dtype_get_mtype(type) == DATA_INT); ut_a(len == 8); - table->stat_sum_of_other_index_sizes + ulint stat_other_idx_size = (ulint) mach_read_from_8(data); + if (!stat_other_idx_size + && UT_LIST_GET_LEN(table->indexes) > 1) { + stat_other_idx_size + = UT_LIST_GET_LEN(table->indexes) - 1; + } + table->stat_sum_of_other_index_sizes + = std::max( + mach_read_from_8(data), + UT_LIST_GET_LEN(table->indexes) - 1); break; - + } default: /* someone changed SELECT @@ -3704,12 +3713,14 @@ dict_stats_fetch_index_stats_step( if (stat_name_len == 4 /* strlen("size") */ && strncasecmp("size", stat_name, stat_name_len) == 0) { - index->stat_index_size = (ulint) stat_value; + index->stat_index_size + = std::max(stat_value, 1); arg->stats_were_modified = true; } else if (stat_name_len == 12 /* strlen("n_leaf_pages") */ && strncasecmp("n_leaf_pages", stat_name, stat_name_len) == 0) { - index->stat_n_leaf_pages = (ulint) stat_value; + index->stat_n_leaf_pages + = std::max(stat_value, 1); arg->stats_were_modified = true; } else if (stat_name_len == 12 /* strlen("n_page_split") */ && strncasecmp("n_page_split", stat_name, stat_name_len) @@ -3789,7 +3800,8 @@ dict_stats_fetch_index_stats_step( index->stat_n_diff_key_vals[n_pfx - 1] = stat_value; if (sample_size != UINT64_UNDEFINED) { - index->stat_n_sample_sizes[n_pfx - 1] = sample_size; + index->stat_n_sample_sizes[n_pfx - 1] = + std::max(sample_size, 1); } else { /* hmm, strange... the user must have UPDATEd the table manually and SET sample_size = NULL */