#At file:///home/tsk/mprog/src/5.3/ based on revid:psergey@askmonty.org-20100716090711-5ijpspzyvmoi5mix 2805 timour@askmonty.org 2010-07-16 Fixed a problem where the temp table of a materialized subquery was not cleaned up between PS re-executions. The reason was two-fold: - a merge with mysql-6.0 missed select_union::cleanup() that should have cleaned up the temp table, and - the subclass of select_union used by materialization didn't call the base class cleanup() method. modified: mysql-test/r/subselect_mat.result mysql-test/t/subselect_mat.test sql/sql_class.cc sql/sql_class.h sql/sql_union.cc === modified file 'mysql-test/r/subselect_mat.result' --- a/mysql-test/r/subselect_mat.result 2010-06-26 10:05:41 +0000 +++ b/mysql-test/r/subselect_mat.result 2010-07-16 11:02:15 +0000 @@ -1246,3 +1246,29 @@ i 4 set session optimizer_switch=@save_optimizer_switch; drop table t1, t2, t3; +create table t0 (a int); +insert into t0 values (0),(1),(2); +create table t1 (a int); +insert into t1 values (0),(1),(2); +explain select a, a in (select a from t1) from t0; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t0 ALL NULL NULL NULL NULL 3 +2 SUBQUERY t1 ALL NULL NULL NULL NULL 3 +select a, a in (select a from t1) from t0; +a a in (select a from t1) +0 1 +1 1 +2 1 +prepare s from 'select a, a in (select a from t1) from t0'; +execute s; +a a in (select a from t1) +0 1 +1 1 +2 1 +update t1 set a=123; +execute s; +a a in (select a from t1) +0 0 +1 0 +2 0 +drop table t0, t1; === modified file 'mysql-test/t/subselect_mat.test' --- a/mysql-test/t/subselect_mat.test 2010-03-13 20:04:52 +0000 +++ b/mysql-test/t/subselect_mat.test 2010-07-16 11:02:15 +0000 @@ -905,3 +905,19 @@ select * from t1 where t1.i in (select t set session optimizer_switch=@save_optimizer_switch; drop table t1, t2, t3; +# +# Test that the contents of the temp table of a materialized subquery is +# cleaned up between PS re-executions. +# + +create table t0 (a int); +insert into t0 values (0),(1),(2); +create table t1 (a int); +insert into t1 values (0),(1),(2); +explain select a, a in (select a from t1) from t0; +select a, a in (select a from t1) from t0; +prepare s from 'select a, a in (select a from t1) from t0'; +execute s; +update t1 set a=123; +execute s; +drop table t0, t1; === modified file 'sql/sql_class.cc' --- a/sql/sql_class.cc 2010-07-10 10:37:30 +0000 +++ b/sql/sql_class.cc 2010-07-16 11:02:15 +0000 @@ -2994,14 +2994,28 @@ create_result_table(THD *thd_arg, List<I if (!stat) return TRUE; - cleanup(); - + reset(); table->file->extra(HA_EXTRA_WRITE_CACHE); table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); return FALSE; } +void select_materialize_with_stats::reset() +{ + memset(col_stat, 0, table->s->fields * sizeof(Column_statistics)); + max_nulls_in_row= 0; + count_rows= 0; +} + + +void select_materialize_with_stats::cleanup() +{ + reset(); + select_union::cleanup(); +} + + /** Override select_union::send_data to analyze each row for NULLs and to update null_statistics before sending data to the client. === modified file 'sql/sql_class.h' --- a/sql/sql_class.h 2010-07-10 10:37:30 +0000 +++ b/sql/sql_class.h 2010-07-16 11:02:15 +0000 @@ -2905,7 +2905,7 @@ public: bool send_data(List<Item> &items); bool send_eof(); bool flush(); - + void cleanup(); virtual bool create_result_table(THD *thd, List<Item> *column_types, bool is_distinct, ulonglong options, const char *alias, bool bit_fields_as_long); @@ -2968,6 +2968,9 @@ protected: */ ha_rows count_rows; +protected: + void reset(); + public: select_materialize_with_stats() {} virtual bool create_result_table(THD *thd, List<Item> *column_types, @@ -2975,12 +2978,7 @@ public: const char *alias, bool bit_fields_as_long); bool init_result_table(ulonglong select_options); bool send_data(List<Item> &items); - void cleanup() - { - memset(col_stat, 0, table->s->fields * sizeof(Column_statistics)); - max_nulls_in_row= 0; - count_rows= 0; - } + void cleanup(); ha_rows get_null_count_of_col(uint idx) { DBUG_ASSERT(idx < table->s->fields); === modified file 'sql/sql_union.cc' --- a/sql/sql_union.cc 2010-07-10 10:37:30 +0000 +++ b/sql/sql_union.cc 2010-07-16 11:02:15 +0000 @@ -136,6 +136,22 @@ select_union::create_result_table(THD *t } +/** + Reset and empty the temporary table that stores the materialized query result. + + @note The cleanup performed here is exactly the same as for the two temp + tables of JOIN - exec_tmp_table_[1 | 2]. +*/ + +void select_union::cleanup() +{ + table->file->extra(HA_EXTRA_RESET_STATE); + table->file->ha_delete_all_rows(); + free_io_cache(table); + filesort_free_buffers(table,0); +} + + /* initialization procedures before fake_select_lex preparation()