List:Commits« Previous MessageNext Message »
From:mhansson Date:January 29 2008 1:17pm
Subject:bk commit into 6.0 tree (mhansson:1.2767) BUG#33062
View as plain text  
Below is the list of changes that have just been committed into a local
6.0 repository of martin. When martin 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, 2008-01-29 14:17:14+01:00, mhansson@stripped +8 -0
  Bug#33062: subquery in stored routine cause crash
  
  Subquery flattening maintained a pointer into the list structure
  representing a WHERE clause, which introduces a dependency on this
  structure not changing. This caused crashed in stored procedures.
  Fixed by doing a lookup in the list instead instead of relying on
  a pointer.

  mysql-test/r/subselect_sj2.result@stripped, 2008-01-29 14:17:07+01:00, mhansson@stripped +29 -0
    Bug#33062: Test result

  mysql-test/t/subselect_sj2.test@stripped, 2008-01-29 14:17:07+01:00, mhansson@stripped +40 -0
    Bug#33062: Test case

  sql/item.h@stripped, 2008-01-29 14:17:07+01:00, mhansson@stripped +23 -0
    Bug#33062: New method declaration

  sql/item_cmpfunc.cc@stripped, 2008-01-29 14:17:07+01:00, mhansson@stripped +24 -0
    Bug#33062: New method's implementation for expression trees.

  sql/item_cmpfunc.h@stripped, 2008-01-29 14:17:07+01:00, mhansson@stripped +2 -0
    Bug#33062: New method override declaration.

  sql/item_subselect.cc@stripped, 2008-01-29 14:17:07+01:00, mhansson@stripped +0 -1
    Bug#33062: Removed pointer.

  sql/item_subselect.h@stripped, 2008-01-29 14:17:07+01:00, mhansson@stripped +0 -1
    Bug#33062: Removed pointer.

  sql/sql_select.cc@stripped, 2008-01-29 14:17:07+01:00, mhansson@stripped +13 -6
    Bug#33062: Corrected comment. Added call to new method instead of 
    using ref_ptr.

diff -Nrup a/mysql-test/r/subselect_sj2.result b/mysql-test/r/subselect_sj2.result
--- a/mysql-test/r/subselect_sj2.result	2007-12-01 22:54:37 +01:00
+++ b/mysql-test/r/subselect_sj2.result	2008-01-29 14:17:07 +01:00
@@ -351,3 +351,32 @@ Canada
 China
 Czech Republic
 drop table t1, t2;
+CREATE TABLE t1(a INT);
+CREATE TABLE t2(c INT);
+CREATE PROCEDURE p1(v1 int)
+BEGIN
+SELECT 1 FROM t1 WHERE a = v1 AND a IN (SELECT c FROM t2);
+END
+//
+CREATE PROCEDURE p2(v1 int)
+BEGIN
+SELECT 1 
+FROM 
+t1 t01,t1 t02,t1 t03,t1 t04,t1 t05,t1 t06,t1 t07,t1 t08,
+t1 t09,t1 t10,t1 t11,t1 t12,t1 t13,t1 t14,t1 t15,t1 t16,
+t1 t17,t1 t18,t1 t19,t1 t20,t1 t21,t1 t22,t1 t23,t1 t24,
+t1 t25,t1 t26,t1 t27,t1 t28,t1 t29,t1 t30,t1 t31,t1 t32,
+t1 t33,t1 t34,t1 t35,t1 t36,t1 t37,t1 t38,t1 t39,t1 t40,
+t1 t41,t1 t42,t1 t43,t1 t44,t1 t45,t1 t46,t1 t47,t1 t48,
+t1 t49,t1 t50,t1 t51,t1 t52,t1 t53,t1 t54,t1 t55,t1 t56,
+t1 t57,t1 t58,t1 t59,t1 t60
+WHERE t01.a IN (SELECT c FROM t2);
+END
+//
+CALL p1(1);
+1
+CALL p2(1);
+1
+DROP TABLE t1, t2;
+DROP PROCEDURE p1;
+DROP PROCEDURE p2;
diff -Nrup a/mysql-test/t/subselect_sj2.test b/mysql-test/t/subselect_sj2.test
--- a/mysql-test/t/subselect_sj2.test	2007-09-26 13:49:29 +02:00
+++ b/mysql-test/t/subselect_sj2.test	2008-01-29 14:17:07 +01:00
@@ -480,3 +480,43 @@ SELECT Name FROM t1 
     SELECT t2.CountryCode FROM t2 WHERE Population > 5000000);
 
 drop table t1, t2;
