mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
Manual merge of mysql-5.1-bugteam to mysql-trunk-merge.
This commit is contained in:
@ -399,10 +399,7 @@ int mysql_update(THD *thd,
|
||||
matching rows before updating the table!
|
||||
*/
|
||||
if (used_index < MAX_KEY && old_covering_keys.is_set(used_index))
|
||||
{
|
||||
table->key_read=1;
|
||||
table->mark_columns_used_by_index(used_index);
|
||||
}
|
||||
else
|
||||
{
|
||||
table->use_all_columns();
|
||||
@ -849,11 +846,7 @@ int mysql_update(THD *thd,
|
||||
err:
|
||||
delete select;
|
||||
free_underlaid_joins(thd, select_lex);
|
||||
if (table->key_read)
|
||||
{
|
||||
table->key_read=0;
|
||||
table->file->extra(HA_EXTRA_NO_KEYREAD);
|
||||
}
|
||||
table->set_keyread(FALSE);
|
||||
thd->abort_on_warning= 0;
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
@ -1199,6 +1192,57 @@ reopen_tables:
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Implementation of the safe update options during UPDATE IGNORE. This syntax
|
||||
causes an UPDATE statement to ignore all errors. In safe update mode,
|
||||
however, we must never ignore the ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE. There
|
||||
is a special hook in my_message_sql that will otherwise delete all errors
|
||||
when the IGNORE option is specified.
|
||||
|
||||
In the future, all IGNORE handling should be used with this class and all
|
||||
traces of the hack outlined below should be removed.
|
||||
|
||||
- The parser detects IGNORE option and sets thd->lex->ignore= 1
|
||||
|
||||
- In JOIN::optimize, if this is set, then
|
||||
thd->lex->current_select->no_error gets set.
|
||||
|
||||
- In my_message_sql(), if the flag above is set then any error is
|
||||
unconditionally converted to a warning.
|
||||
|
||||
We are moving in the direction of using Internal_error_handler subclasses
|
||||
to do all such error tweaking, please continue this effort if new bugs
|
||||
appear.
|
||||
*/
|
||||
class Safe_dml_handler : public Internal_error_handler {
|
||||
|
||||
private:
|
||||
bool m_handled_error;
|
||||
|
||||
public:
|
||||
explicit Safe_dml_handler() : m_handled_error(FALSE) {}
|
||||
|
||||
bool handle_condition(THD *thd,
|
||||
uint sql_errno,
|
||||
const char* sqlstate,
|
||||
MYSQL_ERROR::enum_warning_level level,
|
||||
const char* msg,
|
||||
MYSQL_ERROR ** cond_hdl)
|
||||
{
|
||||
if (level == MYSQL_ERROR::WARN_LEVEL_ERROR &&
|
||||
sql_errno == ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE)
|
||||
{
|
||||
thd->stmt_da->set_error_status(thd, sql_errno, msg, sqlstate);
|
||||
m_handled_error= TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool handled_error() { return m_handled_error; }
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
Setup multi-update handling and call SELECT to do the join
|
||||
*/
|
||||
@ -1231,18 +1275,35 @@ bool mysql_multi_update(THD *thd,
|
||||
MODE_STRICT_ALL_TABLES));
|
||||
|
||||
List<Item> total_list;
|
||||
|
||||
Safe_dml_handler handler;
|
||||
bool using_handler= thd->options & OPTION_SAFE_UPDATES;
|
||||
if (using_handler)
|
||||
thd->push_internal_handler(&handler);
|
||||
|
||||
res= mysql_select(thd, &select_lex->ref_pointer_array,
|
||||
table_list, select_lex->with_wild,
|
||||
total_list,
|
||||
conds, 0, (ORDER *) NULL, (ORDER *)NULL, (Item *) NULL,
|
||||
(ORDER *)NULL,
|
||||
options | SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK |
|
||||
OPTION_SETUP_TABLES_DONE,
|
||||
*result, unit, select_lex);
|
||||
DBUG_PRINT("info",("res: %d report_error: %d", res,
|
||||
(int) thd->is_error()));
|
||||
table_list, select_lex->with_wild,
|
||||
total_list,
|
||||
conds, 0, (ORDER *) NULL, (ORDER *)NULL, (Item *) NULL,
|
||||
(ORDER *)NULL,
|
||||
options | SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK |
|
||||
OPTION_SETUP_TABLES_DONE,
|
||||
*result, unit, select_lex);
|
||||
|
||||
if (using_handler)
|
||||
{
|
||||
Internal_error_handler *top_handler= thd->pop_internal_handler();
|
||||
DBUG_ASSERT(&handler == top_handler);
|
||||
}
|
||||
|
||||
DBUG_PRINT("info",("res: %d report_error: %d", res, (int) thd->is_error()));
|
||||
res|= thd->is_error();
|
||||
if (unlikely(res))
|
||||
/*
|
||||
Todo: remove below code and make Safe_dml_handler do error processing
|
||||
instead. That way we can return the actual error instead of
|
||||
ER_UNKNOWN_ERROR.
|
||||
*/
|
||||
if (unlikely(res) && (!using_handler || !handler.handled_error()))
|
||||
{
|
||||
/* If we had a another error reported earlier then this will be ignored */
|
||||
(*result)->send_error(ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR));
|
||||
|
Reference in New Issue
Block a user