Skip to content

Commit

Permalink
* Reset the warning_count and server_status flags if CLIENT_DEPRECATE…
Browse files Browse the repository at this point in the history
…_EOF is enabled and the query yields a result set, preventing carry forwarding of flag values from the previous query.

* Suppress the display of warning counts in the "SHOW WARNINGS" statement.
  • Loading branch information
rahim-kanji committed Nov 18, 2023
1 parent 045d6bc commit 24c6395
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 18 deletions.
18 changes: 13 additions & 5 deletions deps/mariadb-client-library/client_deprecate_eof.patch
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,7 @@ index e475e25..1a04b2f 100644
}
prev_pos= 0; /* allowed to write at packet[-1] */
pos=mysql->net.read_pos;
@@ -1077,6 +1154,85 @@ int mthd_my_read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, ulong *lengths)
@@ -1077,6 +1154,93 @@ int mthd_my_read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, ulong *lengths)
return 0;
}

Expand Down Expand Up @@ -443,13 +443,21 @@ index e475e25..1a04b2f 100644
+ if (unpack_field(mysql, mem_root, 0, &m_rows, m_fields++))
+ return NULL;
+ }
+ // read EOF packet in case of client not supporting 'CLIENT_DEPRECATE_EOF'
+ if (!(mysql->server_capabilities & CLIENT_DEPRECATE_EOF))
+ {
+ if (mysql->server_capabilities & CLIENT_DEPRECATE_EOF) {
+ // When the `CLIENT_DEPRECATE_EOF` flag is enabled, there is no intermediate EOF marker following field metadata.
+ // As a result, we cannot retrieve warning_count and server_status until all rows have been fetched.
+ // To prevent carrying forward previous query results, we simply reset warning_count and server_status at this point.
+ // ** It is crucial to refrain from using warning_count or server_status immediately after calling mysql_query/mysql_real_query*
+ // when the result yields a result set. Instead, verify these values after fetching all rows.
+ // The essential information is contained in the final OK packet, enabling accurate extraction of
+ // warning_count and server_status.
+ mysql->warning_count = 0;
+ mysql->server_status = 0;
+ } else {
+ // read EOF packet in case of client not supporting 'CLIENT_DEPRECATE_EOF'
+ // read the EOF packet
+ if (packet_error == ma_net_safe_read(mysql, NULL))
+ return 0;
+
+ // verify it's actually an EOF packet
+ if (*(mysql->net.read_pos) == 254)
+ {
Expand Down
2 changes: 1 addition & 1 deletion include/MySQL_Protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 show_warning=false);
void remove_last_eof();
void add_err(MySQL_Data_Stream *_myds);
bool get_resultset(PtrSizeArray *PSarrayFinal);
Expand Down
4 changes: 2 additions & 2 deletions lib/MySQL_Protocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2990,7 +2990,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 show_warning) {
if (myprot) {
unsigned int nTrx=myds->sess->NumActiveTransactions();
uint16_t setStatus = (nTrx ? SERVER_STATUS_IN_TRANS : 0 );
Expand All @@ -3007,7 +3007,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 = (show_warning == false && _myconn) ? _myconn->warning_count : 0;
if (deprecate_eof_active) {
PtrSize_t pkt;
buffer_to_PSarrayOut();
Expand Down
17 changes: 10 additions & 7 deletions lib/MySQL_Session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
14 changes: 11 additions & 3 deletions lib/mysql_connection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -1671,7 +1677,7 @@ 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();
MyRS->add_eof(query.length == 13 && strncasecmp(query.ptr, "SHOW WARNINGS", 13) == 0);
NEXT_IMMEDIATE(ASYNC_QUERY_END);
}
}
Expand Down Expand Up @@ -2615,7 +2621,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);
}
Expand All @@ -2627,7 +2634,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);
Expand Down

0 comments on commit 24c6395

Please sign in to comment.