You've already forked mariadb-connector-c
mirror of
https://github.com/mariadb-corporation/mariadb-connector-c.git
synced 2025-08-08 14:02:17 +03:00
CONC-667: Fix statement handling when unbuffered results are pending.
Resetting a statement will result in an error, if another (different) statement has a pending unbuffered result set (CR_COMMANDS_OUT_OF_SYNC). Freeing a statement result set will return an error, if the statement has no result set or was not executed (CR_STMT_NO_RESULT).
This commit is contained in:
@@ -114,10 +114,11 @@ extern const char *mariadb_client_errors[]; /* Error messages */
|
||||
#define CR_BINLOG_ERROR 5021
|
||||
#define CR_BINLOG_INVALID_FILE 5022
|
||||
#define CR_BINLOG_SEMI_SYNC_ERROR 5023
|
||||
#define CR_STMT_NO_RESULT 5024
|
||||
|
||||
/* Always last, if you add new error codes please update the
|
||||
value for CR_MARIADB_LAST_ERROR */
|
||||
#define CR_MARIADB_LAST_ERROR CR_BINLOG_INVALID_FILE
|
||||
#define CR_MARIADB_LAST_ERROR CR_STMT_NO_RESULT
|
||||
|
||||
#endif
|
||||
|
||||
|
@@ -118,6 +118,7 @@ const char *mariadb_client_errors[] =
|
||||
/* 5021 */ "Binary log error (File: %.*s start_pos=%ld): %s.",
|
||||
/* 5022 */ "File '%s' is not a binary log file",
|
||||
/* 5023 */ "Semi sync request error: %s",
|
||||
/* 5024 */ "Statement has no result set",
|
||||
""
|
||||
};
|
||||
|
||||
|
@@ -1613,6 +1613,12 @@ unsigned int STDCALL mysql_stmt_field_count(MYSQL_STMT *stmt)
|
||||
|
||||
my_bool STDCALL mysql_stmt_free_result(MYSQL_STMT *stmt)
|
||||
{
|
||||
if (stmt->state < MYSQL_STMT_EXECUTED || !stmt->field_count)
|
||||
{
|
||||
stmt_set_error(stmt, CR_STMT_NO_RESULT, SQLSTATE_UNKNOWN, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return madb_reset_stmt(stmt, MADB_RESET_LONGDATA | MADB_RESET_STORED |
|
||||
MADB_RESET_BUFFER | MADB_RESET_ERROR);
|
||||
}
|
||||
@@ -2198,6 +2204,19 @@ static my_bool madb_reset_stmt(MYSQL_STMT *stmt, unsigned int flags)
|
||||
{
|
||||
MYSQL *mysql= stmt->mysql;
|
||||
my_bool ret= 0;
|
||||
LIST *li_stmt= mysql->stmts;
|
||||
|
||||
/* CONC-667: If an other statement has a pending result set, we
|
||||
need to return an error */
|
||||
for (;li_stmt;li_stmt= li_stmt->next)
|
||||
{
|
||||
MYSQL_STMT *s= (MYSQL_STMT *)li_stmt->data;
|
||||
if (s != stmt && s->state == MYSQL_STMT_WAITING_USE_OR_STORE)
|
||||
{
|
||||
stmt_set_error(stmt, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!stmt->mysql)
|
||||
{
|
||||
@@ -2297,7 +2316,8 @@ static my_bool mysql_stmt_internal_reset(MYSQL_STMT *stmt, my_bool is_close)
|
||||
stmt->fetch_row_func == stmt_unbuffered_fetch)
|
||||
flags|= MADB_RESET_BUFFER;
|
||||
|
||||
ret= madb_reset_stmt(stmt, flags);
|
||||
if (ret= madb_reset_stmt(stmt, flags))
|
||||
return ret;
|
||||
|
||||
if (stmt->stmt_id)
|
||||
{
|
||||
|
@@ -5741,7 +5741,47 @@ end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int test_conc667(MYSQL *mysql)
|
||||
{
|
||||
MYSQL_STMT *stmt1, *stmt2;
|
||||
int rc;
|
||||
|
||||
stmt1= mysql_stmt_init(mysql);
|
||||
stmt2= mysql_stmt_init(mysql);
|
||||
|
||||
rc= mysql_stmt_prepare(stmt1, "SELECT 1", -1);
|
||||
check_stmt_rc(rc, stmt1);
|
||||
|
||||
rc= mysql_stmt_prepare(stmt2, "SELECT 2", -1);
|
||||
check_stmt_rc(rc, stmt2);
|
||||
|
||||
rc= mysql_stmt_execute(stmt1);
|
||||
check_stmt_rc(rc, stmt1);
|
||||
|
||||
rc= mysql_stmt_free_result(stmt2);
|
||||
FAIL_IF(!rc || mysql_stmt_errno(stmt2) != CR_STMT_NO_RESULT,
|
||||
"Expected CR_STMT_NO_RESULT");
|
||||
diag("Error (expected) %s", mysql_stmt_error(stmt2));
|
||||
|
||||
rc= mysql_stmt_reset(stmt2);
|
||||
FAIL_IF(!rc || mysql_stmt_errno(stmt2) != CR_COMMANDS_OUT_OF_SYNC,
|
||||
"Expected commands out of sync error");
|
||||
|
||||
rc= mysql_stmt_fetch(stmt1);
|
||||
check_stmt_rc(rc, stmt1);
|
||||
|
||||
mysql_stmt_free_result(stmt1);
|
||||
|
||||
rc= mysql_stmt_close(stmt1);
|
||||
check_stmt_rc(rc, stmt1);
|
||||
rc= mysql_stmt_close(stmt2);
|
||||
check_stmt_rc(rc, stmt2);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
struct my_tests_st my_tests[] = {
|
||||
{"test_conc667", test_conc667, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
|
||||
{"test_conc633", test_conc633, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
|
||||
{"test_conc623", test_conc623, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
|
||||
{"test_conc627", test_conc627, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
|
||||
|
Reference in New Issue
Block a user