Merge bk-internal.mysql.com:/home/bk/mysql-5.0
into mysql.com:/home/dlenev/src/mysql-5.0-bg11973-2 sql/item_subselect.cc: Auto merged sql/sql_class.h: Auto merged sql/sql_parse.cc: Auto merged sql/sql_prepare.cc: Auto merged sql/sql_update.cc: Auto merged mysql-test/r/trigger.result: SCCS merged mysql-test/t/trigger.test: SCCS merged
This commit is contained in:
commit
98da6d5ffb
@ -651,3 +651,16 @@ insert into t1 values (0);
|
|||||||
ERROR 0A000: FLUSH is not allowed in stored function or trigger
|
ERROR 0A000: FLUSH is not allowed in stored function or trigger
|
||||||
drop procedure p1;
|
drop procedure p1;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
create table t1 (id int, data int, username varchar(16));
|
||||||
|
insert into t1 (id, data) values (1, 0);
|
||||||
|
create trigger t1_whoupdated before update on t1 for each row
|
||||||
|
begin
|
||||||
|
declare user varchar(32);
|
||||||
|
declare i int;
|
||||||
|
select user() into user;
|
||||||
|
set NEW.username = user;
|
||||||
|
select count(*) from ((select 1) union (select 2)) as d1 into i;
|
||||||
|
end|
|
||||||
|
update t1 set data = 1;
|
||||||
|
update t1 set data = 2;
|
||||||
|
drop table t1;
|
||||||
|
@ -662,3 +662,26 @@ create procedure p1() flush privileges;
|
|||||||
insert into t1 values (0);
|
insert into t1 values (0);
|
||||||
drop procedure p1;
|
drop procedure p1;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
|
# Test for bug #11973 "SELECT .. INTO var_name; in trigger cause
|
||||||
|
# crash on update"
|
||||||
|
create table t1 (id int, data int, username varchar(16));
|
||||||
|
insert into t1 (id, data) values (1, 0);
|
||||||
|
delimiter |;
|
||||||
|
create trigger t1_whoupdated before update on t1 for each row
|
||||||
|
begin
|
||||||
|
declare user varchar(32);
|
||||||
|
declare i int;
|
||||||
|
select user() into user;
|
||||||
|
set NEW.username = user;
|
||||||
|
select count(*) from ((select 1) union (select 2)) as d1 into i;
|
||||||
|
end|
|
||||||
|
delimiter ;|
|
||||||
|
update t1 set data = 1;
|
||||||
|
|
||||||
|
connect (addconroot, localhost, root,,);
|
||||||
|
connection addconroot;
|
||||||
|
update t1 set data = 2;
|
||||||
|
|
||||||
|
connection default;
|
||||||
|
drop table t1;
|
||||||
|
@ -1276,6 +1276,14 @@ void Item_allany_subselect::print(String *str)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void subselect_engine::set_thd(THD *thd_arg)
|
||||||
|
{
|
||||||
|
thd= thd_arg;
|
||||||
|
if (result)
|
||||||
|
result->set_thd(thd_arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
subselect_single_select_engine::
|
subselect_single_select_engine::
|
||||||
subselect_single_select_engine(st_select_lex *select,
|
subselect_single_select_engine(st_select_lex *select,
|
||||||
select_subselect *result,
|
select_subselect *result,
|
||||||
|
@ -299,8 +299,11 @@ public:
|
|||||||
virtual ~subselect_engine() {}; // to satisfy compiler
|
virtual ~subselect_engine() {}; // to satisfy compiler
|
||||||
virtual void cleanup()= 0;
|
virtual void cleanup()= 0;
|
||||||
|
|
||||||
// set_thd should be called before prepare()
|
/*
|
||||||
void set_thd(THD *thd_arg) { thd= thd_arg; }
|
Also sets "thd" for subselect_engine::result.
|
||||||
|
Should be called before prepare().
|
||||||
|
*/
|
||||||
|
void set_thd(THD *thd_arg);
|
||||||
THD * get_thd() { return thd; }
|
THD * get_thd() { return thd; }
|
||||||
virtual int prepare()= 0;
|
virtual int prepare()= 0;
|
||||||
virtual void fix_length_and_dec(Item_cache** row)= 0;
|
virtual void fix_length_and_dec(Item_cache** row)= 0;
|
||||||
|
@ -1565,6 +1565,7 @@ public:
|
|||||||
statement/stored procedure.
|
statement/stored procedure.
|
||||||
*/
|
*/
|
||||||
virtual void cleanup();
|
virtual void cleanup();
|
||||||
|
void set_thd(THD *thd_arg) { thd= thd_arg; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -1920,14 +1921,13 @@ class multi_delete :public select_result_interceptor
|
|||||||
{
|
{
|
||||||
TABLE_LIST *delete_tables, *table_being_deleted;
|
TABLE_LIST *delete_tables, *table_being_deleted;
|
||||||
Unique **tempfiles;
|
Unique **tempfiles;
|
||||||
THD *thd;
|
|
||||||
ha_rows deleted, found;
|
ha_rows deleted, found;
|
||||||
uint num_of_tables;
|
uint num_of_tables;
|
||||||
int error;
|
int error;
|
||||||
bool do_delete, transactional_tables, normal_tables, delete_while_scanning;
|
bool do_delete, transactional_tables, normal_tables, delete_while_scanning;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
multi_delete(THD *thd, TABLE_LIST *dt, uint num_of_tables);
|
multi_delete(TABLE_LIST *dt, uint num_of_tables);
|
||||||
~multi_delete();
|
~multi_delete();
|
||||||
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
|
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
|
||||||
bool send_data(List<Item> &items);
|
bool send_data(List<Item> &items);
|
||||||
@ -1943,7 +1943,6 @@ class multi_update :public select_result_interceptor
|
|||||||
TABLE_LIST *all_tables; /* query/update command tables */
|
TABLE_LIST *all_tables; /* query/update command tables */
|
||||||
TABLE_LIST *leaves; /* list of leves of join table tree */
|
TABLE_LIST *leaves; /* list of leves of join table tree */
|
||||||
TABLE_LIST *update_tables, *table_being_updated;
|
TABLE_LIST *update_tables, *table_being_updated;
|
||||||
THD *thd;
|
|
||||||
TABLE **tmp_tables, *main_table, *table_to_update;
|
TABLE **tmp_tables, *main_table, *table_to_update;
|
||||||
TMP_TABLE_PARAM *tmp_table_param;
|
TMP_TABLE_PARAM *tmp_table_param;
|
||||||
ha_rows updated, found;
|
ha_rows updated, found;
|
||||||
@ -1955,7 +1954,7 @@ class multi_update :public select_result_interceptor
|
|||||||
bool do_update, trans_safe, transactional_tables, ignore;
|
bool do_update, trans_safe, transactional_tables, ignore;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
multi_update(THD *thd_arg, TABLE_LIST *ut, TABLE_LIST *leaves_list,
|
multi_update(TABLE_LIST *ut, TABLE_LIST *leaves_list,
|
||||||
List<Item> *fields, List<Item> *values,
|
List<Item> *fields, List<Item> *values,
|
||||||
enum_duplicates handle_duplicates, bool ignore);
|
enum_duplicates handle_duplicates, bool ignore);
|
||||||
~multi_update();
|
~multi_update();
|
||||||
|
@ -407,9 +407,8 @@ bool mysql_multi_delete_prepare(THD *thd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
multi_delete::multi_delete(THD *thd_arg, TABLE_LIST *dt,
|
multi_delete::multi_delete(TABLE_LIST *dt, uint num_of_tables_arg)
|
||||||
uint num_of_tables_arg)
|
: delete_tables(dt), deleted(0), found(0),
|
||||||
: delete_tables(dt), thd(thd_arg), deleted(0), found(0),
|
|
||||||
num_of_tables(num_of_tables_arg), error(0),
|
num_of_tables(num_of_tables_arg), error(0),
|
||||||
do_delete(0), transactional_tables(0), normal_tables(0)
|
do_delete(0), transactional_tables(0), normal_tables(0)
|
||||||
{
|
{
|
||||||
|
@ -458,6 +458,7 @@ public:
|
|||||||
inline bool is_prepared() { return prepared; }
|
inline bool is_prepared() { return prepared; }
|
||||||
bool change_result(select_subselect *result, select_subselect *old_result);
|
bool change_result(select_subselect *result, select_subselect *old_result);
|
||||||
void set_limit(st_select_lex *values);
|
void set_limit(st_select_lex *values);
|
||||||
|
void set_thd(THD *thd_arg) { thd= thd_arg; }
|
||||||
|
|
||||||
friend void lex_start(THD *thd, uchar *buf, uint length);
|
friend void lex_start(THD *thd, uchar *buf, uint length);
|
||||||
friend int subselect_union_engine::exec();
|
friend int subselect_union_engine::exec();
|
||||||
|
@ -3318,7 +3318,7 @@ end_with_restore_list:
|
|||||||
if ((res= mysql_multi_delete_prepare(thd)))
|
if ((res= mysql_multi_delete_prepare(thd)))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (!thd->is_fatal_error && (result= new multi_delete(thd,aux_tables,
|
if (!thd->is_fatal_error && (result= new multi_delete(aux_tables,
|
||||||
lex->table_count)))
|
lex->table_count)))
|
||||||
{
|
{
|
||||||
res= mysql_select(thd, &select_lex->ref_pointer_array,
|
res= mysql_select(thd, &select_lex->ref_pointer_array,
|
||||||
|
@ -1855,6 +1855,13 @@ void reinit_stmt_before_use(THD *thd, LEX *lex)
|
|||||||
SELECT_LEX *sl= lex->all_selects_list;
|
SELECT_LEX *sl= lex->all_selects_list;
|
||||||
DBUG_ENTER("reinit_stmt_before_use");
|
DBUG_ENTER("reinit_stmt_before_use");
|
||||||
|
|
||||||
|
/*
|
||||||
|
We have to update "thd" pointer in LEX, all its units and in LEX::result,
|
||||||
|
since statements which belong to trigger body are associated with TABLE
|
||||||
|
object and because of this can be used in different threads.
|
||||||
|
*/
|
||||||
|
lex->thd= thd;
|
||||||
|
|
||||||
if (lex->empty_field_list_on_rset)
|
if (lex->empty_field_list_on_rset)
|
||||||
{
|
{
|
||||||
lex->empty_field_list_on_rset= 0;
|
lex->empty_field_list_on_rset= 0;
|
||||||
@ -1893,6 +1900,7 @@ void reinit_stmt_before_use(THD *thd, LEX *lex)
|
|||||||
unit->types.empty();
|
unit->types.empty();
|
||||||
/* for derived tables & PS (which can't be reset by Item_subquery) */
|
/* for derived tables & PS (which can't be reset by Item_subquery) */
|
||||||
unit->reinit_exec_mechanism();
|
unit->reinit_exec_mechanism();
|
||||||
|
unit->set_thd(thd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1931,7 +1939,10 @@ void reinit_stmt_before_use(THD *thd, LEX *lex)
|
|||||||
lex->select_lex.leaf_tables= lex->leaf_tables_insert;
|
lex->select_lex.leaf_tables= lex->leaf_tables_insert;
|
||||||
|
|
||||||
if (lex->result)
|
if (lex->result)
|
||||||
|
{
|
||||||
lex->result->cleanup();
|
lex->result->cleanup();
|
||||||
|
lex->result->set_thd(thd);
|
||||||
|
}
|
||||||
|
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
@ -821,7 +821,7 @@ bool mysql_multi_update(THD *thd,
|
|||||||
if (mysql_multi_update_prepare(thd))
|
if (mysql_multi_update_prepare(thd))
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
if (!(result= new multi_update(thd, table_list,
|
if (!(result= new multi_update(table_list,
|
||||||
thd->lex->select_lex.leaf_tables,
|
thd->lex->select_lex.leaf_tables,
|
||||||
fields, values,
|
fields, values,
|
||||||
handle_duplicates, ignore)))
|
handle_duplicates, ignore)))
|
||||||
@ -847,13 +847,13 @@ bool mysql_multi_update(THD *thd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
multi_update::multi_update(THD *thd_arg, TABLE_LIST *table_list,
|
multi_update::multi_update(TABLE_LIST *table_list,
|
||||||
TABLE_LIST *leaves_list,
|
TABLE_LIST *leaves_list,
|
||||||
List<Item> *field_list, List<Item> *value_list,
|
List<Item> *field_list, List<Item> *value_list,
|
||||||
enum enum_duplicates handle_duplicates_arg,
|
enum enum_duplicates handle_duplicates_arg,
|
||||||
bool ignore_arg)
|
bool ignore_arg)
|
||||||
:all_tables(table_list), leaves(leaves_list), update_tables(0),
|
:all_tables(table_list), leaves(leaves_list), update_tables(0),
|
||||||
thd(thd_arg), tmp_tables(0), updated(0), found(0), fields(field_list),
|
tmp_tables(0), updated(0), found(0), fields(field_list),
|
||||||
values(value_list), table_count(0), copy_field(0),
|
values(value_list), table_count(0), copy_field(0),
|
||||||
handle_duplicates(handle_duplicates_arg), do_update(1), trans_safe(0),
|
handle_duplicates(handle_duplicates_arg), do_update(1), trans_safe(0),
|
||||||
transactional_tables(1), ignore(ignore_arg)
|
transactional_tables(1), ignore(ignore_arg)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user