Details
- 
    
Bug
 - 
    Status: Closed (View Workflow)
 - 
    
Trivial
 - 
    Resolution: Cannot Reproduce
 - 
    2.0.0, N/A
 - 
    None
 - 
    None
 
Description
Function mysql_stmt_execute can hang up under the following conditions.
1. Call mysql_stmt_bind_result in advance.
2. Call mysql_stmt_execute (It is OK)
3. Do NOT call mysql_stmt_fetch
4. Call mysql_stmt_execute again (hang up)
In case of the following sample code, function good_select can be called twice. On the other hand, bad_select works only once.
					#include <cstring>
			 | 
		
					#include <iostream>
			 | 
		
					#include <mariadb/mysql.h>
			 | 
		
					#include <new>
			 | 
		
| 
					 | 
		
					using namespace std;  | 
		
| 
					 | 
		
					static const char create_table_sql[] =  | 
		
					"CREATE TABLE IF NOT EXISTS test.ids (id INT AUTO_INCREMENT PRIMARY KEY)";  | 
		
| 
					 | 
		
					static const char select_sql[] = "SELECT * from test.ids";  | 
		
| 
					 | 
		
					void show_mysql_error(MYSQL *mysql) {  | 
		
					cerr << "Error(" << mysql_errno(mysql) << ") [" << mysql_sqlstate(mysql)  | 
		
					<< "] " << mysql_error(mysql) << endl;  | 
		
					exit(-1);  | 
		
					}
			 | 
		
| 
					 | 
		
					void show_mysql_error(MYSQL_STMT *stmt) {  | 
		
					cerr << "Error(" << mysql_stmt_errno(stmt) << ") ["  | 
		
					<< mysql_stmt_sqlstate(stmt) << "] " << mysql_stmt_error(stmt) << endl;  | 
		
					exit(-1);  | 
		
					}
			 | 
		
| 
					 | 
		
					void create_table(MYSQL *mysql) {  | 
		
| 
					 | 
		
					if (mysql_query(mysql, create_table_sql))  | 
		
					    show_mysql_error(mysql);
			 | 
		
					}
			 | 
		
| 
					 | 
		
					void bad_select(MYSQL_STMT *stmt) {  | 
		
| 
					 | 
		
					if (mysql_stmt_execute(stmt))  | 
		
					    show_mysql_error(stmt);
			 | 
		
| 
					 | 
		
					if (mysql_stmt_store_result(stmt))  | 
		
					    show_mysql_error(stmt);
			 | 
		
					}
			 | 
		
| 
					 | 
		
					void good_select(MYSQL_STMT *stmt) {  | 
		
| 
					 | 
		
					if (mysql_stmt_execute(stmt))  | 
		
					    show_mysql_error(stmt);
			 | 
		
| 
					 | 
		
					if (mysql_stmt_store_result(stmt))  | 
		
					    show_mysql_error(stmt);
			 | 
		
| 
					 | 
		
					if (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)  | 
		
					    show_mysql_error(stmt);
			 | 
		
					}
			 | 
		
| 
					 | 
		
					int main() {  | 
		
| 
					 | 
		
					  MYSQL *mysql = mysql_init(nullptr);
			 | 
		
					if (!mysql)  | 
		
					throw bad_alloc();  | 
		
| 
					 | 
		
					if (!mysql_real_connect(mysql, "127.0.0.1", "test_user", "", "test", 3306,  | 
		
					                          nullptr, CLIENT_REMEMBER_OPTIONS))
			 | 
		
					    show_mysql_error(mysql);
			 | 
		
| 
					 | 
		
					  create_table(mysql);
			 | 
		
| 
					 | 
		
					  MYSQL_STMT *stmt = mysql_stmt_init(mysql);
			 | 
		
					if (!stmt)  | 
		
					    show_mysql_error(mysql);
			 | 
		
| 
					 | 
		
					if (mysql_stmt_prepare(stmt, select_sql, strlen(select_sql)))  | 
		
					    show_mysql_error(stmt);
			 | 
		
| 
					 | 
		
					  MYSQL_BIND result;
			 | 
		
					memset(&result, 0, sizeof(result));  | 
		
| 
					 | 
		
					int id;  | 
		
					  result.buffer = &id;
			 | 
		
					result.buffer_length = sizeof(id);  | 
		
					  result.buffer_type = MYSQL_TYPE_LONG;
			 | 
		
| 
					 | 
		
					if (mysql_stmt_bind_result(stmt, &result))  | 
		
					    show_mysql_error(stmt);
			 | 
		
| 
					 | 
		
					  good_select(stmt);
			 | 
		
					cout << "good_select done (1st time)" << endl;  | 
		
| 
					 | 
		
					  good_select(stmt);
			 | 
		
					cout << "good_select done (2nd time)" << endl;  | 
		
| 
					 | 
		
					  bad_select(stmt);
			 | 
		
					cout << "bad_select done (1st time)" << endl;  | 
		
| 
					 | 
		
					  bad_select(stmt);
			 | 
		
					cout << "bad_select done (2nd time)" << endl;  | 
		
| 
					 | 
		
					return 0;  | 
		
					}
			 |