From b8b875cb796743240bed71857eae73d37f03c28f Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 26 Nov 2012 21:22:44 +0200 Subject: [PATCH] Fix of MDEV-3874: Server crashes in Item_field::print on a SELECT from a MERGE view with materialization+semijoin, subquery, ORDER BY. The problem was that in debugging binaries it try to print item to assign human readable name to the item. But subquery item was already freed (join_free/cleanup with full cleanup) so Item_field refers to temporary table which memory had been already freed. --- mysql-test/r/view.result | 32 ++++++++++++++++++++++++++++++++ mysql-test/t/view.test | 35 +++++++++++++++++++++++++++++++++++ sql/sql_select.cc | 13 +++++++++++++ sql/sql_select.h | 3 +++ 4 files changed, 83 insertions(+) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 1bcc9fb727f..8d2d1561456 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -4825,4 +4825,36 @@ drop tables t1,t2; # ----------------------------------------------------------------- # -- End of 5.3 tests. # ----------------------------------------------------------------- +# +# MDEV-3874: Server crashes in Item_field::print on a SELECT +# from a MERGE view with materialization+semijoin, subquery, ORDER BY +# +SET @save_optimizer_switch_MDEV_3874=@@optimizer_switch; +SET optimizer_switch = 'materialization=on,semijoin=on'; +CREATE TABLE t1 (a INT) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1),(7); +CREATE TABLE t2 (b INT) ENGINE=MyISAM; +INSERT INTO t2 VALUES (4),(6); +CREATE TABLE t3 (c INT) ENGINE=MyISAM; +INSERT INTO t3 VALUES (1),(2); +CREATE ALGORITHM=MERGE VIEW v1 AS SELECT +( SELECT a FROM t1 WHERE ( 1, 1 ) IN ( +SELECT b, c FROM t2, t3 HAVING c > 2 ) ) AS field1, +b + c AS field2 +FROM t2, t3 AS table1 +GROUP BY field1, field2 ORDER BY field1; +Warnings: +Warning 1354 View merge algorithm can't be used here for now (assumed undefined algorithm) +SELECT * FROM v1; +field1 field2 +NULL 5 +NULL 7 +NULL 6 +NULL 8 +drop view v1; +drop table t1,t2,t3; +SET optimizer_switch=@save_optimizer_switch_MDEV_3874; +# ----------------------------------------------------------------- +# -- End of 5.5 tests. +# ----------------------------------------------------------------- SET optimizer_switch=@save_optimizer_switch; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 817da816c48..d299718b54a 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -4751,4 +4751,39 @@ drop tables t1,t2; --echo # -- End of 5.3 tests. --echo # ----------------------------------------------------------------- +--echo # +--echo # MDEV-3874: Server crashes in Item_field::print on a SELECT +--echo # from a MERGE view with materialization+semijoin, subquery, ORDER BY +--echo # +SET @save_optimizer_switch_MDEV_3874=@@optimizer_switch; + +SET optimizer_switch = 'materialization=on,semijoin=on'; + +CREATE TABLE t1 (a INT) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1),(7); + +CREATE TABLE t2 (b INT) ENGINE=MyISAM; +INSERT INTO t2 VALUES (4),(6); + +CREATE TABLE t3 (c INT) ENGINE=MyISAM; +INSERT INTO t3 VALUES (1),(2); + + +CREATE ALGORITHM=MERGE VIEW v1 AS SELECT +( SELECT a FROM t1 WHERE ( 1, 1 ) IN ( +SELECT b, c FROM t2, t3 HAVING c > 2 ) ) AS field1, +b + c AS field2 +FROM t2, t3 AS table1 +GROUP BY field1, field2 ORDER BY field1; + +SELECT * FROM v1; + +drop view v1; +drop table t1,t2,t3; +SET optimizer_switch=@save_optimizer_switch_MDEV_3874; + +--echo # ----------------------------------------------------------------- +--echo # -- End of 5.5 tests. +--echo # ----------------------------------------------------------------- + SET optimizer_switch=@save_optimizer_switch; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index ceb8827c790..8f7fdab4ed3 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -2074,6 +2074,7 @@ JOIN::reinit() ULL(0)); first_record= 0; + cleaned= false; if (exec_tmp_table1) { @@ -10623,6 +10624,7 @@ void JOIN::cleanup(bool full) { tab->cleanup(); } + cleaned= true; } else { @@ -22409,6 +22411,17 @@ void st_select_lex::print(THD *thd, String *str, enum_query_type query_type) str->append(STRING_WITH_LEN("select ")); + if (join && join->cleaned) + { + /* + JOIN already cleaned up so it is dangerous to print items + because temporary tables they pointed on could be freed. + */ + str->append('#'); + str->append(select_number); + return; + } + /* First add options */ if (options & SELECT_STRAIGHT_JOIN) str->append(STRING_WITH_LEN("straight_join ")); diff --git a/sql/sql_select.h b/sql/sql_select.h index e4687b4f00c..bac29b96c5a 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -1141,6 +1141,8 @@ public: bool skip_sort_order; bool need_tmp, hidden_group_fields; + /* TRUE if there was full cleunap of the JOIN */ + bool cleaned; DYNAMIC_ARRAY keyuse; Item::cond_result cond_value, having_value; List all_fields; ///< to store all fields that used in query @@ -1268,6 +1270,7 @@ public: zero_result_cause= 0; optimized= 0; initialized= 0; + cleaned= 0; cond_equal= 0; having_equal= 0; exec_const_cond= 0;