From 4b9379b2aa0af245fd5944a57d5491dbe48f69f7 Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Sat, 25 Sep 2021 16:07:24 +0200 Subject: [PATCH] Fix for CONC-566: If cursor type is set to read only, and SERVER_STATUS_CURSOR_EXISTS flag was not set in the server_status of EOF packet, the assumption was made that a single result set will follow which will be stored by a call to mysql_stmt_store_result(). As the example in the bug report shows, this is not always the case, since a stored procedure call might also unset the CURSOR flag and will always return multiple result sets. In this case it will be handled now as "normal" unbuffered result set. --- libmariadb/mariadb_stmt.c | 3 ++- unittest/libmariadb/ps_bugs.c | 27 +++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/libmariadb/mariadb_stmt.c b/libmariadb/mariadb_stmt.c index 0e9ae144..ee1c3eb1 100644 --- a/libmariadb/mariadb_stmt.c +++ b/libmariadb/mariadb_stmt.c @@ -1961,7 +1961,8 @@ int stmt_read_execute_response(MYSQL_STMT *stmt) /* Only cursor read */ stmt->default_rset_handler = _mysql_stmt_use_result; - } else if (stmt->flags & CURSOR_TYPE_READ_ONLY) + } else if (stmt->flags & CURSOR_TYPE_READ_ONLY && + !(stmt->upsert_status.server_status & SERVER_MORE_RESULTS_EXIST)) { /* We have asked for CURSOR but got no cursor, because the condition diff --git a/unittest/libmariadb/ps_bugs.c b/unittest/libmariadb/ps_bugs.c index 07a4bac0..b6e63fd5 100644 --- a/unittest/libmariadb/ps_bugs.c +++ b/unittest/libmariadb/ps_bugs.c @@ -5319,7 +5319,34 @@ static int test_conc512(MYSQL *mysql) return OK; } +static int test_conc566(MYSQL *mysql) +{ + int rc; + MYSQL_STMT *stmt = mysql_stmt_init(mysql); + unsigned long cursor = CURSOR_TYPE_READ_ONLY; + const char* query= "call sp()"; + + rc= mysql_query(mysql,"drop procedure if exists sp"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql,"create procedure sp() select 1"); + check_mysql_rc(rc, mysql); + + rc= mysql_stmt_prepare(stmt,query,-1); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, &cursor); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + mysql_stmt_close(stmt); + return OK; +} + struct my_tests_st my_tests[] = { + {"test_conc566", test_conc566, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, {"test_conc512", test_conc512, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, {"test_conc504", test_conc504, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, {"test_returning", test_returning, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},