mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 12:02:42 +01:00
Rewrite IGNORE handling:
- Instead of supressing all errors, only suppress safe ones like: ER_DUP_KEY, ER_BAD_NULL_ERROR, ER_SUBQUERY_NO_1_ROW, ER_ROW_IS_REFERENCED_2
This commit is contained in:
parent
6d4224a31c
commit
1485874619
10 changed files with 66 additions and 106 deletions
|
@ -2853,7 +2853,7 @@ void handler::print_error(int error, myf errflag)
|
|||
str.length(max_length-4);
|
||||
str.append(STRING_WITH_LEN("..."));
|
||||
}
|
||||
my_error(ER_FOREIGN_DUPLICATE_KEY, MYF(0), table_share->table_name.str,
|
||||
my_error(ER_FOREIGN_DUPLICATE_KEY, errflag, table_share->table_name.str,
|
||||
str.c_ptr_safe(), key_nr+1);
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
@ -2861,7 +2861,7 @@ void handler::print_error(int error, myf errflag)
|
|||
break;
|
||||
}
|
||||
case HA_ERR_NULL_IN_SPATIAL:
|
||||
my_error(ER_CANT_CREATE_GEOMETRY_OBJECT, MYF(0));
|
||||
my_error(ER_CANT_CREATE_GEOMETRY_OBJECT, errflag);
|
||||
DBUG_VOID_RETURN;
|
||||
case HA_ERR_FOUND_DUPP_UNIQUE:
|
||||
textno=ER_DUP_UNIQUE;
|
||||
|
@ -2931,21 +2931,21 @@ void handler::print_error(int error, myf errflag)
|
|||
{
|
||||
String str;
|
||||
get_error_message(error, &str);
|
||||
my_error(ER_ROW_IS_REFERENCED_2, MYF(0), str.c_ptr_safe());
|
||||
my_error(ER_ROW_IS_REFERENCED_2, errflag, str.c_ptr_safe());
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
case HA_ERR_NO_REFERENCED_ROW:
|
||||
{
|
||||
String str;
|
||||
get_error_message(error, &str);
|
||||
my_error(ER_NO_REFERENCED_ROW_2, MYF(0), str.c_ptr_safe());
|
||||
my_error(ER_NO_REFERENCED_ROW_2, errflag, str.c_ptr_safe());
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
case HA_ERR_TABLE_DEF_CHANGED:
|
||||
textno=ER_TABLE_DEF_CHANGED;
|
||||
break;
|
||||
case HA_ERR_NO_SUCH_TABLE:
|
||||
my_error(ER_NO_SUCH_TABLE, MYF(0), table_share->db.str,
|
||||
my_error(ER_NO_SUCH_TABLE, errflag, table_share->db.str,
|
||||
table_share->table_name.str);
|
||||
DBUG_VOID_RETURN;
|
||||
case HA_ERR_RBR_LOGGING_FAILED:
|
||||
|
@ -2957,7 +2957,7 @@ void handler::print_error(int error, myf errflag)
|
|||
uint key_nr= get_dup_key(error);
|
||||
if ((int) key_nr >= 0)
|
||||
ptr= table->key_info[key_nr].name;
|
||||
my_error(ER_DROP_INDEX_FK, MYF(0), ptr);
|
||||
my_error(ER_DROP_INDEX_FK, errflag, ptr);
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
case HA_ERR_TABLE_NEEDS_UPGRADE:
|
||||
|
@ -2986,12 +2986,12 @@ void handler::print_error(int error, myf errflag)
|
|||
{
|
||||
const char* engine= table_type();
|
||||
if (temporary)
|
||||
my_error(ER_GET_TEMPORARY_ERRMSG, MYF(0), error, str.c_ptr(),
|
||||
my_error(ER_GET_TEMPORARY_ERRMSG, errflag, error, str.c_ptr(),
|
||||
engine);
|
||||
else
|
||||
{
|
||||
SET_FATAL_ERROR;
|
||||
my_error(ER_GET_ERRMSG, MYF(0), error, str.c_ptr(), engine);
|
||||
my_error(ER_GET_ERRMSG, errflag, error, str.c_ptr(), engine);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -2999,7 +2999,11 @@ void handler::print_error(int error, myf errflag)
|
|||
DBUG_VOID_RETURN;
|
||||
}
|
||||
}
|
||||
if (fatal_error && (debug_assert_if_crashed_table ||
|
||||
if (fatal_error)
|
||||
{
|
||||
/* Ensure this becomes a true error */
|
||||
errflag&= ~(ME_JUST_WARNING | ME_JUST_INFO);
|
||||
if ((debug_assert_if_crashed_table ||
|
||||
global_system_variables.log_warnings > 1))
|
||||
{
|
||||
/*
|
||||
|
@ -3007,7 +3011,7 @@ void handler::print_error(int error, myf errflag)
|
|||
*/
|
||||
errflag|= ME_NOREFRESH;
|
||||
}
|
||||
|
||||
}
|
||||
my_error(textno, errflag, table_share->table_name.str, error);
|
||||
DBUG_ASSERT(!fatal_error || !debug_assert_if_crashed_table);
|
||||
DBUG_VOID_RETURN;
|
||||
|
|
|
@ -3187,22 +3187,6 @@ int my_message_sql(uint error, const char *str, myf MyFlags)
|
|||
|
||||
thd->is_slave_error= 1; // needed to catch query errors during replication
|
||||
|
||||
/*
|
||||
thd->lex->current_select == 0 if lex structure is not inited
|
||||
(not query command (COM_QUERY))
|
||||
*/
|
||||
if (thd->lex->current_select &&
|
||||
thd->lex->current_select->no_error && !thd->is_fatal_error)
|
||||
{
|
||||
DBUG_PRINT("error",
|
||||
("Error converted to warning: current_select: no_error %d "
|
||||
"fatal_error: %d",
|
||||
(thd->lex->current_select ?
|
||||
thd->lex->current_select->no_error : 0),
|
||||
(int) thd->is_fatal_error));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (thd->main_da.is_ok() && !thd->main_da.can_overwrite_status)
|
||||
{
|
||||
/*
|
||||
|
@ -3221,7 +3205,7 @@ int my_message_sql(uint error, const char *str, myf MyFlags)
|
|||
thd->main_da.set_error_status(thd, error, str);
|
||||
}
|
||||
query_cache_abort(&thd->net);
|
||||
}
|
||||
|
||||
/*
|
||||
If a continue handler is found, the error message will be cleared
|
||||
by the stored procedures code.
|
||||
|
|
|
@ -8549,9 +8549,11 @@ fill_record(THD * thd, List<Item> &fields, List<Item> &values,
|
|||
Item *value, *fld;
|
||||
Item_field *field;
|
||||
TABLE *table= 0, *vcol_table= 0;
|
||||
bool abort_on_warning_saved= thd->abort_on_warning;
|
||||
bool save_abort_on_warning= thd->abort_on_warning;
|
||||
bool save_no_errors= thd->no_errors;
|
||||
DBUG_ENTER("fill_record");
|
||||
|
||||
thd->no_errors= ignore_errors;
|
||||
/*
|
||||
Reset the table->auto_increment_field_not_null as it is valid for
|
||||
only one row.
|
||||
|
@ -8596,7 +8598,7 @@ fill_record(THD * thd, List<Item> &fields, List<Item> &values,
|
|||
ER(ER_WARNING_NON_DEFAULT_VALUE_FOR_VIRTUAL_COLUMN),
|
||||
rfield->field_name, table->s->table_name.str);
|
||||
}
|
||||
if ((value->save_in_field(rfield, 0) < 0) && !ignore_errors)
|
||||
if ((value->save_in_field(rfield, 0)) < 0 && !ignore_errors)
|
||||
{
|
||||
my_message(ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR), MYF(0));
|
||||
goto err;
|
||||
|
@ -8614,10 +8616,13 @@ fill_record(THD * thd, List<Item> &fields, List<Item> &values,
|
|||
goto err;
|
||||
}
|
||||
}
|
||||
thd->abort_on_warning= abort_on_warning_saved;
|
||||
thd->abort_on_warning= save_abort_on_warning;
|
||||
thd->no_errors= save_no_errors;
|
||||
DBUG_RETURN(thd->is_error());
|
||||
|
||||
err:
|
||||
thd->abort_on_warning= abort_on_warning_saved;
|
||||
thd->abort_on_warning= save_abort_on_warning;
|
||||
thd->no_errors= save_no_errors;
|
||||
if (table)
|
||||
table->auto_increment_field_not_null= FALSE;
|
||||
DBUG_RETURN(TRUE);
|
||||
|
|
|
@ -2585,7 +2585,8 @@ int select_singlerow_subselect::send_data(List<Item> &items)
|
|||
Item_singlerow_subselect *it= (Item_singlerow_subselect *)item;
|
||||
if (it->assigned())
|
||||
{
|
||||
my_message(ER_SUBQUERY_NO_1_ROW, ER(ER_SUBQUERY_NO_1_ROW), MYF(0));
|
||||
my_message(ER_SUBQUERY_NO_1_ROW, ER(ER_SUBQUERY_NO_1_ROW),
|
||||
MYF(current_thd->lex->ignore ? ME_JUST_WARNING : 0));
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
if (unit->offset_limit_cnt)
|
||||
|
@ -3830,16 +3831,6 @@ void mark_transaction_to_rollback(THD *thd, bool all)
|
|||
{
|
||||
thd->is_fatal_sub_stmt_error= TRUE;
|
||||
thd->transaction_rollback_request= all;
|
||||
/*
|
||||
Aborted transactions can not be IGNOREd.
|
||||
Switch off the IGNORE flag for the current
|
||||
SELECT_LEX. This should allow my_error()
|
||||
to report the error and abort the execution
|
||||
flow, even in presence
|
||||
of IGNORE clause.
|
||||
*/
|
||||
if (thd->lex->current_select)
|
||||
thd->lex->current_select->no_error= FALSE;
|
||||
}
|
||||
}
|
||||
/***************************************************************************
|
||||
|
|
|
@ -124,8 +124,6 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
|
|||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
|
||||
select_lex->no_error= thd->lex->ignore;
|
||||
|
||||
const_cond_result= const_cond && (!conds || conds->val_int());
|
||||
if (thd->is_error())
|
||||
{
|
||||
|
@ -365,16 +363,9 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
|
|||
}
|
||||
else
|
||||
{
|
||||
table->file->print_error(error,MYF(0));
|
||||
/*
|
||||
In < 4.0.14 we set the error number to 0 here, but that
|
||||
was not sensible, because then MySQL would not roll back the
|
||||
failed DELETE, and also wrote it to the binlog. For MyISAM
|
||||
tables a DELETE probably never should fail (?), but for
|
||||
InnoDB it can fail in a FOREIGN KEY error or an
|
||||
out-of-tablespace error.
|
||||
*/
|
||||
if (!select_lex->no_error)
|
||||
table->file->print_error(error,
|
||||
MYF(thd->lex->ignore ? ME_JUST_WARNING : 0));
|
||||
if (thd->is_error())
|
||||
{
|
||||
error= 1;
|
||||
break;
|
||||
|
@ -809,7 +800,7 @@ int multi_delete::send_data(List<Item> &values)
|
|||
TABLE_LIST *del_table;
|
||||
DBUG_ENTER("multi_delete::send_data");
|
||||
|
||||
bool ignore= thd->lex->current_select->no_error;
|
||||
bool ignore= thd->lex->ignore;
|
||||
|
||||
for (del_table= delete_tables;
|
||||
del_table;
|
||||
|
@ -958,11 +949,11 @@ int multi_delete::do_deletes()
|
|||
table_being_deleted= table_being_deleted->next_local, counter++)
|
||||
{
|
||||
TABLE *table = table_being_deleted->table;
|
||||
int local_error;
|
||||
if (tempfiles[counter]->get(table))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
int local_error=
|
||||
do_table_deletes(table, thd->lex->current_select->no_error);
|
||||
local_error= do_table_deletes(table, thd->lex->ignore);
|
||||
|
||||
if (thd->killed && !local_error)
|
||||
DBUG_RETURN(1);
|
||||
|
|
|
@ -1579,11 +1579,12 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
|
|||
else
|
||||
error= 0;
|
||||
/*
|
||||
If ON DUP KEY UPDATE updates a row instead of inserting one, it's
|
||||
like a regular UPDATE statement: it should not affect the value of a
|
||||
next SELECT LAST_INSERT_ID() or mysql_insert_id().
|
||||
Except if LAST_INSERT_ID(#) was in the INSERT query, which is
|
||||
handled separately by THD::arg_of_last_insert_id_function.
|
||||
If ON DUP KEY UPDATE updates a row instead of inserting
|
||||
one, it's like a regular UPDATE statement: it should not
|
||||
affect the value of a next SELECT LAST_INSERT_ID() or
|
||||
mysql_insert_id(). Except if LAST_INSERT_ID(#) was in the
|
||||
INSERT query, which is handled separately by
|
||||
THD::arg_of_last_insert_id_function.
|
||||
*/
|
||||
insert_id_for_cur_row= table->file->insert_id_for_cur_row= 0;
|
||||
trg_error= (table->triggers &&
|
||||
|
@ -1660,11 +1661,12 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
|
|||
}
|
||||
|
||||
/*
|
||||
If more than one iteration of the above while loop is done, from the second
|
||||
one the row being inserted will have an explicit value in the autoinc field,
|
||||
which was set at the first call of handler::update_auto_increment(). This
|
||||
value is saved to avoid thd->insert_id_for_cur_row becoming 0. Use this saved
|
||||
autoinc value.
|
||||
If more than one iteration of the above while loop is done, from
|
||||
the second one the row being inserted will have an explicit
|
||||
value in the autoinc field, which was set at the first call of
|
||||
handler::update_auto_increment(). This value is saved to avoid
|
||||
thd->insert_id_for_cur_row becoming 0. Use this saved autoinc
|
||||
value.
|
||||
*/
|
||||
if (table->file->insert_id_for_cur_row == 0)
|
||||
table->file->insert_id_for_cur_row= insert_id_for_cur_row;
|
||||
|
@ -1704,9 +1706,6 @@ ok_or_after_trg_err:
|
|||
|
||||
err:
|
||||
info->last_errno= error;
|
||||
/* current_select is NULL if this is a delayed insert */
|
||||
if (thd->lex->current_select)
|
||||
thd->lex->current_select->no_error= 0; // Give error
|
||||
table->file->print_error(error,MYF(0));
|
||||
|
||||
before_trg_err:
|
||||
|
@ -3078,8 +3077,6 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
|
|||
*/
|
||||
lex->current_select= &lex->select_lex;
|
||||
|
||||
/* Errors during check_insert_fields() should not be ignored. */
|
||||
lex->current_select->no_error= FALSE;
|
||||
res= (setup_fields(thd, 0, values, MARK_COLUMNS_READ, 0, 0) ||
|
||||
check_insert_fields(thd, table_list, *fields, values,
|
||||
!insert_into_view, 1, &map));
|
||||
|
@ -3213,8 +3210,6 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
|
|||
if (!res)
|
||||
prepare_triggers_for_insert_stmt(table);
|
||||
|
||||
lex->current_select->no_error= lex->ignore;
|
||||
|
||||
DBUG_RETURN(res);
|
||||
}
|
||||
|
||||
|
|
|
@ -1572,7 +1572,7 @@ void st_select_lex_node::init_query()
|
|||
options= 0;
|
||||
sql_cache= SQL_CACHE_UNSPECIFIED;
|
||||
linkage= UNSPECIFIED_TYPE;
|
||||
no_error= no_table_names_allowed= 0;
|
||||
no_table_names_allowed= 0;
|
||||
uncacheable= 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -429,7 +429,6 @@ public:
|
|||
uint8 uncacheable;
|
||||
enum sub_select_type linkage;
|
||||
bool no_table_names_allowed; /* used for global order by */
|
||||
bool no_error; /* suppress error message (convert it to warnings) */
|
||||
|
||||
static void *operator new(size_t size) throw ()
|
||||
{
|
||||
|
|
|
@ -2460,9 +2460,6 @@ void reinit_stmt_before_use(THD *thd, LEX *lex)
|
|||
for (order= sl->order_list.first; order; order= order->next)
|
||||
order->item= &order->item_ptr;
|
||||
sl->handle_derived(lex, DT_REINIT);
|
||||
|
||||
/* clear the no_error flag for INSERT/UPDATE IGNORE */
|
||||
sl->no_error= FALSE;
|
||||
}
|
||||
{
|
||||
SELECT_LEX_UNIT *unit= sl->master_unit();
|
||||
|
|
|
@ -284,7 +284,6 @@ bool handle_select(THD *thd, LEX *lex, select_result *result,
|
|||
}
|
||||
DBUG_PRINT("info",("res: %d report_error: %d", res,
|
||||
thd->is_error()));
|
||||
DBUG_ASSERT(res == 0 || thd->is_error());
|
||||
res|= thd->is_error();
|
||||
if (unlikely(res))
|
||||
result->abort();
|
||||
|
@ -1615,9 +1614,6 @@ JOIN::optimize()
|
|||
|
||||
error= 0;
|
||||
|
||||
// Ignore errors of execution if option IGNORE present
|
||||
if (thd->lex->ignore)
|
||||
thd->lex->current_select->no_error= 1;
|
||||
DBUG_RETURN(0);
|
||||
|
||||
setup_subq_exit:
|
||||
|
@ -9602,8 +9598,6 @@ bool error_if_full_join(JOIN *join)
|
|||
{
|
||||
if (tab->type == JT_ALL && (!tab->select || !tab->select->quick))
|
||||
{
|
||||
/* This error should not be ignored. */
|
||||
join->select_lex->no_error= FALSE;
|
||||
my_message(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,
|
||||
ER(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE), MYF(0));
|
||||
return(1);
|
||||
|
|
Loading…
Reference in a new issue