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).
This commit is contained in:
parent
7840965db9
commit
34c8930c09
@ -4730,4 +4730,23 @@ ORDER BY (SELECT * FROM t1 WHERE MATCH(a) AGAINST ('+abc' IN BOOLEAN MODE));
|
||||
SELECT * FROM t2 UNION SELECT * FROM t2
|
||||
ORDER BY (SELECT * FROM t1 WHERE MATCH(a) AGAINST ('+abc' IN BOOLEAN MODE));
|
||||
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
|
||||
|
@ -3735,4 +3735,28 @@ SELECT * FROM t2 UNION SELECT * FROM t2
|
||||
DROP TABLE t1,t2;
|
||||
--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
|
||||
|
@ -1621,6 +1621,36 @@ void THD::nocheck_register_item_tree_change(Item **place, Item *old_value,
|
||||
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()
|
||||
{
|
||||
|
@ -1568,7 +1568,7 @@ public:
|
||||
/*
|
||||
This is to track items changed during execution of a prepared
|
||||
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
|
||||
empty.
|
||||
*/
|
||||
@ -2175,8 +2175,26 @@ public:
|
||||
nocheck_register_item_tree_change(place, *place, mem_root);
|
||||
*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,
|
||||
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();
|
||||
|
||||
/*
|
||||
|
@ -2890,7 +2890,7 @@ static void fix_prepare_info_in_table_list(THD *thd, TABLE_LIST *tbl)
|
||||
{
|
||||
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);
|
||||
}
|
||||
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,
|
||||
first_execution= 0;
|
||||
if (*conds)
|
||||
{
|
||||
prep_where= *conds;
|
||||
thd->check_and_register_item_tree(&prep_where, conds);
|
||||
*conds= where= prep_where->copy_andor_structure(thd);
|
||||
}
|
||||
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);
|
||||
}
|
||||
fix_prepare_info_in_table_list(thd, table_list.first);
|
||||
|
Loading…
x
Reference in New Issue
Block a user