diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index c41434336e5..80b536bcac6 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 1528f53ff0d..0131c807b68 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 11f218341bd..cd78edfee7b 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 68fa0cca2d5..ed4d683a9d5 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 bc9ad4f36b0..78f981d7759 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 6226fbe1bb5..4844cb95f86 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -212,6 +212,7 @@ public: 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 b8eb9e19cc7..02e502f0ba6 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)