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
|
# 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 #
|
||||||
--echo # End of 5.4 tests
|
--echo # End of 5.4 tests
|
||||||
--echo #
|
--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.
|
we are fixing fields from insert list.
|
||||||
*/
|
*/
|
||||||
lex->current_select= &lex->select_lex;
|
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) ||
|
res= (setup_fields(thd, 0, values, MARK_COLUMNS_READ, 0, 0) ||
|
||||||
check_insert_fields(thd, table_list, *fields, values,
|
check_insert_fields(thd, table_list, *fields, values,
|
||||||
!insert_into_view, 1, &map));
|
!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))
|
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,
|
my_message(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,
|
||||||
ER(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE), MYF(0));
|
ER(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE), MYF(0));
|
||||||
return(1);
|
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
|
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;
|
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,
|
res= mysql_select(thd, &select_lex->ref_pointer_array,
|
||||||
table_list, select_lex->with_wild,
|
table_list, select_lex->with_wild,
|
||||||
total_list,
|
total_list,
|
||||||
@ -1243,21 +1187,9 @@ bool mysql_multi_update(THD *thd,
|
|||||||
OPTION_SETUP_TABLES_DONE,
|
OPTION_SETUP_TABLES_DONE,
|
||||||
*result, unit, select_lex);
|
*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()));
|
DBUG_PRINT("info",("res: %d report_error: %d", res, (int) thd->is_error()));
|
||||||
res|= 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 */
|
/* If we had a another error reported earlier then this will be ignored */
|
||||||
(*result)->send_error(ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR));
|
(*result)->send_error(ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user