Commit 36510232 authored by unknown's avatar unknown

A fix and a test case for Bug#15752 "Lost connection to MySQL server

when calling a SP from C API"

The bug was caused by lack of checks for misuse in mysql_real_query. 
A stored procedure always returns at least one result, which is the 
status of execution of the procedure itself.
This result, or so-called OK packet, is similar to a result
returned by INSERT/UPDATE/CREATE operations: it contains the overall
status of execution, the number of affected rows and the number of
warnings. The client test program attached to the bug did not read this 
result and ivnoked the next query. In turn, libmysql had no check for 
such scenario and mysql_real_query was simply trying to send that query 
without reading the pending response, thus messing up the communication
protocol.

The fix is to return an error from mysql_real_query when it's called
prior to retrieval of all pending results.


client/mysqlbinlog.cc:
  net_safe_read -> cli_safe_read
include/mysql.h:
  Remove a private function from the public header.
include/mysql_com.h:
  Remove a define that is never used.
include/sql_common.h:
  Add a declaration for cli_safe_read - a function that reads one packet
  from the server.
libmysql/libmysql.c:
  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:
  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:
  Remove a name that is never used.
sql/slave.cc:
  net_safe_read -> cli_safe_read
tests/mysql_client_test.c:
  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"
parent 12d6b9c7
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
/* That one is necessary for defines of OPTION_NO_FOREIGN_KEY_CHECKS etc */ /* That one is necessary for defines of OPTION_NO_FOREIGN_KEY_CHECKS etc */
#include "mysql_priv.h" #include "mysql_priv.h"
#include "log_event.h" #include "log_event.h"
#include "sql_common.h"
#define BIN_LOG_HEADER_SIZE 4 #define BIN_LOG_HEADER_SIZE 4
#define PROBE_HEADER_LEN (EVENT_LEN_OFFSET+4) #define PROBE_HEADER_LEN (EVENT_LEN_OFFSET+4)
...@@ -1077,7 +1078,7 @@ could be out of memory"); ...@@ -1077,7 +1078,7 @@ could be out of memory");
const char *error_msg; const char *error_msg;
Log_event *ev; Log_event *ev;
len = net_safe_read(mysql); len= cli_safe_read(mysql);
if (len == packet_error) if (len == packet_error)
{ {
fprintf(stderr, "Got error reading packet from server: %s\n", fprintf(stderr, "Got error reading packet from server: %s\n",
......
...@@ -837,7 +837,6 @@ int STDCALL mysql_drop_db(MYSQL *mysql, const char *DB); ...@@ -837,7 +837,6 @@ int STDCALL mysql_drop_db(MYSQL *mysql, const char *DB);
#define simple_command(mysql, command, arg, length, skip_check) \ #define simple_command(mysql, command, arg, length, skip_check) \
(*(mysql)->methods->advanced_command)(mysql, command, \ (*(mysql)->methods->advanced_command)(mysql, command, \
NullS, 0, arg, length, skip_check) NullS, 0, arg, length, skip_check)
unsigned long net_safe_read(MYSQL* mysql);
#ifdef __NETWARE__ #ifdef __NETWARE__
#pragma pack(pop) /* restore alignment */ #pragma pack(pop) /* restore alignment */
......
...@@ -140,7 +140,6 @@ enum enum_server_command ...@@ -140,7 +140,6 @@ enum enum_server_command
#define SERVER_STATUS_IN_TRANS 1 /* Transaction has started */ #define SERVER_STATUS_IN_TRANS 1 /* Transaction has started */
#define SERVER_STATUS_AUTOCOMMIT 2 /* Server in auto_commit mode */ #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_MORE_RESULTS_EXISTS 8 /* Multi query - next query exists */
#define SERVER_QUERY_NO_GOOD_INDEX_USED 16 #define SERVER_QUERY_NO_GOOD_INDEX_USED 16
#define SERVER_QUERY_NO_INDEX_USED 32 #define SERVER_QUERY_NO_INDEX_USED 32
......
...@@ -35,7 +35,7 @@ my_bool ...@@ -35,7 +35,7 @@ my_bool
cli_advanced_command(MYSQL *mysql, enum enum_server_command command, cli_advanced_command(MYSQL *mysql, enum enum_server_command command,
const char *header, ulong header_length, const char *header, ulong header_length,
const char *arg, ulong arg_length, my_bool skip_check); 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, void set_stmt_errmsg(MYSQL_STMT * stmt, const char *err, int errcode,
const char *sqlstate); const char *sqlstate);
void set_mysql_error(MYSQL *mysql, int errcode, const char *sqlstate); void set_mysql_error(MYSQL *mysql, int errcode, const char *sqlstate);
......
...@@ -645,7 +645,7 @@ int cli_read_change_user_result(MYSQL *mysql, char *buff, const char *passwd) ...@@ -645,7 +645,7 @@ int cli_read_change_user_result(MYSQL *mysql, char *buff, const char *passwd)
NET *net= &mysql->net; NET *net= &mysql->net;
ulong pkt_length; ulong pkt_length;
pkt_length= net_safe_read(mysql); pkt_length= cli_safe_read(mysql);
if (pkt_length == packet_error) if (pkt_length == packet_error)
return 1; return 1;
...@@ -666,7 +666,7 @@ int cli_read_change_user_result(MYSQL *mysql, char *buff, const char *passwd) ...@@ -666,7 +666,7 @@ int cli_read_change_user_result(MYSQL *mysql, char *buff, const char *passwd)
return 1; return 1;
} }
/* Read what server thinks about out new auth message report */ /* 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 1;
} }
return 0; return 0;
...@@ -1887,7 +1887,7 @@ my_bool cli_read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt) ...@@ -1887,7 +1887,7 @@ my_bool cli_read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt)
DBUG_ENTER("cli_read_prepare_result"); DBUG_ENTER("cli_read_prepare_result");
mysql= mysql->last_used_con; 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); DBUG_RETURN(1);
mysql->warning_count= 0; mysql->warning_count= 0;
...@@ -2505,7 +2505,8 @@ int cli_stmt_execute(MYSQL_STMT *stmt) ...@@ -2505,7 +2505,8 @@ int cli_stmt_execute(MYSQL_STMT *stmt)
if (stmt->param_count) if (stmt->param_count)
{ {
NET *net= &stmt->mysql->net; MYSQL *mysql= stmt->mysql;
NET *net= &mysql->net;
MYSQL_BIND *param, *param_end; MYSQL_BIND *param, *param_end;
char *param_data; char *param_data;
ulong length; ulong length;
...@@ -2517,7 +2518,8 @@ int cli_stmt_execute(MYSQL_STMT *stmt) ...@@ -2517,7 +2518,8 @@ int cli_stmt_execute(MYSQL_STMT *stmt)
set_stmt_error(stmt, CR_PARAMS_NOT_BOUND, unknown_sqlstate); set_stmt_error(stmt, CR_PARAMS_NOT_BOUND, unknown_sqlstate);
DBUG_RETURN(1); 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); set_stmt_error(stmt, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
DBUG_RETURN(1); DBUG_RETURN(1);
...@@ -4531,7 +4533,7 @@ static int stmt_fetch_row(MYSQL_STMT *stmt, uchar *row) ...@@ -4531,7 +4533,7 @@ static int stmt_fetch_row(MYSQL_STMT *stmt, uchar *row)
int cli_unbuffered_fetch(MYSQL *mysql, char **row) int cli_unbuffered_fetch(MYSQL *mysql, char **row)
{ {
if (packet_error == net_safe_read(mysql)) if (packet_error == cli_safe_read(mysql))
return 1; return 1;
*row= ((mysql->net.read_pos[0] == 254) ? NULL : *row= ((mysql->net.read_pos[0] == 254) ? NULL :
...@@ -4640,7 +4642,7 @@ int cli_read_binary_rows(MYSQL_STMT *stmt) ...@@ -4640,7 +4642,7 @@ int cli_read_binary_rows(MYSQL_STMT *stmt)
mysql= mysql->last_used_con; 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; cp= net->read_pos;
if (cp[0] != 254 || pkt_len >= 8) if (cp[0] != 254 || pkt_len >= 8)
......
...@@ -584,7 +584,7 @@ HANDLE create_shared_memory(MYSQL *mysql,NET *net, uint connect_timeout) ...@@ -584,7 +584,7 @@ HANDLE create_shared_memory(MYSQL *mysql,NET *net, uint connect_timeout)
*****************************************************************************/ *****************************************************************************/
ulong ulong
net_safe_read(MYSQL *mysql) cli_safe_read(MYSQL *mysql)
{ {
NET *net= &mysql->net; NET *net= &mysql->net;
ulong len=0; ulong len=0;
...@@ -627,6 +627,16 @@ net_safe_read(MYSQL *mysql) ...@@ -627,6 +627,16 @@ net_safe_read(MYSQL *mysql)
} }
else else
set_mysql_error(mysql, CR_UNKNOWN_ERROR, unknown_sqlstate); 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)", DBUG_PRINT("error",("Got error: %d/%s (%s)",
net->last_errno, net->sqlstate, net->last_error)); net->last_errno, net->sqlstate, net->last_error));
...@@ -652,7 +662,7 @@ cli_advanced_command(MYSQL *mysql, enum enum_server_command command, ...@@ -652,7 +662,7 @@ cli_advanced_command(MYSQL *mysql, enum enum_server_command command,
NET *net= &mysql->net; NET *net= &mysql->net;
my_bool result= 1; my_bool result= 1;
init_sigpipe_variables 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 */ /* Don't give sigpipe errors if the client doesn't want them */
set_sigpipe(mysql); set_sigpipe(mysql);
...@@ -662,7 +672,8 @@ cli_advanced_command(MYSQL *mysql, enum enum_server_command command, ...@@ -662,7 +672,8 @@ cli_advanced_command(MYSQL *mysql, enum enum_server_command command,
if (mysql_reconnect(mysql)) if (mysql_reconnect(mysql))
DBUG_RETURN(1); 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)); DBUG_PRINT("error",("state: %d", mysql->status));
set_mysql_error(mysql, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate); set_mysql_error(mysql, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
...@@ -701,7 +712,7 @@ cli_advanced_command(MYSQL *mysql, enum enum_server_command command, ...@@ -701,7 +712,7 @@ cli_advanced_command(MYSQL *mysql, enum enum_server_command command,
} }
result=0; result=0;
if (!skip_check) 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); 1 : 0);
end: end:
reset_sigpipe(mysql); reset_sigpipe(mysql);
...@@ -753,7 +764,7 @@ static void cli_flush_use_result(MYSQL *mysql) ...@@ -753,7 +764,7 @@ static void cli_flush_use_result(MYSQL *mysql)
for (;;) for (;;)
{ {
ulong pkt_len; ulong pkt_len;
if ((pkt_len=net_safe_read(mysql)) == packet_error) if ((pkt_len=cli_safe_read(mysql)) == packet_error)
break; break;
if (pkt_len <= 8 && mysql->net.read_pos[0] == 254) if (pkt_len <= 8 && mysql->net.read_pos[0] == 254)
{ {
...@@ -1275,7 +1286,7 @@ MYSQL_DATA *cli_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, ...@@ -1275,7 +1286,7 @@ MYSQL_DATA *cli_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
NET *net = &mysql->net; NET *net = &mysql->net;
DBUG_ENTER("cli_read_rows"); 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); DBUG_RETURN(0);
if (!(result=(MYSQL_DATA*) my_malloc(sizeof(MYSQL_DATA), if (!(result=(MYSQL_DATA*) my_malloc(sizeof(MYSQL_DATA),
MYF(MY_WME | MY_ZEROFILL)))) MYF(MY_WME | MY_ZEROFILL))))
...@@ -1340,7 +1351,7 @@ MYSQL_DATA *cli_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, ...@@ -1340,7 +1351,7 @@ MYSQL_DATA *cli_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
} }
} }
cur->data[field]=to; /* End of last field */ 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); free_rows(result);
DBUG_RETURN(0); DBUG_RETURN(0);
...@@ -1372,7 +1383,7 @@ read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, ulong *lengths) ...@@ -1372,7 +1383,7 @@ read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, ulong *lengths)
uchar *pos, *prev_pos, *end_pos; uchar *pos, *prev_pos, *end_pos;
NET *net= &mysql->net; NET *net= &mysql->net;
if ((pkt_len=net_safe_read(mysql)) == packet_error) if ((pkt_len=cli_safe_read(mysql)) == packet_error)
return -1; return -1;
if (pkt_len <= 8 && net->read_pos[0] == 254) if (pkt_len <= 8 && net->read_pos[0] == 254)
{ {
...@@ -1649,23 +1660,23 @@ static MYSQL_RES *cli_use_result(MYSQL *mysql); ...@@ -1649,23 +1660,23 @@ static MYSQL_RES *cli_use_result(MYSQL *mysql);
static MYSQL_METHODS client_methods= static MYSQL_METHODS client_methods=
{ {
cli_read_query_result, cli_read_query_result, /* read_query_result */
cli_advanced_command, cli_advanced_command, /* advanced_command */
cli_read_rows, cli_read_rows, /* read_rows */
cli_use_result, cli_use_result, /* use_result */
cli_fetch_lengths, cli_fetch_lengths, /* fetch_lengths */
cli_flush_use_result cli_flush_use_result /* flush_use_result */
#ifndef MYSQL_SERVER #ifndef MYSQL_SERVER
,cli_list_fields, ,cli_list_fields, /* list_fields */
cli_read_prepare_result, cli_read_prepare_result, /* read_prepare_result */
cli_stmt_execute, cli_stmt_execute, /* stmt_execute */
cli_read_binary_rows, cli_read_binary_rows, /* read_binary_rows */
cli_unbuffered_fetch, cli_unbuffered_fetch, /* unbuffered_fetch */
NULL, NULL, /* free_embedded_thd */
cli_read_statistics, cli_read_statistics, /* read_statistics */
cli_read_query_result, cli_read_query_result, /* next_result */
cli_read_change_user_result, cli_read_change_user_result, /* read_change_user_result */
cli_read_binary_rows cli_read_binary_rows /* read_rows_from_cursor */
#endif #endif
}; };
...@@ -1999,7 +2010,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, ...@@ -1999,7 +2010,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
Part 1: Connection established, read and parse first packet 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; goto error;
/* Check if version of protocol matches current one */ /* Check if version of protocol matches current one */
...@@ -2223,7 +2234,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, ...@@ -2223,7 +2234,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
OK-packet, or re-request scrambled password. 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; goto error;
if (pkt_length == 1 && net->read_pos[0] == 254 && if (pkt_length == 1 && net->read_pos[0] == 254 &&
...@@ -2240,7 +2251,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, ...@@ -2240,7 +2251,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
goto error; goto error;
} }
/* Read what server thinks about out new auth message report */ /* 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; goto error;
} }
...@@ -2564,7 +2575,7 @@ static my_bool cli_read_query_result(MYSQL *mysql) ...@@ -2564,7 +2575,7 @@ static my_bool cli_read_query_result(MYSQL *mysql)
*/ */
mysql = mysql->last_used_con; mysql = mysql->last_used_con;
if ((length = net_safe_read(mysql)) == packet_error) if ((length = cli_safe_read(mysql)) == packet_error)
DBUG_RETURN(1); DBUG_RETURN(1);
free_old_query(mysql); /* Free old result */ free_old_query(mysql); /* Free old result */
#ifdef MYSQL_CLIENT /* Avoid warn of unused labels*/ #ifdef MYSQL_CLIENT /* Avoid warn of unused labels*/
...@@ -2599,7 +2610,7 @@ static my_bool cli_read_query_result(MYSQL *mysql) ...@@ -2599,7 +2610,7 @@ static my_bool cli_read_query_result(MYSQL *mysql)
if (field_count == NULL_LENGTH) /* LOAD DATA LOCAL INFILE */ if (field_count == NULL_LENGTH) /* LOAD DATA LOCAL INFILE */
{ {
int error=handle_local_infile(mysql,(char*) pos); 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); DBUG_RETURN(1);
goto get_info; /* Get info packet */ goto get_info; /* Get info packet */
} }
......
...@@ -322,7 +322,7 @@ static char eof_buff[1]= { (char) 254 }; /* Marker for end of fields */ ...@@ -322,7 +322,7 @@ static char eof_buff[1]= { (char) 254 }; /* Marker for end of fields */
254 Marker (1 byte) 254 Marker (1 byte)
warning_count Stored in 2 bytes; New in 4.1 protocol warning_count Stored in 2 bytes; New in 4.1 protocol
status_flag Stored in 2 bytes; 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 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 we don't want to report the warning count until all data is sent to the
......
...@@ -3051,7 +3051,7 @@ static ulong read_event(MYSQL* mysql, MASTER_INFO *mi, bool* suppress_warnings) ...@@ -3051,7 +3051,7 @@ static ulong read_event(MYSQL* mysql, MASTER_INFO *mi, bool* suppress_warnings)
return packet_error; return packet_error;
#endif #endif
len = net_safe_read(mysql); len = cli_safe_read(mysql);
if (len == packet_error || (long) len < 1) if (len == packet_error || (long) len < 1)
{ {
if (mysql_errno(mysql) == ER_NET_READ_INTERRUPTED) if (mysql_errno(mysql) == ER_NET_READ_INTERRUPTED)
......
...@@ -50,7 +50,6 @@ static unsigned int opt_port; ...@@ -50,7 +50,6 @@ static unsigned int opt_port;
static my_bool tty_password= 0, opt_silent= 0; static my_bool tty_password= 0, opt_silent= 0;
static MYSQL *mysql= 0; static MYSQL *mysql= 0;
static char query[MAX_TEST_QUERY_LENGTH];
static char current_db[]= "client_test_db"; static char current_db[]= "client_test_db";
static unsigned int test_count= 0; static unsigned int test_count= 0;
static unsigned int opt_count= 0; static unsigned int opt_count= 0;
...@@ -269,6 +268,7 @@ mysql_simple_prepare(MYSQL *mysql, const char *query) ...@@ -269,6 +268,7 @@ mysql_simple_prepare(MYSQL *mysql, const char *query)
static void client_connect(ulong flag) static void client_connect(ulong flag)
{ {
int rc; int rc;
static char query[MAX_TEST_QUERY_LENGTH];
myheader_r("client_connect"); myheader_r("client_connect");
if (!opt_silent) if (!opt_silent)
...@@ -326,6 +326,8 @@ static void client_connect(ulong flag) ...@@ -326,6 +326,8 @@ static void client_connect(ulong flag)
static void client_disconnect() static void client_disconnect()
{ {
static char query[MAX_TEST_QUERY_LENGTH];
myheader_r("client_disconnect"); myheader_r("client_disconnect");
if (mysql) if (mysql)
...@@ -657,6 +659,7 @@ int my_stmt_result(const char *buff) ...@@ -657,6 +659,7 @@ int my_stmt_result(const char *buff)
static void verify_col_data(const char *table, const char *col, static void verify_col_data(const char *table, const char *col,
const char *exp_data) const char *exp_data)
{ {
static char query[MAX_TEST_QUERY_LENGTH];
MYSQL_RES *result; MYSQL_RES *result;
MYSQL_ROW row; MYSQL_ROW row;
int rc, field= 1; int rc, field= 1;
...@@ -1362,6 +1365,7 @@ static void test_prepare_insert_update() ...@@ -1362,6 +1365,7 @@ static void test_prepare_insert_update()
for (cur_query= testcase; *cur_query; cur_query++) for (cur_query= testcase; *cur_query; cur_query++)
{ {
char query[MAX_TEST_QUERY_LENGTH];
printf("\nRunning query: %s", *cur_query); printf("\nRunning query: %s", *cur_query);
strmov(query, *cur_query); strmov(query, *cur_query);
stmt= mysql_simple_prepare(mysql, query); stmt= mysql_simple_prepare(mysql, query);
...@@ -1396,6 +1400,7 @@ static void test_prepare_simple() ...@@ -1396,6 +1400,7 @@ static void test_prepare_simple()
{ {
MYSQL_STMT *stmt; MYSQL_STMT *stmt;
int rc; int rc;
char query[MAX_TEST_QUERY_LENGTH];
myheader("test_prepare_simple"); myheader("test_prepare_simple");
...@@ -1466,6 +1471,7 @@ static void test_prepare_field_result() ...@@ -1466,6 +1471,7 @@ static void test_prepare_field_result()
MYSQL_STMT *stmt; MYSQL_STMT *stmt;
MYSQL_RES *result; MYSQL_RES *result;
int rc; int rc;
char query[MAX_TEST_QUERY_LENGTH];
myheader("test_prepare_field_result"); myheader("test_prepare_field_result");
...@@ -1517,6 +1523,7 @@ static void test_prepare_syntax() ...@@ -1517,6 +1523,7 @@ static void test_prepare_syntax()
{ {
MYSQL_STMT *stmt; MYSQL_STMT *stmt;
int rc; int rc;
char query[MAX_TEST_QUERY_LENGTH];
myheader("test_prepare_syntax"); myheader("test_prepare_syntax");
...@@ -1558,6 +1565,7 @@ static void test_prepare() ...@@ -1558,6 +1565,7 @@ static void test_prepare()
my_bool is_null[7]; my_bool is_null[7];
char llbuf[22]; char llbuf[22];
MYSQL_BIND bind[7]; MYSQL_BIND bind[7];
char query[MAX_TEST_QUERY_LENGTH];
myheader("test_prepare"); myheader("test_prepare");
...@@ -1731,6 +1739,7 @@ static void test_double_compare() ...@@ -1731,6 +1739,7 @@ static void test_double_compare()
MYSQL_RES *result; MYSQL_RES *result;
MYSQL_BIND bind[3]; MYSQL_BIND bind[3];
ulong length[3]; ulong length[3];
char query[MAX_TEST_QUERY_LENGTH];
myheader("test_double_compare"); myheader("test_double_compare");
...@@ -1813,6 +1822,7 @@ static void test_null() ...@@ -1813,6 +1822,7 @@ static void test_null()
uint nData; uint nData;
MYSQL_BIND bind[2]; MYSQL_BIND bind[2];
my_bool is_null[2]; my_bool is_null[2];
char query[MAX_TEST_QUERY_LENGTH];
myheader("test_null"); myheader("test_null");
...@@ -1959,6 +1969,7 @@ static void test_ps_null_param() ...@@ -1959,6 +1969,7 @@ static void test_ps_null_param()
/* Execute several queries, all returning NULL in result. */ /* Execute several queries, all returning NULL in result. */
for(cur_query= queries; *cur_query; cur_query++) for(cur_query= queries; *cur_query; cur_query++)
{ {
char query[MAX_TEST_QUERY_LENGTH];
strmov(query, *cur_query); strmov(query, *cur_query);
stmt= mysql_simple_prepare(mysql, query); stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt); check_stmt(stmt);
...@@ -1990,6 +2001,7 @@ static void test_fetch_null() ...@@ -1990,6 +2001,7 @@ static void test_fetch_null()
MYSQL_BIND bind[11]; MYSQL_BIND bind[11];
ulong length[11]; ulong length[11];
my_bool is_null[11]; my_bool is_null[11];
char query[MAX_TEST_QUERY_LENGTH];
myheader("test_fetch_null"); myheader("test_fetch_null");
...@@ -2218,6 +2230,7 @@ static void test_select() ...@@ -2218,6 +2230,7 @@ static void test_select()
int nData= 1; int nData= 1;
MYSQL_BIND bind[2]; MYSQL_BIND bind[2];
ulong length[2]; ulong length[2];
char query[MAX_TEST_QUERY_LENGTH];
myheader("test_select"); myheader("test_select");
...@@ -2289,6 +2302,7 @@ static void test_ps_conj_select() ...@@ -2289,6 +2302,7 @@ static void test_ps_conj_select()
int32 int_data; int32 int_data;
char str_data[32]; char str_data[32];
unsigned long str_length; unsigned long str_length;
char query[MAX_TEST_QUERY_LENGTH];
myheader("test_ps_conj_select"); myheader("test_ps_conj_select");
rc= mysql_query(mysql, "drop table if exists t1"); rc= mysql_query(mysql, "drop table if exists t1");
...@@ -2346,6 +2360,7 @@ static void test_bug1115() ...@@ -2346,6 +2360,7 @@ static void test_bug1115()
MYSQL_BIND bind[1]; MYSQL_BIND bind[1];
ulong length[1]; ulong length[1];
char szData[11]; char szData[11];
char query[MAX_TEST_QUERY_LENGTH];
myheader("test_bug1115"); myheader("test_bug1115");
...@@ -2457,6 +2472,7 @@ static void test_bug1180() ...@@ -2457,6 +2472,7 @@ static void test_bug1180()
MYSQL_BIND bind[1]; MYSQL_BIND bind[1];
ulong length[1]; ulong length[1];
char szData[11]; char szData[11];
char query[MAX_TEST_QUERY_LENGTH];
myheader("test_select_bug"); myheader("test_select_bug");
...@@ -2547,6 +2563,7 @@ static void test_bug1644() ...@@ -2547,6 +2563,7 @@ static void test_bug1644()
int num; int num;
my_bool isnull; my_bool isnull;
int rc, i; int rc, i;
char query[MAX_TEST_QUERY_LENGTH];
myheader("test_bug1644"); myheader("test_bug1644");
...@@ -2646,6 +2663,7 @@ static void test_select_show() ...@@ -2646,6 +2663,7 @@ static void test_select_show()
{ {
MYSQL_STMT *stmt; MYSQL_STMT *stmt;
int rc; int rc;
char query[MAX_TEST_QUERY_LENGTH];
myheader("test_select_show"); myheader("test_select_show");
...@@ -2714,6 +2732,7 @@ static void test_simple_update() ...@@ -2714,6 +2732,7 @@ static void test_simple_update()
MYSQL_RES *result; MYSQL_RES *result;
MYSQL_BIND bind[2]; MYSQL_BIND bind[2];
ulong length[2]; ulong length[2];
char query[MAX_TEST_QUERY_LENGTH];
myheader("test_simple_update"); myheader("test_simple_update");
...@@ -2791,6 +2810,7 @@ static void test_long_data() ...@@ -2791,6 +2810,7 @@ static void test_long_data()
char *data= NullS; char *data= NullS;
MYSQL_RES *result; MYSQL_RES *result;
MYSQL_BIND bind[3]; MYSQL_BIND bind[3];
char query[MAX_TEST_QUERY_LENGTH];
myheader("test_long_data"); myheader("test_long_data");
...@@ -2877,6 +2897,7 @@ static void test_long_data_str() ...@@ -2877,6 +2897,7 @@ static void test_long_data_str()
MYSQL_RES *result; MYSQL_RES *result;
MYSQL_BIND bind[2]; MYSQL_BIND bind[2];
my_bool is_null[2]; my_bool is_null[2];
char query[MAX_TEST_QUERY_LENGTH];
myheader("test_long_data_str"); myheader("test_long_data_str");
...@@ -2969,6 +2990,7 @@ static void test_long_data_str1() ...@@ -2969,6 +2990,7 @@ static void test_long_data_str1()
MYSQL_RES *result; MYSQL_RES *result;
MYSQL_BIND bind[2]; MYSQL_BIND bind[2];
MYSQL_FIELD *field; MYSQL_FIELD *field;
char query[MAX_TEST_QUERY_LENGTH];
myheader("test_long_data_str1"); myheader("test_long_data_str1");
...@@ -3124,6 +3146,7 @@ static void test_long_data_bin() ...@@ -3124,6 +3146,7 @@ static void test_long_data_bin()
long length; long length;
MYSQL_RES *result; MYSQL_RES *result;
MYSQL_BIND bind[2]; MYSQL_BIND bind[2];
char query[MAX_TEST_QUERY_LENGTH];
myheader("test_long_data_bin"); myheader("test_long_data_bin");
...@@ -3203,6 +3226,7 @@ static void test_simple_delete() ...@@ -3203,6 +3226,7 @@ static void test_simple_delete()
MYSQL_RES *result; MYSQL_RES *result;
MYSQL_BIND bind[2]; MYSQL_BIND bind[2];
ulong length[2]; ulong length[2];
char query[MAX_TEST_QUERY_LENGTH];
myheader("test_simple_delete"); myheader("test_simple_delete");
...@@ -3285,6 +3309,7 @@ static void test_update() ...@@ -3285,6 +3309,7 @@ static void test_update()
MYSQL_RES *result; MYSQL_RES *result;
MYSQL_BIND bind[2]; MYSQL_BIND bind[2];
ulong length[2]; ulong length[2];
char query[MAX_TEST_QUERY_LENGTH];
myheader("test_update"); myheader("test_update");
...@@ -3381,6 +3406,7 @@ static void test_prepare_noparam() ...@@ -3381,6 +3406,7 @@ static void test_prepare_noparam()
MYSQL_STMT *stmt; MYSQL_STMT *stmt;
int rc; int rc;
MYSQL_RES *result; MYSQL_RES *result;
char query[MAX_TEST_QUERY_LENGTH];
myheader("test_prepare_noparam"); myheader("test_prepare_noparam");
...@@ -4237,6 +4263,7 @@ static void test_prepare_ext() ...@@ -4237,6 +4263,7 @@ static void test_prepare_ext()
short sData= 10; short sData= 10;
longlong bData= 20; longlong bData= 20;
MYSQL_BIND bind[6]; MYSQL_BIND bind[6];
char query[MAX_TEST_QUERY_LENGTH];
myheader("test_prepare_ext"); myheader("test_prepare_ext");
rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_prepare_ext"); rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_prepare_ext");
...@@ -4624,6 +4651,7 @@ static void test_stmt_close() ...@@ -4624,6 +4651,7 @@ static void test_stmt_close()
MYSQL_RES *result; MYSQL_RES *result;
unsigned int count; unsigned int count;
int rc; int rc;
char query[MAX_TEST_QUERY_LENGTH];
myheader("test_stmt_close"); myheader("test_stmt_close");
...@@ -5270,6 +5298,7 @@ static void test_manual_sample() ...@@ -5270,6 +5298,7 @@ static void test_manual_sample()
ulonglong affected_rows; ulonglong affected_rows;
MYSQL_BIND bind[3]; MYSQL_BIND bind[3];
my_bool is_null; my_bool is_null;
char query[MAX_TEST_QUERY_LENGTH];
myheader("test_manual_sample"); myheader("test_manual_sample");
...@@ -5624,6 +5653,7 @@ static void test_prepare_multi_statements() ...@@ -5624,6 +5653,7 @@ static void test_prepare_multi_statements()
{ {
MYSQL *mysql_local; MYSQL *mysql_local;
MYSQL_STMT *stmt; MYSQL_STMT *stmt;
char query[MAX_TEST_QUERY_LENGTH];
myheader("test_prepare_multi_statements"); myheader("test_prepare_multi_statements");
if (!(mysql_local= mysql_init(NULL))) if (!(mysql_local= mysql_init(NULL)))
...@@ -5841,6 +5871,7 @@ static void test_store_result2() ...@@ -5841,6 +5871,7 @@ static void test_store_result2()
int nData; int nData;
ulong length; ulong length;
MYSQL_BIND bind[1]; MYSQL_BIND bind[1];
char query[MAX_TEST_QUERY_LENGTH];
myheader("test_store_result2"); myheader("test_store_result2");
...@@ -7120,6 +7151,7 @@ static void test_set_option() ...@@ -7120,6 +7151,7 @@ static void test_set_option()
static void test_prepare_grant() static void test_prepare_grant()
{ {
int rc; int rc;
char query[MAX_TEST_QUERY_LENGTH];
myheader("test_prepare_grant"); myheader("test_prepare_grant");
...@@ -8592,6 +8624,7 @@ static void test_sqlmode() ...@@ -8592,6 +8624,7 @@ static void test_sqlmode()
MYSQL_BIND bind[2]; MYSQL_BIND bind[2];
char c1[5], c2[5]; char c1[5], c2[5];
int rc; int rc;
char query[MAX_TEST_QUERY_LENGTH];
myheader("test_sqlmode"); myheader("test_sqlmode");
...@@ -8735,6 +8768,7 @@ static void test_ts() ...@@ -8735,6 +8768,7 @@ static void test_ts()
ulong length; ulong length;
int rc, field_count; int rc, field_count;
char name; char name;
char query[MAX_TEST_QUERY_LENGTH];
myheader("test_ts"); myheader("test_ts");
...@@ -15019,6 +15053,65 @@ static void test_bug20152() ...@@ -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 Read and parse arguments and MySQL options from my.cnf
...@@ -15287,7 +15380,8 @@ static struct my_tests_st my_tests[]= { ...@@ -15287,7 +15380,8 @@ static struct my_tests_st my_tests[]= {
{ "test_bug20152", test_bug20152 }, { "test_bug20152", test_bug20152 },
{ "test_bug14169", test_bug14169 }, { "test_bug14169", test_bug14169 },
{ "test_bug17667", test_bug17667 }, { "test_bug17667", test_bug17667 },
{ "test_bug19671", test_bug19671}, { "test_bug19671", test_bug19671 },
{ "test_bug15752", test_bug15752 },
{ 0, 0 } { 0, 0 }
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment