diff options
author | Igor Babaev <igor@askmonty.org> | 2012-08-27 14:19:25 -0700 |
---|---|---|
committer | Igor Babaev <igor@askmonty.org> | 2012-08-27 14:19:25 -0700 |
commit | d0ad93fbc7eca575364e46f67c4613efb0807047 (patch) | |
tree | 6b9aae82750afbb2093c2d997076666b91838dcc | |
parent | f4631d6f71c19a98eccf4998eccb49dd69897661 (diff) | |
download | mariadb-git-d0ad93fbc7eca575364e46f67c4613efb0807047.tar.gz |
Fixed bug mdev-487.
The function collect_statistics_for_table() when scanning a table
did not take into account that the handler function ha_rnd_next
could return the code HA_ERR_RECORD_DELETE that should not be
considered as an indication of an error.
Also fixed a potential memory leak in this function.
-rw-r--r-- | mysql-test/r/stat_tables.result | 11 | ||||
-rw-r--r-- | mysql-test/r/stat_tables_innodb.result | 11 | ||||
-rw-r--r-- | mysql-test/t/stat_tables.test | 13 | ||||
-rw-r--r-- | sql/sql_statistics.cc | 36 |
4 files changed, 65 insertions, 6 deletions
diff --git a/mysql-test/r/stat_tables.result b/mysql-test/r/stat_tables.result index 4cc486b10ef..3cc650e7050 100644 --- a/mysql-test/r/stat_tables.result +++ b/mysql-test/r/stat_tables.result @@ -353,4 +353,15 @@ Table Op Msg_type Msg_text test.t1 analyze status Table is already up to date alter table t1 add column a varchar(8); drop table t1; +# +# Bug mdev-487: memory leak in ANALYZE with stat tables +# +SET use_stat_tables = 'preferably'; +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2); +DELETE FROM t1 WHERE a=1; +ANALYZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 analyze status OK +DROP TABLE t1; set use_stat_tables=@save_use_stat_tables; diff --git a/mysql-test/r/stat_tables_innodb.result b/mysql-test/r/stat_tables_innodb.result index 250f24fee02..bb0497ee331 100644 --- a/mysql-test/r/stat_tables_innodb.result +++ b/mysql-test/r/stat_tables_innodb.result @@ -380,6 +380,17 @@ Table Op Msg_type Msg_text test.t1 analyze status OK alter table t1 add column a varchar(8); drop table t1; +# +# Bug mdev-487: memory leak in ANALYZE with stat tables +# +SET use_stat_tables = 'preferably'; +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2); +DELETE FROM t1 WHERE a=1; +ANALYZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 analyze status OK +DROP TABLE t1; set use_stat_tables=@save_use_stat_tables; set optimizer_switch=@save_optimizer_switch_for_stat_tables_test; SET SESSION STORAGE_ENGINE=DEFAULT; diff --git a/mysql-test/t/stat_tables.test b/mysql-test/t/stat_tables.test index 67e66a52a6a..3ef5b4e9b92 100644 --- a/mysql-test/t/stat_tables.test +++ b/mysql-test/t/stat_tables.test @@ -166,5 +166,18 @@ alter table t1 add column a varchar(8); drop table t1; +--echo # +--echo # Bug mdev-487: memory leak in ANALYZE with stat tables +--echo # + +SET use_stat_tables = 'preferably'; + +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2); +DELETE FROM t1 WHERE a=1; + +ANALYZE TABLE t1; + +DROP TABLE t1; set use_stat_tables=@save_use_stat_tables; diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc index f58659862c4..c3d95da007e 100644 --- a/sql/sql_statistics.cc +++ b/sql/sql_statistics.cc @@ -179,6 +179,7 @@ public: inline void init(THD *thd, Field * table_field); inline void add(ha_rows rowno); inline void finish(ha_rows rows); + inline void cleanup(); }; @@ -1895,6 +1896,22 @@ void Column_statistics_collected::finish(ha_rows rows) /** @brief + Clean up auxiliary structures used for aggregation +*/ + +inline +void Column_statistics_collected::cleanup() +{ + if (count_distinct) + { + delete count_distinct; + count_distinct= NULL; + } +} + + +/** + @brief Collect statistical data on an index @param @@ -2047,7 +2064,11 @@ int collect_statistics_for_table(THD *thd, TABLE *table) break; if (rc) + { + if (rc == HA_ERR_RECORD_DELETED) + continue; break; + } for (field_ptr= table->field; *field_ptr; field_ptr++) { @@ -2071,14 +2092,17 @@ int collect_statistics_for_table(THD *thd, TABLE *table) { table->collected_stats->cardinality_is_null= FALSE; table->collected_stats->cardinality= rows; + } - for (field_ptr= table->field; *field_ptr; field_ptr++) - { - table_field= *field_ptr; - if (!bitmap_is_set(table->read_set, table_field->field_index)) - continue; + for (field_ptr= table->field; *field_ptr; field_ptr++) + { + table_field= *field_ptr; + if (!bitmap_is_set(table->read_set, table_field->field_index)) + continue; + if (!rc) table_field->collected_stats->finish(rows); - } + else + table_field->collected_stats->cleanup(); } if (!rc) |