diff options
author | Jon Olav Hauglid <jon.hauglid@oracle.com> | 2010-08-09 14:11:29 +0200 |
---|---|---|
committer | Jon Olav Hauglid <jon.hauglid@oracle.com> | 2010-08-09 14:11:29 +0200 |
commit | fa69eeb1135e18beeee6f85338a8b208276a425b (patch) | |
tree | 8578afc04afde36b010302fa689040e1eda71652 | |
parent | a0919642873ae7b3172705578d67c8f093fc5fba (diff) | |
parent | d62bfebc7ede98df28ac75ec0d0880fd07f201db (diff) | |
download | mariadb-git-fa69eeb1135e18beeee6f85338a8b208276a425b.tar.gz |
manual merge from mysql-5.1-bugteam
-rw-r--r-- | mysql-test/r/insert.result | 15 | ||||
-rw-r--r-- | mysql-test/t/insert.test | 25 | ||||
-rw-r--r-- | sql/sql_insert.cc | 3 | ||||
-rw-r--r-- | sql/sql_select.cc | 2 | ||||
-rw-r--r-- | sql/sql_update.cc | 70 |
5 files changed, 46 insertions, 69 deletions
diff --git a/mysql-test/r/insert.result b/mysql-test/r/insert.result index b322c5da73a..655303be7f4 100644 --- a/mysql-test/r/insert.result +++ b/mysql-test/r/insert.result @@ -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; diff --git a/mysql-test/t/insert.test b/mysql-test/t/insert.test index 4f918504597..2bf543511ac 100644 --- a/mysql-test/t/insert.test +++ b/mysql-test/t/insert.test @@ -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; diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index a0d347f48de..326a5defa9b 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -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)); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index ccfd93a1bc8..3c9eb215641 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -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); diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 35478e28520..68440f6623a 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -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)); |