Loading mysql-test/r/multi_update.result +7 −0 Original line number Diff line number Diff line Loading @@ -455,3 +455,10 @@ create table t3 (a int, primary key (a)); delete t1,t3 from t1,t2 where t1.a=t2.a and t2.a=(select t3.a from t3 where t1.a=t3.a); ERROR 42S02: Unknown table 't3' in MULTI DELETE drop table t1, t2, t3; create table t1 (col1 int); create table t2 (col1 int); update t1,t2 set t1.col1 = (select max(col1) from t1) where t1.col1 = t2.col1; ERROR HY000: You can't specify target table 't1' for update in FROM clause delete t1 from t1,t2 where t1.col1 < (select max(col1) from t1) and t1.col1 = t2.col1; ERROR HY000: You can't specify target table 't1' for update in FROM clause drop table t1,t2; mysql-test/t/multi_update.test +11 −0 Original line number Diff line number Diff line Loading @@ -417,3 +417,14 @@ create table t3 (a int, primary key (a)); -- error 1109 delete t1,t3 from t1,t2 where t1.a=t2.a and t2.a=(select t3.a from t3 where t1.a=t3.a); drop table t1, t2, t3; # # multi* unique updating table check # create table t1 (col1 int); create table t2 (col1 int); -- error 1093 update t1,t2 set t1.col1 = (select max(col1) from t1) where t1.col1 = t2.col1; -- error 1093 delete t1 from t1,t2 where t1.col1 < (select max(col1) from t1) and t1.col1 = t2.col1; drop table t1,t2; sql/sql_lex.cc +21 −1 Original line number Diff line number Diff line Loading @@ -1550,6 +1550,7 @@ bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num) 1 - found 0 - OK (table did not found) */ bool st_select_lex_unit::check_updateable(char *db, char *table) { for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select()) Loading @@ -1561,7 +1562,7 @@ bool st_select_lex_unit::check_updateable(char *db, char *table) /* Find db.table which will be updated in this select and underlayed ones (except derived tables) underlaying ones (except derived tables) SYNOPSIS st_select_lex::check_updateable() Loading @@ -1572,11 +1573,30 @@ bool st_select_lex_unit::check_updateable(char *db, char *table) 1 - found 0 - OK (table did not found) */ bool st_select_lex::check_updateable(char *db, char *table) { if (find_real_table_in_list(get_table_list(), db, table)) return 1; return check_updateable_in_subqueries(db, table); } /* Find db.table which will be updated in underlaying subqueries SYNOPSIS st_select_lex::check_updateable_in_subqueries() db - data base name table - real table name RETURN 1 - found 0 - OK (table did not found) */ bool st_select_lex::check_updateable_in_subqueries(char *db, char *table) { for (SELECT_LEX_UNIT *un= first_inner_unit(); un; un= un->next_unit()) Loading sql/sql_lex.h +1 −0 Original line number Diff line number Diff line Loading @@ -517,6 +517,7 @@ class st_select_lex: public st_select_lex_node } bool setup_ref_array(THD *thd, uint order_group_num); bool check_updateable(char *db, char *table); bool check_updateable_in_subqueries(char *db, char *table); void print(THD *thd, String *str); static void print_order(String *str, ORDER *order); void print_limit(THD *thd, String *str); Loading sql/sql_parse.cc +9 −14 Original line number Diff line number Diff line Loading @@ -2796,26 +2796,21 @@ mysql_execute_command(THD *thd) target_tbl; target_tbl= target_tbl->next) { target_tbl->table= target_tbl->table_list->table; TABLE_LIST *orig= target_tbl->table_list; target_tbl->table= orig->table; /* Multi-delete can't be constructed over-union => we always have single SELECT on top and have to check underlaying SELECTs of it */ for (SELECT_LEX_UNIT *un= lex->select_lex.first_inner_unit(); un; un= un->next_unit()) { if (un->first_select()->linkage != DERIVED_TABLE_TYPE && un->check_updateable(target_tbl->table_list->db, target_tbl->table_list->real_name)) if (lex->select_lex.check_updateable_in_subqueries(orig->db, orig->real_name)) { my_error(ER_UPDATE_TABLE_USED, MYF(0), target_tbl->table_list->real_name); orig->real_name); res= -1; break; } } } if (!thd->is_fatal_error && (result= new multi_delete(thd,aux_tables, table_count))) Loading Loading
mysql-test/r/multi_update.result +7 −0 Original line number Diff line number Diff line Loading @@ -455,3 +455,10 @@ create table t3 (a int, primary key (a)); delete t1,t3 from t1,t2 where t1.a=t2.a and t2.a=(select t3.a from t3 where t1.a=t3.a); ERROR 42S02: Unknown table 't3' in MULTI DELETE drop table t1, t2, t3; create table t1 (col1 int); create table t2 (col1 int); update t1,t2 set t1.col1 = (select max(col1) from t1) where t1.col1 = t2.col1; ERROR HY000: You can't specify target table 't1' for update in FROM clause delete t1 from t1,t2 where t1.col1 < (select max(col1) from t1) and t1.col1 = t2.col1; ERROR HY000: You can't specify target table 't1' for update in FROM clause drop table t1,t2;
mysql-test/t/multi_update.test +11 −0 Original line number Diff line number Diff line Loading @@ -417,3 +417,14 @@ create table t3 (a int, primary key (a)); -- error 1109 delete t1,t3 from t1,t2 where t1.a=t2.a and t2.a=(select t3.a from t3 where t1.a=t3.a); drop table t1, t2, t3; # # multi* unique updating table check # create table t1 (col1 int); create table t2 (col1 int); -- error 1093 update t1,t2 set t1.col1 = (select max(col1) from t1) where t1.col1 = t2.col1; -- error 1093 delete t1 from t1,t2 where t1.col1 < (select max(col1) from t1) and t1.col1 = t2.col1; drop table t1,t2;
sql/sql_lex.cc +21 −1 Original line number Diff line number Diff line Loading @@ -1550,6 +1550,7 @@ bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num) 1 - found 0 - OK (table did not found) */ bool st_select_lex_unit::check_updateable(char *db, char *table) { for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select()) Loading @@ -1561,7 +1562,7 @@ bool st_select_lex_unit::check_updateable(char *db, char *table) /* Find db.table which will be updated in this select and underlayed ones (except derived tables) underlaying ones (except derived tables) SYNOPSIS st_select_lex::check_updateable() Loading @@ -1572,11 +1573,30 @@ bool st_select_lex_unit::check_updateable(char *db, char *table) 1 - found 0 - OK (table did not found) */ bool st_select_lex::check_updateable(char *db, char *table) { if (find_real_table_in_list(get_table_list(), db, table)) return 1; return check_updateable_in_subqueries(db, table); } /* Find db.table which will be updated in underlaying subqueries SYNOPSIS st_select_lex::check_updateable_in_subqueries() db - data base name table - real table name RETURN 1 - found 0 - OK (table did not found) */ bool st_select_lex::check_updateable_in_subqueries(char *db, char *table) { for (SELECT_LEX_UNIT *un= first_inner_unit(); un; un= un->next_unit()) Loading
sql/sql_lex.h +1 −0 Original line number Diff line number Diff line Loading @@ -517,6 +517,7 @@ class st_select_lex: public st_select_lex_node } bool setup_ref_array(THD *thd, uint order_group_num); bool check_updateable(char *db, char *table); bool check_updateable_in_subqueries(char *db, char *table); void print(THD *thd, String *str); static void print_order(String *str, ORDER *order); void print_limit(THD *thd, String *str); Loading
sql/sql_parse.cc +9 −14 Original line number Diff line number Diff line Loading @@ -2796,26 +2796,21 @@ mysql_execute_command(THD *thd) target_tbl; target_tbl= target_tbl->next) { target_tbl->table= target_tbl->table_list->table; TABLE_LIST *orig= target_tbl->table_list; target_tbl->table= orig->table; /* Multi-delete can't be constructed over-union => we always have single SELECT on top and have to check underlaying SELECTs of it */ for (SELECT_LEX_UNIT *un= lex->select_lex.first_inner_unit(); un; un= un->next_unit()) { if (un->first_select()->linkage != DERIVED_TABLE_TYPE && un->check_updateable(target_tbl->table_list->db, target_tbl->table_list->real_name)) if (lex->select_lex.check_updateable_in_subqueries(orig->db, orig->real_name)) { my_error(ER_UPDATE_TABLE_USED, MYF(0), target_tbl->table_list->real_name); orig->real_name); res= -1; break; } } } if (!thd->is_fatal_error && (result= new multi_delete(thd,aux_tables, table_count))) Loading