From 66dfceb11fe2392c98ec0f481a01e8da7b4314b8 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 30 May 2012 19:10:18 +0300 Subject: [PATCH] Fix for bug lp:1006231 Analysis: When a subquery that needs a temp table is executed during the prepare or optimize phase of the outer query, at the end of the subquery execution all the JOIN_TABs of the subquery are replaced by a new JOIN_TAB that selects from the temp table. However that temp table has no corresponding TABLE_LIST. Once EXPLAIN execution reaches its last phase, it tries to print the names of the subquery tables through its TABLE_LISTs, but in the case of this bug there is no such TABLE_LIST (it is NULL), hence a crash. Solution: The fix is to block subquery evaluation inside Item_func_like::fix_fields and Item_func_like::select_optimize() using the Item::is_expensive() test. --- mysql-test/r/subselect_innodb.result | 15 +++++++++++++++ mysql-test/t/subselect_innodb.test | 12 ++++++++++++ sql/item_cmpfunc.cc | 5 +++-- 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/subselect_innodb.result b/mysql-test/r/subselect_innodb.result index f77ac03db3f..ee28a6cdb37 100644 --- a/mysql-test/r/subselect_innodb.result +++ b/mysql-test/r/subselect_innodb.result @@ -365,4 +365,19 @@ GROUP BY 1 MAX( f1 ) NULL drop table t1, t2, t3; +# +# LP BUG#1006231 crash in select_describe +# +create table t1(a1 int) ENGINE=InnoDB; +insert into t1 values (1); +explain +select 1 from t1 where 1 like (select 1 from t1 where 1 <=> (select 1 from t1 group by a1)); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 1 +2 SUBQUERY t1 ALL NULL NULL NULL NULL 1 +3 SUBQUERY t1 ALL NULL NULL NULL NULL 1 Using temporary; Using filesort +select 1 from t1 where 1 like (select 1 from t1 where 1 <=> (select 1 from t1 group by a1)); +1 +1 +drop table t1; set optimizer_switch=@subselect_innodb_tmp; diff --git a/mysql-test/t/subselect_innodb.test b/mysql-test/t/subselect_innodb.test index a0c52196412..26ff1072e30 100644 --- a/mysql-test/t/subselect_innodb.test +++ b/mysql-test/t/subselect_innodb.test @@ -356,4 +356,16 @@ WHERE f2 >= ( drop table t1, t2, t3; +--echo # +--echo # LP BUG#1006231 crash in select_describe +--echo # + +create table t1(a1 int) ENGINE=InnoDB; +insert into t1 values (1); +explain +select 1 from t1 where 1 like (select 1 from t1 where 1 <=> (select 1 from t1 group by a1)); +select 1 from t1 where 1 like (select 1 from t1 where 1 <=> (select 1 from t1 group by a1)); +drop table t1; + + set optimizer_switch=@subselect_innodb_tmp; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index f0ba4917685..0983fb1e81d 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -4656,7 +4656,7 @@ longlong Item_func_like::val_int() Item_func::optimize_type Item_func_like::select_optimize() const { - if (args[1]->const_item()) + if (args[1]->const_item() && !args[1]->is_expensive()) { String* res2= args[1]->val_str((String *)&cmp.value2); const char *ptr2; @@ -4743,7 +4743,8 @@ bool Item_func_like::fix_fields(THD *thd, Item **ref) We could also do boyer-more for non-const items, but as we would have to recompute the tables for each row it's not worth it. */ - if (args[1]->const_item() && !use_strnxfrm(collation.collation)) + if (args[1]->const_item() && !use_strnxfrm(collation.collation) && + !args[1]->is_expensive()) { String* res2 = args[1]->val_str(&cmp.value2); if (!res2)