manual merge from mysql-5.1-bugteam
This commit is contained in:
commit
6d3078e231
@ -671,3 +671,18 @@ drop table t1;
|
||||
#
|
||||
# End of 5.4 tests
|
||||
#
|
||||
#
|
||||
# Bug#54106 assert in Protocol::end_statement,
|
||||
# INSERT IGNORE ... SELECT ... UNION SELECT ...
|
||||
#
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1 (a INT);
|
||||
INSERT INTO t1 (a, a) VALUES (1, 1);
|
||||
ERROR 42000: Column 'a' specified twice
|
||||
INSERT IGNORE t1 (a, a) VALUES (1, 1);
|
||||
ERROR 42000: Column 'a' specified twice
|
||||
INSERT IGNORE t1 (a, a) SELECT 1,1;
|
||||
ERROR 42000: Column 'a' specified twice
|
||||
INSERT IGNORE t1 (a, a) SELECT 1,1 UNION SELECT 2,2;
|
||||
ERROR 42000: Column 'a' specified twice
|
||||
DROP TABLE t1;
|
||||
|
@ -525,3 +525,28 @@ drop table t1;
|
||||
--echo #
|
||||
--echo # End of 5.4 tests
|
||||
--echo #
|
||||
|
||||
--echo #
|
||||
--echo # Bug#54106 assert in Protocol::end_statement,
|
||||
--echo # INSERT IGNORE ... SELECT ... UNION SELECT ...
|
||||
--echo #
|
||||
|
||||
--disable_warnings
|
||||
DROP TABLE IF EXISTS t1;
|
||||
--enable_warnings
|
||||
|
||||
CREATE TABLE t1 (a INT);
|
||||
|
||||
--error ER_FIELD_SPECIFIED_TWICE
|
||||
INSERT INTO t1 (a, a) VALUES (1, 1);
|
||||
# Verify that ER_FIELD_SPECIFIED_TWICE is not ignorable
|
||||
--error ER_FIELD_SPECIFIED_TWICE
|
||||
INSERT IGNORE t1 (a, a) VALUES (1, 1);
|
||||
|
||||
--error ER_FIELD_SPECIFIED_TWICE
|
||||
INSERT IGNORE t1 (a, a) SELECT 1,1;
|
||||
# Used to cause an assert
|
||||
--error ER_FIELD_SPECIFIED_TWICE
|
||||
INSERT IGNORE t1 (a, a) SELECT 1,1 UNION SELECT 2,2;
|
||||
|
||||
DROP TABLE t1;
|
||||
|
@ -3043,6 +3043,9 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
|
||||
we are fixing fields from insert list.
|
||||
*/
|
||||
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));
|
||||
|
@ -6914,6 +6914,8 @@ 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);
|
||||
|
@ -1145,57 +1145,6 @@ int mysql_multi_update_prepare(THD *thd)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
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
|
||||
*/
|
||||
@ -1229,11 +1178,6 @@ bool mysql_multi_update(THD *thd,
|
||||
|
||||
List<Item> total_list;
|
||||
|
||||
Safe_dml_handler handler;
|
||||
bool using_handler= thd->variables.option_bits & 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,
|
||||
@ -1243,21 +1187,9 @@ bool mysql_multi_update(THD *thd,
|
||||
OPTION_SETUP_TABLES_DONE,
|
||||
*result, unit, select_lex);
|
||||
|
||||
if (using_handler)
|
||||
{
|
||||
Internal_error_handler *top_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();
|
||||
/*
|
||||
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 (unlikely(res))
|
||||
{
|
||||
/* If we had a another error reported earlier then this will be ignored */
|
||||
(*result)->send_error(ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR));
|
||||
|
Loading…
x
Reference in New Issue
Block a user