List:Commits« Previous MessageNext Message »
From:<gshchepa Date:August 23 2007 5:24pm
Subject:bk commit into 5.1 tree (gshchepa:1.2569) BUG#30396
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of uchum. When uchum does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2007-08-23 22:24:31+05:00, gshchepa@stripped +7 -0
  Fixed bug #30396.
  Recommit to 5.1.22.
  The bug caused memory corruption for some queries with top OR level
  in the WHERE condition if they contained equality predicates and 
  other sargable predicates in disjunctive parts of the condition.
  
  The corruption happened because the upper bound of the memory
  allocated for KEY_FIELD and SARGABLE_PARAM internal structures
  containing info about potential lookup keys was calculated incorrectly
  in some cases. In particular it was calculated incorrectly when the
  WHERE condition was an OR formula with disjuncts being AND formulas
  including equalities and other sargable predicates.

  mysql-test/r/select.result@stripped, 2007-08-23 22:18:38+05:00, gshchepa@stripped +57 -0
    Added a test case for bug #30396.
    Recommit to 5.1.22.

  mysql-test/t/select.test@stripped, 2007-08-23 22:18:44+05:00, gshchepa@stripped +60 -0
    Added a test case for bug #30396.
    Recommit to 5.1.22.

  sql/item_cmpfunc.h@stripped, 2007-08-23 22:18:45+05:00, gshchepa@stripped +0 -1
    Removed max_members from the COND_EQUAL class as not useful anymore. 
    Recommit to 5.1.22.

  sql/sql_base.cc@stripped, 2007-08-23 22:18:46+05:00, gshchepa@stripped +1 -0
    Added the max_equal_elems field to the st_select_lex structure.
    Recommit to 5.1.22.

  sql/sql_lex.cc@stripped, 2007-08-23 22:18:46+05:00, gshchepa@stripped +1 -0
    Added the max_equal_elems field to the st_select_lex structure.
    Recommit to 5.1.22.

  sql/sql_lex.h@stripped, 2007-08-23 22:18:47+05:00, gshchepa@stripped +2 -1
    Added the max_equal_elems field to the st_select_lex structure.
    The field contains the maximal number of elements in multiple equalities
    built for the query conditions.
    Recommit to 5.1.22.

  sql/sql_select.cc@stripped, 2007-08-23 22:18:47+05:00, gshchepa@stripped +12 -26
    Fixed bug #30396.
    Recommit to 5.1.22.
    The bug caused memory corruption for some queries with top OR level
    in the WHERE condition if they contained equality predicates and 
    other sargable predicates in disjunctive parts of the condition.
    
    The corruption happened because the upper bound of the memory
    allocated for KEY_FIELD and SARGABLE_PARAM internal structures
    containing info about potential lookup keys was calculated incorrectly
    in some cases. In particular it was calculated incorrectly when the
    WHERE condition was an OR formula with disjuncts being AND formulas
    including equalities and other sargable predicates.
     
    The max_equal_elems field to the st_select_lex structure is used now
    to calculate the above mentioned upper bound. The field contains the
    maximal number of elements in multiple equalities built for the query
    conditions.

diff -Nrup a/mysql-test/r/select.result b/mysql-test/r/select.result
--- a/mysql-test/r/select.result	2007-06-26 16:15:02 +05:00
+++ b/mysql-test/r/select.result	2007-08-23 22:18:38 +05:00
@@ -3980,4 +3980,61 @@ id	select_type	table	type	possible_keys	
 1	SIMPLE	f1	index	inx	inx	10	NULL	7	Using where; Using index
 1	SIMPLE	f2	ref	inx	inx	5	test.f1.b	1	Using where; Using index
 DROP TABLE t1;
+CREATE TABLE t1 (
+c1 int(11) NOT NULL AUTO_INCREMENT,
+c2 varchar(1000) DEFAULT NULL,
+c3 bigint(20) DEFAULT NULL,
+c4 bigint(20) DEFAULT NULL,
+PRIMARY KEY (c1)
+);
+EXPLAIN EXTENDED 
+SELECT  join_2.c1  
+FROM 
+t1 AS join_0, 
+t1 AS join_1, 
+t1 AS join_2, 
+t1 AS join_3, 
+t1 AS join_4, 
+t1 AS join_5, 
+t1 AS join_6, 
+t1 AS join_7
+WHERE 
+join_0.c1=join_1.c1  AND 
+join_1.c1=join_2.c1  AND 
+join_2.c1=join_3.c1  AND 
+join_3.c1=join_4.c1  AND 
+join_4.c1=join_5.c1  AND 
+join_5.c1=join_6.c1  AND 
+join_6.c1=join_7.c1 
+OR 
+join_0.c2 < '?'  AND 
+join_1.c2 < '?'  AND
+join_2.c2 > '?'  AND
+join_2.c2 < '!'  AND
+join_3.c2 > '?'  AND 
+join_4.c2 = '?'  AND 
+join_5.c2 <> '?' AND
+join_6.c2 <> '?' AND 
+join_7.c2 >= '?' AND
+join_0.c1=join_1.c1  AND 
+join_1.c1=join_2.c1  AND 
+join_2.c1=join_3.c1  AND
+join_3.c1=join_4.c1  AND 
+join_4.c1=join_5.c1  AND 
+join_5.c1=join_6.c1  AND 
+join_6.c1=join_7.c1
+GROUP BY 
+join_3.c1,
+join_2.c1,
+join_7.c1,
+join_1.c1,
+join_0.c1;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	NULL	NULL	NULL	NULL	NULL	NULL	NULL	Impossible WHERE noticed after reading const tables
+Warnings:
+Note	1003	select '0' AS `c1` from `test`.`t1` `join_0` join `test`.`t1` `join_1` join `test`.`t1` `join_2` join `test`.`t1` `join_3` join `test`.`t1` `join_4` join `test`.`t1` `join_5` join `test`.`t1` `join_6` join `test`.`t1` `join_7` where 0 group by '0','0','0','0','0'
+SHOW WARNINGS;
+Level	Code	Message
+Note	1003	select '0' AS `c1` from `test`.`t1` `join_0` join `test`.`t1` `join_1` join `test`.`t1` `join_2` join `test`.`t1` `join_3` join `test`.`t1` `join_4` join `test`.`t1` `join_5` join `test`.`t1` `join_6` join `test`.`t1` `join_7` where 0 group by '0','0','0','0','0'
+DROP TABLE t1;
 End of 5.0 tests
