diff --git a/libmariadb/mariadb_stmt.c b/libmariadb/mariadb_stmt.c index 5b00a1cc..8c70a3c0 100644 --- a/libmariadb/mariadb_stmt.c +++ b/libmariadb/mariadb_stmt.c @@ -56,6 +56,9 @@ #include #include +#define UPDATE_STMT_ERROR(stmt)\ +SET_CLIENT_STMT_ERROR((stmt), (stmt)->mysql->net.last_errno, (stmt)->mysql->net.sqlstate, (stmt)->mysql->net.last_error) + #define STMT_NUM_OFS(type, a,r) ((type *)(a))[r] #define MADB_RESET_ERROR 1 #define MADB_RESET_LONGDATA 2 @@ -310,7 +313,10 @@ static int stmt_cursor_fetch(MYSQL_STMT *stmt, uchar **row) int4store(buf + STMT_ID_LENGTH, stmt->prefetch_rows); if (stmt->mysql->methods->db_command(stmt->mysql, COM_STMT_FETCH, (char *)buf, sizeof(buf), 1, stmt)) + { + UPDATE_STMT_ERROR(stmt); return(1); + } /* free previously allocated buffer */ ma_free_root(&result->alloc, MYF(MY_KEEP_PREALLOC)); @@ -1327,7 +1333,7 @@ static my_bool net_stmt_close(MYSQL_STMT *stmt, my_bool remove) if (stmt->mysql->methods->db_command(stmt->mysql,COM_STMT_CLOSE, stmt_id, sizeof(stmt_id), 1, stmt)) { - SET_CLIENT_STMT_ERROR(stmt, stmt->mysql->net.last_errno, stmt->mysql->net.sqlstate, stmt->mysql->net.last_error); + UPDATE_STMT_ERROR(stmt); return 1; } } @@ -1671,8 +1677,7 @@ int STDCALL mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, unsigned lon fail: stmt->state= MYSQL_STMT_INITTED; - SET_CLIENT_STMT_ERROR(stmt, mysql->net.last_errno, mysql->net.sqlstate, - mysql->net.last_error); + UPDATE_STMT_ERROR(stmt); return(rc); } @@ -1886,7 +1891,8 @@ int stmt_read_execute_response(MYSQL_STMT *stmt) } } - if (stmt->upsert_status.server_status & SERVER_STATUS_CURSOR_EXISTS) + if ((stmt->upsert_status.server_status & SERVER_STATUS_CURSOR_EXISTS) && + (stmt->flags & CURSOR_TYPE_READ_ONLY)) { stmt->cursor_exists = TRUE; mysql->status = MYSQL_STATUS_READY; @@ -2006,8 +2012,7 @@ int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt) if (ret) { - SET_CLIENT_STMT_ERROR(stmt, mysql->net.last_errno, mysql->net.sqlstate, - mysql->net.last_error); + UPDATE_STMT_ERROR(stmt); return(1); } @@ -2078,8 +2083,7 @@ static my_bool madb_reset_stmt(MYSQL_STMT *stmt, unsigned int flags) if ((ret= stmt->mysql->methods->db_command(mysql,COM_STMT_RESET, (char *)cmd_buf, sizeof(cmd_buf), 0, stmt))) { - SET_CLIENT_STMT_ERROR(stmt, mysql->net.last_errno, mysql->net.sqlstate, - mysql->net.last_error); + UPDATE_STMT_ERROR(stmt); return(ret); } } @@ -2231,6 +2235,8 @@ my_bool STDCALL mysql_stmt_send_long_data(MYSQL_STMT *stmt, uint param_number, stmt->params[param_number].long_data_used= 1; ret= stmt->mysql->methods->db_command(stmt->mysql, COM_STMT_SEND_LONG_DATA, (char *)cmd_buff, packet_len, 1, stmt); + if (ret) + UPDATE_STMT_ERROR(stmt); free(cmd_buff); return(ret); } @@ -2441,8 +2447,7 @@ int STDCALL mariadb_stmt_execute_direct(MYSQL_STMT *stmt, fail: /* check if we need to set error message */ if (!mysql_stmt_errno(stmt)) - SET_CLIENT_STMT_ERROR(stmt, mysql->net.last_errno, mysql->net.sqlstate, - mysql->net.last_error); + UPDATE_STMT_ERROR(stmt); do { stmt->mysql->methods->db_stmt_flush_unbuffered(stmt); } while(mysql_stmt_more_results(stmt)); diff --git a/unittest/libmariadb/ps_bugs.c b/unittest/libmariadb/ps_bugs.c index f151573b..3b55bf2c 100644 --- a/unittest/libmariadb/ps_bugs.c +++ b/unittest/libmariadb/ps_bugs.c @@ -5042,8 +5042,77 @@ static int test_zerofill_1byte(MYSQL *mysql) return OK; } +static int test_conc424(MYSQL *mysql) +{ + int rc; + MYSQL_STMT *stmt; + my_bool max_len= 1; + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_table1"); + check_mysql_rc(rc, mysql); + rc= mysql_query(mysql, "CREATE TABLE test_table1 (test_int INT, b int)"); + check_mysql_rc(rc, mysql); + rc= mysql_query(mysql, "INSERT INTO test_table1 values(10,11),(11,12)"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "DROP PROCEDURE IF EXISTS testCursor"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "CREATE PROCEDURE testCursor()\n" + "BEGIN\n" + "DECLARE test_int INT;\n" + "DECLARE b INT;\n" + "DECLARE done INT DEFAULT FALSE;\n" + "DECLARE testCursor CURSOR\n" + "FOR\n" + "SELECT test_int,b FROM test_table1;\n" + "DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;\n" + "OPEN testCursor;\n" + + " read_loop: LOOP\n" + " FETCH testCursor INTO test_int, b;\n" + " IF done THEN\n" + " LEAVE read_loop;\n" + " END IF;\n" + " SELECT test_int,b;" + " END LOOP;\n" + "CLOSE testCursor;\n" + "END"); + check_mysql_rc(rc, mysql); + + stmt= mysql_stmt_init(mysql); + rc= mysql_stmt_prepare(stmt, SL("CALL testCursor()")); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, &max_len); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + do { + if (mysql_stmt_field_count(stmt)) + { + MYSQL_RES *res= mysql_stmt_result_metadata(stmt); + rc= mysql_stmt_fetch(stmt); + FAIL_IF(rc, "Wrong return code"); + mysql_free_result(res); + } + rc= mysql_stmt_next_result(stmt); + + } while (!rc); + + rc= mysql_query(mysql, "DROP PROCEDURE testCursor"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "DROP TABLE test_table1"); + check_mysql_rc(rc, mysql); + + return OK; +} struct my_tests_st my_tests[] = { + {"test_conc424", test_conc424, TEST_CONNECTION_NEW, 0, NULL, NULL}, {"test_conc344", test_conc344, TEST_CONNECTION_NEW, 0, NULL, NULL}, {"test_conc334", test_conc334, TEST_CONNECTION_NEW, 0, NULL, NULL}, {"test_compress", test_compress, TEST_CONNECTION_NEW, CLIENT_COMPRESS, NULL, NULL},