From d8bf426b807ae612c6d062df834b039e1e48ca11 Mon Sep 17 00:00:00 2001
From: "pem@mysql.comhem.se" <>
Date: Thu, 27 Nov 2003 16:48:21 +0100
Subject: [PATCH] Fixed BUG#1965: Opening a cursor hangs client when malformed
 select fails   and BUG#1966: "select 1 into a" on top-level hangs client

---
 include/mysql_com.h          |  3 ++-
 mysql-test/r/sp-error.result | 11 +++++++++++
 mysql-test/t/sp-error.test   | 21 +++++++++++++++++++++
 sql/net_serv.cc              |  1 +
 sql/protocol.cc              |  2 +-
 sql/sp_rcontext.cc           |  6 +++---
 sql/sp_rcontext.h            |  2 +-
 sql/sql_yacc.yy              |  7 +++----
 8 files changed, 43 insertions(+), 10 deletions(-)

diff --git a/include/mysql_com.h b/include/mysql_com.h
index cc773160b3..28a649876d 100644
--- a/include/mysql_com.h
+++ b/include/mysql_com.h
@@ -157,7 +157,8 @@ typedef struct st_net {
   unsigned int *return_status;
   unsigned char reading_or_writing;
   char save_char;
-  my_bool no_send_ok;
+  my_bool no_send_ok;  /* For SPs and other things that do multiple stmts */
+  my_bool no_send_eof; /* For SPs' first version read-only cursors */
   /*
     Pointer to query object in query cache, do not equal NULL (0) for
     queries in cache that have not stored its results yet
diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result
index a2f7d5def2..5f75559245 100644
--- a/mysql-test/r/sp-error.result
+++ b/mysql-test/r/sp-error.result
@@ -259,4 +259,15 @@ declare c cursor for select * from t1;
 declare c cursor for select field from t1;
 end;
 ERROR 42000: Duplicate cursor: c
+create procedure bug1965()
+begin
+declare c cursor for select val from t1 order by valname;
+open c;
+close c;
+end;
+call bug1965();
+ERROR 42S22: Unknown column 'valname' in 'order clause'
+drop procedure bug1965;
+select 1 into a;
+ERROR 42000: Undeclared variable: a
 drop table t1;
diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test
index 211c4a63b8..132a6b086c 100644
--- a/mysql-test/t/sp-error.test
+++ b/mysql-test/t/sp-error.test
@@ -341,6 +341,27 @@ begin
   declare c cursor for select field from t1;
 end|
 
+#
+# BUG#1965
+#
+create procedure bug1965()
+begin
+  declare c cursor for select val from t1 order by valname;
+  open c;
+  close c;
+end|
+
+--error 1054
+call bug1965()|
+drop procedure bug1965|
+
+#
+# BUG#1966
+#
+--error 1308
+select 1 into a|
+
+
 drop table t1|
 
 delimiter ;|
diff --git a/sql/net_serv.cc b/sql/net_serv.cc
index 7944a528b8..0120ad80c0 100644
--- a/sql/net_serv.cc
+++ b/sql/net_serv.cc
@@ -123,6 +123,7 @@ my_bool my_net_init(NET *net, Vio* vio)
   net->buff_end=net->buff+net->max_packet;
   net->vio = vio;
   net->no_send_ok = 0;
+  net->no_send_eof = 0;
   net->error=0; net->return_errno=0; net->return_status=0;
   net->pkt_nr=net->compress_pkt_nr=0;
   net->write_pos=net->read_pos = net->buff;
diff --git a/sql/protocol.cc b/sql/protocol.cc
index 1b2e4bc020..c28c1e1abb 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -347,7 +347,7 @@ send_eof(THD *thd, bool no_flush)
   static char eof_buff[1]= { (char) 254 };	/* Marker for end of fields */
   NET *net= &thd->net;
   DBUG_ENTER("send_eof");
-  if (net->vio != 0)
+  if (net->vio != 0 && !net->no_send_eof)
   {
     if (!no_flush && (thd->client_capabilities & CLIENT_PROTOCOL_41))
     {
diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc
index 07fd08b007..a25cd9ee63 100644
--- a/sql/sp_rcontext.cc
+++ b/sql/sp_rcontext.cc
@@ -149,15 +149,15 @@ sp_cursor::pre_open(THD *thd)
   m_oprot= thd->protocol;	// Save the original protocol
   thd->protocol= m_prot;
 
-  m_ovio= thd->net.vio;		// Prevent send_eof()
-  thd->net.vio= 0;
+  m_nseof= thd->net.no_send_eof;
+  thd->net.no_send_eof= TRUE;
   return m_lex;
 }
 
 void
 sp_cursor::post_open(THD *thd, my_bool isopen)
 {
-  thd->net.vio= m_ovio;		// Restore the originals
+  thd->net.no_send_eof= m_nseof; // Restore the originals
   thd->protocol= m_oprot;
   m_isopen= isopen;
   m_current_row= m_prot->data;
diff --git a/sql/sp_rcontext.h b/sql/sp_rcontext.h
index e69ac9bf4b..6526ed5857 100644
--- a/sql/sp_rcontext.h
+++ b/sql/sp_rcontext.h
@@ -240,7 +240,7 @@ private:
   LEX *m_lex;
   Protocol_cursor *m_prot;
   my_bool m_isopen;
-  Vio *m_ovio;			// Original vio
+  my_bool m_nseof;		// Original no_send_eof
   Protocol *m_oprot;		// Original protcol
   MYSQL_ROWS *m_current_row;
   
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 2d25301fc0..1b06b7f34f 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -4555,12 +4555,11 @@ select_var_ident:
            | ident_or_text
            {
              LEX *lex=Lex;
-	     if (!lex->spcont)
-	       YYABORT;
 	     sp_pvar_t *t;
-	     if (!(t=lex->spcont->find_pvar(&$1)))
+
+	     if (!lex->spcont || !(t=lex->spcont->find_pvar(&$1)))
 	     {
-	       send_error(lex->thd, ER_SP_UNDECLARED_VAR);
+	       net_printf(YYTHD, ER_SP_UNDECLARED_VAR, $1.str);
 	       YYABORT;
 	     }
 	     if (! lex->result)
-- 
2.30.9