summaryrefslogtreecommitdiff
path: root/libmysql
diff options
context:
space:
mode:
authorunknown <kostja@bodhi.local>2006-07-24 14:56:53 +0400
committerunknown <kostja@bodhi.local>2006-07-24 14:56:53 +0400
commit36510232aa5ab3788de36d17202254e3789441f4 (patch)
tree9e665cae0cf874da93929345fdbe6d3d6d97debb /libmysql
parent12d6b9c7f131cd623e384b8f176806d5e5dac7e2 (diff)
downloadmariadb-git-36510232aa5ab3788de36d17202254e3789441f4.tar.gz
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"
Diffstat (limited to 'libmysql')
-rw-r--r--libmysql/libmysql.c16
1 files changed, 9 insertions, 7 deletions
diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c
index a851d62b108..884c0b3a4db 100644
--- a/libmysql/libmysql.c
+++ b/libmysql/libmysql.c
@@ -645,7 +645,7 @@ int cli_read_change_user_result(MYSQL *mysql, char *buff, const char *passwd)
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 *mysql, char *buff, const char *passwd)
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 *mysql, MYSQL_STMT *stmt)
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 *stmt, uchar *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;
*row= ((mysql->net.read_pos[0] == 254) ? NULL :
@@ -4640,7 +4642,7 @@ int cli_read_binary_rows(MYSQL_STMT *stmt)
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)