Skip to content

Commit

Permalink
* Update warning_count as soon as query is executed.
Browse files Browse the repository at this point in the history
  • Loading branch information
rahim-kanji committed Nov 7, 2023
1 parent 7223ba1 commit 05208e2
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 40 deletions.
2 changes: 1 addition & 1 deletion include/MySQL_Session.h
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ class MySQL_Session
MySQL_Backend * find_or_create_backend(int, MySQL_Data_Stream *_myds=NULL);

void SQLite3_to_MySQL(SQLite3_result *, char *, int , MySQL_Protocol *, bool in_transaction=false, bool deprecate_eof_active=false);
void MySQL_Result_to_MySQL_wire(MYSQL *mysql, MySQL_ResultSet *MyRS, MySQL_Data_Stream *_myds=NULL);
void MySQL_Result_to_MySQL_wire(MYSQL *mysql, MySQL_ResultSet *MyRS, unsigned int warning_count, MySQL_Data_Stream *_myds=NULL);
void MySQL_Stmt_Result_to_MySQL_wire(MYSQL_STMT *stmt, MySQL_Connection *myconn);
unsigned int NumActiveTransactions(bool check_savpoint=false);
bool HasOfflineBackends();
Expand Down
12 changes: 6 additions & 6 deletions lib/MySQL_Session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4598,9 +4598,9 @@ void MySQL_Session::handler_minus1_GenerateErrorMessage(MySQL_Data_Stream *myds,
switch (status) {
case PROCESSING_QUERY:
if (myconn) {
MySQL_Result_to_MySQL_wire(myconn->mysql, myconn->MyRS, myds);
MySQL_Result_to_MySQL_wire(myconn->mysql, myconn->MyRS, myconn->warning_count, myds);
} else {
MySQL_Result_to_MySQL_wire(NULL, NULL, myds);
MySQL_Result_to_MySQL_wire(NULL, NULL, 0, myds);
}
break;
case PROCESSING_STMT_PREPARE:
Expand Down Expand Up @@ -5076,7 +5076,7 @@ int MySQL_Session::handler() {

switch (status) {
case PROCESSING_QUERY:
MySQL_Result_to_MySQL_wire(myconn->mysql, myconn->MyRS, myconn->myds);
MySQL_Result_to_MySQL_wire(myconn->mysql, myconn->MyRS, myconn->warning_count, myconn->myds);
break;
case PROCESSING_STMT_PREPARE:
{
Expand Down Expand Up @@ -5165,7 +5165,7 @@ int MySQL_Session::handler() {
break;
// rc==2 : a multi-resultset (or multi statement) was detected, and the current statement is completed
case 2:
MySQL_Result_to_MySQL_wire(myconn->mysql, myconn->MyRS, myconn->myds);
MySQL_Result_to_MySQL_wire(myconn->mysql, myconn->MyRS, myconn->warning_count, myconn->myds);
if (myconn->MyRS) { // we also need to clear MyRS, so that the next staement will recreate it if needed
if (myconn->MyRS_reuse) {
delete myconn->MyRS_reuse;
Expand Down Expand Up @@ -7355,7 +7355,7 @@ void MySQL_Session::MySQL_Stmt_Result_to_MySQL_wire(MYSQL_STMT *stmt, MySQL_Conn
}
}

void MySQL_Session::MySQL_Result_to_MySQL_wire(MYSQL *mysql, MySQL_ResultSet *MyRS, MySQL_Data_Stream *_myds) {
void MySQL_Session::MySQL_Result_to_MySQL_wire(MYSQL *mysql, MySQL_ResultSet *MyRS, unsigned int warning_count, MySQL_Data_Stream *_myds) {
if (mysql == NULL) {
// error
client_myds->myprot.generate_pkt_ERR(true,NULL,NULL,client_myds->pkt_sid+1, 2013, (char *)"HY000" ,(char *)"Lost connection to MySQL server during query");
Expand Down Expand Up @@ -7413,7 +7413,7 @@ void MySQL_Session::MySQL_Result_to_MySQL_wire(MYSQL *mysql, MySQL_ResultSet *My
setStatus |= SERVER_MORE_RESULTS_EXIST;
setStatus |= ( mysql->server_status & ~SERVER_STATUS_AUTOCOMMIT ); // get flags from server_status but ignore autocommit
setStatus = setStatus & ~SERVER_STATUS_CURSOR_EXISTS; // Do not send cursor #1128
client_myds->myprot.generate_pkt_OK(true,NULL,NULL,client_myds->pkt_sid+1,num_rows,mysql->insert_id, setStatus, mysql->warning_count,mysql->info);
client_myds->myprot.generate_pkt_OK(true,NULL,NULL,client_myds->pkt_sid+1,num_rows,mysql->insert_id, setStatus, warning_count, mysql->info);
//client_myds->pkt_sid++;
} else {
// error
Expand Down
24 changes: 13 additions & 11 deletions lib/mysql_connection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2018,6 +2018,12 @@ int MySQL_Connection::async_query(short event, char *stmt, unsigned long length,
if (mysql_errno(mysql)) {
return -1;
} else {
if (myds && myds->sess && myds->sess->CurrentQuery.QueryParserArgs.digest_text) {
const bool handle_warnings_enabled = parent->myhgc->handle_warnings_enabled();
if (handle_warnings_enabled && this->mysql && mysql_warning_count(this->mysql) > 0) {
warning_count = mysql_warning_count(this->mysql);
}
}
return 0;
}
}
Expand Down Expand Up @@ -2579,14 +2585,12 @@ void MySQL_Connection::ProcessQueryAndSetStatusFlags(char *query_digest_text) {
if (get_status(STATUS_MYSQL_CONNECTION_HAS_WARNINGS) == false) {
const bool handle_warnings_enabled = parent->myhgc->handle_warnings_enabled();
if (handle_warnings_enabled && this->mysql && mysql_warning_count(this->mysql) > 0) {
if (myds && myds->sess) {
// '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;
warning_count = mysql_warning_count(this->mysql);
// enabling multiplexing
set_status(true, STATUS_MYSQL_CONNECTION_HAS_WARNINGS);
}
// '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;
//warning_count = mysql_warning_count(this->mysql);
// enabling multiplexing
set_status(true, STATUS_MYSQL_CONNECTION_HAS_WARNINGS);
}
} else { // reset warning_in_hg
const char* dig = myds->sess->CurrentQuery.QueryParserArgs.digest_text;
Expand All @@ -2596,9 +2600,7 @@ 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))) {
if (myds && myds->sess) {
myds->sess->warning_in_hg = -1;
}
myds->sess->warning_in_hg = -1;
warning_count = 0;
// disabling multiplexing
set_status(false, STATUS_MYSQL_CONNECTION_HAS_WARNINGS);
Expand Down
89 changes: 67 additions & 22 deletions test/tap/tests/test_warnings-t.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -172,9 +172,46 @@ int check_proxysql_internal_session(MYSQL* proxysql, int exp_status) {
return EXIT_SUCCESS;
}

const std::vector<TestInfo> mysql_variable_test = {
{ ConnectionType::kAdmin, {"DELETE FROM mysql_query_rules", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ConnectionType::kAdmin, {"LOAD MYSQL QUERY RULES TO RUNTIME", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ConnectionType::kAdmin, {"SET mysql-handle_warnings=0", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ConnectionType::kAdmin, {"LOAD MYSQL VARIABLES TO RUNTIME", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ConnectionType::kMySQL, {"SELECT 1/0", true}, {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) },
{ ConnectionType::kMySQL, {"DO 1/0", false}, {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) },
{ ConnectionType::kAdmin, {"SET mysql-handle_warnings=1", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ConnectionType::kAdmin, {"LOAD MYSQL VARIABLES TO RUNTIME", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ConnectionType::kMySQL, {"SELECT 1/0", true}, {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) },
{ ConnectionType::kMySQL, {"SELECT 1" , true}, {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) },
{ ConnectionType::kMySQL, {"DO 1/0", false}, {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) },
{ ConnectionType::kMySQL, {"DO 1", false}, {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) }
};

const std::vector<TestInfo> hostgroup_attributes_test = {
{ ConnectionType::kAdmin, {"SET mysql-handle_warnings=1", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ConnectionType::kAdmin, {"LOAD MYSQL VARIABLES TO RUNTIME", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ConnectionType::kAdmin, {"DELETE FROM mysql_hostgroup_attributes", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ConnectionType::kAdmin, {"INSERT INTO mysql_hostgroup_attributes (hostgroup_id, hostgroup_settings) VALUES (0, '{\"handle_warnings\":0}')", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ConnectionType::kAdmin, {"LOAD MYSQL SERVERS TO RUNTIME", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
// Hostgroup attributes take precedence and should override the global variable value for the specified hostgroup.
{ ConnectionType::kMySQL, {"DO 1/0", false}, {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled)},
{ ConnectionType::kMySQL, {"SELECT 1/0", true}, {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled)},
{ ConnectionType::kMySQL, {"DO 1", false}, {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) },
{ ConnectionType::kMySQL, {"SELECT 1", true}, {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) },
{ ConnectionType::kAdmin, {"SET mysql-handle_warnings=0", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ConnectionType::kAdmin, {"LOAD MYSQL VARIABLES TO RUNTIME", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ConnectionType::kAdmin, {"DELETE FROM mysql_hostgroup_attributes", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ConnectionType::kAdmin, {"INSERT INTO mysql_hostgroup_attributes (hostgroup_id, hostgroup_settings) VALUES (0, '{\"handle_warnings\":1}')", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ConnectionType::kAdmin, {"LOAD MYSQL SERVERS TO RUNTIME", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ConnectionType::kMySQL, {"DO 1/0", false}, {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) },
{ ConnectionType::kMySQL, {"SELECT 1/0", true}, {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) } // intentional
};

const std::vector<TestInfo> select_test = {
{ ConnectionType::kMySQL, {"SELECT 1/0", true}, {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) },
{ ConnectionType::kMySQL, {"SELECT 1" , true}, {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) }
{ ConnectionType::kMySQL, {"SELECT 1" , true}, {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) },
{ ConnectionType::kMySQL, {"DO 1/0", false}, {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) },
{ ConnectionType::kMySQL, {"DO 1" , false}, {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) }
};

const std::vector<TestInfo> insert_test = {
Expand All @@ -188,7 +225,7 @@ const std::vector<TestInfo> insert_test = {
};

const std::vector<TestInfo> query_cache_test = {
{ ConnectionType::kAdmin, {"SET mysql-query_cache_with_warnings_support=0", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ConnectionType::kAdmin, {"SET mysql-query_cache_handle_warnings=0", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ConnectionType::kAdmin, {"LOAD MYSQL VARIABLES TO RUNTIME", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ConnectionType::kAdmin, {"DELETE FROM mysql_query_rules", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ConnectionType::kAdmin, {"INSERT INTO mysql_query_rules (rule_id,active,match_digest,cache_ttl,apply) VALUES (1,1,'SELECT ?/?',60000,1)", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
Expand All @@ -198,7 +235,7 @@ const std::vector<TestInfo> query_cache_test = {
// this entry should not be saved in cache
{ ConnectionType::kMySQL, {"SELECT 1/0", true}, {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) },
{ ConnectionType::kMySQL, {"SELECT 1", true}, {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) },
{ ConnectionType::kAdmin, {"SET mysql-query_cache_with_warnings_support=1", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ConnectionType::kAdmin, {"SET mysql-query_cache_handle_warnings=1", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ConnectionType::kAdmin, {"LOAD MYSQL VARIABLES TO RUNTIME", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ConnectionType::kMySQL, {"SELECT 1/0", true}, {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) },
// resultset will be retrived from cache, with warning count zero
Expand Down Expand Up @@ -242,12 +279,14 @@ int main(int argc, char** argv) {
return -1;
}

plan((7+2) + // select test: 7 warning checks, 2 multiplex status checks
(9+4) + // insert test: 9 warning checks, 4 multiplex status checks
(3+1) + // query digest test: 3 warning checks, 1 multiplex status checks
(18+5) + // query cache test: 18 warning checks, 5 multiplex status checks
(7+2) + // warning log test: 7 warning checks, 2 multiplex status checks
(7+3)); // multiplexing test: 7 warning checks, 3 multiplex status checks
plan((20 + 6) + // mysql variable test: 20 warning checks, 6 multiplex status checks
(20 + 6) + // hostgroup attributes test: 20 warning checks, 6 multiplex status checks
(14 + 4) + // select test: 14 warning checks, 4 multiplex status checks
(9 + 4) + // insert test: 9 warning checks, 4 multiplex status checks
(3 + 1) + // query digest test: 3 warning checks, 1 multiplex status checks
(18 + 5) + // query cache test: 18 warning checks, 5 multiplex status checks
(7 + 2) + // warning log test: 7 warning checks, 2 multiplex status checks
(7 + 3)); // multiplexing test: 7 warning checks, 3 multiplex status checks

// Initialize Admin connection
MYSQL* proxysql_admin = mysql_init(NULL);
Expand All @@ -274,25 +313,31 @@ int main(int argc, char** argv) {
return exit_status();
}

std::vector<std::pair<const char*, std::vector<TestInfo>>> all_tests(6);
std::vector<std::pair<const char*, std::vector<TestInfo>>> all_tests(8);

all_tests[0].first = "SELECT";
all_tests[0].second.insert(all_tests[0].second.end(), select_test.begin(), select_test.end());
all_tests[0].first = "MYSQL VARIABLE (mysql-handle_warnings)";
all_tests[0].second.insert(all_tests[0].second.end(), mysql_variable_test.begin(), mysql_variable_test.end());

all_tests[1].first = "HOSTGROUP ATTRIBUTES (handle_warnings)";
all_tests[1].second.insert(all_tests[1].second.end(), hostgroup_attributes_test.begin(), hostgroup_attributes_test.end());

all_tests[2].first = "SELECT";
all_tests[2].second.insert(all_tests[2].second.end(), select_test.begin(), select_test.end());

all_tests[1].first = "INSERT";
all_tests[1].second.insert(all_tests[1].second.end(), insert_test.begin(), insert_test.end());
all_tests[3].first = "INSERT";
all_tests[3].second.insert(all_tests[3].second.end(), insert_test.begin(), insert_test.end());

all_tests[2].first = "QUERY_DIGEST";
all_tests[2].second.insert(all_tests[2].second.end(), query_digest_test.begin(), query_digest_test.end());
all_tests[4].first = "QUERY_DIGEST";
all_tests[4].second.insert(all_tests[4].second.end(), query_digest_test.begin(), query_digest_test.end());

all_tests[3].first = "QUERY_CACHE";
all_tests[3].second.insert(all_tests[3].second.end(), query_cache_test.begin(), query_cache_test.end());
all_tests[5].first = "QUERY_CACHE";
all_tests[5].second.insert(all_tests[5].second.end(), query_cache_test.begin(), query_cache_test.end());

all_tests[4].first = "WARNING_LOGS";
all_tests[4].second.insert(all_tests[4].second.end(), warning_log_test.begin(), warning_log_test.end());
all_tests[6].first = "WARNING_LOGS";
all_tests[6].second.insert(all_tests[6].second.end(), warning_log_test.begin(), warning_log_test.end());

all_tests[5].first = "MULTIPLEXING";
all_tests[5].second.insert(all_tests[5].second.end(), multiplexing_test.begin(), multiplexing_test.end());
all_tests[7].first = "MULTIPLEXING";
all_tests[7].second.insert(all_tests[7].second.end(), multiplexing_test.begin(), multiplexing_test.end());

for (const auto& test : all_tests) {
diag("Executing [%s] test...", test.first);
Expand Down

0 comments on commit 05208e2

Please sign in to comment.