summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <timour@askmonty.org>2010-04-06 00:15:15 +0300
committerunknown <timour@askmonty.org>2010-04-06 00:15:15 +0300
commit3b05fc78e5dceebaa47c10d36ba667fb7be38fac (patch)
tree1ea66b0fcf606058c81d608a2cb51debb3d6b6cd
parent3fc85580c9bc1e585de752697e3ae7ad02a64957 (diff)
downloadmariadb-git-3b05fc78e5dceebaa47c10d36ba667fb7be38fac.tar.gz
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.
-rw-r--r--mysql-test/r/subselect_mat.result26
-rw-r--r--mysql-test/t/subselect_mat.test16
-rw-r--r--sql/sql_class.cc22
-rw-r--r--sql/sql_class.h12
-rw-r--r--sql/sql_union.cc16
5 files changed, 81 insertions, 11 deletions
diff --git a/mysql-test/r/subselect_mat.result b/mysql-test/r/subselect_mat.result
index 7b175d5216a..823025cf0d6 100644
--- a/mysql-test/r/subselect_mat.result
+++ b/mysql-test/r/subselect_mat.result
@@ -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;
diff --git a/mysql-test/t/subselect_mat.test b/mysql-test/t/subselect_mat.test
index 54b1b5e15f9..dff9a7cf223 100644
--- a/mysql-test/t/subselect_mat.test
+++ b/mysql-test/t/subselect_mat.test
@@ -905,3 +905,19 @@ select * from t1 where t1.i in (select t2.i from t2 join t3 where t2.i + t3.i =
set session optimizer_switch=@save_optimizer_switch;
drop table t1, t2, t3;
+#
+# Test that the contentes of the temp table of a materialized subquery is
+# cleanup up between PS reexecutions.
+#
+
+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;
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 769e78ab86b..da638feb8b4 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -2942,8 +2942,7 @@ bool select_dumpvar::send_eof()
}
-bool
-select_materialize_with_stats::
+bool select_materialize_with_stats::
create_result_table(THD *thd_arg, List<Item> *column_types,
bool is_union_distinct, ulonglong options,
const char *table_alias, bool bit_fields_as_long)
@@ -2962,14 +2961,29 @@ create_result_table(THD *thd_arg, List<Item> *column_types,
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.
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 4388f26c0ce..a0fb22a453f 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -2820,7 +2820,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);
@@ -2883,6 +2883,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,
@@ -2890,12 +2893,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);
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index ee9ff833726..1080b45d60d 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -136,6 +136,22 @@ select_union::create_result_table(THD *thd_arg, List<Item> *column_types,
}
+/**
+ 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()