diff --git a/include/MySQL_Protocol.h b/include/MySQL_Protocol.h index a7b68994c3..ad849a124f 100644 --- a/include/MySQL_Protocol.h +++ b/include/MySQL_Protocol.h @@ -51,7 +51,7 @@ class MySQL_ResultSet { unsigned int add_row(MYSQL_ROWS *rows); unsigned int add_row(MYSQL_ROW row); unsigned int add_row2(MYSQL_ROWS *row, unsigned char *offset); - void add_eof(); + void add_eof(bool suppress_warning_count=false); void remove_last_eof(); void add_err(MySQL_Data_Stream *_myds); bool get_resultset(PtrSizeArray *PSarrayFinal); diff --git a/lib/MySQL_Protocol.cpp b/lib/MySQL_Protocol.cpp index f19d5957bf..ddcbc84228 100644 --- a/lib/MySQL_Protocol.cpp +++ b/lib/MySQL_Protocol.cpp @@ -2726,7 +2726,9 @@ void MySQL_ResultSet::init(MySQL_Protocol *_myprot, MYSQL_RES *_res, MYSQL *_my, // up to 2.2.0 we used to add an EOF here. // due to bug #3547 we move the logic into add_eof() that can now handle also prepared statements PROXY_TRACE2(); - add_eof(); + // if the backend server has CLIENT_DEPRECATE_EOF enabled, and the client does not support + // CLIENT_DEPRECATE_EOF, warning_count will be excluded from the intermediate EOF packet + add_eof((mysql->server_capabilities & CLIENT_DEPRECATE_EOF)); } } @@ -2990,7 +2992,7 @@ unsigned int MySQL_ResultSet::add_row2(MYSQL_ROWS *row, unsigned char *offset) { return length; } -void MySQL_ResultSet::add_eof() { +void MySQL_ResultSet::add_eof(bool suppress_warning_count) { if (myprot) { unsigned int nTrx=myds->sess->NumActiveTransactions(); uint16_t setStatus = (nTrx ? SERVER_STATUS_IN_TRANS : 0 ); @@ -3007,7 +3009,7 @@ void MySQL_ResultSet::add_eof() { const MySQL_Data_Stream* _server_myds = (_mybe && _mybe->server_myds) ? _mybe->server_myds : nullptr; const MySQL_Connection* _myconn = (_server_myds && _server_myds->myds_type == MYDS_BACKEND && _server_myds->myconn) ? _server_myds->myconn : nullptr; - const unsigned int warning_count = (_myconn) ? _myconn->warning_count : 0; + const unsigned int warning_count = (_myconn && suppress_warning_count == false) ? _myconn->warning_count : 0; if (deprecate_eof_active) { PtrSize_t pkt; buffer_to_PSarrayOut(); diff --git a/lib/MySQL_Session.cpp b/lib/MySQL_Session.cpp index d904d84712..fe9736fb48 100644 --- a/lib/MySQL_Session.cpp +++ b/lib/MySQL_Session.cpp @@ -8168,13 +8168,16 @@ void MySQL_Session::reset_warning_hostgroup_flag_and_release_connection() // if we've reached this point, it means that warning was found in the previous query, but the // current executed query is not 'SHOW WARNINGS' or 'SHOW COUNT(*) FROM WARNINGS', so we can safely reset warning_in_hg and // return connection back to the connection pool. - MySQL_Backend* _mybe = NULL; - _mybe = find_backend(warning_in_hg); - MySQL_Data_Stream* myds = _mybe->server_myds; - myds->myconn->warning_count = 0; - myds->myconn->set_status(false, STATUS_MYSQL_CONNECTION_HAS_WARNINGS); - if ((myds->myconn->reusable == true) && myds->myconn->IsActiveTransaction() == false && myds->myconn->MultiplexDisabled() == false) { - myds->return_MySQL_Connection_To_Pool(); + MySQL_Backend* _mybe = find_backend(warning_in_hg); + if (_mybe) { + MySQL_Data_Stream* myds = _mybe->server_myds; + if (myds && myds->myconn) { + myds->myconn->warning_count = 0; + myds->myconn->set_status(false, STATUS_MYSQL_CONNECTION_HAS_WARNINGS); + if ((myds->myconn->reusable == true) && myds->myconn->IsActiveTransaction() == false && myds->myconn->MultiplexDisabled() == false) { + myds->return_MySQL_Connection_To_Pool(); + } + } } warning_in_hg = -1; } diff --git a/lib/mysql_connection.cpp b/lib/mysql_connection.cpp index 3788287b13..c5cb83a8c1 100644 --- a/lib/mysql_connection.cpp +++ b/lib/mysql_connection.cpp @@ -1565,6 +1565,12 @@ MDB_ASYNC_ST MySQL_Connection::handler(short event) { NEXT_IMMEDIATE(ASYNC_QUERY_END); } else { // since 'add_eof' utilizes 'warning_count,' we are setting the 'warning_count' here + + // Note: There is a possibility of obtaining inaccurate warning_count and server_status at this point + // if the backend server has CLIENT_DEPRECATE_EOF enabled, and the client does not support CLIENT_DEPRECATE_EOF, + // especially when the query generates a warning. This information will be included in the intermediate EOF packet. + // Correct information becomes available only after fetching all rows, + // and the warning_count and status flag details are extracted from the final OK packet. update_warning_count_from_connection(); if (myds->sess->mirror==false) { if (MyRS_reuse == NULL) { @@ -1671,7 +1677,8 @@ MDB_ASYNC_ST MySQL_Connection::handler(short event) { // since 'add_eof' utilizes 'warning_count,' we are setting the 'warning_count' here update_warning_count_from_connection(); // we reach here if there was no error - MyRS->add_eof(); + // exclude warning_count from the OK/EOF packet for the ‘SHOW WARNINGS’ statement + MyRS->add_eof(query.length == 13 && strncasecmp(query.ptr, "SHOW WARNINGS", 13) == 0); NEXT_IMMEDIATE(ASYNC_QUERY_END); } } @@ -2615,7 +2622,8 @@ void MySQL_Connection::ProcessQueryAndSetStatusFlags(char *query_digest_text) { if (warning_count > 0) { // 'warning_in_hg' will be used if the next query is 'SHOW WARNINGS' or // 'SHOW COUNT(*) WARNINGS' - myds->sess->warning_in_hg = myds->sess->current_hostgroup; + if (myds && myds->sess) + myds->sess->warning_in_hg = myds->sess->current_hostgroup; // enabling multiplexing set_status(true, STATUS_MYSQL_CONNECTION_HAS_WARNINGS); } @@ -2627,7 +2635,8 @@ void MySQL_Connection::ProcessQueryAndSetStatusFlags(char *query_digest_text) { // on backend. if (!((dig_len == 22 && strncasecmp(dig, "SHOW COUNT(*) WARNINGS", 22) == 0) || (dig_len == 13 && strncasecmp(dig, "SHOW WARNINGS", 13) == 0))) { - myds->sess->warning_in_hg = -1; + if (myds && myds->sess) + myds->sess->warning_in_hg = -1; warning_count = 0; // disabling multiplexing set_status(false, STATUS_MYSQL_CONNECTION_HAS_WARNINGS);