diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 4454f818efb..3d48a9f2803 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -3264,4 +3264,63 @@ bug131333() NULL drop procedure bug131333| drop function bug131333| +drop function if exists bug12379| +drop procedure if exists bug12379_1| +drop procedure if exists bug12379_2| +drop procedure if exists bug12379_3| +drop table if exists t3| +create table t3 (c1 char(1) primary key not null)| +create function bug12379() +returns integer +begin +insert into t3 values('X'); +insert into t3 values('X'); +return 0; +end| +create procedure bug12379_1() +begin +declare exit handler for sqlexception select 42; +select bug12379(); +END| +create procedure bug12379_2() +begin +declare exit handler for sqlexception begin end; +select bug12379(); +end| +create procedure bug12379_3() +begin +select bug12379(); +end| +select bug12379()| +ERROR 23000: Duplicate entry 'X' for key 1 +select 1| +1 +1 +call bug12379_1()| +bug12379() +42 +42 +Warnings: +Error 1062 Duplicate entry 'X' for key 1 +Warning 1417 A routine failed and has neither NO SQL nor READS SQL DATA in its declaration and binary logging is enabled; if non-transactional tables were updated, the binary log will miss their changes +select 2| +2 +2 +call bug12379_2()| +bug12379() +Warnings: +Error 1062 Duplicate entry 'X' for key 1 +Warning 1417 A routine failed and has neither NO SQL nor READS SQL DATA in its declaration and binary logging is enabled; if non-transactional tables were updated, the binary log will miss their changes +select 3| +3 +3 +call bug12379_3()| +ERROR 23000: Duplicate entry 'X' for key 1 +select 4| +4 +4 +drop function bug12379| +drop procedure bug12379_1| +drop procedure bug12379_2| +drop procedure bug12379_3| drop table t1,t2; diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 2b705329961..7a9738e8ada 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -4108,6 +4108,61 @@ drop procedure bug131333| drop function bug131333| +# +# BUG#12379: PROCEDURE with HANDLER calling FUNCTION with error get +# strange result +# +--disable_warnings +drop function if exists bug12379| +drop procedure if exists bug12379_1| +drop procedure if exists bug12379_2| +drop procedure if exists bug12379_3| +drop table if exists t3| +--enable_warnings + +create table t3 (c1 char(1) primary key not null)| + +create function bug12379() + returns integer +begin + insert into t3 values('X'); + insert into t3 values('X'); + return 0; +end| + +create procedure bug12379_1() +begin + declare exit handler for sqlexception select 42; + + select bug12379(); +END| +create procedure bug12379_2() +begin + declare exit handler for sqlexception begin end; + + select bug12379(); +end| +create procedure bug12379_3() +begin + select bug12379(); +end| + +--error 1062 +select bug12379()| +select 1| +call bug12379_1()| +select 2| +call bug12379_2()| +select 3| +--error 1062 +call bug12379_3()| +select 4| + +drop function bug12379| +drop procedure bug12379_1| +drop procedure bug12379_2| +drop procedure bug12379_3| + # # BUG#NNNN: New bug synopsis # diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 975014b9780..2699a4fa628 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -865,9 +865,34 @@ sql_exchange::sql_exchange(char *name,bool flag) bool select_send::send_fields(List &list, uint flags) { - return thd->protocol->send_fields(&list, flags); + bool res; + if (!(res= thd->protocol->send_fields(&list, flags))) + status= 1; + return res; } +void select_send::abort() +{ + DBUG_ENTER("select_send::abort"); + if (status && thd->spcont && + thd->spcont->find_handler(thd->net.last_errno, + MYSQL_ERROR::WARN_LEVEL_ERROR)) + { + /* + Executing stored procedure without a handler. + Here we should actually send an error to the client, + but as an error will break a multiple result set, the only thing we + can do for now is to nicely end the current data set and remembering + the error so that the calling routine will abort + */ + thd->net.report_error= 0; + send_eof(); + thd->net.report_error= 1; // Abort SP + } + DBUG_VOID_RETURN; +} + + /* Send data to client. Returns 0 if ok */ bool select_send::send_data(List &items) @@ -930,6 +955,7 @@ bool select_send::send_eof() if (!thd->net.report_error) { ::send_eof(thd); + status= 0; return 0; } else diff --git a/sql/sql_class.h b/sql/sql_class.h index a0c61944c6a..1a215d39841 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1658,12 +1658,14 @@ public: class select_send :public select_result { + int status; public: - select_send() {} + select_send() :status(0) {} bool send_fields(List &list, uint flags); bool send_data(List &items); bool send_eof(); bool simple_select() { return 1; } + void abort(); };