diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 4afc3ec5925..b4fc40bc78a 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -2456,7 +2456,7 @@ static my_bool execute(MYSQL_STMT *stmt, char *packet, ulong length) int4store(buff+5, 1); /* iteration count */ res= test(cli_advanced_command(mysql, COM_STMT_EXECUTE, buff, sizeof(buff), - packet, length, 1, NULL) || + packet, length, 1, stmt) || (*mysql->methods->read_query_result)(mysql)); stmt->affected_rows= mysql->affected_rows; stmt->server_status= mysql->server_status; @@ -2673,7 +2673,7 @@ stmt_read_row_from_cursor(MYSQL_STMT *stmt, unsigned char **row) int4store(buff + 4, stmt->prefetch_rows); /* number of rows to fetch */ if ((*mysql->methods->advanced_command)(mysql, COM_STMT_FETCH, buff, sizeof(buff), NullS, 0, - 1, NULL)) + 1, stmt)) { set_stmt_errmsg(stmt, net->last_error, net->last_errno, net->sqlstate); return 1; @@ -3340,7 +3340,7 @@ mysql_stmt_send_long_data(MYSQL_STMT *stmt, uint param_number, */ if ((*mysql->methods->advanced_command)(mysql, COM_STMT_SEND_LONG_DATA, buff, sizeof(buff), data, - length, 1, NULL)) + length, 1, stmt)) { set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno, mysql->net.sqlstate); @@ -4737,6 +4737,13 @@ int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt) MYSQL_DATA *result= &stmt->result; DBUG_ENTER("mysql_stmt_store_result"); + if (!mysql) + { + /* mysql can be reset in mysql_close called from mysql_reconnect */ + set_stmt_error(stmt, CR_SERVER_LOST, unknown_sqlstate); + DBUG_RETURN(1); + } + mysql= mysql->last_used_con; if (!stmt->field_count) @@ -4762,7 +4769,7 @@ int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt) int4store(buff, stmt->stmt_id); int4store(buff + 4, (int)~0); /* number of rows to fetch */ if (cli_advanced_command(mysql, COM_STMT_FETCH, buff, sizeof(buff), - NullS, 0, 1, NULL)) + NullS, 0, 1, stmt)) { set_stmt_errmsg(stmt, net->last_error, net->last_errno, net->sqlstate); DBUG_RETURN(1); @@ -4949,7 +4956,7 @@ static my_bool reset_stmt_handle(MYSQL_STMT *stmt, uint flags) char buff[MYSQL_STMT_HEADER]; /* packet header: 4 bytes for stmt id */ int4store(buff, stmt->stmt_id); if ((*mysql->methods->advanced_command)(mysql, COM_STMT_RESET, buff, - sizeof(buff), 0, 0, 0, NULL)) + sizeof(buff), 0, 0, 0, stmt)) { set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno, mysql->net.sqlstate); diff --git a/sql-common/client.c b/sql-common/client.c index 1fc73549520..8b619b5452d 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -665,11 +665,12 @@ my_bool cli_advanced_command(MYSQL *mysql, enum enum_server_command command, const char *header, ulong header_length, const char *arg, ulong arg_length, my_bool skip_check, - MYSQL_STMT *stmt __attribute__((unused))) + MYSQL_STMT *stmt) { NET *net= &mysql->net; my_bool result= 1; init_sigpipe_variables + my_bool stmt_skip= stmt ? stmt->state != MYSQL_STMT_INIT_DONE : FALSE; DBUG_ENTER("cli_advanced_command"); /* Don't give sigpipe errors if the client doesn't want them */ @@ -677,7 +678,7 @@ cli_advanced_command(MYSQL *mysql, enum enum_server_command command, if (mysql->net.vio == 0) { /* Do reconnect if possible */ - if (mysql_reconnect(mysql)) + if (mysql_reconnect(mysql) || stmt_skip) DBUG_RETURN(1); } if (mysql->status != MYSQL_STATUS_READY || @@ -708,7 +709,7 @@ cli_advanced_command(MYSQL *mysql, enum enum_server_command command, goto end; } end_server(mysql); - if (mysql_reconnect(mysql)) + if (mysql_reconnect(mysql) || stmt_skip) goto end; if (net_write_command(net,(uchar) command, header, header_length, arg, arg_length)) @@ -2503,6 +2504,9 @@ my_bool mysql_reconnect(MYSQL *mysql) if (stmt->state != MYSQL_STMT_INIT_DONE) { stmt->mysql= 0; + stmt->last_errno= CR_SERVER_LOST; + strmov(stmt->last_error, ER(CR_SERVER_LOST)); + strmov(stmt->sqlstate, unknown_sqlstate); } else { diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 18cfd8d7dfc..207183f567c 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -2516,7 +2516,7 @@ void mysql_stmt_close(THD *thd, char *packet) DBUG_ENTER("mysql_stmt_close"); if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_close"))) - DBUG_VOID_RETURN; + goto out; /* The only way currently a statement can be deallocated when it's @@ -2525,6 +2525,9 @@ void mysql_stmt_close(THD *thd, char *packet) DBUG_ASSERT(! (stmt->flags & (uint) Prepared_statement::IS_IN_USE)); (void) stmt->deallocate(); +out: + /* clear errors, response packet is not expected */ + thd->clear_error(); DBUG_VOID_RETURN; } @@ -2591,10 +2594,7 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length) #ifndef EMBEDDED_LIBRARY /* Minimal size of long data packet is 6 bytes */ if (packet_length <= MYSQL_LONG_DATA_HEADER) - { - my_error(ER_WRONG_ARGUMENTS, MYF(0), "mysql_stmt_send_long_data"); - DBUG_VOID_RETURN; - } + goto out; #endif stmt_id= uint4korr(packet); @@ -2614,7 +2614,7 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length) stmt->last_errno= ER_WRONG_ARGUMENTS; sprintf(stmt->last_error, ER(ER_WRONG_ARGUMENTS), "mysql_stmt_send_long_data"); - DBUG_VOID_RETURN; + goto out; } #endif @@ -2630,6 +2630,10 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length) stmt->last_errno= ER_OUTOFMEMORY; sprintf(stmt->last_error, ER(ER_OUTOFMEMORY), 0); } + +out: + /* clear errors, response packet is not expected */ + thd->clear_error(); DBUG_VOID_RETURN; } diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 0deb37d25c3..142fd741443 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -11746,6 +11746,7 @@ static void test_bug5194() rc= mysql_stmt_execute(stmt); check_execute(stmt, rc); + mysql_stmt_reset(stmt); } mysql_stmt_close(stmt); @@ -15942,83 +15943,6 @@ static void test_bug27592() DBUG_VOID_RETURN; } -#if 0 - -static void test_bug29948() -{ - MYSQL *dbc=NULL; - MYSQL_STMT *stmt=NULL; - MYSQL_BIND bind; - - int res=0; - my_bool auto_reconnect=1, error=0, is_null=0; - char kill_buf[20]; - const char *query; - int buf; - unsigned long length, cursor_type; - - dbc = mysql_init(NULL); - DIE_UNLESS(dbc); - - mysql_options(dbc, MYSQL_OPT_RECONNECT, (char*)&auto_reconnect); - if (!mysql_real_connect(dbc, opt_host, opt_user, - opt_password, current_db, opt_port, - opt_unix_socket, - (CLIENT_FOUND_ROWS | CLIENT_MULTI_STATEMENTS | - CLIENT_MULTI_RESULTS))) - { - printf("connection failed: %s (%d)", mysql_error(dbc), - mysql_errno(dbc)); - exit(1); - } - - bzero(&bind, sizeof(bind)); - bind.buffer_type= MYSQL_TYPE_LONG; - bind.buffer= (char *)&buf; - bind.is_null= &is_null; - bind.error= &error; - bind.length= &length; - - res= mysql_query(dbc, "DROP TABLE IF EXISTS t1"); - myquery(res); - res= mysql_query(dbc, "CREATE TABLE t1 (a INT)"); - myquery(res); - res= mysql_query(dbc, "INSERT INTO t1 VALUES(1)"); - myquery(res); - - stmt= mysql_stmt_init(dbc); - check_stmt(stmt); - - cursor_type= CURSOR_TYPE_READ_ONLY; - res= mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void *)&cursor_type); - myquery(res); - - query= "SELECT * from t1 where a=?"; - res= mysql_stmt_prepare(stmt, query, strlen(query)); - myquery(res); - - res= mysql_stmt_bind_param(stmt, &bind); - myquery(res); - - res= mysql_stmt_execute(stmt); - check_execute(stmt, res); - - res= mysql_stmt_bind_result(stmt,&bind); - check_execute(stmt, res); - - sprintf(kill_buf, "kill %ld", dbc->thread_id); - mysql_query(dbc, kill_buf); - - res= mysql_stmt_store_result(stmt); - DIE_UNLESS(res); - - mysql_stmt_free_result(stmt); - mysql_stmt_close(stmt); - mysql_query(dbc, "DROP TABLE t1"); - mysql_close(dbc); -} - -#endif /** Bug#29306 Truncated data in MS Access with decimal (3,1) columns in a VIEW @@ -16546,7 +16470,6 @@ static struct my_tests_st my_tests[]= { { "test_bug28505", test_bug28505 }, { "test_bug28934", test_bug28934 }, { "test_bug27592", test_bug27592 }, - /* { "test_bug29948", test_bug29948 }, Bug#35103 */ { "test_bug29306", test_bug29306 }, { "test_bug31669", test_bug31669 }, { "test_bug32265", test_bug32265 },