+
+#
+# Bug#33062: subquery in stored routine cause crash
+#
+
+CREATE TABLE t1(a INT);
+CREATE TABLE t2(c INT);
+
+DELIMITER //;
+
+CREATE PROCEDURE p1(v1 int)
+BEGIN
+  SELECT 1 FROM t1 WHERE a = v1 AND a IN (SELECT c FROM t2);
+END
+//
+
+CREATE PROCEDURE p2(v1 int)
+BEGIN
+  SELECT 1 
+  FROM 
+    t1 t01,t1 t02,t1 t03,t1 t04,t1 t05,t1 t06,t1 t07,t1 t08,
+    t1 t09,t1 t10,t1 t11,t1 t12,t1 t13,t1 t14,t1 t15,t1 t16,
+    t1 t17,t1 t18,t1 t19,t1 t20,t1 t21,t1 t22,t1 t23,t1 t24,
+    t1 t25,t1 t26,t1 t27,t1 t28,t1 t29,t1 t30,t1 t31,t1 t32,
+    t1 t33,t1 t34,t1 t35,t1 t36,t1 t37,t1 t38,t1 t39,t1 t40,
+    t1 t41,t1 t42,t1 t43,t1 t44,t1 t45,t1 t46,t1 t47,t1 t48,
+    t1 t49,t1 t50,t1 t51,t1 t52,t1 t53,t1 t54,t1 t55,t1 t56,
+    t1 t57,t1 t58,t1 t59,t1 t60
+  WHERE t01.a IN (SELECT c FROM t2);
+END
+//
+
+DELIMITER ;//
+
+CALL p1(1);
+CALL p2(1);
+
+DROP TABLE t1, t2;
+DROP PROCEDURE p1;
+DROP PROCEDURE p2;
diff -Nrup a/sql/item.h b/sql/item.h
--- a/sql/item.h	2007-12-13 13:56:19 +01:00
+++ b/sql/item.h	2008-01-29 14:17:07 +01:00
@@ -2115,6 +2115,29 @@ public:
     save_in_field(result_field, no_conversions);
   }
   void cleanup();
+  
+  /**
+     @brief Replaces an expression destructively in an expression tree.
+     The expression is matched using pointer comparison. This function is
+     used when flattening semijoins.
+     @param thd The thread context.
+     @param top Handle to the root if the expression tree.
+     @param old_cond The expression to be replaced.
+     @param new_cond The expression to be substituted.
+     @param fix_fields If true, Item::fix_fields(THD*, Item**) is called for
+     the new expression.
+     @return TRUE if there was an error, FALSE if successful.
+   */
+  virtual bool replace_subcondition(THD *thd, Item **top, Item *old_cond, 
+                                    Item *new_cond, bool fix_fields)
+  {
+    if (*top == this && old_cond == this)
+      *top= new_cond;
+    if (fix_fields)
+      return new_cond->fix_fields(thd, top);
+    return FALSE;
+  }
+
 };
 
 
diff -Nrup a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
--- a/sql/item_cmpfunc.cc	2007-12-13 13:56:19 +01:00
+++ b/sql/item_cmpfunc.cc	2008-01-29 14:17:07 +01:00
@@ -4113,6 +4113,30 @@ Item *Item_cond::compile(Item_analyzer a
   return Item_func::transform(transformer, arg_t);
 }
 
+/**
+   @brief Replaces an expression destructively inside an AND/OR/XOR expression
+   tree.  
+
+   @note Because of current requirements for semijoin flattening, we do not
+   need to recurse here, hence this function will only examine the top-level
+   AND conditions. (see JOIN::prepare, comment above the line 
+   'if (do_materialize)'
+*/
+bool Item_cond::replace_subcondition(THD *thd, Item **top, Item *old_cond, 
+                                     Item *new_cond, bool fix_fields)
+{
+  if (old_cond == new_cond)
+    return FALSE;
+  List_iterator<Item> li(list);
+  Item *item;
+  while ((item= li++))
+    if (item == old_cond)
+      li.replace(new_cond);
+  if (fix_fields)
+    return new_cond->fix_fields(thd, top);
+  return FALSE;
+}
+
 void Item_cond::traverse_cond(Cond_traverser traverser,
                               void *arg, traverse_order order)
 {
diff -Nrup a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
--- a/sql/item_cmpfunc.h	2007-12-13 13:47:14 +01:00
+++ b/sql/item_cmpfunc.h	2008-01-29 14:17:07 +01:00
@@ -1462,6 +1462,8 @@ public:
   bool subst_argument_checker(uchar **arg) { return TRUE; }
   Item *compile(Item_analyzer analyzer, uchar **arg_p,
                 Item_transformer transformer, uchar *arg_t);
+  bool replace_subcondition(THD *thd, Item **top, Item *old_cond, 
+                            Item *new_cond, bool fix_fields);
 };
 
 