diff -Nrup a/mysql-test/t/select.test b/mysql-test/t/select.test
--- a/mysql-test/t/select.test	2007-04-12 02:42:21 +05:00
+++ b/mysql-test/t/select.test	2007-08-23 22:18:44 +05:00
@@ -3359,4 +3359,64 @@ EXPLAIN SELECT COUNT(*) FROM t1 f1 INNER
     WHERE 1 AND f1.b NOT IN (100,2232,3343,51111);
 DROP TABLE t1;    
 
+#
+# Bug #30396: crash for a join with equalities and sargable predicates
+#             in disjunctive parts of the WHERE condition 
+#
+
+CREATE TABLE t1 (
+  c1 int(11) NOT NULL AUTO_INCREMENT,
+  c2 varchar(1000) DEFAULT NULL,
+  c3 bigint(20) DEFAULT NULL,
+  c4 bigint(20) DEFAULT NULL,
+  PRIMARY KEY (c1)
+);
+
+EXPLAIN EXTENDED 
+SELECT  join_2.c1  
+FROM 
+	t1 AS join_0, 
+	t1 AS join_1, 
+	t1 AS join_2, 
+	t1 AS join_3, 
+	t1 AS join_4, 
+	t1 AS join_5, 
+	t1 AS join_6, 
+	t1 AS join_7
+WHERE 
+	join_0.c1=join_1.c1  AND 
+	join_1.c1=join_2.c1  AND 
+	join_2.c1=join_3.c1  AND 
+	join_3.c1=join_4.c1  AND 
+	join_4.c1=join_5.c1  AND 
+	join_5.c1=join_6.c1  AND 
+	join_6.c1=join_7.c1 
+         OR 
+	join_0.c2 < '?'  AND 
+	join_1.c2 < '?'  AND
+	join_2.c2 > '?'  AND
+	join_2.c2 < '!'  AND
+	join_3.c2 > '?'  AND 
+	join_4.c2 = '?'  AND 
+	join_5.c2 <> '?' AND
+	join_6.c2 <> '?' AND 
+	join_7.c2 >= '?' AND
+        join_0.c1=join_1.c1  AND 
+	join_1.c1=join_2.c1  AND 
+        join_2.c1=join_3.c1  AND
+	join_3.c1=join_4.c1  AND 
+	join_4.c1=join_5.c1  AND 
+	join_5.c1=join_6.c1  AND 
+	join_6.c1=join_7.c1
+GROUP BY 
+	join_3.c1,
+	join_2.c1,
+	join_7.c1,
+	join_1.c1,
+	join_0.c1;
+	
+SHOW WARNINGS;
+
+DROP TABLE t1;
+
 --echo End of 5.0 tests
diff -Nrup a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
--- a/sql/item_cmpfunc.h	2007-08-13 18:11:11 +05:00
+++ b/sql/item_cmpfunc.h	2007-08-23 22:18:45 +05:00
@@ -1569,7 +1569,6 @@ public:
                                      the current and level           */
   COND_EQUAL()
   { 
-    max_members= 0;
     upper_levels= 0;
   }
 };
