Loading sql/sql_class.h +1 −1 Original line number Diff line number Diff line Loading @@ -684,7 +684,7 @@ class Unique :public Sql_alloc enum enum_duplicates dupl; uint num_of_tables, num_fields, num_updated, *save_time_stamps, *field_sequence; int error; bool do_update; bool do_update, not_trans_safe; public: multi_update(THD *thd_arg, TABLE_LIST *ut, List<Item> &fs, enum enum_duplicates handle_duplicates, Loading sql/sql_parse.cc +59 −65 Original line number Diff line number Diff line Loading @@ -1224,8 +1224,6 @@ mysql_execute_command(void) (table_rules_on && tables && thd->slave_thread && !tables_ok(thd,tables))) DBUG_VOID_RETURN; if (lex->sql_command==SQLCOM_UPDATE && select_lex->table_list.elements > 1) lex->sql_command=SQLCOM_MULTI_UPDATE; thread_safe_increment(com_stat[lex->sql_command],&LOCK_thread_count); switch (lex->sql_command) { Loading Loading @@ -1697,6 +1695,8 @@ mysql_execute_command(void) send_error(&thd->net,ER_WRONG_VALUE_COUNT); DBUG_VOID_RETURN; } if (select_lex->table_list.elements == 1) { res = mysql_update(thd,tables, select_lex->item_list, lex->value_list, Loading @@ -1709,6 +1709,53 @@ mysql_execute_command(void) #ifdef DELETE_ITEMS delete select_lex->where; #endif } else { multi_update *result; uint table_count; TABLE_LIST *auxi; lex->sql_command=SQLCOM_MULTI_UPDATE; for (auxi=(TABLE_LIST*) tables, table_count=0 ; auxi ; auxi=auxi->next) { table_count++; auxi->lock_type=TL_WRITE; } if (select_lex->order_list.elements || (select_lex->select_limit && select_lex->select_limit < INT_MAX)) { send_error(&thd->net,ER_NOT_ALLOWED_COMMAND); /// will have to come up with something better eventually DBUG_VOID_RETURN; } tables->grant.want_privilege=(SELECT_ACL & ~tables->grant.privilege); if ((res=open_and_lock_tables(thd,tables))) break; if (!setup_fields(thd,tables,select_lex->item_list,1,0,0) && !setup_fields(thd,tables,lex->value_list,0,0,0) && ! thd->fatal_error && (result=new multi_update(thd,tables,select_lex->item_list,lex->duplicates, lex->lock_option, table_count))) { List <Item> total_list; List_iterator <Item> field_list(select_lex->item_list); List_iterator <Item> value_list(lex->value_list); Item *item; while ((item=field_list++)) total_list.push_back(item); while ((item=value_list++)) total_list.push_back(item); res=mysql_select(thd,tables,total_list, select_lex->where, (ORDER *)NULL,(ORDER *)NULL,(Item *)NULL, (ORDER *)NULL, select_lex->options | thd->options | SELECT_NO_JOIN_CACHE, result); delete result; } else res= -1; // Error is not sent close_thread_tables(thd); } break; case SQLCOM_INSERT: if (check_access(thd,INSERT_ACL,tables->db,&tables->grant.privilege)) Loading Loading @@ -1879,59 +1926,6 @@ mysql_execute_command(void) close_thread_tables(thd); break; } case SQLCOM_MULTI_UPDATE: multi_update *result; uint table_count; TABLE_LIST *auxi; if (check_access(thd,UPDATE_ACL,tables->db,&tables->grant.privilege)) goto error; if (grant_option && check_grant(thd,UPDATE_ACL,tables)) goto error; if (select_lex->item_list.elements != lex->value_list.elements) { send_error(&thd->net,ER_WRONG_VALUE_COUNT); DBUG_VOID_RETURN; } for (auxi=(TABLE_LIST*) tables, table_count=0 ; auxi ; auxi=auxi->next) { table_count++; auxi->lock_type=TL_WRITE; } if (select_lex->order_list.elements || (select_lex->select_limit && select_lex->select_limit < INT_MAX)) { send_error(&thd->net,ER_NOT_ALLOWED_COMMAND); /// will have to come up with something better eventually DBUG_VOID_RETURN; } tables->grant.want_privilege=(SELECT_ACL & ~tables->grant.privilege); if ((res=open_and_lock_tables(thd,tables))) break; if (!setup_fields(thd,tables,select_lex->item_list,1,0,0) && !setup_fields(thd,tables,lex->value_list,0,0,0) && ! thd->fatal_error && (result=new multi_update(thd,tables,select_lex->item_list,lex->duplicates, lex->lock_option, table_count))) { List <Item> total_list; List_iterator <Item> field_list(select_lex->item_list); List_iterator <Item> value_list(lex->value_list); Item *item; while ((item=field_list++)) total_list.push_back(item); while ((item=value_list++)) total_list.push_back(item); res=mysql_select(thd,tables,total_list, select_lex->where, (ORDER *)NULL,(ORDER *)NULL,(Item *)NULL, (ORDER *)NULL, select_lex->options | thd->options | SELECT_NO_JOIN_CACHE, result); delete result; } else res= -1; // Error is not sent close_thread_tables(thd); break; case SQLCOM_DROP_TABLE: { if (check_table_access(thd,DROP_ACL,tables)) Loading sql/sql_update.cc +10 −22 Original line number Diff line number Diff line Loading @@ -359,6 +359,7 @@ multi_update::multi_update(THD *thd_arg, TABLE_LIST *ut, List<Item> &fs, tmp_tables = (TABLE **)NULL; int counter=0; ulong timestamp_query_id; not_trans_safe=false; for (TABLE_LIST *dt=ut ; dt ; dt=dt->next,counter++) { TABLE *table=ut->table; Loading Loading @@ -420,6 +421,9 @@ multi_update::prepare(List<Item> &values) { num_updated++; table_ref->shared=1; if (!not_trans_safe && !table_ref->table->file->has_transactions()) not_trans_safe=true; table_ref->table->no_keyread=1; // to be moved if initialize_tables has to be used break; } } Loading Loading @@ -529,6 +533,7 @@ multi_update::~multi_update() { TABLE *table=table_being_updated->table; (void)table->file->extra(HA_EXTRA_READCHECK); table->no_keyread=0; if (error) table->time_stamp=save_time_stamps[counter]; } Loading Loading @@ -629,27 +634,13 @@ bool multi_update::send_data(List<Item> &values) return 0; } /* Return true if some table is not transaction safe */ static bool some_table_is_not_transaction_safe (TABLE_LIST *tl) { for (; tl ; tl=tl->next) { if (!(tl->table->file->has_transactions())) return true; } return false; } void multi_update::send_error(uint errcode,const char *err) { /* First send error what ever it is ... */ ::send_error(&thd->net,errcode,err); /* reset used flags */ update_tables->table->no_keyread=0; // update_tables->table->no_keyread=0; /* If nothing updated return */ if (!updated) Loading @@ -665,8 +656,7 @@ void multi_update::send_error(uint errcode,const char *err) In all other cases do attempt updates ... */ if ((table_being_updated->table->file->has_transactions() && table_being_updated == update_tables) || !some_table_is_not_transaction_safe(update_tables->next)) table_being_updated == update_tables) || !not_trans_safe) ha_rollback_stmt(thd); else if (do_update) VOID(do_updates(true)); Loading Loading @@ -721,7 +711,6 @@ int multi_update::do_updates (bool from_send_error) error = tmp_table->file->rnd_init(1); if (error) return error; bool not_trans_safe = some_table_is_not_transaction_safe(update_tables); while (!(error=tmp_table->file->rnd_next(tmp_table->record[0])) && (!thd->killed || from_send_error || not_trans_safe)) { Loading Loading @@ -756,7 +745,7 @@ bool multi_update::send_eof() int error = do_updates(false); /* do_updates returns 0 if success */ /* reset used flags */ update_tables->table->no_keyread=0; // update_tables->table->no_keyread=0; if (error == -1) error = 0; thd->proc_info="end"; if (error) Loading @@ -767,8 +756,7 @@ bool multi_update::send_eof() was a non-transaction-safe table involved, since modifications in it cannot be rolled back. */ if (updated && (!error || some_table_is_not_transaction_safe(update_tables))) if (updated || not_trans_safe) { mysql_update_log.write(thd,thd->query,thd->query_length); Query_log_event qinfo(thd, thd->query); Loading @@ -777,7 +765,7 @@ bool multi_update::send_eof() is not used */ if (mysql_bin_log.is_open() && mysql_bin_log.write(&qinfo) && !some_table_is_not_transaction_safe(update_tables)) !not_trans_safe) error=1; /* Log write failed: roll back the SQL statement */ Loading Loading
sql/sql_class.h +1 −1 Original line number Diff line number Diff line Loading @@ -684,7 +684,7 @@ class Unique :public Sql_alloc enum enum_duplicates dupl; uint num_of_tables, num_fields, num_updated, *save_time_stamps, *field_sequence; int error; bool do_update; bool do_update, not_trans_safe; public: multi_update(THD *thd_arg, TABLE_LIST *ut, List<Item> &fs, enum enum_duplicates handle_duplicates, Loading
sql/sql_parse.cc +59 −65 Original line number Diff line number Diff line Loading @@ -1224,8 +1224,6 @@ mysql_execute_command(void) (table_rules_on && tables && thd->slave_thread && !tables_ok(thd,tables))) DBUG_VOID_RETURN; if (lex->sql_command==SQLCOM_UPDATE && select_lex->table_list.elements > 1) lex->sql_command=SQLCOM_MULTI_UPDATE; thread_safe_increment(com_stat[lex->sql_command],&LOCK_thread_count); switch (lex->sql_command) { Loading Loading @@ -1697,6 +1695,8 @@ mysql_execute_command(void) send_error(&thd->net,ER_WRONG_VALUE_COUNT); DBUG_VOID_RETURN; } if (select_lex->table_list.elements == 1) { res = mysql_update(thd,tables, select_lex->item_list, lex->value_list, Loading @@ -1709,6 +1709,53 @@ mysql_execute_command(void) #ifdef DELETE_ITEMS delete select_lex->where; #endif } else { multi_update *result; uint table_count; TABLE_LIST *auxi; lex->sql_command=SQLCOM_MULTI_UPDATE; for (auxi=(TABLE_LIST*) tables, table_count=0 ; auxi ; auxi=auxi->next) { table_count++; auxi->lock_type=TL_WRITE; } if (select_lex->order_list.elements || (select_lex->select_limit && select_lex->select_limit < INT_MAX)) { send_error(&thd->net,ER_NOT_ALLOWED_COMMAND); /// will have to come up with something better eventually DBUG_VOID_RETURN; } tables->grant.want_privilege=(SELECT_ACL & ~tables->grant.privilege); if ((res=open_and_lock_tables(thd,tables))) break; if (!setup_fields(thd,tables,select_lex->item_list,1,0,0) && !setup_fields(thd,tables,lex->value_list,0,0,0) && ! thd->fatal_error && (result=new multi_update(thd,tables,select_lex->item_list,lex->duplicates, lex->lock_option, table_count))) { List <Item> total_list; List_iterator <Item> field_list(select_lex->item_list); List_iterator <Item> value_list(lex->value_list); Item *item; while ((item=field_list++)) total_list.push_back(item); while ((item=value_list++)) total_list.push_back(item); res=mysql_select(thd,tables,total_list, select_lex->where, (ORDER *)NULL,(ORDER *)NULL,(Item *)NULL, (ORDER *)NULL, select_lex->options | thd->options | SELECT_NO_JOIN_CACHE, result); delete result; } else res= -1; // Error is not sent close_thread_tables(thd); } break; case SQLCOM_INSERT: if (check_access(thd,INSERT_ACL,tables->db,&tables->grant.privilege)) Loading Loading @@ -1879,59 +1926,6 @@ mysql_execute_command(void) close_thread_tables(thd); break; } case SQLCOM_MULTI_UPDATE: multi_update *result; uint table_count; TABLE_LIST *auxi; if (check_access(thd,UPDATE_ACL,tables->db,&tables->grant.privilege)) goto error; if (grant_option && check_grant(thd,UPDATE_ACL,tables)) goto error; if (select_lex->item_list.elements != lex->value_list.elements) { send_error(&thd->net,ER_WRONG_VALUE_COUNT); DBUG_VOID_RETURN; } for (auxi=(TABLE_LIST*) tables, table_count=0 ; auxi ; auxi=auxi->next) { table_count++; auxi->lock_type=TL_WRITE; } if (select_lex->order_list.elements || (select_lex->select_limit && select_lex->select_limit < INT_MAX)) { send_error(&thd->net,ER_NOT_ALLOWED_COMMAND); /// will have to come up with something better eventually DBUG_VOID_RETURN; } tables->grant.want_privilege=(SELECT_ACL & ~tables->grant.privilege); if ((res=open_and_lock_tables(thd,tables))) break; if (!setup_fields(thd,tables,select_lex->item_list,1,0,0) && !setup_fields(thd,tables,lex->value_list,0,0,0) && ! thd->fatal_error && (result=new multi_update(thd,tables,select_lex->item_list,lex->duplicates, lex->lock_option, table_count))) { List <Item> total_list; List_iterator <Item> field_list(select_lex->item_list); List_iterator <Item> value_list(lex->value_list); Item *item; while ((item=field_list++)) total_list.push_back(item); while ((item=value_list++)) total_list.push_back(item); res=mysql_select(thd,tables,total_list, select_lex->where, (ORDER *)NULL,(ORDER *)NULL,(Item *)NULL, (ORDER *)NULL, select_lex->options | thd->options | SELECT_NO_JOIN_CACHE, result); delete result; } else res= -1; // Error is not sent close_thread_tables(thd); break; case SQLCOM_DROP_TABLE: { if (check_table_access(thd,DROP_ACL,tables)) Loading
sql/sql_update.cc +10 −22 Original line number Diff line number Diff line Loading @@ -359,6 +359,7 @@ multi_update::multi_update(THD *thd_arg, TABLE_LIST *ut, List<Item> &fs, tmp_tables = (TABLE **)NULL; int counter=0; ulong timestamp_query_id; not_trans_safe=false; for (TABLE_LIST *dt=ut ; dt ; dt=dt->next,counter++) { TABLE *table=ut->table; Loading Loading @@ -420,6 +421,9 @@ multi_update::prepare(List<Item> &values) { num_updated++; table_ref->shared=1; if (!not_trans_safe && !table_ref->table->file->has_transactions()) not_trans_safe=true; table_ref->table->no_keyread=1; // to be moved if initialize_tables has to be used break; } } Loading Loading @@ -529,6 +533,7 @@ multi_update::~multi_update() { TABLE *table=table_being_updated->table; (void)table->file->extra(HA_EXTRA_READCHECK); table->no_keyread=0; if (error) table->time_stamp=save_time_stamps[counter]; } Loading Loading @@ -629,27 +634,13 @@ bool multi_update::send_data(List<Item> &values) return 0; } /* Return true if some table is not transaction safe */ static bool some_table_is_not_transaction_safe (TABLE_LIST *tl) { for (; tl ; tl=tl->next) { if (!(tl->table->file->has_transactions())) return true; } return false; } void multi_update::send_error(uint errcode,const char *err) { /* First send error what ever it is ... */ ::send_error(&thd->net,errcode,err); /* reset used flags */ update_tables->table->no_keyread=0; // update_tables->table->no_keyread=0; /* If nothing updated return */ if (!updated) Loading @@ -665,8 +656,7 @@ void multi_update::send_error(uint errcode,const char *err) In all other cases do attempt updates ... */ if ((table_being_updated->table->file->has_transactions() && table_being_updated == update_tables) || !some_table_is_not_transaction_safe(update_tables->next)) table_being_updated == update_tables) || !not_trans_safe) ha_rollback_stmt(thd); else if (do_update) VOID(do_updates(true)); Loading Loading @@ -721,7 +711,6 @@ int multi_update::do_updates (bool from_send_error) error = tmp_table->file->rnd_init(1); if (error) return error; bool not_trans_safe = some_table_is_not_transaction_safe(update_tables); while (!(error=tmp_table->file->rnd_next(tmp_table->record[0])) && (!thd->killed || from_send_error || not_trans_safe)) { Loading Loading @@ -756,7 +745,7 @@ bool multi_update::send_eof() int error = do_updates(false); /* do_updates returns 0 if success */ /* reset used flags */ update_tables->table->no_keyread=0; // update_tables->table->no_keyread=0; if (error == -1) error = 0; thd->proc_info="end"; if (error) Loading @@ -767,8 +756,7 @@ bool multi_update::send_eof() was a non-transaction-safe table involved, since modifications in it cannot be rolled back. */ if (updated && (!error || some_table_is_not_transaction_safe(update_tables))) if (updated || not_trans_safe) { mysql_update_log.write(thd,thd->query,thd->query_length); Query_log_event qinfo(thd, thd->query); Loading @@ -777,7 +765,7 @@ bool multi_update::send_eof() is not used */ if (mysql_bin_log.is_open() && mysql_bin_log.write(&qinfo) && !some_table_is_not_transaction_safe(update_tables)) !not_trans_safe) error=1; /* Log write failed: roll back the SQL statement */ Loading