List:Commits« Previous MessageNext Message »
From:Timour Katchaounov Date:October 17 2008 9:46am
Subject:bzr commit into mysql-6.0-opt branch (timour:2694) Bug#37896
View as plain text  
#At file:///home/tkatchaounov/mysql/bzr/6.0-b37896/

 2694 Timour Katchaounov	2008-10-17
      BUG#37896 Assertion on entry of Item_in_subselect::exec on subquery with AND NOT
            
      Problem:
      The assertion failure is due to a shortcut in JOIN::optimize where if opt_sum_query
      detects that:
      a) a MIN/MAX function can be computed and substituted by an index lookup, and
      b) the WHERE clause doesn't reference any table in the FROM clause,
         then it does constant substitution, sets JOIN::tables_list = 0, and returns.
         As a result JOIN::optimize never calls setup_subquery_materialization, and never
         creates the correct subselect_engine. JOIN::exec still needs to execute the
         table-independent WHERE clause to check whether there is any result at all.
         This is when the assertion detects this inconsistent state.
            
            
      Solution:
      Call setup_subquery_materialization after the call to opt_sum_query detected that
      (a) and (b) above hold true.
            
      Note:
      This fix makes the behavior the same as that of subquery execution via the IN=>EXISTS
      transformation, thus the same as that of 5.x. However, as BUG#40037 explains, this
      behavior is incorrect because MIN/MAX should return NULL, if the query result is
      empty. This problem is filed as a separate bug since it is not related to materialization
      and is present in older versions.
modified:
  mysql-test/r/subselect_mat.result
  mysql-test/t/subselect_mat.test
  sql/item_subselect.cc
  sql/sql_select.cc

per-file messages:
  mysql-test/r/subselect_mat.result
    Test result for BUG#37896.
  mysql-test/t/subselect_mat.test
    Test result for BUG#37896.
  sql/item_subselect.cc
    The fact that a query has no tables, or all tables were optimized away is expressed
    in one more way, so we add this extra condition.
  sql/sql_select.cc
    Call setup_subquery_materialization() before RETURN-ing prematurely, because if there
    are IN predicates, they still might be executed and need to be setup.
=== modified file 'mysql-test/r/subselect_mat.result'
--- a/mysql-test/r/subselect_mat.result	2008-04-24 23:59:38 +0000
+++ b/mysql-test/r/subselect_mat.result	2008-10-17 09:46:06 +0000
@@ -1145,3 +1145,33 @@ t2.a = 3 and not t2.a not in (select t2.
 1
 1
 drop table t2;
+create table t1 (a1 int key);
+create table t2 (b1 int);
+insert into t1 values (5);
+explain select min(a1) from t1 where 7 in (select b1 from t2 group by b1);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	PRIMARY	NULL	NULL	NULL	NULL	NULL	NULL	NULL	Select tables optimized away
+2	SUBQUERY	t2	system	NULL	NULL	NULL	NULL	0	const row not found
+select min(a1) from t1 where 7 in (select b1 from t2 group by b1);
+min(a1)
+set @@optimizer_switch='no_materialization';
+explain select min(a1) from t1 where 7 in (select b1 from t2 group by b1);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	PRIMARY	NULL	NULL	NULL	NULL	NULL	NULL	NULL	Select tables optimized away
+2	DEPENDENT SUBQUERY	t2	system	NULL	NULL	NULL	NULL	0	const row not found
+select min(a1) from t1 where 7 in (select b1 from t2 group by b1);
+min(a1)
+set @@optimizer_switch='no_semijoin';
+explain select min(a1) from t1 where 7 in (select b1 from t2);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	PRIMARY	NULL	NULL	NULL	NULL	NULL	NULL	NULL	Select tables optimized away
+2	SUBQUERY	t2	system	NULL	NULL	NULL	NULL	0	const row not found
+select min(a1) from t1 where 7 in (select b1 from t2);
+min(a1)
+set @@optimizer_switch='no_materialization';
+explain select min(a1) from t1 where 7 in (select b1 from t2);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	PRIMARY	NULL	NULL	NULL	NULL	NULL	NULL	NULL	Impossible WHERE noticed after reading const tables
+select min(a1) from t1 where 7 in (select b1 from t2);
+min(a1)
+NULL

=== modified file 'mysql-test/t/subselect_mat.test'
--- a/mysql-test/t/subselect_mat.test	2008-04-24 23:59:38 +0000
+++ b/mysql-test/t/subselect_mat.test	2008-10-17 09:46:06 +0000
@@ -806,3 +806,29 @@ select 1 from t2 where  
     t2.a = 3 and not t2.a not in (select t2.b from t2);
 drop table t2;
 
+#
+# BUG#37896 Assertion on entry of Item_in_subselect::exec on subquery with AND NOT
+#
+create table t1 (a1 int key);
+create table t2 (b1 int);
+insert into t1 values (5);
+
+# Query with group by, executed via materialization
+explain select min(a1) from t1 where 7 in (select b1 from t2 group by b1);
+select min(a1) from t1 where 7 in (select b1 from t2 group by b1);
+# Query with group by, executed via IN=>EXISTS
+set @@optimizer_switch='no_materialization';
+explain select min(a1) from t1 where 7 in (select b1 from t2 group by b1);
+select min(a1) from t1 where 7 in (select b1 from t2 group by b1);
+
+# Executed with materialization
+set @@optimizer_switch='no_semijoin';
+explain select min(a1) from t1 where 7 in (select b1 from t2);
+select min(a1) from t1 where 7 in (select b1 from t2);
+# Executed with semi-join. Notice, this time we get a different result (NULL).
+# This is the only correct result of all four queries. This difference is
+# filed as BUG#40037.
+set @@optimizer_switch='no_materialization';
+explain select min(a1) from t1 where 7 in (select b1 from t2);
+select min(a1) from t1 where 7 in (select b1 from t2);
+

=== modified file 'sql/item_subselect.cc'
--- a/sql/item_subselect.cc	2008-07-24 10:00:56 +0000
+++ b/sql/item_subselect.cc	2008-10-17 09:46:06 +0000
@@ -1896,7 +1896,11 @@ bool Item_in_subselect::init_left_expr_c
   bool use_result_field= FALSE;
 
   outer_join= unit->outer_select()->join;
-  if (!outer_join || !outer_join->tables)
+  /*
+    An IN predicate might be evaluated in a query for which all tables have
+    been optimzied away.
+  */ 
+  if (!outer_join || !outer_join->tables || !outer_join->tables_list)
     return TRUE;
   /*
     If we use end_[send | write]_group to handle complete rows of the outer

=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc	2008-09-13 14:16:20 +0000
+++ b/sql/sql_select.cc	2008-10-17 09:46:06 +0000
@@ -1555,6 +1555,9 @@ JOIN::optimize()
                                  QT_ORDINARY););
         conds= table_independent_conds;
       }
+      /* Create all structures needed for materialized subquery execution. */
+      if (setup_subquery_materialization())
+        DBUG_RETURN(1);
     }
   }
   if (!tables_list)

Thread
bzr commit into mysql-6.0-opt branch (timour:2694) Bug#37896Timour Katchaounov17 Oct