diff options
Diffstat (limited to 'sql/sql_update.cc')
-rw-r--r-- | sql/sql_update.cc | 95 |
1 files changed, 65 insertions, 30 deletions
diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 3e9bb0b753b..918a4c769b4 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -70,8 +70,6 @@ int mysql_update(THD *thd, READ_RECORD info; TABLE_LIST *update_table_list= ((TABLE_LIST*) thd->lex->select_lex.table_list.first); - TABLE_LIST tables; - List<Item> all_fields; DBUG_ENTER("mysql_update"); LINT_INIT(used_index); @@ -86,30 +84,13 @@ int mysql_update(THD *thd, /* Calculate "table->used_keys" based on the WHERE */ table->used_keys=table->keys_in_use; table->quick_keys.clear_all(); + #ifndef NO_EMBEDDED_ACCESS_CHECKS - want_privilege=table->grant.want_privilege; - table->grant.want_privilege=(SELECT_ACL & ~table->grant.privilege); + want_privilege= table->grant.want_privilege; #endif - - bzero((char*) &tables,sizeof(tables)); // For ORDER BY - tables.table= table; - tables.alias= table_list->alias; - - if (setup_tables(update_table_list) || - setup_conds(thd,update_table_list,&conds) || - thd->lex->select_lex.setup_ref_array(thd, order_num) || - setup_order(thd, thd->lex->select_lex.ref_pointer_array, - &tables, all_fields, all_fields, order) || - setup_ftfuncs(&thd->lex->select_lex)) - DBUG_RETURN(-1); /* purecov: inspected */ - - /* Check that we are not using table that we are updating in a sub select */ - if (find_real_table_in_list(table_list->next, - table_list->db, table_list->real_name)) - { - my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->real_name); - DBUG_RETURN(-1); - } + if ((error= mysql_prepare_update(thd, table_list, update_table_list, + &conds, order_num, order))) + DBUG_RETURN(error); old_used_keys= table->used_keys; // Keys used in WHERE /* @@ -420,6 +401,59 @@ err: DBUG_RETURN(-1); } +/* + Prepare items in UPDATE statement + + SYNOPSIS + mysql_prepare_update() + thd - thread handler + table_list - global table list + update_table_list - local table list of UPDATE SELECT_LEX + conds - conditions + order_num - number of ORDER BY list entries + order - ORDER BY clause list + + RETURN VALUE + 0 - OK + 1 - error (message is sent to user) + -1 - error (message is not sent to user) +*/ +int mysql_prepare_update(THD *thd, TABLE_LIST *table_list, + TABLE_LIST *update_table_list, + Item **conds, uint order_num, ORDER *order) +{ + TABLE *table= table_list->table; + TABLE_LIST tables; + List<Item> all_fields; + DBUG_ENTER("mysql_prepare_update"); + +#ifndef NO_EMBEDDED_ACCESS_CHECKS + table->grant.want_privilege= (SELECT_ACL & ~table->grant.privilege); +#endif + + bzero((char*) &tables,sizeof(tables)); // For ORDER BY + tables.table= table; + tables.alias= table_list->alias; + + if (setup_tables(update_table_list) || + setup_conds(thd, update_table_list, conds) || + thd->lex->select_lex.setup_ref_array(thd, order_num) || + setup_order(thd, thd->lex->select_lex.ref_pointer_array, + update_table_list, all_fields, all_fields, order) || + setup_ftfuncs(&thd->lex->select_lex)) + DBUG_RETURN(-1); + + /* Check that we are not using table that we are updating in a sub select */ + if (find_real_table_in_list(table_list->next, + table_list->db, table_list->real_name)) + { + my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->real_name); + DBUG_RETURN(-1); + } + + DBUG_RETURN(0); +} + /*************************************************************************** Update multiple tables from join @@ -441,6 +475,7 @@ int mysql_multi_update(THD *thd, int res; multi_update *result; TABLE_LIST *tl; + TABLE_LIST *update_list= (TABLE_LIST*) thd->lex->select_lex.table_list.first; table_map item_tables= 0, derived_tables= 0; DBUG_ENTER("mysql_multi_update"); @@ -453,7 +488,7 @@ int mysql_multi_update(THD *thd, Ensure that we have update privilege for all tables and columns in the SET part */ - for (tl= table_list ; tl ; tl=tl->next) + for (tl= update_list; tl; tl= tl->next) { TABLE *table= tl->table; /* @@ -470,14 +505,14 @@ int mysql_multi_update(THD *thd, { // Assign table map values to check updatability of derived tables uint tablenr=0; - for (TABLE_LIST *table_list= (TABLE_LIST*) select_lex->table_list.first; + for (TABLE_LIST *table_list= update_list; table_list; table_list= table_list->next, tablenr++) { table_list->table->map= (table_map) 1 << tablenr; } } - if (setup_fields(thd, 0, table_list, *fields, 1, 0, 0)) + if (setup_fields(thd, 0, update_list, *fields, 1, 0, 0)) DBUG_RETURN(-1); if (thd->lex->derived_tables) { @@ -493,7 +528,7 @@ int mysql_multi_update(THD *thd, /* Count tables and setup timestamp handling */ - for (tl= select_lex->get_table_list() ; tl ; tl= tl->next) + for (tl= update_list; tl; tl= tl->next) { TABLE *table= tl->table; @@ -510,7 +545,7 @@ int mysql_multi_update(THD *thd, if (thd->lex->derived_tables && (item_tables & derived_tables)) { // find derived table which cause error - for (tl= select_lex->get_table_list() ; tl ; tl= tl->next) + for (tl= update_list; tl; tl= tl->next) { if (tl->derived && (item_tables & tl->table->map)) { @@ -521,7 +556,7 @@ int mysql_multi_update(THD *thd, } } - if (!(result=new multi_update(thd, table_list, fields, values, + if (!(result=new multi_update(thd, update_list, fields, values, handle_duplicates))) DBUG_RETURN(-1); |