Commit 34c8930c authored by unknown's avatar unknown

Fix of LP BUG#675248.

Registration of pointer change if we assign it to other pointer which should be identical after statement execution (PS/SP).

mysql-test/r/subselect.result:
  Test suite.
mysql-test/t/subselect.test:
  Test suite.
sql/sql_class.cc:
  The procedure of the pointer registration.
sql/sql_class.h:
  The procedure of the pointer registration.
sql/sql_lex.cc:
  Registration of pointer change if we assign it to other pointer which should be identical after statement execution (PS/SP).
parent 7840965d
...@@ -4730,4 +4730,23 @@ ORDER BY (SELECT * FROM t1 WHERE MATCH(a) AGAINST ('+abc' IN BOOLEAN MODE)); ...@@ -4730,4 +4730,23 @@ ORDER BY (SELECT * FROM t1 WHERE MATCH(a) AGAINST ('+abc' IN BOOLEAN MODE));
SELECT * FROM t2 UNION SELECT * FROM t2 SELECT * FROM t2 UNION SELECT * FROM t2
ORDER BY (SELECT * FROM t1 WHERE MATCH(a) AGAINST ('+abc' IN BOOLEAN MODE)); ORDER BY (SELECT * FROM t1 WHERE MATCH(a) AGAINST ('+abc' IN BOOLEAN MODE));
DROP TABLE t1,t2; DROP TABLE t1,t2;
# LP BUG#675248 - select->prep_where references on freed memory
CREATE TABLE t1 (a int, b int);
insert into t1 values (1,1),(0,0);
CREATE TABLE t2 (c int);
insert into t2 values (1),(2);
prepare stmt1 from "select sum(a),(select sum(c) from t2 where table1.b) as sub
from t1 as table1 group by sub";
execute stmt1;
sum(a) sub
0 NULL
1 3
deallocate prepare stmt1;
prepare stmt1 from "select sum(a),(select sum(c) from t2 having table1.b) as sub
from t1 as table1";
execute stmt1;
sum(a) sub
1 3
deallocate prepare stmt1;
drop table t1,t2;
End of 5.1 tests End of 5.1 tests
...@@ -3735,4 +3735,28 @@ SELECT * FROM t2 UNION SELECT * FROM t2 ...@@ -3735,4 +3735,28 @@ SELECT * FROM t2 UNION SELECT * FROM t2
DROP TABLE t1,t2; DROP TABLE t1,t2;
--enable_result_log --enable_result_log
--echo # LP BUG#675248 - select->prep_where references on freed memory
CREATE TABLE t1 (a int, b int);
insert into t1 values (1,1),(0,0);
CREATE TABLE t2 (c int);
insert into t2 values (1),(2);
prepare stmt1 from "select sum(a),(select sum(c) from t2 where table1.b) as sub
from t1 as table1 group by sub";
execute stmt1;
deallocate prepare stmt1;
prepare stmt1 from "select sum(a),(select sum(c) from t2 having table1.b) as sub
from t1 as table1";
execute stmt1;
deallocate prepare stmt1;
drop table t1,t2;
--echo End of 5.1 tests --echo End of 5.1 tests
...@@ -1621,6 +1621,36 @@ void THD::nocheck_register_item_tree_change(Item **place, Item *old_value, ...@@ -1621,6 +1621,36 @@ void THD::nocheck_register_item_tree_change(Item **place, Item *old_value,
change_list.append(change); change_list.append(change);
} }
/**
Check and register item change if needed
@param place place where we should assign new value
@param new_value place of the new value
@details
Let C be a reference to an item that changed the reference A
at the location (occurrence) L1 and this change has been registered.
If C is substituted for reference A another location (occurrence) L2
that is to be registered as well than this change has to be
consistent with the first change in order the procedure that rollback
changes to substitute the same reference at both locations L1 and L2.
*/
void THD::check_and_register_item_tree_change(Item **place, Item **new_value,
MEM_ROOT *runtime_memroot)
{
Item_change_record *change;
I_List_iterator<Item_change_record> it(change_list);
while ((change= it++))
{
if (change->place == new_value)
break; // we need only very first value
}
if (change)
nocheck_register_item_tree_change(place, change->old_value,
runtime_memroot);
}
void THD::rollback_item_tree_changes() void THD::rollback_item_tree_changes()
{ {
......
...@@ -1568,7 +1568,7 @@ public: ...@@ -1568,7 +1568,7 @@ public:
/* /*
This is to track items changed during execution of a prepared This is to track items changed during execution of a prepared
statement/stored procedure. It's created by statement/stored procedure. It's created by
register_item_tree_change() in memory root of THD, and freed in nocheck_register_item_tree_change() in memory root of THD, and freed in
rollback_item_tree_changes(). For conventional execution it's always rollback_item_tree_changes(). For conventional execution it's always
empty. empty.
*/ */
...@@ -2175,8 +2175,26 @@ public: ...@@ -2175,8 +2175,26 @@ public:
nocheck_register_item_tree_change(place, *place, mem_root); nocheck_register_item_tree_change(place, *place, mem_root);
*place= new_value; *place= new_value;
} }
/**
Make change in item tree after checking whether it needs registering
@param place place where we should assign new value
@param new_value place of the new value
@details
see check_and_register_item_tree_change details
*/
void check_and_register_item_tree(Item **place, Item **new_value)
{
if (!stmt_arena->is_conventional())
check_and_register_item_tree_change(place, new_value, mem_root);
*place= *new_value;
}
void nocheck_register_item_tree_change(Item **place, Item *old_value, void nocheck_register_item_tree_change(Item **place, Item *old_value,
MEM_ROOT *runtime_memroot); MEM_ROOT *runtime_memroot);
void check_and_register_item_tree_change(Item **place, Item **new_value,
MEM_ROOT *runtime_memroot);
void rollback_item_tree_changes(); void rollback_item_tree_changes();
/* /*
......
...@@ -2890,7 +2890,7 @@ static void fix_prepare_info_in_table_list(THD *thd, TABLE_LIST *tbl) ...@@ -2890,7 +2890,7 @@ static void fix_prepare_info_in_table_list(THD *thd, TABLE_LIST *tbl)
{ {
if (tbl->on_expr) if (tbl->on_expr)
{ {
tbl->prep_on_expr= tbl->on_expr; thd->check_and_register_item_tree(&tbl->prep_on_expr, &tbl->on_expr);
tbl->on_expr= tbl->on_expr->copy_andor_structure(thd); tbl->on_expr= tbl->on_expr->copy_andor_structure(thd);
} }
fix_prepare_info_in_table_list(thd, tbl->merge_underlying_list); fix_prepare_info_in_table_list(thd, tbl->merge_underlying_list);
...@@ -2924,12 +2924,12 @@ void st_select_lex::fix_prepare_information(THD *thd, Item **conds, ...@@ -2924,12 +2924,12 @@ void st_select_lex::fix_prepare_information(THD *thd, Item **conds,
first_execution= 0; first_execution= 0;
if (*conds) if (*conds)
{ {
prep_where= *conds; thd->check_and_register_item_tree(&prep_where, conds);
*conds= where= prep_where->copy_andor_structure(thd); *conds= where= prep_where->copy_andor_structure(thd);
} }
if (*having_conds) if (*having_conds)
{ {
prep_having= *having_conds; thd->check_and_register_item_tree(&prep_having, having_conds);
*having_conds= having= prep_having->copy_andor_structure(thd); *having_conds= having= prep_having->copy_andor_structure(thd);
} }
fix_prepare_info_in_table_list(thd, table_list.first); fix_prepare_info_in_table_list(thd, table_list.first);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment