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
|
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
|
|||||||
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,
|
|||||||
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:
|
|||||||
/*
|
/*
|
||||||
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:
|
|||||||
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)
|
|||||||
{
|
{
|
||||||
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,
|
|||||||
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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user