diff -Nrup a/sql/item_subselect.cc b/sql/item_subselect.cc
--- a/sql/item_subselect.cc	2007-11-23 12:41:55 +01:00
+++ b/sql/item_subselect.cc	2008-01-29 14:17:07 +01:00
@@ -1709,7 +1709,6 @@ void Item_in_subselect::print(String *st
 bool Item_in_subselect::fix_fields(THD *thd_arg, Item **ref)
 {
   bool result = 0;
-  ref_ptr= ref;
 
   if (exec_method == SEMI_JOIN)
     return !( (*ref)= new Item_int(1));
diff -Nrup a/sql/item_subselect.h b/sql/item_subselect.h
--- a/sql/item_subselect.h	2007-10-30 15:25:47 +01:00
+++ b/sql/item_subselect.h	2008-01-29 14:17:07 +01:00
@@ -295,7 +295,6 @@ public:
      - (TABLE_LIST*)1 if the predicate is in the WHERE.
   */
   TABLE_LIST *expr_join_nest;
-  Item **ref_ptr;
 
   /* The method chosen to execute the IN predicate.  */
   enum enum_exec_method {
diff -Nrup a/sql/sql_select.cc b/sql/sql_select.cc
--- a/sql/sql_select.cc	2007-12-13 13:56:21 +01:00
+++ b/sql/sql_select.cc	2008-01-29 14:17:07 +01:00
@@ -3333,14 +3333,19 @@ bool JOIN::flatten_subqueries()
   */
   sj_subselects.sort(subq_sj_candidate_cmp);
   // #tables-in-parent-query + #tables-in-subquery < MAX_TABLES
-  /* Replace all subqueries to be flattened for Item_int(1) */
+  /* Replace all subqueries to be flattened with Item_int(1) */
   arena= thd->activate_stmt_arena_if_needed(&backup);
   for (in_subq= sj_subselects.front(); 
        in_subq != in_subq_end && 
        tables + ((*in_subq)->sj_convert_priority % MAX_TABLES) < MAX_TABLES;
        in_subq++)
   {
-    *((*in_subq)->ref_ptr)= new Item_int(1);
+    if (conds->is_result_field()) {
+      Item_result_field *item_result_field= (Item_result_field*)conds;
+      if (item_result_field->replace_subcondition(thd, &conds, *in_subq,
+                                                  new Item_int(1), FALSE))
+        DBUG_RETURN(TRUE);
+    }
   }
  
   for (in_subq= sj_subselects.front(); 
@@ -3365,12 +3370,14 @@ bool JOIN::flatten_subqueries()
     if (res == Item_subselect::RES_ERROR)
       DBUG_RETURN(TRUE);
 
-    *((*in_subq)->ref_ptr)= (*in_subq)->substitution;
     (*in_subq)->changed= 1;
     (*in_subq)->fixed= 1;
-    if (!(*in_subq)->substitution->fixed &&
-      (*in_subq)->substitution->fix_fields(thd, (*in_subq)->ref_ptr))
-      DBUG_RETURN(TRUE);
+    if (conds->is_result_field()) {
+      Item_result_field *item_result_field= (Item_result_field*)conds;
+      item_result_field->replace_subcondition(thd, &conds, *in_subq, 
+                                              (*in_subq)->substitution, 
+                                              !(*in_subq)->substitution->fixed);
+    }
 
     //if ((*in_subq)->fix_fields(thd, (*in_subq)->ref_ptr))
     //  DBUG_RETURN(TRUE);
Thread
bk commit into 6.0 tree (mhansson:1.2767) BUG#33062mhansson29 Jan