1
0
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:
Georg Richter
2024-03-23 12:27:55 +01:00
parent 4a1c5ef53b
commit b64282a9dd
4 changed files with 64 additions and 2 deletions

View File

@@ -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

View File

@@ -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",
""
};

View File

@@ -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)
{

View File

@@ -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},