diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index c41434336e52f23f0a3397093aa6d72ddbf3b04c..80b536bcac6079de9c28c2b90ce48165072d3a15 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -1151,3 +1151,16 @@ INSERT INTO t1 VALUES (1,0,NULL,NULL),(2,0,NULL,NULL); SELECT DISTINCT REF_ID FROM t1 WHERE ID= (SELECT DISTINCT REF_ID FROM t1 WHERE ID=2); REF_ID DROP TABLE t1; +create table t1 (a int, b int); +create table t2 (a int, b int); +insert into t1 values (1,0), (2,0), (3,0); +insert into t2 values (1,1), (2,1), (3,1), (2,2); +update ignore t1 set b=(select b from t2 where t1.a=t2.a); +Warnings: +Error 1240 Subselect returns more than 1 record +select * from t1; +a b +1 1 +2 NULL +3 1 +drop table t1, t2; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 1528f53ff0d60681def4be25e931d4f236b222dd..0131c807b6889e03b191c981671d1be59136458b 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -732,3 +732,17 @@ CREATE TABLE t1 ( INSERT INTO t1 VALUES (1,0,NULL,NULL),(2,0,NULL,NULL); SELECT DISTINCT REF_ID FROM t1 WHERE ID= (SELECT DISTINCT REF_ID FROM t1 WHERE ID=2); DROP TABLE t1; + +# +# uninterruptable update +# +create table t1 (a int, b int); +create table t2 (a int, b int); + +insert into t1 values (1,0), (2,0), (3,0); +insert into t2 values (1,1), (2,1), (3,1), (2,2); + +update ignore t1 set b=(select b from t2 where t1.a=t2.a); +select * from t1; + +drop table t1, t2; diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 11f218341bd5a2cc61b4cf5ece4c529e03007b24..cd78edfee7b5824fed8d33221fe040700432ca37 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -824,6 +824,8 @@ int subselect_single_select_engine::exec() { DBUG_ENTER("subselect_single_select_engine::exec"); char const *save_where= join->thd->where; + SELECT_LEX_NODE *save_select= join->thd->lex.current_select; + join->thd->lex.current_select= select_lex; if (!optimized) { optimized=1; @@ -831,6 +833,7 @@ int subselect_single_select_engine::exec() { join->thd->where= save_where; executed= 1; + join->thd->lex.current_select= save_select; DBUG_RETURN(join->error?join->error:1); } } @@ -839,6 +842,7 @@ int subselect_single_select_engine::exec() if (join->reinit()) { join->thd->where= save_where; + join->thd->lex.current_select= save_select; DBUG_RETURN(1); } item->reset(); @@ -846,15 +850,14 @@ int subselect_single_select_engine::exec() } if (!executed) { - SELECT_LEX_NODE *save_select= join->thd->lex.current_select; - join->thd->lex.current_select= select_lex; join->exec(); - join->thd->lex.current_select= save_select; executed= 1; join->thd->where= save_where; + join->thd->lex.current_select= save_select; DBUG_RETURN(join->error||thd->is_fatal_error); } join->thd->where= save_where; + join->thd->lex.current_select= save_select; DBUG_RETURN(0); } diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 68fa0cca2d56af2838a37f08fa390db417d69b56..ed4d683a9d5fdb6bbc6e23bd88e45fe521d2aeb6 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1818,15 +1818,23 @@ extern "C" int my_message_sql(uint error, const char *str, { THD *thd; DBUG_ENTER("my_message_sql"); - DBUG_PRINT("error",("Message: '%s'",str)); - if ((thd=current_thd)) + DBUG_PRINT("error", ("Message: '%s'", str)); + if ((thd= current_thd)) { - NET *net= &thd->net; - net->report_error= 1; - if (!net->last_error[0]) // Return only first message + if (thd->lex.current_select->no_error && !thd->is_fatal_error) { - strmake(net->last_error,str,sizeof(net->last_error)-1); - net->last_errno=error ? error : ER_UNKNOWN_ERROR; + DBUG_PRINT("error", ("above error converted to warning")); + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, error, str); + } + else + { + NET *net= &thd->net; + net->report_error= 1; + if (!net->last_error[0]) // Return only first message + { + strmake(net->last_error, str, sizeof(net->last_error)-1); + net->last_errno= error ? error : ER_UNKNOWN_ERROR; + } } } else diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index bc9ad4f36b06bdd84a2dc20dff1609c62a32b807..78f981d77593d9453048a366aef71d1c6296d980 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -122,6 +122,7 @@ LEX *lex_start(THD *thd, uchar *buf,uint length) lex->yacc_yyss=lex->yacc_yyvs=0; lex->ignore_space=test(thd->variables.sql_mode & MODE_IGNORE_SPACE); lex->sql_command=SQLCOM_END; + lex->duplicates= DUP_ERROR; return lex; } @@ -965,7 +966,7 @@ void st_select_lex_node::init_query() { options= 0; linkage= UNSPECIFIED_TYPE; - no_table_names_allowed= uncacheable= dependent= 0; + no_error= no_table_names_allowed= uncacheable= dependent= 0; ref_pointer_array= 0; } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 6226fbe1bb592414ca053bfba67352afbe375946..4844cb95f8616963b91ac0e2d93c580269cfdf3f 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -212,6 +212,7 @@ class st_select_lex_node { bool dependent; /* dependent from outer select subselect */ bool uncacheable; /* result of this query can't be cached */ 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) { diff --git a/sql/sql_select.cc b/sql/sql_select.cc index b8eb9e19cc79fb1b300d2a514396e91be2648901..02e502f0ba6818164f5a0bc36cbb553d8776f39e 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -436,6 +436,9 @@ JOIN::optimize() DBUG_RETURN(0); optimized= 1; + // Ignore errors of execution if option IGNORE present + if (thd->lex.duplicates == DUP_IGNORE) + thd->lex.current_select->no_error= 1; #ifdef HAVE_REF_TO_FIELDS // Not done yet /* Add HAVING to WHERE if possible */ if (having && !group_list && !sum_func_count)