diff --git a/libmariadb/mariadb_stmt.c b/libmariadb/mariadb_stmt.c index 37d5d3d1..09cb0b65 100644 --- a/libmariadb/mariadb_stmt.c +++ b/libmariadb/mariadb_stmt.c @@ -1782,7 +1782,11 @@ int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt) } if (stmt->state > MYSQL_STMT_WAITING_USE_OR_STORE && stmt->state < MYSQL_STMT_FETCH_DONE && !stmt->result.data) { - mysql->methods->db_stmt_flush_unbuffered(stmt); + do { + if (!stmt->cursor_exists) + mysql->methods->db_stmt_flush_unbuffered(stmt); + } + while (mysql_stmt_next_result(stmt) == 0); stmt->state= MYSQL_STMT_PREPARED; stmt->mysql->status= MYSQL_STATUS_READY; } diff --git a/unittest/libmariadb/CMakeLists.txt b/unittest/libmariadb/CMakeLists.txt index d9718672..82845bc9 100644 --- a/unittest/libmariadb/CMakeLists.txt +++ b/unittest/libmariadb/CMakeLists.txt @@ -26,7 +26,7 @@ INCLUDE_DIRECTORIES(${CC_SOURCE_DIR}/include ${CC_SOURCE_DIR}/unittest/libmariadb) ADD_DEFINITIONS(-DLIBMARIADB) -SET(API_TESTS "performance" "basic-t" "fetch" "charset" "logs" "cursor" "errors" "view" "ps" "ps_bugs" "sp" "result" "connection" "misc" "ps_new" "sqlite3" "thread" "features-10_2" "bulk1" ) +SET(API_TESTS "bulk1" "performance" "basic-t" "fetch" "charset" "logs" "cursor" "errors" "view" "ps" "ps_bugs" "sp" "result" "connection" "misc" "ps_new" "sqlite3" "thread" "features-10_2" "bulk1") IF(WITH_DYNCOL) SET(API_TESTS ${API_TESTS} "dyncol") ENDIF() diff --git a/unittest/libmariadb/bulk1.c b/unittest/libmariadb/bulk1.c index efaa1850..978f36d8 100644 --- a/unittest/libmariadb/bulk1.c +++ b/unittest/libmariadb/bulk1.c @@ -402,6 +402,7 @@ static int bulk5(MYSQL *mysql) res= mysql_store_result(mysql); rows= (unsigned long)mysql_num_rows(res); + diag("rows: %d", rows); mysql_free_result(res); FAIL_IF(rows != 5, "expected 5 rows"); diff --git a/unittest/libmariadb/features-10_2.c b/unittest/libmariadb/features-10_2.c index 12bf46f5..d46e6acc 100644 --- a/unittest/libmariadb/features-10_2.c +++ b/unittest/libmariadb/features-10_2.c @@ -190,8 +190,31 @@ static int conc_218(MYSQL *mysql) return OK; } +static int test_cursor(MYSQL *mysql) +{ + int rc; + MYSQL_STMT *stmt; + unsigned int prefetch_rows= 1; + unsigned long cursor_type= CURSOR_TYPE_READ_ONLY; + + stmt= mysql_stmt_init(mysql); + rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, &cursor_type); + check_stmt_rc(rc, stmt); + rc= mysql_stmt_attr_set(stmt, STMT_ATTR_PREFETCH_ROWS, &prefetch_rows); + check_stmt_rc(rc, stmt); + rc= mariadb_stmt_execute_direct(stmt, "SELECT 1 FROM DUAL UNION SELECT 2 FROM DUAL", -1); + check_stmt_rc(rc, stmt); + rc= mysql_stmt_fetch(stmt); + check_stmt_rc(rc, stmt); + rc= mariadb_stmt_execute_direct(stmt, "SELECT 1 FROM DUAL UNION SELECT 2 FROM DUAL", -1); + check_stmt_rc(rc, stmt); + mysql_stmt_close(stmt); + return OK; +} + struct my_tests_st my_tests[] = { + {"test_cursor", test_cursor, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, {"conc_218", conc_218, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, {"conc_212", conc_212, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, {"conc_213", conc_213, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, diff --git a/unittest/libmariadb/ps.c b/unittest/libmariadb/ps.c index 169f722a..dc40696a 100644 --- a/unittest/libmariadb/ps.c +++ b/unittest/libmariadb/ps.c @@ -4974,7 +4974,81 @@ static int test_bit2tiny(MYSQL *mysql) return OK; } +static int test_reexecute(MYSQL *mysql) +{ + MYSQL_STMT *stmt; + MYSQL_BIND ps_params[3]; /* input parameter buffers */ + int int_data[3]; /* input/output values */ + int rc; + + /* set up stored procedure */ + rc = mysql_query(mysql, "DROP PROCEDURE IF EXISTS p1"); + check_mysql_rc(rc, mysql); + + rc = mysql_query(mysql, + "CREATE PROCEDURE p1(" + " IN p_in INT, " + " OUT p_out INT, " + " INOUT p_inout INT) " + "BEGIN " + " SELECT p_in, p_out, p_inout; " + " SET p_in = 100, p_out = 200, p_inout = 300; " + " SELECT p_in, p_out, p_inout; " + "END"); + check_mysql_rc(rc, mysql); + + /* initialize and prepare CALL statement with parameter placeholders */ + stmt = mysql_stmt_init(mysql); + if (!stmt) + { + diag("Could not initialize statement"); + exit(1); + } + rc = mysql_stmt_prepare(stmt, "CALL p1(?, ?, ?)", 16); + check_stmt_rc(rc, stmt); + + /* initialize parameters: p_in, p_out, p_inout (all INT) */ + memset(ps_params, 0, sizeof (ps_params)); + + ps_params[0].buffer_type = MYSQL_TYPE_LONG; + ps_params[0].buffer = (char *) &int_data[0]; + ps_params[0].length = 0; + ps_params[0].is_null = 0; + + ps_params[1].buffer_type = MYSQL_TYPE_LONG; + ps_params[1].buffer = (char *) &int_data[1]; + ps_params[1].length = 0; + ps_params[1].is_null = 0; + + ps_params[2].buffer_type = MYSQL_TYPE_LONG; + ps_params[2].buffer = (char *) &int_data[2]; + ps_params[2].length = 0; + ps_params[2].is_null = 0; + + /* bind parameters */ + rc = mysql_stmt_bind_param(stmt, ps_params); + check_stmt_rc(rc, stmt); + + /* assign values to parameters and execute statement */ + int_data[0]= 10; /* p_in */ + int_data[1]= 20; /* p_out */ + int_data[2]= 30; /* p_inout */ + + rc = mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + mysql_stmt_close(stmt); + + rc = mysql_query(mysql, "DROP PROCEDURE IF EXISTS p1"); + check_mysql_rc(rc, mysql); + return OK; +} + struct my_tests_st my_tests[] = { + {"test_reexecute", test_reexecute, TEST_CONNECTION_NEW, 0, NULL, NULL}, {"test_bit2tiny", test_bit2tiny, TEST_CONNECTION_NEW, 0, NULL, NULL}, {"test_conc97", test_conc97, TEST_CONNECTION_NEW, 0, NULL, NULL}, {"test_conc83", test_conc83, TEST_CONNECTION_NONE, 0, NULL, NULL},