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#33062 | mhansson | 29 Jan |