Commit 6d3078e2 authored by Jon Olav Hauglid's avatar Jon Olav Hauglid

manual merge from mysql-5.1-bugteam

parents cad519be cc3be1ae
......@@ -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));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment