fix: Fix mysql_query failure path and affected_rows race condition

Fix two issues in Query_Tool_Handler's execute_query functions:

1. mysql_query() failure path now returns immediately after
   return_connection() instead of continuing to process on bad state.

2. Capture affected_rows BEFORE return_connection() to avoid race
   condition. Previously, mysql_affected_rows() was called after
   return_connection(), potentially accessing a stale connection.

Apply fixes to both execute_query() and execute_query_with_schema().

Addresses coderabbitai review comments.
pull/5310/head^2
Rene Cannao 3 months ago
parent b3edc6524b
commit bbc04974f1

@ -365,21 +365,28 @@ std::string Query_Tool_Handler::execute_query(const std::string& query) {
return "{\"error\": \"No available connection\"}";
}
std::string result = "{\"error\": \"Query execution failed\"}";
MYSQL* mysql_ptr = static_cast<MYSQL*>(mysql);
if (mysql_query(static_cast<MYSQL*>(mysql), query.c_str())) {
proxy_error("Query_Tool_Handler: Query failed: %s\n", mysql_error(static_cast<MYSQL*>(mysql)));
if (mysql_query(mysql_ptr, query.c_str())) {
proxy_error("Query_Tool_Handler: Query failed: %s\n", mysql_error(mysql_ptr));
return_connection(mysql);
json j;
j["success"] = false;
j["error"] = std::string(mysql_error(mysql_ptr));
return j.dump();
}
MYSQL_RES* res = mysql_store_result(static_cast<MYSQL*>(mysql));
MYSQL_RES* res = mysql_store_result(mysql_ptr);
// Capture affected_rows BEFORE return_connection to avoid race condition
unsigned long affected_rows_val = mysql_affected_rows(mysql_ptr);
return_connection(mysql);
if (!res) {
// No result set (e.g., INSERT/UPDATE)
json j;
j["success"] = true;
j["affected_rows"] = static_cast<long>(mysql_affected_rows(static_cast<MYSQL*>(mysql)));
j["affected_rows"] = static_cast<long>(affected_rows_val);
return j.dump();
}
@ -444,13 +451,16 @@ std::string Query_Tool_Handler::execute_query_with_schema(
}
MYSQL_RES* res = mysql_store_result(mysql_ptr);
// Capture affected_rows BEFORE return_connection to avoid race condition
unsigned long affected_rows_val = mysql_affected_rows(mysql_ptr);
return_connection(mysql);
if (!res) {
// No result set (e.g., INSERT/UPDATE)
json j;
j["success"] = true;
j["affected_rows"] = static_cast<long>(mysql_affected_rows(mysql_ptr));
j["affected_rows"] = static_cast<long>(affected_rows_val);
return j.dump();
}

Loading…
Cancel
Save