* Execute all test cases with 'CLIENT_DEPRECATE_EOF' both enabled and disabled.

* Introduced 'ps_type' enum to differentiate between preparing a statement and executing a statement
* Fixed issue where the warning count fails to reset when the SET statement generates a warning.
* Resolved the issue where the 'server_status' and 'warning count' were not accurately represented in the statement.
* Replaced 'mysql_warning_count' with 'mysql_stmt_warning_count' for retrieving the warning count in statements.
* Added 'handle_warning' field in hostgroup_attributes TAP test
* Updated warnings TAP test
pull/4365/head
Rahim Kanji 3 years ago
parent ffb6676991
commit 045d6bcaeb

@ -653,7 +653,7 @@ index 0aaaf1a..229023b 100644
{
/* allocate space for rows */
if (!(current= (MYSQL_ROWS *)ma_alloc_root(&result->alloc, sizeof(MYSQL_ROWS) + packet_len)))
@@ -276,10 +284,14 @@ int mthd_stmt_read_all_rows(MYSQL_STMT *stmt)
@@ -276,10 +284,16 @@ int mthd_stmt_read_all_rows(MYSQL_STMT *stmt)
{
*pprevious= 0;
/* sace status info */
@ -664,6 +664,8 @@ index 0aaaf1a..229023b 100644
+
+ if (stmt->mysql->server_capabilities & CLIENT_DEPRECATE_EOF && !is_data_packet) {
+ ma_read_ok_packet(stmt->mysql, p + 1, packet_len);
+ stmt->upsert_status.warning_count= stmt->mysql->warning_count;
+ stmt->upsert_status.server_status= stmt->mysql->server_status;
+ } else {
+ stmt->upsert_status.warning_count= stmt->mysql->warning_count= uint2korr(p + 1);
+ stmt->upsert_status.server_status= stmt->mysql->server_status= uint2korr(p + 3);

@ -24,6 +24,12 @@ enum proxysql_session_type {
PROXYSQL_SESSION_NONE
};
enum ps_type : uint8_t {
ps_type_not_set = 0x0,
ps_type_prepare_stmt = 0x1,
ps_type_execute_stmt = 0x2
};
std::string proxysql_session_type_str(enum proxysql_session_type session_type);
// these structs will be used for various regex hardcoded
@ -121,7 +127,7 @@ class MySQL_Session
void handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_COM_SET_OPTION(PtrSize_t *);
void handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_COM_STATISTICS(PtrSize_t *);
void handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_COM_PROCESS_KILL(PtrSize_t *);
bool handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_COM_QUERY_qpo(PtrSize_t *, bool *lock_hostgroup, bool ps=false);
bool handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_COM_QUERY_qpo(PtrSize_t *, bool *lock_hostgroup, ps_type prepare_stmt_type=ps_type_not_set);
void handler___client_DSS_QUERY_SENT___server_DSS_NOT_INITIALIZED__get_connection();

@ -3289,7 +3289,7 @@ void MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C
}
assert(qpo); // GloQPro->process_mysql_query() should always return a qpo
// setting 'prepared' to prevent fetching results from the cache if the digest matches
rc_break=handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_COM_QUERY_qpo(&pkt, &lock_hostgroup, true);
rc_break=handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_COM_QUERY_qpo(&pkt, &lock_hostgroup, ps_type_prepare_stmt);
if (rc_break==true) {
return;
}
@ -3457,7 +3457,7 @@ void MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C
CurrentQuery.stmt_meta=stmt_meta;
//current_hostgroup=qpo->destination_hostgroup;
rc_break=handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_COM_QUERY_qpo(&pkt, &lock_hostgroup, true);
rc_break=handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_COM_QUERY_qpo(&pkt, &lock_hostgroup, ps_type_execute_stmt);
if (rc_break==true) {
return;
}
@ -5992,7 +5992,7 @@ int MySQL_Session::handler_WCD_SS_MCQ_qpo_Parse_SQL_LOG_BIN(PtrSize_t *pkt, bool
}
*/
bool MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_COM_QUERY_qpo(PtrSize_t *pkt, bool *lock_hostgroup, bool prepared) {
bool MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_COM_QUERY_qpo(PtrSize_t *pkt, bool *lock_hostgroup, ps_type prepare_stmt_type) {
/*
lock_hostgroup:
If this variable is set to true, this session will get lock to a
@ -6027,7 +6027,7 @@ bool MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C
return true;
}
if (prepared) { // for prepared statement we exit here
if (prepare_stmt_type & ps_type_execute_stmt) { // for prepared statement execute we exit here
reset_warning_hostgroup_flag_and_release_connection();
goto __exit_set_destination_hostgroup;
}
@ -6043,7 +6043,6 @@ bool MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C
if (warning_in_hg > -1) {
proxy_debug(PROXY_DEBUG_MYSQL_COM, 5, "Changing current_hostgroup to '%d'\n", warning_in_hg);
current_hostgroup = warning_in_hg;
//warning_in_hg = -1;
return false;
} else {
proxy_debug(PROXY_DEBUG_MYSQL_COM, 5, "No warnings were detected in the previous query. Sending an empty response.\n");
@ -6951,12 +6950,12 @@ bool MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C
}
// handle command KILL #860
if (prepared == false) {
//if (prepared == false) {
if (handle_command_query_kill(pkt)) {
return true;
}
}
if (qpo->cache_ttl>0) {
//}
if (qpo->cache_ttl>0 && ((prepare_stmt_type & ps_type_prepare_stmt) == 0)) {
bool deprecate_eof_active = client_myds->myconn->options.client_flag & CLIENT_DEPRECATE_EOF;
uint32_t resbuf=0;
unsigned char *aa=GloQC->get(

@ -554,11 +554,13 @@ void MySQL_Connection::update_warning_count_from_connection() {
// 'mysql_thread_query_digest' is set to false, fetching that statement from the cache may still contain the digest text.
// To prevent this, we will check the digest text in conjunction with 'mysql_thread_query_digest' to verify whether it
// is enabled or disabled.
if (myds && myds->sess && (myds->sess->CurrentQuery.QueryParserArgs.digest_text ||
(myds->sess->CurrentQuery.stmt_info && myds->sess->CurrentQuery.stmt_info->digest_text &&
mysql_thread___query_digests == true))) {
const bool handle_warnings_enabled = parent->myhgc->handle_warnings_enabled();
if (handle_warnings_enabled && mysql_errno(mysql) == 0 && mysql_warning_count(mysql) > 0) {
if (myds && myds->sess && myds->sess->CurrentQuery.QueryParserArgs.digest_text) {
const char* dig_text = myds->sess->CurrentQuery.QueryParserArgs.digest_text;
const size_t dig_len = strlen(dig_text);
// SHOW WARNINGS doesn't have any impact warning count,
// so we are replication same behaviour here
if (parent->myhgc->handle_warnings_enabled() &&
(dig_len != 13 || strncasecmp(dig_text, "SHOW WARNINGS", 13) != 0)) {
warning_count = mysql_warning_count(mysql);
}
}
@ -571,8 +573,7 @@ void MySQL_Connection::update_warning_count_from_statement() {
// is enabled or disabled.
if (myds && myds->sess && myds->sess->CurrentQuery.stmt_info && myds->sess->CurrentQuery.stmt_info->digest_text &&
mysql_thread___query_digests == true) {
const bool handle_warnings_enabled = parent->myhgc->handle_warnings_enabled();
if (handle_warnings_enabled && mysql_stmt_warning_count(query.stmt) > 0) {
if (parent->myhgc->handle_warnings_enabled()) {
warning_count = mysql_stmt_warning_count(query.stmt);
}
}
@ -1382,7 +1383,7 @@ handler_again:
if (query.stmt_result==NULL) {
NEXT_IMMEDIATE(ASYNC_STMT_EXECUTE_END);
} else {
update_warning_count_from_connection(); //update_warning_count_from_statement();
update_warning_count_from_statement();
if (myds->sess->mirror==false) {
if (MyRS_reuse == NULL) {
MyRS = new MySQL_ResultSet();
@ -1497,7 +1498,7 @@ handler_again:
NEXT_IMMEDIATE(ASYNC_STMT_EXECUTE_SUCCESSFUL);
}
*/
update_warning_count_from_connection(); //update_warning_count_from_statement();
update_warning_count_from_statement();
break;
// case ASYNC_STMT_EXECUTE_SUCCESSFUL:
// break;
@ -2615,7 +2616,6 @@ void MySQL_Connection::ProcessQueryAndSetStatusFlags(char *query_digest_text) {
// '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);
}

@ -1070,7 +1070,7 @@ int main(int, char**) {
std::make_tuple(18, 2, -1, 20, "SET sql_mode = \"\"", 0, 0, 100, "", "", ""),
std::make_tuple(19, 2, -1, 20, "SET sql_mode = \"\"", 0, 0, 100, "{}", "{}", "{}"),
std::make_tuple(20, 0, 0, 30, "SET long_query_time = 0", 1, 0, 123, "{\"session_variables\":[\"tmp_table_size\",\"join_buffer_size\"]}", "", ""),
std::make_tuple(21, 2, -1, 50, "SET sql_mode = \"\"", 1, 0, 125, "{\"session_variables\":[\"tmp_table_size\",\"join_buffer_size\"]}", "{}", ""),
std::make_tuple(21, 2, -1, 50, "SET sql_mode = \"\"", 1, 0, 125, "{\"session_variables\":[\"tmp_table_size\",\"join_buffer_size\"]}", "{\"handle_warnings\":1}", ""),
std::make_tuple(22, 3, -1, 40, "SET sql_mode = \"\"", 1, 0, 124, "{\"session_variables\":[\"tmp_table_size\",\"join_buffer_size\"]}", "", "{\"weight\": 100, \"max_connections\": 1000}")
};
std::vector<std::string> insert_mysql_hostgroup_attributes_queries{};

@ -31,7 +31,12 @@ using MESSAGE = std::string;
} \
} while(0)
#define MYSQL_CLEAR_RESULT(mysql) mysql_free_result(mysql_store_result(mysql));
#define MYSQL_CLEAR_RESULT(mysql) mysql_free_result(mysql_store_result(mysql));
#define MYSQL_CLEAR_STMT_RESULT(stmt) mysql_stmt_store_result(stmt); \
mysql_stmt_free_result(stmt);
#define INIT_QUERY_TEXT(QUERY, IS_SELECT) {QUERY, IS_SELECT, false}
#define INIT_QUERY_PREPARE_STMT(QUERY, IS_SELECT) {QUERY, IS_SELECT, true}
enum MultiplexStatus {
kNotApplicable = 0,
@ -42,8 +47,8 @@ enum MultiplexStatus {
};
enum ConnectionType {
kAdmin,
kMySQL
kAdmin = 0,
kMySQL = 1
};
enum class WarningCheckType {
@ -57,6 +62,7 @@ enum class WarningCheckType {
struct QueryInfo {
const char* query;
bool is_select;
bool prepare_stmt;
};
struct WarningCheckInfo {
@ -65,13 +71,60 @@ struct WarningCheckInfo {
std::vector<int> warning_codes;
};
struct TestInfo {
struct Connection {
ConnectionType conn_type;
size_t id;
};
struct TestInfo {
Connection conn;
QueryInfo query_info;
WarningCheckInfo warning_check_info;
int multiplex_status;
};
#define MYSQL_CONN_DEFAULT {ConnectionType::kMySQL, 0}
#define ADMIN_CONN_DEFAULT {ConnectionType::kAdmin, 0}
#define MYSQL_CONN(ID) {ConnectionType::kMySQL, ID}
#define ADMIN_CONN(ID) {ConnectionType::kAdmin, ID}
CommandLine cl;
std::array<std::map<size_t, MYSQL*>,2> conn_pool;
MYSQL* get_connection(const Connection& conn, bool enable_client_deprecate_eof) {
auto& my_conn = conn_pool[conn.conn_type];
const auto& itr = my_conn.find(conn.id);
if (itr != my_conn.end()) {
return itr->second;
}
// Initialize connection
MYSQL* proxysql = mysql_init(NULL);
if (!proxysql) {
fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxysql));
return NULL;
}
if (enable_client_deprecate_eof) {
// enable 'CLIENT_DEPRECATE_EOF' support
proxysql->options.client_flag |= CLIENT_DEPRECATE_EOF;
}
if (conn.conn_type == kAdmin) {
// Connnect to ProxySQL
if (!mysql_real_connect(proxysql, cl.host, cl.admin_username, cl.admin_password, NULL, cl.admin_port, NULL, 0)) {
fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxysql));
return NULL;
}
} else if (conn.conn_type == kMySQL) {
// Connect to ProxySQL
if (!mysql_real_connect(proxysql, cl.host, cl.username, cl.password, NULL, cl.port, NULL, 0)) {
fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxysql));
return NULL;
}
}
my_conn[conn.id] = proxysql;
return proxysql;
}
void parse_result_json_column(MYSQL_RES* result, nlohmann::json& j) {
if (!result) return;
@ -89,11 +142,41 @@ int execute_query(MYSQL* proxysql, const QueryInfo& query_info) {
return EXIT_SUCCESS;
}
int prepare_and_execute_stmt(MYSQL* mysql, const QueryInfo& query_info, MYSQL_STMT** stmt_out) {
assert(stmt_out);
MYSQL_STMT* stmt = mysql_stmt_init(mysql);
if (!stmt) {
fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(mysql));
return EXIT_FAILURE;
}
if (mysql_stmt_prepare(stmt, query_info.query, strlen(query_info.query))) {
fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_stmt_error(stmt));
mysql_stmt_close(stmt);
return EXIT_FAILURE;
}
if (mysql_stmt_execute(stmt) != 0) {
fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_stmt_error(stmt));
mysql_stmt_close(stmt);
return EXIT_FAILURE;
}
if (query_info.is_select) {
MYSQL_CLEAR_STMT_RESULT(stmt);
}
std::this_thread::sleep_for(std::chrono::milliseconds(100));
*stmt_out = stmt;
return EXIT_SUCCESS;
}
// get warning count from MySQL connection (MYSQL::warning_count)
int get_warnings_count_from_connection(MYSQL* mysql) {
return mysql_warning_count(mysql);
}
// get warning count from statement (MYSQL_STMT::mysql_upsert_status::warning_count)
int get_warnings_count_from_statement(MYSQL_STMT* stmt) {
return mysql_stmt_warning_count(stmt);
}
// retrieve warning count through a query. This action does not clear the warning message list.
int get_warnings_count(MYSQL* mysql) {
MYSQL_QUERY(mysql, "SHOW COUNT(*) WARNINGS");
@ -173,184 +256,209 @@ int check_proxysql_internal_session(MYSQL* proxysql, int exp_status) {
}
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) }
{ ADMIN_CONN_DEFAULT, INIT_QUERY_TEXT("DELETE FROM mysql_query_rules", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ADMIN_CONN_DEFAULT, INIT_QUERY_TEXT("LOAD MYSQL QUERY RULES TO RUNTIME", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ADMIN_CONN_DEFAULT, INIT_QUERY_TEXT("DELETE FROM mysql_hostgroup_attributes", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ADMIN_CONN_DEFAULT, INIT_QUERY_TEXT("LOAD MYSQL SERVERS TO RUNTIME", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ADMIN_CONN_DEFAULT, INIT_QUERY_TEXT("SET mysql-handle_warnings=0", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ADMIN_CONN_DEFAULT, INIT_QUERY_TEXT("LOAD MYSQL VARIABLES TO RUNTIME", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_TEXT("SELECT 1/0", true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_TEXT("DO 1/0", false), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_PREPARE_STMT("SELECT 1/0", true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_PREPARE_STMT("DO 1/0", false), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) },
{ ADMIN_CONN_DEFAULT, INIT_QUERY_TEXT("SET mysql-handle_warnings=1", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ADMIN_CONN_DEFAULT, INIT_QUERY_TEXT("LOAD MYSQL VARIABLES TO RUNTIME", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_TEXT("SELECT 1/0", true), {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_TEXT("SELECT 1" , true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_TEXT("DO 1/0", false), {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_TEXT("DO 1", false), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_PREPARE_STMT("SELECT 1/0", true), {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_PREPARE_STMT("SELECT 1" , true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_PREPARE_STMT("DO 1/0", false), {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_PREPARE_STMT("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) },
{ ADMIN_CONN_DEFAULT, INIT_QUERY_TEXT("SET mysql-handle_warnings=1", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ADMIN_CONN_DEFAULT, INIT_QUERY_TEXT("LOAD MYSQL VARIABLES TO RUNTIME", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ADMIN_CONN_DEFAULT, INIT_QUERY_TEXT("DELETE FROM mysql_hostgroup_attributes", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ADMIN_CONN_DEFAULT, INIT_QUERY_TEXT("INSERT INTO mysql_hostgroup_attributes (hostgroup_id, hostgroup_settings) VALUES (0, '{\"handle_warnings\":0}')", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ADMIN_CONN_DEFAULT, INIT_QUERY_TEXT("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
{ MYSQL_CONN_DEFAULT, INIT_QUERY_TEXT("DO 1/0", false), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled)},
{ MYSQL_CONN_DEFAULT, INIT_QUERY_TEXT("SELECT 1/0", true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled)},
{ MYSQL_CONN_DEFAULT, INIT_QUERY_TEXT("DO 1", false), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_TEXT("SELECT 1", true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_PREPARE_STMT("DO 1/0", false), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled)},
{ MYSQL_CONN_DEFAULT, INIT_QUERY_PREPARE_STMT("SELECT 1/0", true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled)},
{ MYSQL_CONN_DEFAULT, INIT_QUERY_PREPARE_STMT("DO 1", false), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_PREPARE_STMT("SELECT 1", true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) },
{ ADMIN_CONN_DEFAULT, INIT_QUERY_TEXT("SET mysql-handle_warnings=0", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ADMIN_CONN_DEFAULT, INIT_QUERY_TEXT("LOAD MYSQL VARIABLES TO RUNTIME", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ADMIN_CONN_DEFAULT, INIT_QUERY_TEXT("DELETE FROM mysql_hostgroup_attributes", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ADMIN_CONN_DEFAULT, INIT_QUERY_TEXT("INSERT INTO mysql_hostgroup_attributes (hostgroup_id, hostgroup_settings) VALUES (0, '{\"handle_warnings\":1}')", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ADMIN_CONN_DEFAULT, INIT_QUERY_TEXT("LOAD MYSQL SERVERS TO RUNTIME", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_TEXT("DO 1/0", false), {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_TEXT("SELECT 1/0", true), {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_TEXT("SELECT 1", true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_PREPARE_STMT("DO 1/0", false), {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_PREPARE_STMT("SELECT 1/0", true), {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_PREPARE_STMT("SELECT 1", true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) }
};
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, {"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> random_test = {
{ MYSQL_CONN_DEFAULT, INIT_QUERY_TEXT("SELECT 1/0", true), {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_TEXT("SELECT 1" , true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_TEXT("DO 1/0", false), {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_TEXT("DO 1" , false), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_TEXT("SET character_set_database='latin1'", false), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_TEXT("SELECT 1" , true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_PREPARE_STMT("SELECT 1/0", true), {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_PREPARE_STMT("SELECT 1" , true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_PREPARE_STMT("DO 1/0", false), {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_PREPARE_STMT("DO 1" , false), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_PREPARE_STMT("SET character_set_database='latin2'", false), {WarningCheckType::kAll, 1, {1681}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_PREPARE_STMT("SELECT 1" , true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) }
};
const std::vector<TestInfo> insert_test = {
{ ConnectionType::kMySQL, {"SET sql_mode='ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ConnectionType::kMySQL, {"DROP DATABASE IF EXISTS testdb", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ConnectionType::kMySQL, {"CREATE DATABASE testdb", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ConnectionType::kMySQL, {"CREATE TABLE testdb.t1 (a TINYINT NOT NULL, b CHAR(4))", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kMultiplexingDisabled) },
{ ConnectionType::kMySQL, {"INSERT INTO testdb.t1 VALUES(10, 'mysql'), (NULL, 'test'), (300, 'xyz')", false}, {WarningCheckType::kAll, 3, {1265,1048,1264}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) },
{ ConnectionType::kMySQL, {"SELECT 1", true}, {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) },
{ ConnectionType::kMySQL, {"DROP DATABASE IF EXISTS testdb", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kMultiplexingDisabled) }
{ MYSQL_CONN_DEFAULT, INIT_QUERY_TEXT("SET sql_mode='ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_TEXT("DROP DATABASE IF EXISTS testdb", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_TEXT("CREATE DATABASE testdb", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_TEXT("CREATE TABLE testdb.t1 (a TINYINT NOT NULL, b CHAR(4))", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kMultiplexingDisabled) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_TEXT("INSERT INTO testdb.t1 VALUES(10, 'mysql'), (NULL, 'test'), (300, 'xyz')", false), {WarningCheckType::kAll, 3, {1265,1048,1264}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_TEXT("SELECT 1", true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_PREPARE_STMT("INSERT INTO testdb.t1 VALUES(10, 'mysql'), (NULL, 'test'), (300, 'xyz')", false), {WarningCheckType::kAll, 3, {1265,1048,1264}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_PREPARE_STMT("SELECT 1", true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_TEXT("DROP DATABASE IF EXISTS testdb", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kMultiplexingDisabled) }
};
const std::vector<TestInfo> query_cache_test = {
{ 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) },
{ ConnectionType::kAdmin, {"LOAD MYSQL QUERY RULES TO RUNTIME", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ConnectionType::kAdmin, {"PROXYSQL FLUSH QUERY CACHE", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ConnectionType::kMySQL, {"SELECT 1/0", true}, {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) },
{ ADMIN_CONN_DEFAULT, INIT_QUERY_TEXT("SET mysql-query_cache_handle_warnings=0", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ADMIN_CONN_DEFAULT, INIT_QUERY_TEXT("LOAD MYSQL VARIABLES TO RUNTIME", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ADMIN_CONN_DEFAULT, INIT_QUERY_TEXT("DELETE FROM mysql_query_rules", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ADMIN_CONN_DEFAULT, INIT_QUERY_TEXT("INSERT INTO mysql_query_rules (rule_id,active,match_digest,cache_ttl,apply) VALUES (1,1,'SELECT ?/?',60000,1)", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ADMIN_CONN_DEFAULT, INIT_QUERY_TEXT("LOAD MYSQL QUERY RULES TO RUNTIME", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ADMIN_CONN_DEFAULT, INIT_QUERY_TEXT("PROXYSQL FLUSH QUERY CACHE", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_TEXT("SELECT 1/0", true), {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) },
// 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_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) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_TEXT("SELECT 1/0", true), {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_TEXT("SELECT 1", true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) },
// to check if prepare statement conflicts with cache
{ MYSQL_CONN_DEFAULT, INIT_QUERY_PREPARE_STMT("SELECT 1/0", true), {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) },
// { MYSQL_CONN_DEFAULT, INIT_QUERY_PREPARE_STMT("SELECT 1", true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) },
{ ADMIN_CONN_DEFAULT, INIT_QUERY_TEXT("SET mysql-query_cache_handle_warnings=1", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ADMIN_CONN_DEFAULT, INIT_QUERY_TEXT("LOAD MYSQL VARIABLES TO RUNTIME", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_TEXT("SELECT 1/0", true), {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) },
// resultset will be retrived from cache, with warning count zero
{ ConnectionType::kMySQL, {"SELECT 1/0", true}, {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) },
{ 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, {"PROXYSQL FLUSH QUERY CACHE", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }
{ MYSQL_CONN_DEFAULT, INIT_QUERY_TEXT("SELECT 1/0", true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) },
// to check if prepare statement conflicts with cache
{ MYSQL_CONN_DEFAULT, INIT_QUERY_PREPARE_STMT("SELECT 1/0", true), {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) },
{ ADMIN_CONN_DEFAULT, INIT_QUERY_TEXT("DELETE FROM mysql_query_rules", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ADMIN_CONN_DEFAULT, INIT_QUERY_TEXT("LOAD MYSQL QUERY RULES TO RUNTIME", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ADMIN_CONN_DEFAULT, INIT_QUERY_TEXT("PROXYSQL FLUSH QUERY CACHE", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }
};
const std::vector<TestInfo> query_digest_test = {
{ ConnectionType::kAdmin, {"SET mysql-query_digests='false'", 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::kAdmin, {"SET mysql-query_digests='true'", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ConnectionType::kAdmin, {"LOAD MYSQL VARIABLES TO RUNTIME", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }
{ ADMIN_CONN_DEFAULT, INIT_QUERY_TEXT("SET mysql-query_digests='false'", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ADMIN_CONN_DEFAULT, INIT_QUERY_TEXT("LOAD MYSQL VARIABLES TO RUNTIME", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_TEXT("SELECT 1/0", true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_TEXT("DO 1/0", false), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_PREPARE_STMT("SELECT 1/0", true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_PREPARE_STMT("DO 1/0", false), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) },
{ ADMIN_CONN_DEFAULT, INIT_QUERY_TEXT("SET mysql-query_digests='true'", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ADMIN_CONN_DEFAULT, INIT_QUERY_TEXT("LOAD MYSQL VARIABLES TO RUNTIME", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_TEXT("SELECT 1/0", true), {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_TEXT("SELECT 1", true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_TEXT("DO 1/0", false), {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_TEXT("DO 1", false), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_PREPARE_STMT("SELECT 1/0", true), {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_PREPARE_STMT("SELECT 1", true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) }
};
const std::vector<TestInfo> warning_log_test = {
{ ConnectionType::kAdmin, {"SET mysql-log_mysql_warnings_enabled='true'", 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::kAdmin, {"SET mysql-log_mysql_warnings_enabled='false'", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ConnectionType::kAdmin, {"LOAD MYSQL VARIABLES TO RUNTIME", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }
{ ADMIN_CONN_DEFAULT, INIT_QUERY_TEXT("SET mysql-log_mysql_warnings_enabled='true'", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ADMIN_CONN_DEFAULT, INIT_QUERY_TEXT("LOAD MYSQL VARIABLES TO RUNTIME", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_TEXT("SELECT 1/0", true), {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_TEXT("SELECT 1", true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_TEXT("DO 1/0", false), {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_TEXT("DO 1", false), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_PREPARE_STMT("SELECT 1/0", true), {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_PREPARE_STMT("SELECT 1", true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) },
{ ADMIN_CONN_DEFAULT, INIT_QUERY_TEXT("SET mysql-log_mysql_warnings_enabled='false'", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) },
{ ADMIN_CONN_DEFAULT, INIT_QUERY_TEXT("LOAD MYSQL VARIABLES TO RUNTIME", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }
};
const std::vector<TestInfo> multiplexing_test = {
{ ConnectionType::kMySQL, {"SELECT @@sql_mode", true}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kUserVariables) },
{ ConnectionType::kMySQL, {"SELECT 1/0", true}, {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kUserVariables | MultiplexStatus::kHasWarnings) },
{ ConnectionType::kMySQL, {"SELECT 1", true}, {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kUserVariables) }
{ MYSQL_CONN_DEFAULT, INIT_QUERY_TEXT("SELECT @@sql_mode", true), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kUserVariables) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_TEXT("SELECT 1/0", true), {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kUserVariables | MultiplexStatus::kHasWarnings) },
{ MYSQL_CONN_DEFAULT, INIT_QUERY_TEXT("SELECT 1", true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kUserVariables) },
{ MYSQL_CONN(1), INIT_QUERY_TEXT("SELECT @@sql_mode", true), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kUserVariables)},
{ MYSQL_CONN(1), INIT_QUERY_TEXT("DO 1/0", false), {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kUserVariables | MultiplexStatus::kHasWarnings)},
{ MYSQL_CONN(1), INIT_QUERY_TEXT("DO 1", false), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kUserVariables)},
{ MYSQL_CONN(2), INIT_QUERY_PREPARE_STMT("SELECT @@sql_mode", true), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kUserVariables)},
{ MYSQL_CONN(2), INIT_QUERY_PREPARE_STMT("SELECT 1/0", true), {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kUserVariables | MultiplexStatus::kHasWarnings)},
{ MYSQL_CONN(2), INIT_QUERY_PREPARE_STMT("SELECT 1", true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kUserVariables) },
{ MYSQL_CONN(3), INIT_QUERY_PREPARE_STMT("SET @test_variable = 44", true), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kUserVariables)},
{ MYSQL_CONN(3), INIT_QUERY_PREPARE_STMT("SELECT 1", true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kUserVariables) }
};
#define IS_BIT_MASK_SET(variable,flag) ((variable & static_cast<int>(flag)) == static_cast<int>(flag))
int main(int argc, char** argv) {
// base case
size_t check_count() { return 0; }
CommandLine cl;
template <class First, class... Rest>
size_t check_count(First&& first, Rest&&... rest) {
if (cl.getEnv()) {
diag("Failed to get the required environmental variables.");
return -1;
}
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);
if (!proxysql_admin) {
fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxysql_admin));
return -1;
}
// Connnect to ProxySQL Admin
if (!mysql_real_connect(proxysql_admin, cl.host, cl.admin_username, cl.admin_password, NULL, cl.admin_port, NULL, 0)) {
fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxysql_admin));
return exit_status();
}
// Initialize ProxySQL connection
MYSQL* proxysql = mysql_init(NULL);
if (!proxysql) {
fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxysql));
return exit_status();
}
// Connect to ProxySQL
if (!mysql_real_connect(proxysql, cl.host, cl.username, cl.password, NULL, cl.port, NULL, 0)) {
fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxysql));
return exit_status();
}
std::vector<std::pair<const char*, std::vector<TestInfo>>> all_tests(8);
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());
size_t count = 0;
all_tests[2].first = "SELECT";
all_tests[2].second.insert(all_tests[2].second.end(), select_test.begin(), select_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[4].first = "QUERY_DIGEST";
all_tests[4].second.insert(all_tests[4].second.end(), query_digest_test.begin(), query_digest_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());
for (const auto& val : first) {
if (val.warning_check_info.type != WarningCheckType::kNotApplicable) {
if (val.warning_check_info.type == WarningCheckType::kAll)
count += 3;
else
count += 1;
count += val.warning_check_info.warning_codes.size();
}
if (val.multiplex_status != 0)
count += 1;
}
return (count + check_count(rest...));
}
all_tests[6].first = "WARNING_LOGS";
all_tests[6].second.insert(all_tests[6].second.end(), warning_log_test.begin(), warning_log_test.end());
template <class... Args>
constexpr size_t test_size(Args&&... args) {
return sizeof...(args);
}
all_tests[7].first = "MULTIPLEXING";
all_tests[7].second.insert(all_tests[7].second.end(), multiplexing_test.begin(), multiplexing_test.end());
#define TESTS_COMBINED mysql_variable_test, hostgroup_attributes_test, random_test, insert_test, query_digest_test, \
query_cache_test, warning_log_test, multiplexing_test
void execute_tests(const std::vector<std::pair<const char*, std::vector<TestInfo>>>& all_tests, bool enable_client_deprecate_eof) {
for (const auto& test : all_tests) {
diag("Executing [%s] test...", test.first);
diag("Executing [%s] test... [CLIENT_DEPRECATE_EOF=%s]", test.first, (enable_client_deprecate_eof ? "TRUE" : "FALSE"));
for (const auto& test_info : test.second) {
MYSQL* mysql = (test_info.conn_type == ConnectionType::kMySQL ? proxysql : proxysql_admin);
if (execute_query(mysql, test_info.query_info) == EXIT_FAILURE)
MYSQL_STMT* stmt = nullptr;
MYSQL* mysql = get_connection(test_info.conn, enable_client_deprecate_eof);
if (!mysql) {
goto __exit;
}
if (test_info.query_info.prepare_stmt) {
if (prepare_and_execute_stmt(mysql, test_info.query_info, &stmt) == EXIT_FAILURE)
goto __exit;
} else {
if (execute_query(mysql, test_info.query_info) == EXIT_FAILURE)
goto __exit;
}
const int check_type = static_cast<int>(test_info.warning_check_info.type);
if (IS_BIT_MASK_SET(check_type, WarningCheckType::kConnection)) {
const int count = get_warnings_count_from_connection(mysql);
int count = get_warnings_count_from_connection(mysql);
if (test_info.query_info.prepare_stmt) {
count &= get_warnings_count_from_statement(stmt);
}
ok((count == test_info.warning_check_info.warning_count), "Connection warning count should match. Expected count:'%d' Actual count:'%d'", test_info.warning_check_info.warning_count, count);
}
if (IS_BIT_MASK_SET(check_type, WarningCheckType::kCountQuery)) {
@ -379,15 +487,76 @@ int main(int argc, char** argv) {
}
if (test_info.multiplex_status != MultiplexStatus::kNotApplicable) {
if (check_proxysql_internal_session(mysql, test_info.multiplex_status) != EXIT_SUCCESS)
if (check_proxysql_internal_session(mysql, test_info.multiplex_status) != EXIT_SUCCESS) {
if (stmt)
mysql_stmt_close(stmt);
goto __exit;
}
}
if (stmt)
mysql_stmt_close(stmt);
}
}
__exit:
mysql_close(proxysql);
mysql_close(proxysql_admin);
for (const auto& mysql_conn : conn_pool[kAdmin]) {
mysql_close(mysql_conn.second);
}
conn_pool[kAdmin].clear();
for (const auto& mysql_conn : conn_pool[kMySQL]) {
mysql_close(mysql_conn.second);
}
conn_pool[kMySQL].clear();
}
int main(int argc, char** argv) {
if (cl.getEnv()) {
diag("Failed to get the required environmental variables.");
return -1;
}
plan(check_count(TESTS_COMBINED)*2); // also check with client_deprecate_eof flag
/*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) + // random 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
*/
std::vector<std::pair<const char*, std::vector<TestInfo>>> all_tests(test_size(TESTS_COMBINED));
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 = "RANDOM";
all_tests[2].second.insert(all_tests[2].second.end(), random_test.begin(), random_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[4].first = "QUERY_DIGEST";
all_tests[4].second.insert(all_tests[4].second.end(), query_digest_test.begin(), query_digest_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[6].first = "WARNING_LOGS";
all_tests[6].second.insert(all_tests[6].second.end(), warning_log_test.begin(), warning_log_test.end());
all_tests[7].first = "MULTIPLEXING";
all_tests[7].second.insert(all_tests[7].second.end(), multiplexing_test.begin(), multiplexing_test.end());
execute_tests(all_tests, false);
execute_tests(all_tests, true);
return exit_status();
}

Loading…
Cancel
Save