mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
MDEV-4603 mysql_stmt_reset returns "commands out of sync" error
This commit is contained in:
committed by
Sergei Golubchik
parent
4c788b06d4
commit
ae87e63184
@ -1273,6 +1273,7 @@ static my_bool setup_one_fetch_function(MYSQL_BIND *, MYSQL_FIELD *field);
|
|||||||
#define RESET_LONG_DATA 2
|
#define RESET_LONG_DATA 2
|
||||||
#define RESET_STORE_RESULT 4
|
#define RESET_STORE_RESULT 4
|
||||||
#define RESET_CLEAR_ERROR 8
|
#define RESET_CLEAR_ERROR 8
|
||||||
|
#define RESET_ALL_BUFFERS 16
|
||||||
|
|
||||||
static my_bool reset_stmt_handle(MYSQL_STMT *stmt, uint flags);
|
static my_bool reset_stmt_handle(MYSQL_STMT *stmt, uint flags);
|
||||||
|
|
||||||
@ -4615,6 +4616,14 @@ static my_bool reset_stmt_handle(MYSQL_STMT *stmt, uint flags)
|
|||||||
*mysql->unbuffered_fetch_owner= TRUE;
|
*mysql->unbuffered_fetch_owner= TRUE;
|
||||||
mysql->status= MYSQL_STATUS_READY;
|
mysql->status= MYSQL_STATUS_READY;
|
||||||
}
|
}
|
||||||
|
if (flags & RESET_ALL_BUFFERS)
|
||||||
|
{
|
||||||
|
/* mysql_stmt_next_result will flush all pending
|
||||||
|
result sets
|
||||||
|
*/
|
||||||
|
while (mysql_more_results(mysql) &&
|
||||||
|
mysql_stmt_next_result(stmt) == 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (flags & RESET_SERVER_SIDE)
|
if (flags & RESET_SERVER_SIDE)
|
||||||
{
|
{
|
||||||
@ -4679,27 +4688,18 @@ my_bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt)
|
|||||||
{
|
{
|
||||||
mysql->stmts= list_delete(mysql->stmts, &stmt->list);
|
mysql->stmts= list_delete(mysql->stmts, &stmt->list);
|
||||||
/*
|
/*
|
||||||
Clear NET error state: if the following commands come through
|
Clear NET error state: if the following commands come through
|
||||||
successfully, connection will still be usable for other commands.
|
successfully, connection will still be usable for other commands.
|
||||||
*/
|
*/
|
||||||
net_clear_error(&mysql->net);
|
net_clear_error(&mysql->net);
|
||||||
|
|
||||||
if ((int) stmt->state > (int) MYSQL_STMT_INIT_DONE)
|
if ((int) stmt->state > (int) MYSQL_STMT_INIT_DONE)
|
||||||
{
|
{
|
||||||
uchar buff[MYSQL_STMT_HEADER]; /* 4 bytes - stmt id */
|
uchar buff[MYSQL_STMT_HEADER]; /* 4 bytes - stmt id */
|
||||||
|
|
||||||
if (mysql->unbuffered_fetch_owner == &stmt->unbuffered_fetch_cancelled)
|
if ((rc= reset_stmt_handle(stmt, RESET_ALL_BUFFERS | RESET_CLEAR_ERROR)))
|
||||||
mysql->unbuffered_fetch_owner= 0;
|
return rc;
|
||||||
if (mysql->status != MYSQL_STATUS_READY)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
Flush result set of the connection. If it does not belong
|
|
||||||
to this statement, set a warning.
|
|
||||||
*/
|
|
||||||
(*mysql->methods->flush_use_result)(mysql, TRUE);
|
|
||||||
if (mysql->unbuffered_fetch_owner)
|
|
||||||
*mysql->unbuffered_fetch_owner= TRUE;
|
|
||||||
mysql->status= MYSQL_STATUS_READY;
|
|
||||||
}
|
|
||||||
int4store(buff, stmt->stmt_id);
|
int4store(buff, stmt->stmt_id);
|
||||||
if ((rc= stmt_command(mysql, COM_STMT_CLOSE, buff, 4, stmt)))
|
if ((rc= stmt_command(mysql, COM_STMT_CLOSE, buff, 4, stmt)))
|
||||||
{
|
{
|
||||||
@ -4731,7 +4731,7 @@ my_bool STDCALL mysql_stmt_reset(MYSQL_STMT *stmt)
|
|||||||
/* Reset the client and server sides of the prepared statement */
|
/* Reset the client and server sides of the prepared statement */
|
||||||
DBUG_RETURN(reset_stmt_handle(stmt,
|
DBUG_RETURN(reset_stmt_handle(stmt,
|
||||||
RESET_SERVER_SIDE | RESET_LONG_DATA |
|
RESET_SERVER_SIDE | RESET_LONG_DATA |
|
||||||
RESET_CLEAR_ERROR));
|
RESET_ALL_BUFFERS | RESET_CLEAR_ERROR));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -4843,7 +4843,6 @@ int STDCALL mysql_next_result(MYSQL *mysql)
|
|||||||
DBUG_RETURN(-1); /* No more results */
|
DBUG_RETURN(-1); /* No more results */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int STDCALL mysql_stmt_next_result(MYSQL_STMT *stmt)
|
int STDCALL mysql_stmt_next_result(MYSQL_STMT *stmt)
|
||||||
{
|
{
|
||||||
MYSQL *mysql= stmt->mysql;
|
MYSQL *mysql= stmt->mysql;
|
||||||
|
@ -18749,6 +18749,109 @@ static void test_bug12337762()
|
|||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
MDEV-4603: mysql_stmt_reset doesn't clear
|
||||||
|
all result sets (from stored procedures).
|
||||||
|
This test requires also fix for MDEV-4604
|
||||||
|
*/
|
||||||
|
static void test_mdev4603()
|
||||||
|
{
|
||||||
|
MYSQL *my;
|
||||||
|
MYSQL_STMT *stmt;
|
||||||
|
int i, rc;
|
||||||
|
int a[] = {10,20,30};
|
||||||
|
MYSQL_BIND bind[3];
|
||||||
|
|
||||||
|
myheader("test_mdev4603");
|
||||||
|
my= mysql_client_init(NULL);
|
||||||
|
|
||||||
|
if (!mysql_real_connect(my, opt_host, opt_user,
|
||||||
|
opt_password, current_db, opt_port,
|
||||||
|
opt_unix_socket, CLIENT_MULTI_RESULTS))
|
||||||
|
DIE("mysql_real_connect failed");
|
||||||
|
|
||||||
|
/* 1st test:
|
||||||
|
use a procedure with out param
|
||||||
|
*/
|
||||||
|
rc= mysql_query(my, "DROP PROCEDURE IF EXISTS p1");
|
||||||
|
myquery(rc);
|
||||||
|
|
||||||
|
rc= mysql_query(mysql, "CREATE PROCEDURE p1(OUT p_out VARCHAR(19), IN p_in INT, INOUT p_inout INT)"
|
||||||
|
"BEGIN "
|
||||||
|
" SET p_in = 300, p_out := 'This is OUT param', p_inout = 200; "
|
||||||
|
" SELECT p_inout, p_in, substring(p_out, 9);"
|
||||||
|
"END");
|
||||||
|
myquery(rc);
|
||||||
|
|
||||||
|
stmt= mysql_stmt_init(mysql);
|
||||||
|
DIE_UNLESS(stmt != NULL);
|
||||||
|
|
||||||
|
rc= mysql_stmt_prepare(stmt, "CALL P1(?,?,?)", 14);
|
||||||
|
DIE_UNLESS(rc == 0);
|
||||||
|
|
||||||
|
DIE_UNLESS(mysql_stmt_param_count(stmt) == 3);
|
||||||
|
|
||||||
|
memset(bind, 0, sizeof(MYSQL_BIND) * 3);
|
||||||
|
for (i=0; i < 3; i++)
|
||||||
|
{
|
||||||
|
bind[i].buffer= &a[i];
|
||||||
|
bind[i].buffer_type= MYSQL_TYPE_LONG;
|
||||||
|
}
|
||||||
|
bind[0].buffer_type= MYSQL_TYPE_NULL;
|
||||||
|
rc= mysql_stmt_bind_param(stmt, bind);
|
||||||
|
DIE_UNLESS(rc == 0);
|
||||||
|
|
||||||
|
rc= mysql_stmt_execute(stmt);
|
||||||
|
DIE_UNLESS(rc == 0);
|
||||||
|
|
||||||
|
rc= mysql_stmt_fetch(stmt);
|
||||||
|
DIE_UNLESS(rc == 0);
|
||||||
|
|
||||||
|
rc= mysql_stmt_reset(stmt);
|
||||||
|
DIE_UNLESS(rc == 0);
|
||||||
|
|
||||||
|
/*connection shouldn't be blocked now */
|
||||||
|
|
||||||
|
rc= mysql_query(mysql, "DROP PROCEDURE p1");
|
||||||
|
myquery(rc);
|
||||||
|
|
||||||
|
/* 2nd test:
|
||||||
|
reset all result sets */
|
||||||
|
rc= mysql_query(my, "CREATE PROCEDURE p1() "
|
||||||
|
"BEGIN"
|
||||||
|
" SELECT 1,2,3 FROM DUAL;"
|
||||||
|
" SELECT 'foo' FROM DUAL;"
|
||||||
|
"END");
|
||||||
|
myquery(rc);
|
||||||
|
|
||||||
|
rc= mysql_stmt_prepare(stmt, "CALL P1()", 9);
|
||||||
|
DIE_UNLESS(rc == 0);
|
||||||
|
|
||||||
|
rc= mysql_stmt_execute(stmt);
|
||||||
|
DIE_UNLESS(rc == 0);
|
||||||
|
|
||||||
|
rc= mysql_stmt_reset(stmt);
|
||||||
|
DIE_UNLESS(rc == 0);
|
||||||
|
|
||||||
|
/* 3rd test:
|
||||||
|
mysql_stmt_close should also flush all pending
|
||||||
|
result sets
|
||||||
|
*/
|
||||||
|
|
||||||
|
rc= mysql_stmt_prepare(stmt, "CALL P1()", 9);
|
||||||
|
DIE_UNLESS(rc == 0);
|
||||||
|
|
||||||
|
rc= mysql_stmt_execute(stmt);
|
||||||
|
DIE_UNLESS(rc == 0);
|
||||||
|
|
||||||
|
rc= mysql_stmt_close(stmt);
|
||||||
|
DIE_UNLESS(rc == 0);
|
||||||
|
|
||||||
|
rc= mysql_query(my, "DROP PROCEDURE p1");
|
||||||
|
myquery(rc);
|
||||||
|
|
||||||
|
mysql_close(my);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
BUG 11754979 - 46675: ON DUPLICATE KEY UPDATE AND UPDATECOUNT() POSSIBLY WRONG
|
BUG 11754979 - 46675: ON DUPLICATE KEY UPDATE AND UPDATECOUNT() POSSIBLY WRONG
|
||||||
@ -19289,6 +19392,7 @@ static struct my_tests_st my_tests[]= {
|
|||||||
{ "test_bug57058", test_bug57058 },
|
{ "test_bug57058", test_bug57058 },
|
||||||
{ "test_bug56976", test_bug56976 },
|
{ "test_bug56976", test_bug56976 },
|
||||||
{ "test_mdev3885", test_mdev3885 },
|
{ "test_mdev3885", test_mdev3885 },
|
||||||
|
{ "test_mdev4603", test_mdev4603 },
|
||||||
{ "test_bug11766854", test_bug11766854 },
|
{ "test_bug11766854", test_bug11766854 },
|
||||||
{ "test_bug12337762", test_bug12337762 },
|
{ "test_bug12337762", test_bug12337762 },
|
||||||
{ "test_progress_reporting", test_progress_reporting },
|
{ "test_progress_reporting", test_progress_reporting },
|
||||||
|
Reference in New Issue
Block a user