List:Commits« Previous MessageNext Message »
From:konstantin Date:July 22 2006 12:52pm
Subject:bk commit into 5.0 tree (kostja:1.2238) BUG#15752
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of kostja. When kostja does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2006-07-22 16:52:19+04:00, kostja@stripped +9 -0
  A fix and a test case for Bug#15752

  client/mysqlbinlog.cc@stripped, 2006-07-22 16:52:14+04:00, kostja@stripped +2 -1
    net_safe_read -> cli_safe_read

  include/mysql.h@stripped, 2006-07-22 16:52:14+04:00, kostja@stripped +0 -1
    Remove a private function from the public header.

  include/mysql_com.h@stripped, 2006-07-22 16:52:14+04:00, kostja@stripped +0 -1
    Remove a define that is never used.

  include/sql_common.h@stripped, 2006-07-22 16:52:15+04:00, kostja@stripped +1 -1
    Add a declaration for cli_safe_read - a function that reads one packet
    from the server.

  libmysql/libmysql.c@stripped, 2006-07-22 16:52:15+04:00, kostja@stripped +9 -7
    net_safe_read -> cli_safe_read
    Return CR_COMMANDS_OUT_OF_SYNC on attempt to execute a statement
    using a connection which has pending result sets.

  sql-common/client.c@stripped, 2006-07-22 16:52:15+04:00, kostja@stripped +40 -29
    Actual fix for Bug#15752: if the server has pending result sets for
    the client, return CR_COMMANDS_OUT_OF_SYNC on attempt to execute
    another query. Similarly to the behaviour of mysql_use_result(),
    multiple result sets block the connection and must be fetched
    before it can be used for another query.
    This uncovered an error in the protocol: the server doesn't drop
    SERVER_MORE_RESULTS_EXISTS status flag upon an error, so in case of
    a multi-query like SELECT 1; SELECT syntax_error; SELECT 2; 
    the client has no way to know that the server won't ever come to 
    execution of the third query and won't return any result sets for it.
    For now, fix it in cli_safe_read, as a proper fix requires extension
    of the client-server protocol.

  sql/protocol.cc@stripped, 2006-07-22 16:52:15+04:00, kostja@stripped +1 -1
    Remove a name that is never used.

  sql/slave.cc@stripped, 2006-07-22 16:52:15+04:00, kostja@stripped +1 -1
    net_safe_read -> cli_safe_read

  tests/mysql_client_test.c@stripped, 2006-07-22 16:52:15+04:00, kostja@stripped +96 -2
    Make 'query' a local variable to avoid name clash.
    Add a test case for Bug#15752 "Lost connection to MySQL server when
    calling an SP from C API"

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	kostja
# Host:	bodhi.local
# Root:	/opt/local/work/mysql-5.0-15752