diff -Nrup a/sql/sql_base.cc b/sql/sql_base.cc
--- a/sql/sql_base.cc	2007-08-03 19:54:35 +05:00
+++ b/sql/sql_base.cc	2007-08-23 22:18:46 +05:00
@@ -6738,6 +6738,7 @@ int setup_conds(THD *thd, TABLE_LIST *ta
   DBUG_PRINT("info", ("thd->mark_used_columns: %d", thd->mark_used_columns));
   select_lex->cond_count= 0;
   select_lex->between_count= 0;
+  select_lex->max_equal_elems= 0;
 
   for (table= tables; table; table= table->next_local)
   {
diff -Nrup a/sql/sql_lex.cc b/sql/sql_lex.cc
--- a/sql/sql_lex.cc	2007-08-14 00:39:25 +05:00
+++ b/sql/sql_lex.cc	2007-08-23 22:18:46 +05:00
@@ -1517,6 +1517,7 @@ void st_select_lex::init_query()
   */
   parent_lex->push_context(&context);
   cond_count= between_count= with_wild= 0;
+  max_equal_elems= 0;
   conds_processed_with_permanent_arena= 0;
   ref_pointer_array= 0;
   select_n_where_fields= 0;
diff -Nrup a/sql/sql_lex.h b/sql/sql_lex.h
--- a/sql/sql_lex.h	2007-08-03 22:04:52 +05:00
+++ b/sql/sql_lex.h	2007-08-23 22:18:47 +05:00
@@ -606,7 +606,8 @@ public:
   */
   uint select_n_having_items;
   uint cond_count;    /* number of arguments of and/or/xor in where/having/on */
-  uint between_count; /* number of between predicates in where/having/on      */   
+  uint between_count; /* number of between predicates in where/having/on      */
+  uint max_equal_elems; /* maximal number of elements in multiple equalities  */   
   /*
     Number of fields used in select list or where clause of current select
     and all inner subselects.
diff -Nrup a/sql/sql_select.cc b/sql/sql_select.cc
--- a/sql/sql_select.cc	2007-08-14 00:39:25 +05:00
+++ b/sql/sql_select.cc	2007-08-23 22:18:47 +05:00
@@ -3562,10 +3562,7 @@ update_ref_and_keys(THD *thd, DYNAMIC_AR
   uint	and_level,i,found_eq_constant;
   KEY_FIELD *key_fields, *end, *field;
   uint sz;
-  uint m= 1;
-  
-  if (cond_equal && cond_equal->max_members)
-    m= cond_equal->max_members;
+  uint m= max(select_lex->max_equal_elems,1);
   
   /* 
     We use the same piece of memory to store both  KEY_FIELD 
@@ -3585,7 +3582,8 @@ update_ref_and_keys(THD *thd, DYNAMIC_AR
     it is considered as sargable only for its first argument.
     Multiple equality can add  elements that are filled after
     substitution of field arguments by equal fields. There
-    can be not more than cond_equal->max_members such substitutions.
+    can be not more than select_lex->max_equal_elems such 
+    substitutions.
   */ 
   sz= max(sizeof(KEY_FIELD),sizeof(SARGABLE_PARAM))*
       (((thd->lex->current_select->cond_count+1)*2 +
@@ -7387,8 +7385,7 @@ static bool check_equality(THD *thd, Ite
     just an argument of a comparison predicate.
     The function also determines the maximum number of members in 
     equality lists of each Item_cond_and object assigning it to
-    cond_equal->max_members of this object and updating accordingly
-    the upper levels COND_EQUAL structures.  
+    thd->lex->current_select->max_equal_elems.
 
   NOTES
     Multiple equality predicate =(f1,..fn) is equivalent to the conjuction of
@@ -7433,7 +7430,6 @@ static COND *build_equal_items_for_cond(
                                         COND_EQUAL *inherited)
 {
   Item_equal *item_equal;
-  uint members;
   COND_EQUAL cond_equal;
   cond_equal.upper_levels= inherited;
 
@@ -7471,19 +7467,8 @@ static COND *build_equal_items_for_cond(
       {
         item_equal->fix_length_and_dec();
         item_equal->update_used_tables();
-        members= item_equal->members();
-        if (cond_equal.max_members < members)
-          cond_equal.max_members= members; 
-      }
-      members= cond_equal.max_members;
-      if (inherited && inherited->max_members < members)
-      {
-        do
-        {
-	  inherited->max_members= members;
-          inherited= inherited->upper_levels;
-        }
-        while (inherited);
+        set_if_bigger(thd->lex->current_select->max_equal_elems,
+                      item_equal->members());  
       }
 
       ((Item_cond_and*)cond)->cond_equal= cond_equal;
@@ -7538,10 +7523,12 @@ static COND *build_equal_items_for_cond(
         {
           item_equal->fix_length_and_dec();
           item_equal->update_used_tables();
-          return item_equal;
 	}
         else
-          return eq_list.pop();
+          item_equal= (Item_equal *) eq_list.pop();
+        set_if_bigger(thd->lex->current_select->max_equal_elems,
+                      item_equal->members());  
+        return item_equal;
       }
       else
       {
@@ -7557,9 +7544,8 @@ static COND *build_equal_items_for_cond(
         {
           item_equal->fix_length_and_dec();
           item_equal->update_used_tables();
-          members= item_equal->members();
-          if (cond_equal.max_members < members)
-            cond_equal.max_members= members; 
+          set_if_bigger(thd->lex->current_select->max_equal_elems,
+                        item_equal->members());  
         }
         and_cond->cond_equal= cond_equal;
         args->concat((List<Item> *)&cond_equal.current_level);
Thread
bk commit into 5.1 tree (gshchepa:1.2569) BUG#30396gshchepa23 Aug