From 4a90f7d04f4717f1d88e38849b4d4183e135394d Mon Sep 17 00:00:00 2001 From: "sergefp@mysql.com" <> Date: Mon, 4 Jul 2005 23:00:23 +0000 Subject: [PATCH 1/2] Fix for BUG#9814: Clear thd->net.no_send_error before each SP instruction execution. Failure to do so caused the erroneous statements to send nothing and hang the client. --- mysql-test/r/sp-error.result | 30 ++++++++++++++++++++++++++++ mysql-test/t/sp-error.test | 38 ++++++++++++++++++++++++++++++++++++ sql/sp_head.cc | 6 ++++++ 3 files changed, 74 insertions(+) diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index bfbfb87ac43..171978fdb06 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -1,3 +1,4 @@ +drop table if exists t1, t2; delete from mysql.proc; create procedure syntaxerror(t int)| ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1 @@ -635,3 +636,32 @@ ERROR 0A000: EXECUTE is not allowed in stored procedures create function f() returns int begin execute stmt; ERROR 0A000: EXECUTE is not allowed in stored procedures deallocate prepare stmt; +create table t1(f1 int); +create table t2(f1 int); +CREATE PROCEDURE SP001() +P1: BEGIN +DECLARE ENDTABLE INT DEFAULT 0; +DECLARE TEMP_NUM INT; +DECLARE TEMP_SUM INT; +DECLARE C1 CURSOR FOR SELECT F1 FROM t1; +DECLARE C2 CURSOR FOR SELECT F1 FROM t2; +DECLARE CONTINUE HANDLER FOR NOT FOUND SET ENDTABLE = 1; +SET ENDTABLE=0; +SET TEMP_SUM=0; +SET TEMP_NUM=0; +OPEN C1; +FETCH C1 INTO TEMP_NUM; +WHILE ENDTABLE = 0 DO +SET TEMP_SUM=TEMP_NUM+TEMP_SUM; +FETCH C1 INTO TEMP_NUM; +END WHILE; +SELECT TEMP_SUM; +CLOSE C1; +CLOSE C1; +SELECT 'end of proc'; +END P1| +call SP001(); +TEMP_SUM +0 +drop procedure SP001; +drop table t1, t2; diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index f5a9e53e710..e8243dfd343 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -2,6 +2,10 @@ # Stored PROCEDURE error tests # +--disable_warnings +drop table if exists t1, t2; +--enable_warnings + # Make sure we don't have any procedures left. delete from mysql.proc; @@ -933,3 +937,37 @@ create procedure p() execute stmt; create function f() returns int begin execute stmt; deallocate prepare stmt; +# BUG#9814: Closing a cursor that is not open +create table t1(f1 int); +create table t2(f1 int); + +delimiter |; +CREATE PROCEDURE SP001() +P1: BEGIN + DECLARE ENDTABLE INT DEFAULT 0; + DECLARE TEMP_NUM INT; + DECLARE TEMP_SUM INT; + DECLARE C1 CURSOR FOR SELECT F1 FROM t1; + DECLARE C2 CURSOR FOR SELECT F1 FROM t2; + DECLARE CONTINUE HANDLER FOR NOT FOUND SET ENDTABLE = 1; + + SET ENDTABLE=0; + SET TEMP_SUM=0; + SET TEMP_NUM=0; + + OPEN C1; + + FETCH C1 INTO TEMP_NUM; + WHILE ENDTABLE = 0 DO + SET TEMP_SUM=TEMP_NUM+TEMP_SUM; + FETCH C1 INTO TEMP_NUM; + END WHILE; + SELECT TEMP_SUM; + CLOSE C1; + CLOSE C1; + SELECT 'end of proc'; +END P1| +delimiter ;| +call SP001(); +drop procedure SP001; +drop table t1, t2; diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 6be80568186..9bbcaffa5dd 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -642,6 +642,12 @@ sp_head::execute(THD *thd) items made during other permanent subquery transformations). */ thd->current_arena= i; + /* + no_send_error may have been set by the previous SP instruction when it + sent eof. Allow the current SP instruction to produce an error. + (multi-statement execution code clears no_send_error, too) + */ + thd->net.no_send_error= 0; ret= i->execute(thd, &ip); if (i->free_list) cleanup_items(i->free_list); From 3d5d366c7252166e876950a97790ec260eb47235 Mon Sep 17 00:00:00 2001 From: "sergefp@mysql.com" <> Date: Mon, 4 Jul 2005 23:40:01 +0000 Subject: [PATCH 2/2] BUG#9814: post-review fixes: clear thd->net.no_send error after SP instruction execution, not before. --- sql/sp_head.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 9bbcaffa5dd..904909a53fa 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -642,13 +642,13 @@ sp_head::execute(THD *thd) items made during other permanent subquery transformations). */ thd->current_arena= i; + ret= i->execute(thd, &ip); /* - no_send_error may have been set by the previous SP instruction when it - sent eof. Allow the current SP instruction to produce an error. - (multi-statement execution code clears no_send_error, too) + If this SP instruction have sent eof, it has caused no_send_error to be + set. Clear it back to allow the next instruction to send error. (multi- + statement execution code clears no_send_error between statements too) */ thd->net.no_send_error= 0; - ret= i->execute(thd, &ip); if (i->free_list) cleanup_items(i->free_list); i->state= Query_arena::EXECUTED;