--- 1.158/include/mysql.h	2006-07-22 16:52:28 +04:00
+++ 1.159/include/mysql.h	2006-07-22 16:52:28 +04:00
@@ -837,7 +837,6 @@ int		STDCALL mysql_drop_db(MYSQL *mysql,
 #define simple_command(mysql, command, arg, length, skip_check) \
   (*(mysql)->methods->advanced_command)(mysql, command,         \
 					NullS, 0, arg, length, skip_check)
-unsigned long net_safe_read(MYSQL* mysql);
 
 #ifdef __NETWARE__
 #pragma pack(pop)		/* restore alignment */

--- 1.103/include/mysql_com.h	2006-07-22 16:52:28 +04:00
+++ 1.104/include/mysql_com.h	2006-07-22 16:52:28 +04:00
@@ -140,7 +140,6 @@ enum enum_server_command
 
 #define SERVER_STATUS_IN_TRANS     1	/* Transaction has started */
 #define SERVER_STATUS_AUTOCOMMIT   2	/* Server in auto_commit mode */
-#define SERVER_STATUS_MORE_RESULTS 4	/* More results on server */
 #define SERVER_MORE_RESULTS_EXISTS 8    /* Multi query - next query exists */
 #define SERVER_QUERY_NO_GOOD_INDEX_USED 16
 #define SERVER_QUERY_NO_INDEX_USED      32

--- 1.244/libmysql/libmysql.c	2006-07-22 16:52:28 +04:00
+++ 1.245/libmysql/libmysql.c	2006-07-22 16:52:28 +04:00
@@ -645,7 +645,7 @@ int cli_read_change_user_result(MYSQL *m
   NET *net= &mysql->net;
   ulong pkt_length;
 
-  pkt_length= net_safe_read(mysql);
+  pkt_length= cli_safe_read(mysql);
   
   if (pkt_length == packet_error)
     return 1;
@@ -666,7 +666,7 @@ int cli_read_change_user_result(MYSQL *m
       return 1;
     }
     /* Read what server thinks about out new auth message report */
-    if (net_safe_read(mysql) == packet_error)
+    if (cli_safe_read(mysql) == packet_error)
       return 1;
   }
   return 0;
@@ -1887,7 +1887,7 @@ my_bool cli_read_prepare_result(MYSQL *m
   DBUG_ENTER("cli_read_prepare_result");
 
   mysql= mysql->last_used_con;
-  if ((packet_length= net_safe_read(mysql)) == packet_error)
+  if ((packet_length= cli_safe_read(mysql)) == packet_error)
     DBUG_RETURN(1);
   mysql->warning_count= 0;
 
@@ -2505,7 +2505,8 @@ int cli_stmt_execute(MYSQL_STMT *stmt)
 
   if (stmt->param_count)
   {
-    NET        *net= &stmt->mysql->net;
+    MYSQL *mysql= stmt->mysql;
+    NET        *net= &mysql->net;
     MYSQL_BIND *param, *param_end;
     char       *param_data;
     ulong length;
@@ -2517,7 +2518,8 @@ int cli_stmt_execute(MYSQL_STMT *stmt)
       set_stmt_error(stmt, CR_PARAMS_NOT_BOUND, unknown_sqlstate);
       DBUG_RETURN(1);
     }
-    if (stmt->mysql->status != MYSQL_STATUS_READY)
+    if (mysql->status != MYSQL_STATUS_READY ||
+        mysql->server_status & SERVER_MORE_RESULTS_EXISTS)
     {
       set_stmt_error(stmt, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
       DBUG_RETURN(1);
@@ -4531,7 +4533,7 @@ static int stmt_fetch_row(MYSQL_STMT *st
 
 int cli_unbuffered_fetch(MYSQL *mysql, char **row)
 {
-  if (packet_error == net_safe_read(mysql))
+  if (packet_error == cli_safe_read(mysql))
     return 1;
 
   *row= ((mysql->net.read_pos[0] == 254) ? NULL :
@@ -4640,7 +4642,7 @@ int cli_read_binary_rows(MYSQL_STMT *stm
 
   mysql= mysql->last_used_con;
 
-  while ((pkt_len= net_safe_read(mysql)) != packet_error)
+  while ((pkt_len= cli_safe_read(mysql)) != packet_error)
   {
     cp= net->read_pos;
     if (cp[0] != 254 || pkt_len >= 8)

--- 1.127/client/mysqlbinlog.cc	2006-07-22 16:52:28 +04:00
+++ 1.128/client/mysqlbinlog.cc	2006-07-22 16:52:28 +04:00
@@ -36,6 +36,7 @@
 /* That one is necessary for defines of OPTION_NO_FOREIGN_KEY_CHECKS etc */
 #include "mysql_priv.h" 
 #include "log_event.h"
+#include "sql_common.h"
 
 #define BIN_LOG_HEADER_SIZE	4
 #define PROBE_HEADER_LEN	(EVENT_LEN_OFFSET+4)
@@ -1077,7 +1078,7 @@ could be out of memory");
     const char *error_msg;
     Log_event *ev;
 
-    len = net_safe_read(mysql);
+    len= cli_safe_read(mysql);
     if (len == packet_error)
     {
       fprintf(stderr, "Got error reading packet from server: %s\n",

--- 1.113/sql/protocol.cc	2006-07-22 16:52:28 +04:00
+++ 1.114/sql/protocol.cc	2006-07-22 16:52:28 +04:00
@@ -322,7 +322,7 @@ static char eof_buff[1]= { (char) 254 };
     254			Marker (1 byte)
     warning_count	Stored in 2 bytes; New in 4.1 protocol
     status_flag		Stored in 2 bytes;
-			For flags like SERVER_STATUS_MORE_RESULTS
+			For flags like SERVER_MORE_RESULTS_EXISTS
 
     Note that the warning count will not be sent if 'no_flush' is set as
     we don't want to report the warning count until all data is sent to the

--- 1.273/sql/slave.cc	2006-07-22 16:52:28 +04:00
+++ 1.274/sql/slave.cc	2006-07-22 16:52:28 +04:00
@@ -3051,7 +3051,7 @@ static ulong read_event(MYSQL* mysql, MA
     return packet_error;      
 #endif
   
-  len = net_safe_read(mysql);
+  len = cli_safe_read(mysql);
   if (len == packet_error || (long) len < 1)
   {
     if (mysql_errno(mysql) == ER_NET_READ_INTERRUPTED)

--- 1.15/include/sql_common.h	2006-07-22 16:52:28 +04:00
+++ 1.16/include/sql_common.h	2006-07-22 16:52:28 +04:00
@@ -35,7 +35,7 @@ my_bool
 cli_advanced_command(MYSQL *mysql, enum enum_server_command command,
 		     const char *header, ulong header_length,
 		     const char *arg, ulong arg_length, my_bool skip_check);
-
+unsigned long cli_safe_read(MYSQL *mysql);
 void set_stmt_errmsg(MYSQL_STMT * stmt, const char *err, int errcode,
 		     const char *sqlstate);
 void set_mysql_error(MYSQL *mysql, int errcode, const char *sqlstate);

--- 1.93/sql-common/client.c	2006-07-22 16:52:28 +04:00
+++ 1.94/sql-common/client.c	2006-07-22 16:52:28 +04:00
@@ -584,7 +584,7 @@ err:
 *****************************************************************************/
 
 ulong
-net_safe_read(MYSQL *mysql)
+cli_safe_read(MYSQL *mysql)
 {
   NET *net= &mysql->net;
   ulong len=0;
@@ -627,6 +627,16 @@ net_safe_read(MYSQL *mysql)
     }
     else
       set_mysql_error(mysql, CR_UNKNOWN_ERROR, unknown_sqlstate);
+    /*
+      Cover a protocol design error: error packet does not
+      contain the server status. Therefore, the client has no way
+      to find out whether there are more result sets of
+      a multiple-result-set statement pending. Luckily, in 5.0 an
+      error always aborts execution of a statement, wherever it is
+      a multi-statement or a stored procedure, so it should be
+      safe to unconditionally turn off the flag here.
+    */
+    mysql->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
 
     DBUG_PRINT("error",("Got error: %d/%s (%s)",
 			net->last_errno, net->sqlstate, net->last_error));
@@ -652,7 +662,7 @@ cli_advanced_command(MYSQL *mysql, enum 
   NET *net= &mysql->net;
   my_bool result= 1;
   init_sigpipe_variables
-    DBUG_ENTER("cli_advanced_command");
+  DBUG_ENTER("cli_advanced_command");
 
   /* Don't give sigpipe errors if the client doesn't want them */
   set_sigpipe(mysql);
@@ -662,7 +672,8 @@ cli_advanced_command(MYSQL *mysql, enum 
     if (mysql_reconnect(mysql))
       DBUG_RETURN(1);
   }
-  if (mysql->status != MYSQL_STATUS_READY)
+  if (mysql->status != MYSQL_STATUS_READY ||
+      mysql->server_status & SERVER_MORE_RESULTS_EXISTS)
   {
     DBUG_PRINT("error",("state: %d", mysql->status));
     set_mysql_error(mysql, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
@@ -701,7 +712,7 @@ cli_advanced_command(MYSQL *mysql, enum 
   }
   result=0;
   if (!skip_check)
-    result= ((mysql->packet_length=net_safe_read(mysql)) == packet_error ?
+    result= ((mysql->packet_length=cli_safe_read(mysql)) == packet_error ?
 	     1 : 0);
 end:
   reset_sigpipe(mysql);
@@ -753,7 +764,7 @@ static void cli_flush_use_result(MYSQL *
   for (;;)
   {
     ulong pkt_len;
-    if ((pkt_len=net_safe_read(mysql)) == packet_error)
+    if ((pkt_len=cli_safe_read(mysql)) == packet_error)
       break;
     if (pkt_len <= 8 && mysql->net.read_pos[0] == 254)
     {
@@ -1275,7 +1286,7 @@ MYSQL_DATA *cli_read_rows(MYSQL *mysql,M
   NET *net = &mysql->net;
   DBUG_ENTER("cli_read_rows");
 
-  if ((pkt_len= net_safe_read(mysql)) == packet_error)
+  if ((pkt_len= cli_safe_read(mysql)) == packet_error)
     DBUG_RETURN(0);
   if (!(result=(MYSQL_DATA*) my_malloc(sizeof(MYSQL_DATA),
 				       MYF(MY_WME | MY_ZEROFILL))))
@@ -1340,7 +1351,7 @@ MYSQL_DATA *cli_read_rows(MYSQL *mysql,M
       }
     }
     cur->data[field]=to;			/* End of last field */
-    if ((pkt_len=net_safe_read(mysql)) == packet_error)
+    if ((pkt_len=cli_safe_read(mysql)) == packet_error)
     {
       free_rows(result);
       DBUG_RETURN(0);
@@ -1372,7 +1383,7 @@ read_one_row(MYSQL *mysql,uint fields,MY
   uchar *pos, *prev_pos, *end_pos;
   NET *net= &mysql->net;
 
-  if ((pkt_len=net_safe_read(mysql)) == packet_error)
+  if ((pkt_len=cli_safe_read(mysql)) == packet_error)
     return -1;
   if (pkt_len <= 8 && net->read_pos[0] == 254)
   {
@@ -1649,23 +1660,23 @@ static MYSQL_RES *cli_use_result(MYSQL *
 
 static MYSQL_METHODS client_methods=
 {
-  cli_read_query_result,
-  cli_advanced_command,
-  cli_read_rows,
-  cli_use_result,
-  cli_fetch_lengths,
-  cli_flush_use_result
+  cli_read_query_result,                       /* read_query_result */
+  cli_advanced_command,                        /* advanced_command */
+  cli_read_rows,                               /* read_rows */
+  cli_use_result,                              /* use_result */
+  cli_fetch_lengths,                           /* fetch_lengths */
+  cli_flush_use_result                         /* flush_use_result */
 #ifndef MYSQL_SERVER
-  ,cli_list_fields,
-  cli_read_prepare_result,
-  cli_stmt_execute,
-  cli_read_binary_rows,
-  cli_unbuffered_fetch,
-  NULL,
-  cli_read_statistics,
-  cli_read_query_result,
-  cli_read_change_user_result,
-  cli_read_binary_rows
+  ,cli_list_fields,                            /* list_fields */
+  cli_read_prepare_result,                     /* read_prepare_result */
+  cli_stmt_execute,                            /* stmt_execute */
+  cli_read_binary_rows,                        /* read_binary_rows */
+  cli_unbuffered_fetch,                        /* unbuffered_fetch */
+  NULL,                                        /* free_embedded_thd */
+  cli_read_statistics,                         /* read_statistics */
+  cli_read_query_result,                       /* next_result */
+  cli_read_change_user_result,                 /* read_change_user_result */
+  cli_read_binary_rows                         /* read_rows_from_cursor */
 #endif
 };
 
@@ -1999,7 +2010,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,cons
     Part 1: Connection established, read and parse first packet
   */
 
-  if ((pkt_length=net_safe_read(mysql)) == packet_error)
+  if ((pkt_length=cli_safe_read(mysql)) == packet_error)
     goto error;
 
   /* Check if version of protocol matches current one */
@@ -2223,7 +2234,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,cons
     OK-packet, or re-request scrambled password.
   */
 
-  if ((pkt_length=net_safe_read(mysql)) == packet_error)
+  if ((pkt_length=cli_safe_read(mysql)) == packet_error)
     goto error;
 
   if (pkt_length == 1 && net->read_pos[0] == 254 && 
@@ -2240,7 +2251,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,cons
       goto error;
     }
     /* Read what server thinks about out new auth message report */
-    if (net_safe_read(mysql) == packet_error)
+    if (cli_safe_read(mysql) == packet_error)
       goto error;
   }
 
@@ -2564,7 +2575,7 @@ static my_bool cli_read_query_result(MYS
   */
   mysql = mysql->last_used_con;
 
-  if ((length = net_safe_read(mysql)) == packet_error)
+  if ((length = cli_safe_read(mysql)) == packet_error)
     DBUG_RETURN(1);
   free_old_query(mysql);		/* Free old result */
 #ifdef MYSQL_CLIENT			/* Avoid warn of unused labels*/
@@ -2599,7 +2610,7 @@ get_info:
   if (field_count == NULL_LENGTH)		/* LOAD DATA LOCAL INFILE */
   {
     int error=handle_local_infile(mysql,(char*) pos);
-    if ((length=net_safe_read(mysql)) == packet_error || error)
+    if ((length= cli_safe_read(mysql)) == packet_error || error)
       DBUG_RETURN(1);
     goto get_info;				/* Get info packet */
   }

--- 1.189/tests/mysql_client_test.c	2006-07-22 16:52:28 +04:00
+++ 1.190/tests/mysql_client_test.c	2006-07-22 16:52:28 +04:00
@@ -50,7 +50,6 @@ static unsigned int  opt_port;
 static my_bool tty_password= 0, opt_silent= 0;
 
 static MYSQL *mysql= 0;
-static char query[MAX_TEST_QUERY_LENGTH];
 static char current_db[]= "client_test_db";
 static unsigned int test_count= 0;
 static unsigned int opt_count= 0;
@@ -269,6 +268,7 @@ mysql_simple_prepare(MYSQL  *mysql, cons
 static void client_connect(ulong flag)
 {
   int  rc;
+  static char query[MAX_TEST_QUERY_LENGTH];
   myheader_r("client_connect");
 
   if (!opt_silent)
@@ -326,6 +326,8 @@ static void client_connect(ulong flag)
 
 static void client_disconnect()
 {
+  static char query[MAX_TEST_QUERY_LENGTH];
+
   myheader_r("client_disconnect");
 
   if (mysql)
@@ -657,6 +659,7 @@ int my_stmt_result(const char *buff)
 static void verify_col_data(const char *table, const char *col,
                             const char *exp_data)
 {
+  static char query[MAX_TEST_QUERY_LENGTH];
   MYSQL_RES *result;
   MYSQL_ROW row;
   int       rc, field= 1;
@@ -1362,6 +1365,7 @@ static void test_prepare_insert_update()
   
   for (cur_query= testcase; *cur_query; cur_query++)
   {
+    char query[MAX_TEST_QUERY_LENGTH];
     printf("\nRunning query: %s", *cur_query);
     strmov(query, *cur_query);
     stmt= mysql_simple_prepare(mysql, query);
@@ -1396,6 +1400,7 @@ static void test_prepare_simple()
 {
   MYSQL_STMT *stmt;
   int        rc;
+  char query[MAX_TEST_QUERY_LENGTH];
 
   myheader("test_prepare_simple");
 
@@ -1466,6 +1471,7 @@ static void test_prepare_field_result()
   MYSQL_STMT *stmt;
   MYSQL_RES  *result;
   int        rc;
+  char query[MAX_TEST_QUERY_LENGTH];
 
   myheader("test_prepare_field_result");
 
@@ -1517,6 +1523,7 @@ static void test_prepare_syntax()
 {
   MYSQL_STMT *stmt;
   int        rc;
+  char query[MAX_TEST_QUERY_LENGTH];
 
   myheader("test_prepare_syntax");
 
@@ -1558,6 +1565,7 @@ static void test_prepare()
   my_bool    is_null[7];
   char	     llbuf[22];
   MYSQL_BIND bind[7];
+  char query[MAX_TEST_QUERY_LENGTH];
 
   myheader("test_prepare");
 
@@ -1731,6 +1739,7 @@ static void test_double_compare()
   MYSQL_RES  *result;
   MYSQL_BIND bind[3];
   ulong      length[3];
+  char query[MAX_TEST_QUERY_LENGTH];
 
   myheader("test_double_compare");
 
@@ -1813,6 +1822,7 @@ static void test_null()
   uint       nData;
   MYSQL_BIND bind[2];
   my_bool    is_null[2];
+  char query[MAX_TEST_QUERY_LENGTH];
 
   myheader("test_null");
 
@@ -1959,6 +1969,7 @@ static void test_ps_null_param()
   /* Execute several queries, all returning NULL in result. */
   for(cur_query= queries; *cur_query; cur_query++)
   {
+    char query[MAX_TEST_QUERY_LENGTH];
     strmov(query, *cur_query);
     stmt= mysql_simple_prepare(mysql, query);
     check_stmt(stmt);
@@ -1990,6 +2001,7 @@ static void test_fetch_null()
   MYSQL_BIND bind[11];
   ulong      length[11];
   my_bool    is_null[11];
+  char query[MAX_TEST_QUERY_LENGTH];
 
   myheader("test_fetch_null");
 
@@ -2218,6 +2230,7 @@ static void test_select()
   int        nData= 1;
   MYSQL_BIND bind[2];
   ulong length[2];
+  char query[MAX_TEST_QUERY_LENGTH];
 
   myheader("test_select");
 
@@ -2289,6 +2302,7 @@ static void test_ps_conj_select()
   int32      int_data;
   char       str_data[32];
   unsigned long str_length;
+  char query[MAX_TEST_QUERY_LENGTH];
   myheader("test_ps_conj_select");
 
   rc= mysql_query(mysql, "drop table if exists t1");
@@ -2346,6 +2360,7 @@ static void test_bug1115()
   MYSQL_BIND bind[1];
   ulong length[1];
   char szData[11];
+  char query[MAX_TEST_QUERY_LENGTH];
 
   myheader("test_bug1115");
 
@@ -2457,6 +2472,7 @@ static void test_bug1180()
   MYSQL_BIND bind[1];
   ulong length[1];
   char szData[11];
+  char query[MAX_TEST_QUERY_LENGTH];
 
   myheader("test_select_bug");
 
@@ -2547,6 +2563,7 @@ static void test_bug1644()
   int num;
   my_bool isnull;
   int rc, i;
+  char query[MAX_TEST_QUERY_LENGTH];
 
   myheader("test_bug1644");
 
@@ -2646,6 +2663,7 @@ static void test_select_show()
 {
   MYSQL_STMT *stmt;
   int        rc;
+  char query[MAX_TEST_QUERY_LENGTH];
 
   myheader("test_select_show");
 
@@ -2714,6 +2732,7 @@ static void test_simple_update()
   MYSQL_RES  *result;
   MYSQL_BIND bind[2];
   ulong      length[2];
+  char query[MAX_TEST_QUERY_LENGTH];
 
   myheader("test_simple_update");
 
@@ -2791,6 +2810,7 @@ static void test_long_data()
   char       *data= NullS;
   MYSQL_RES  *result;
   MYSQL_BIND bind[3];
+  char query[MAX_TEST_QUERY_LENGTH];
 
   myheader("test_long_data");
 
@@ -2877,6 +2897,7 @@ static void test_long_data_str()
   MYSQL_RES  *result;
   MYSQL_BIND bind[2];
   my_bool    is_null[2];
+  char query[MAX_TEST_QUERY_LENGTH];
 
   myheader("test_long_data_str");
 
@@ -2969,6 +2990,7 @@ static void test_long_data_str1()
   MYSQL_RES  *result;
   MYSQL_BIND bind[2];
   MYSQL_FIELD *field;
+  char query[MAX_TEST_QUERY_LENGTH];
 
   myheader("test_long_data_str1");
 
@@ -3124,6 +3146,7 @@ static void test_long_data_bin()
   long       length;
   MYSQL_RES  *result;
   MYSQL_BIND bind[2];
+  char query[MAX_TEST_QUERY_LENGTH];
 
 
   myheader("test_long_data_bin");
@@ -3203,6 +3226,7 @@ static void test_simple_delete()
   MYSQL_RES  *result;
   MYSQL_BIND bind[2];
   ulong length[2];
+  char query[MAX_TEST_QUERY_LENGTH];
 
   myheader("test_simple_delete");
 
@@ -3285,6 +3309,7 @@ static void test_update()
   MYSQL_RES  *result;
   MYSQL_BIND bind[2];
   ulong length[2];
+  char query[MAX_TEST_QUERY_LENGTH];
 
   myheader("test_update");
 
@@ -3381,6 +3406,7 @@ static void test_prepare_noparam()
   MYSQL_STMT *stmt;
   int        rc;
   MYSQL_RES  *result;
+  char query[MAX_TEST_QUERY_LENGTH];
 
   myheader("test_prepare_noparam");
 
@@ -4237,6 +4263,7 @@ static void test_prepare_ext()
   short      sData= 10;
   longlong   bData= 20;
   MYSQL_BIND bind[6];
+  char query[MAX_TEST_QUERY_LENGTH];
   myheader("test_prepare_ext");
 
   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_prepare_ext");
@@ -4624,6 +4651,7 @@ static void test_stmt_close()
   MYSQL_RES   *result;
   unsigned int  count;
   int   rc;
+  char query[MAX_TEST_QUERY_LENGTH];
 
   myheader("test_stmt_close");
 
@@ -5270,6 +5298,7 @@ static void test_manual_sample()
   ulonglong    affected_rows;
   MYSQL_BIND   bind[3];
   my_bool      is_null;
+  char query[MAX_TEST_QUERY_LENGTH];
 
   myheader("test_manual_sample");
 
@@ -5624,6 +5653,7 @@ static void test_prepare_multi_statement
 {
   MYSQL *mysql_local;
   MYSQL_STMT *stmt;
+  char query[MAX_TEST_QUERY_LENGTH];
   myheader("test_prepare_multi_statements");
 
   if (!(mysql_local= mysql_init(NULL)))
@@ -5841,6 +5871,7 @@ static void test_store_result2()
   int        nData;
   ulong      length;
   MYSQL_BIND bind[1];
+  char query[MAX_TEST_QUERY_LENGTH];
 
   myheader("test_store_result2");
 
@@ -7120,6 +7151,7 @@ static void test_set_option()
 static void test_prepare_grant()
 {
   int rc;
+  char query[MAX_TEST_QUERY_LENGTH];
 
   myheader("test_prepare_grant");
 
@@ -8592,6 +8624,7 @@ static void test_sqlmode()
   MYSQL_BIND bind[2];
   char       c1[5], c2[5];
   int        rc;
+  char query[MAX_TEST_QUERY_LENGTH];
 
   myheader("test_sqlmode");
 
@@ -8735,6 +8768,7 @@ static void test_ts()
   ulong      length;
   int        rc, field_count;
   char       name;
+  char query[MAX_TEST_QUERY_LENGTH];
 
   myheader("test_ts");
 
@@ -15019,6 +15053,65 @@ static void test_bug20152()
   }
 }
 
+/* Bug#15752 "Lost connection to MySQL server when calling a SP from C API" */
+
+static void test_bug15752()
+{
+  MYSQL mysql_local;
+  int rc, i;
+  const int ITERATION_COUNT= 100;
+  char *query= "CALL p1()";
+
+  myheader("test_bug15752");
+
+  rc= mysql_query(mysql, "drop procedure if exists p1");
+  myquery(rc);
+  rc= mysql_query(mysql, "create procedure p1() select 1");
+  myquery(rc);
+
+  mysql_init(&mysql_local);
+  if (! mysql_real_connect(&mysql_local, opt_host, opt_user,
+                           opt_password, current_db, opt_port,
+                           opt_unix_socket,
+                           CLIENT_MULTI_STATEMENTS|CLIENT_MULTI_RESULTS))
+  {
+    printf("Unable connect to MySQL server: %s\n", mysql_error(&mysql_local));
+    DIE_UNLESS(0);
+  }
+  rc= mysql_real_query(&mysql_local, query, strlen(query));
+  myquery(rc);
+  mysql_free_result(mysql_store_result(&mysql_local));
+
+  rc= mysql_real_query(&mysql_local, query, strlen(query));
+  DIE_UNLESS(rc && mysql_errno(&mysql_local) == CR_COMMANDS_OUT_OF_SYNC);
+
+  if (! opt_silent)
+    printf("Got error (as expected): %s\n", mysql_error(&mysql_local));
+
+  /* Check some other commands too */
+
+  DIE_UNLESS(mysql_next_result(&mysql_local) == 0);
+  mysql_free_result(mysql_store_result(&mysql_local));
+  DIE_UNLESS(mysql_next_result(&mysql_local) == -1);
+
+  /* The second problem is not reproducible: add the test case */
+  for (i = 0; i < ITERATION_COUNT; i++)
+  {
+    if (mysql_real_query(&mysql_local, query, strlen(query)))
+    {
+      printf("\ni=%d %s failed: %s\n", i, query, mysql_error(&mysql_local));
+      break;
+    }
+    mysql_free_result(mysql_store_result(&mysql_local));
+    DIE_UNLESS(mysql_next_result(&mysql_local) == 0);
+    mysql_free_result(mysql_store_result(&mysql_local));
+    DIE_UNLESS(mysql_next_result(&mysql_local) == -1);
+
+  }
+  mysql_close(&mysql_local);
+  rc= mysql_query(mysql, "drop procedure p1");
+  myquery(rc);
+}
 
 /*
   Read and parse arguments and MySQL options from my.cnf
@@ -15287,7 +15380,8 @@ static struct my_tests_st my_tests[]= {
   { "test_bug20152", test_bug20152 },
   { "test_bug14169", test_bug14169 },
   { "test_bug17667", test_bug17667 },
-  { "test_bug19671", test_bug19671},
+  { "test_bug19671", test_bug19671 },
+  { "test_bug15752", test_bug15752 },
   { 0, 0 }
 };
 
Thread
bk commit into 5.0 tree (kostja:1.2238) BUG#15752konstantin22 Jul