#At file:///home/rl136806/mysql/repo/mysql-work0/ based on revid:roy.lyseng@stripped
3395 Roy Lyseng 2011-06-28
iBug#12603141: JOIN::flatten_subqueries asrt/simplify_joins sig11/...
When preparing a prepared statement, we need to save a copy of
WHERE and HAVING condition trees in the prep_where and prep_having
fields of SELECT_LEX. However, the semantic analysis needs to wrap
some Item_field objects using Item_ref objects, which are scoped for
the lifetime of the preparation. This is usually not a problem,
but when the Item_field is the root object of the condition, the
Item_ref object is attempted saved in prep_where or prep_having.
The destructor for the Item_ref is called at the end of the
preparation, so that when execution of the statement is performed,
the destroyed Item_ref object will be referenced.
One possible solution to this problem is to detect that the root
object is an Item_ref object when saving prep_where and prep_having,
and unwrap this object before saving it. The procedure must be
applied recursively because sometimes an Item_field is wrapped in
multiple Item_ref objects.
mysql-test/t/ps.test
Added test case for bug#12603141.
sql/sql_lex.cc
In st_select_lex::fix_prepare_information(), unwrap Item_ref
objects when saving the prep_where and prep_having fields.
sql/sql_select.cc
In JOIN::optimize(), unwrap Item_ref objects when saving the
prep_where field.
modified:
mysql-test/r/ps.result
mysql-test/t/ps.test
sql/sql_lex.cc
sql/sql_select.cc
=== modified file 'mysql-test/r/ps.result'
--- a/mysql-test/r/ps.result 2011-03-22 12:06:52 +0000
+++ b/mysql-test/r/ps.result 2011-06-28 07:04:32 +0000
@@ -3721,3 +3721,29 @@ FROM (SELECT 1 UNION SELECT 2) t;
2
#
# End of 5.5 tests.
+#
+# Bug#12603141: JOIN::flatten_subqueries asrt/simplify_joins sig11/...
+#
+CREATE TABLE t1(
+a INTEGER PRIMARY KEY
+) engine=Innodb;
+INSERT INTO t1 VALUES (0),(1),(2);
+CREATE TABLE t2(
+a INTEGER PRIMARY KEY
+) engine=Innodb;
+INSERT INTO t2 VALUES (1);
+PREPARE stmt FROM '
+SELECT (SELECT 1 FROM t2 WHERE ot.a) AS d
+FROM t1 AS ot
+GROUP BY d';
+EXECUTE stmt;
+d
+NULL
+1
+EXECUTE stmt;
+d
+NULL
+1
+DROP TABLE t1, t2;
+#
+# End of 5.6 tests.
=== modified file 'mysql-test/t/ps.test'
--- a/mysql-test/t/ps.test 2011-03-22 12:06:52 +0000
+++ b/mysql-test/t/ps.test 2011-06-28 07:04:32 +0000
@@ -3327,4 +3327,28 @@ FROM (SELECT 1 UNION SELECT 2) t;
--echo #
--echo # End of 5.5 tests.
+--echo #
+--echo # Bug#12603141: JOIN::flatten_subqueries asrt/simplify_joins sig11/...
+--echo #
+
+CREATE TABLE t1(
+ a INTEGER PRIMARY KEY
+) engine=Innodb;
+INSERT INTO t1 VALUES (0),(1),(2);
+CREATE TABLE t2(
+ a INTEGER PRIMARY KEY
+) engine=Innodb;
+INSERT INTO t2 VALUES (1);
+PREPARE stmt FROM '
+SELECT (SELECT 1 FROM t2 WHERE ot.a) AS d
+FROM t1 AS ot
+GROUP BY d';
+EXECUTE stmt;
+EXECUTE stmt;
+DROP TABLE t1, t2;
+
+
+--echo #
+--echo # End of 5.6 tests.
+
###########################################################################
=== modified file 'sql/sql_lex.cc'
--- a/sql/sql_lex.cc 2011-04-01 14:04:52 +0000
+++ b/sql/sql_lex.cc 2011-06-28 07:04:32 +0000
@@ -3072,13 +3072,19 @@ void st_select_lex::fix_prepare_informat
first_execution= 0;
if (*conds)
{
- prep_where= *conds;
- *conds= where= prep_where->copy_andor_structure(thd);
+ Item *item= *conds;
+ while (item->type() == Item::REF_ITEM)
+ item= *(((Item_ref *)item)->ref);
+ prep_where= item;
+ *conds= where= (*conds)->copy_andor_structure(thd);
}
if (*having_conds)
{
- prep_having= *having_conds;
- *having_conds= having= prep_having->copy_andor_structure(thd);
+ Item *item= *having_conds;
+ while (item->type() == Item::REF_ITEM)
+ item= *(((Item_ref *)item)->ref);
+ prep_having= item;
+ *having_conds= having= (*having_conds)->copy_andor_structure(thd);
}
fix_prepare_info_in_table_list(thd, table_list.first);
}
=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc 2011-06-27 07:17:26 +0000
+++ b/sql/sql_select.cc 2011-06-28 07:04:32 +0000
@@ -1904,8 +1904,21 @@ JOIN::optimize()
conds= simplify_joins(this, join_list, conds, TRUE, FALSE);
build_bitmap_for_nested_joins(join_list, 0);
- sel->prep_where= conds ? conds->copy_andor_structure(thd) : 0;
-
+ /*
+ This should really have been performed when preparing the select_lex.
+ Doing it now means that we must take care not to include wrapper
+ objects added to the root of the condition tree during
+ execution-time resolving.
+ */
+ if (conds == NULL)
+ sel->prep_where= NULL;
+ else
+ {
+ Item *item= conds;
+ while (item->type() == Item::REF_ITEM)
+ item= *(((Item_ref *)item)->ref);
+ sel->prep_where= item->copy_andor_structure(thd);
+ }
if (arena)
thd->restore_active_arena(arena, &backup);
}
Attachment: [text/bzr-bundle] bzr/roy.lyseng@oracle.com-20110628070432-hbfzhjgsnxnox3h0.bundle
| Thread |
|---|
| • bzr commit into mysql-trunk branch (roy.lyseng:3395) | Roy Lyseng | 28 Jun |