From cc424b71ac0f8b502e6da8444160e2e7ed61fb90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Canna=C3=B2?= Date: Fri, 26 Mar 2021 23:59:25 +0100 Subject: [PATCH 1/8] Parse "SET wait_timeout" #3184 --- lib/MySQL_Thread.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/MySQL_Thread.cpp b/lib/MySQL_Thread.cpp index b37ec3ab6..d875c3723 100644 --- a/lib/MySQL_Thread.cpp +++ b/lib/MySQL_Thread.cpp @@ -4036,7 +4036,7 @@ bool MySQL_Thread::init() { match_regexes[0]=new Session_Regex((char *)"^SET (|SESSION |@@|@@session.)SQL_LOG_BIN( *)(:|)=( *)"); std::stringstream ss; - ss << "^SET (|SESSION |@@|@@session.)(" << mysql_variables.variables_regexp << "SESSION_TRACK_GTIDS|TX_ISOLATION( *)(:|)=( *))"; + ss << "^SET (|SESSION |@@|@@session.)(" << mysql_variables.variables_regexp << "wait_timeout|SESSION_TRACK_GTIDS|TX_ISOLATION( *)(:|)=( *))"; match_regexes[1]=new Session_Regex((char *)ss.str().c_str()); match_regexes[2]=new Session_Regex((char *)"^SET(?: +)(|SESSION +)TRANSACTION(?: +)(?:(?:(ISOLATION(?: +)LEVEL)(?: +)(REPEATABLE(?: +)READ|READ(?: +)COMMITTED|READ(?: +)UNCOMMITTED|SERIALIZABLE))|(?:(READ)(?: +)(WRITE|ONLY)))"); From f0e3a87159fd1834bdc19f3555a2b5a19fc9f086 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Canna=C3=B2?= Date: Mon, 29 Mar 2021 13:00:49 +0200 Subject: [PATCH 2/8] Introduce ignore_vars in MySQL_Variables This vector lists all the variables that proxysql will parse but ignore --- include/MySQL_Variables.h | 3 ++- lib/MySQL_Session.cpp | 3 +++ lib/MySQL_Thread.cpp | 2 +- lib/MySQL_Variables.cpp | 8 ++++++++ 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/include/MySQL_Variables.h b/include/MySQL_Variables.h index 692c83df0..60755da11 100644 --- a/include/MySQL_Variables.h +++ b/include/MySQL_Variables.h @@ -30,7 +30,8 @@ class MySQL_Variables { public: std::string variables_regexp; - + // ignore_vars is a list of all variables that proxysql will parse but ignore its value + std::vector ignore_vars; public: MySQL_Variables(); diff --git a/lib/MySQL_Session.cpp b/lib/MySQL_Session.cpp index 51433a6a2..38ecfcceb 100644 --- a/lib/MySQL_Session.cpp +++ b/lib/MySQL_Session.cpp @@ -5738,6 +5738,9 @@ bool MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C return false; proxy_debug(PROXY_DEBUG_MYSQL_COM, 8, "Changing connection TX ISOLATION to %s\n", value1.c_str()); } + } else if (std::find(mysql_variables.ignore_vars.begin(), mysql_variables.ignore_vars.end(), var) != mysql_variables.ignore_vars.end()) { + std::string value1 = *values; + proxy_info("%s = %s\n", var.c_str(), value1.c_str()); } else { std::string value1 = *values; std::size_t found_at = value1.find("@"); diff --git a/lib/MySQL_Thread.cpp b/lib/MySQL_Thread.cpp index d875c3723..b37ec3ab6 100644 --- a/lib/MySQL_Thread.cpp +++ b/lib/MySQL_Thread.cpp @@ -4036,7 +4036,7 @@ bool MySQL_Thread::init() { match_regexes[0]=new Session_Regex((char *)"^SET (|SESSION |@@|@@session.)SQL_LOG_BIN( *)(:|)=( *)"); std::stringstream ss; - ss << "^SET (|SESSION |@@|@@session.)(" << mysql_variables.variables_regexp << "wait_timeout|SESSION_TRACK_GTIDS|TX_ISOLATION( *)(:|)=( *))"; + ss << "^SET (|SESSION |@@|@@session.)(" << mysql_variables.variables_regexp << "SESSION_TRACK_GTIDS|TX_ISOLATION( *)(:|)=( *))"; match_regexes[1]=new Session_Regex((char *)ss.str().c_str()); match_regexes[2]=new Session_Regex((char *)"^SET(?: +)(|SESSION +)TRANSACTION(?: +)(?:(?:(ISOLATION(?: +)LEVEL)(?: +)(REPEATABLE(?: +)READ|READ(?: +)COMMITTED|READ(?: +)UNCOMMITTED|SERIALIZABLE))|(?:(READ)(?: +)(WRITE|ONLY)))"); diff --git a/lib/MySQL_Variables.cpp b/lib/MySQL_Variables.cpp index 2c56553b1..ddf766e9e 100644 --- a/lib/MySQL_Variables.cpp +++ b/lib/MySQL_Variables.cpp @@ -20,6 +20,10 @@ update_var MySQL_Variables::updaters[SQL_NAME_LAST]; MySQL_Variables::MySQL_Variables() { + // add here all the variables we want proxysql to recognize, but ignore + ignore_vars.push_back("interactve_timeout"); + ignore_vars.push_back("wait_timeout"); + ignore_vars.push_back("net_read_timeout"); variables_regexp = ""; for (auto i = 0; i < SQL_NAME_LAST; i++) { if (i == SQL_CHARACTER_SET || i == SQL_CHARACTER_ACTION || i == SQL_SET_NAMES) { @@ -38,6 +42,10 @@ MySQL_Variables::MySQL_Variables() { variables_regexp += "|"; } } + for (std::vector::iterator it=ignore_vars.begin(); it != ignore_vars.end(); it++) { + variables_regexp += *it; + variables_regexp += "|"; + } } MySQL_Variables::~MySQL_Variables() {} From 111c737d80ec90bf4027662921a4eb0fa989e92d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Canna=C3=B2?= Date: Mon, 29 Mar 2021 13:02:33 +0200 Subject: [PATCH 3/8] SetParser also parses user defined variables --- lib/set_parser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/set_parser.cpp b/lib/set_parser.cpp index 5c1af1023..c096fcfc3 100644 --- a/lib/set_parser.cpp +++ b/lib/set_parser.cpp @@ -34,7 +34,7 @@ std::map> SetParser::parse1() { std::map> result; #define SESSION_P1 "(?:|SESSION +|@@|@@session.)" -#define VAR_P1 "(\\w+)" +#define VAR_P1 "(@\\w+|\\w+)" //#define VAR_VALUE "((?:[\\w/\\d:\\+\\-]|,)+)" //#define VAR_VALUE "((?:CONCAT\\((?:(REPLACE|CONCAT)\\()+@@sql_mode,(?:(?:'|\\w|,| |\"|\\))+(?:\\)))|(?:[@\\w/\\d:\\+\\-]|,)+|(?:)))" #define VAR_VALUE_P1 "(((?:CONCAT\\()*(?:((?: )*REPLACE|IFNULL|CONCAT)\\()+(?: )*(?:NULL|@OLD_SQL_MODE|@@sql_mode),(?:(?:'|\\w|,| |\"|\\))+(?:\\))*)|(?:[@\\w/\\d:\\+\\-]|,)+|(?:)))" From 76deab2fade4db82d631d56dab88b141a95fb558 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Canna=C3=B2?= Date: Mon, 29 Mar 2021 18:18:04 +0200 Subject: [PATCH 4/8] Add lock on hostgroup for any not parsed variable --- lib/MySQL_Session.cpp | 17 ++++++++++++----- lib/MySQL_Variables.cpp | 2 +- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/lib/MySQL_Session.cpp b/lib/MySQL_Session.cpp index 38ecfcceb..5609464fe 100644 --- a/lib/MySQL_Session.cpp +++ b/lib/MySQL_Session.cpp @@ -5386,6 +5386,7 @@ bool MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C unsigned int nTrx=NumActiveTransactions(); if ((locked_on_hostgroup == -1) && (strncasecmp(dig,(char *)"SET ",4)==0)) { // this code is executed only if locked_on_hostgroup is not set yet + // if locked_on_hostgroup is set, we do not try to parse the SET statement #ifdef DEBUG { string nqn = string((char *)CurrentQuery.QueryPointer,CurrentQuery.QueryLength); @@ -5739,13 +5740,19 @@ bool MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C proxy_debug(PROXY_DEBUG_MYSQL_COM, 8, "Changing connection TX ISOLATION to %s\n", value1.c_str()); } } else if (std::find(mysql_variables.ignore_vars.begin(), mysql_variables.ignore_vars.end(), var) != mysql_variables.ignore_vars.end()) { + // this is a variable we parse but ignore + // see MySQL_Variables::MySQL_Variables() for a list of ignored variables +#ifdef DEBUG std::string value1 = *values; - proxy_info("%s = %s\n", var.c_str(), value1.c_str()); + proxy_debug(PROXY_DEBUG_MYSQL_COM, 5, "Processing SET %s value %s\n", var.c_str(), value1.c_str()); +#endif // DEBUG } else { - std::string value1 = *values; - std::size_t found_at = value1.find("@"); - if (found_at != std::string::npos) { - unable_to_parse_set_statement(lock_hostgroup); + // if we reach here, proxysql didn't recognize every variable in a set statement + // unable_to_parse_set_statement() will consider the value of qpo->multiplex, + // therefore unable_to_parse_set_statement() may set or not set lock_hostgroup. + // if host_hostgroup is set, we return immediately + unable_to_parse_set_statement(lock_hostgroup); + if (lock_hostgroup) { return false; } } diff --git a/lib/MySQL_Variables.cpp b/lib/MySQL_Variables.cpp index ddf766e9e..f3f9660a5 100644 --- a/lib/MySQL_Variables.cpp +++ b/lib/MySQL_Variables.cpp @@ -21,7 +21,7 @@ update_var MySQL_Variables::updaters[SQL_NAME_LAST]; MySQL_Variables::MySQL_Variables() { // add here all the variables we want proxysql to recognize, but ignore - ignore_vars.push_back("interactve_timeout"); + ignore_vars.push_back("interactive_timeout"); ignore_vars.push_back("wait_timeout"); ignore_vars.push_back("net_read_timeout"); variables_regexp = ""; From cda3fef7463b2bf30b7498109e90a3ce0d9824ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Jaramago=20Fern=C3=A1ndez?= Date: Fri, 26 Mar 2021 10:05:33 +0100 Subject: [PATCH 5/8] Added regression test 'reg_test_3184-set_wait_timeout-t.cpp' for changes to 'SET wait_timeout' handling --- .../reg_test_3184-set_wait_timeout-t.cpp | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 test/tap/tests/reg_test_3184-set_wait_timeout-t.cpp diff --git a/test/tap/tests/reg_test_3184-set_wait_timeout-t.cpp b/test/tap/tests/reg_test_3184-set_wait_timeout-t.cpp new file mode 100644 index 000000000..399f85dd6 --- /dev/null +++ b/test/tap/tests/reg_test_3184-set_wait_timeout-t.cpp @@ -0,0 +1,93 @@ +/** + * @file reg_test_3184-set_wait_timeout-t.cpp + * @brief This test is a regression test for issue #3184. + * @details The test performs all the valid supported combinations of + * 'SET @@wait_timeout' queries that ProxySQL should ignore, returning + * an okay packet. The check is performed via 'PROXYSQL INTERNAL SESSION', + * checking that multiplexing hasn't been disable due to an unknown + * 'SET' statement. + * + * @date 2021-03-26 + */ + +#include +#include +#include +#include + +#include "tap.h" +#include "command_line.h" +#include "utils.h" +#include "json.hpp" + +using std::string; +using namespace nlohmann; + + +/** + * @brief Helper function to convert a 'MYSQL_RES' into a + * nlohmann::json. + * + * @param result The 'MYSQL_RES*' to be converted into JSON. + * @param j 'nlohmann::json' output parameter holding the + * converted 'MYSQL_RES' supplied. + */ +void parse_result_json_column(MYSQL_RES *result, json& j) { + if(!result) return; + MYSQL_ROW row; + + while ((row = mysql_fetch_row(result))) { + j = json::parse(row[0]); + } +} + +/** + * @brief Valid variations of 'SET wait_timeout' supported + * by ProxySQL to be ignored. + */ +std::vector valids_set_wait_timeout { + "SET @@wait_timeout = 2147483", + "SET @@wait_timeout=2147483", + "SET @@SESSION.wait_timeout = 2147483", + "SET @@SESSION.wait_timeout=2147483", + "SET wait_timeout = 2147483", + "SET wait_timeout=2147483", + "SET SESSION wait_timeout = 2147483", + "SET SESSION wait_timeout=2147483" +}; + +int main(int argc, char** argv) { + CommandLine cl; + + if (cl.getEnv()) { + diag("Failed to get the required environmental variables."); + return -1; + } + + plan(2 * valids_set_wait_timeout.size()); + + MYSQL* proxysql_mysql = mysql_init(NULL); + + if (!mysql_real_connect(proxysql_mysql, 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_mysql)); + return -1; + } + + for (const auto& set_wait_timeout : valids_set_wait_timeout) { + int query_err = mysql_query(proxysql_mysql, set_wait_timeout.c_str()); + ok (query_err == 0, "Query '%s' should be properly executed.", set_wait_timeout.c_str()); + + MYSQL_QUERY(proxysql_mysql, "PROXYSQL INTERNAL SESSION"); + json j_status {}; + MYSQL_RES* int_session_res = mysql_store_result(proxysql_mysql); + parse_result_json_column(int_session_res, j_status); + mysql_free_result(int_session_res); + + bool found_backends = j_status.contains("backends"); + ok(found_backends == false, "No backends should be found for the current connection."); + } + + mysql_close(proxysql_mysql); + + return exit_status(); +} From 53ede7fca74d4814adf55cf10c784fe42ecb8a96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Jaramago=20Fern=C3=A1ndez?= Date: Fri, 26 Mar 2021 13:36:12 +0100 Subject: [PATCH 6/8] Added tap test 'test_filtered_set_statements-t.cpp' to check that supported 'SET' statements are being properly filtered by ProxySQL --- .../tests/test_filtered_set_statements-t.cpp | 139 ++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 test/tap/tests/test_filtered_set_statements-t.cpp diff --git a/test/tap/tests/test_filtered_set_statements-t.cpp b/test/tap/tests/test_filtered_set_statements-t.cpp new file mode 100644 index 000000000..053b196f7 --- /dev/null +++ b/test/tap/tests/test_filtered_set_statements-t.cpp @@ -0,0 +1,139 @@ +/** + * @file test_filtered_set_statements-t.cpp + * @brief Test for checking that all the supported 'SET statements' are + * handled properly by ProxySQL. + * @details The test performs all the valid supported combinations of + * all the specified 'SET' statements that should be specially handled + * by ProxySQL. For confirming that this is being the case, the test + * checks that 'sum_time' is always '0' for all these special queries + * after issuing them. + * + * @date 2021-03-26 + */ + +#include +#include +#include +#include + +#include "proxysql_utils.h" +#include "tap.h" +#include "command_line.h" +#include "utils.h" +#include + +/** + * @brief Queries to be tested that are known to be filtered by ProxySQL. + * + * TODO: Fill with all the statements that should be properly handled by ProxySQL. + */ +std::vector> filtered_set_queries { + { "sql_mode", "" }, + { "wait_timeout", "param" }, + { "character_set_results", "latin1" }, + { "character_set_connection", "latin1" }, + { "character_set_database", "latin1" }, +// TODO: This queries fails for some values +// { "character_set_server", "latin1" }, +// { "character_set_client", "latin1" }, + { "autocommit", "1" }, + { "sql_select_limit", "4294967295" }, + { "net_write_timeout", "25" }, + { "max_join_size", "18446744073709551615" }, + { "wsrep_sync_wait", "12" }, + { "group_concat_max_len", "4294967295" }, + { "sql_safe_updates", "true" }, + { "session_track_gtids", "OWN_GTID" } +}; + +std::vector get_valid_set_query_set(const std::string& set_query, const std::string param) { + std::vector result {}; + + result.push_back(std::string("SET @@") + set_query + "=" + param); + result.push_back(std::string("SET @@") + set_query + " = " + param); + result.push_back(std::string("SET @@SESSION ") + set_query + " = " + param); + result.push_back(std::string("SET @@SESSION ") + set_query + "=" + param); + result.push_back(std::string("SET ") + set_query + "=" + param); + result.push_back(std::string("SET ") + set_query + " = " + param); + result.push_back(std::string("SET SESSION ") + set_query + "=" + param); + result.push_back(std::string("SET SESSION ") + set_query + " = " + param); + + return result; +} + +int main(int argc, char** argv) { + CommandLine cl; + + if (cl.getEnv()) { + diag("Failed to get the required environmental variables."); + return -1; + } + + // plan one test per statement attempt + one check 'SUM(sum_time) == 0' for each 'filtered_set_queries' + plan(filtered_set_queries.size() + filtered_set_queries.size()*get_valid_set_query_set("", "").size()); + + // create a regular connection to 'proxysql' + MYSQL* proxysql_mysql = mysql_init(NULL); + if (!mysql_real_connect(proxysql_mysql, 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_mysql)); + return -1; + } + + // create a connection to 'proxysql_admin' + MYSQL* proxysql_admin = mysql_init(NULL); + if (!mysql_real_connect(proxysql_admin, cl.host, cl.admin_password, 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 -1; + } + + // first clean the 'stats_mysql_query_digest' table + MYSQL_QUERY(proxysql_admin, "SELECT null FROM stats.stats_mysql_query_digest_reset LIMIT 0"); + MYSQL_RES* reset_result = mysql_store_result(proxysql_admin); + mysql_free_result(reset_result); + + std::string t_sum_query { "SELECT SUM(sum_time) FROM stats.stats_mysql_query_digest WHERE digest_text LIKE '%%%s%%'" }; + + for (const auto& filtered_query : filtered_set_queries) { + const std::vector f_filtered_query_set = + get_valid_set_query_set(filtered_query.first, filtered_query.second); + + for (const auto& set_query : f_filtered_query_set) { + int query_err = mysql_query(proxysql_mysql, set_query.c_str()); + ok (query_err == 0, "Query '%s' should be properly executed.", set_query.c_str()); + + } + + std::string sum_query { "" }; + string_format(t_sum_query, sum_query, filtered_query.first.c_str()); + MYSQL_QUERY(proxysql_admin, sum_query.c_str()); + + MYSQL_RES* sum_query_res = mysql_store_result(proxysql_admin); + int sum_sum_time = -1; + + int field_count = mysql_num_fields(sum_query_res); + if (field_count == 1) { + MYSQL_ROW row = mysql_fetch_row(sum_query_res); + + if (row[0] != nullptr) { + sum_sum_time = atoi(row[0]); + } + } + + mysql_free_result(sum_query_res); + + ok ( + sum_sum_time == 0, + "The SUM(sum_time) of all the variations for the 'set_statements:%s' should be zero. Value was: %d", + filtered_query.first.c_str(), + sum_sum_time + ); + } + + // close proxysql connection + mysql_close(proxysql_mysql); + + // close admin connection + mysql_close(proxysql_admin); + + return exit_status(); +} From 70299f79a756ac9a269e93f85dc4f6f220c4fa1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Jaramago=20Fern=C3=A1ndez?= Date: Mon, 29 Mar 2021 21:46:51 +0200 Subject: [PATCH 7/8] Added new variables 'interactive_timeout' and 'net_read_timeout' to tap tests 'test_filtered_set_statements-t' and 'reg_test_3184-set_wait_timeout-t' --- .../reg_test_3184-set_wait_timeout-t.cpp | 21 ++++++++++++++++++- .../tests/test_filtered_set_statements-t.cpp | 4 +++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/test/tap/tests/reg_test_3184-set_wait_timeout-t.cpp b/test/tap/tests/reg_test_3184-set_wait_timeout-t.cpp index 399f85dd6..cb3f967d0 100644 --- a/test/tap/tests/reg_test_3184-set_wait_timeout-t.cpp +++ b/test/tap/tests/reg_test_3184-set_wait_timeout-t.cpp @@ -53,7 +53,26 @@ std::vector valids_set_wait_timeout { "SET wait_timeout = 2147483", "SET wait_timeout=2147483", "SET SESSION wait_timeout = 2147483", - "SET SESSION wait_timeout=2147483" + "SET SESSION wait_timeout=2147483", + + "SET @@net_read_timeout = 2147483", + "SET @@net_read_timeout=2147483", + "SET @@SESSION.net_read_timeout = 2147483", + "SET @@SESSION.net_read_timeout=2147483", + "SET net_read_timeout = 2147483", + "SET net_read_timeout=2147483", + "SET SESSION net_read_timeout = 2147483", + "SET SESSION net_read_timeout=2147483", + + "SET @@interactive_timeout = 2147483", + "SET @@interactive_timeout=2147483", + "SET @@SESSION.interactive_timeout = 2147483", + "SET @@SESSION.interactive_timeout=2147483", + "SET interactive_timeout = 2147483", + "SET interactive_timeout=2147483", + "SET SESSION interactive_timeout = 2147483", + "SET SESSION interactive_timeout=2147483" + }; int main(int argc, char** argv) { diff --git a/test/tap/tests/test_filtered_set_statements-t.cpp b/test/tap/tests/test_filtered_set_statements-t.cpp index 053b196f7..99fee1976 100644 --- a/test/tap/tests/test_filtered_set_statements-t.cpp +++ b/test/tap/tests/test_filtered_set_statements-t.cpp @@ -43,7 +43,9 @@ std::vector> filtered_set_queries { { "wsrep_sync_wait", "12" }, { "group_concat_max_len", "4294967295" }, { "sql_safe_updates", "true" }, - { "session_track_gtids", "OWN_GTID" } + { "session_track_gtids", "OWN_GTID" }, + { "interactive_timeout", "param" }, + { "net_read_timeout", "param" }, }; std::vector get_valid_set_query_set(const std::string& set_query, const std::string param) { From bcb55895066ffe36373d7e97bbc25d929aed5f67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Jaramago=20Fern=C3=A1ndez?= Date: Mon, 29 Mar 2021 21:49:53 +0200 Subject: [PATCH 8/8] Fixed typo in comment --- lib/MySQL_Session.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/MySQL_Session.cpp b/lib/MySQL_Session.cpp index 5609464fe..c7b0b269a 100644 --- a/lib/MySQL_Session.cpp +++ b/lib/MySQL_Session.cpp @@ -5750,7 +5750,7 @@ bool MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C // if we reach here, proxysql didn't recognize every variable in a set statement // unable_to_parse_set_statement() will consider the value of qpo->multiplex, // therefore unable_to_parse_set_statement() may set or not set lock_hostgroup. - // if host_hostgroup is set, we return immediately + // if lock_hostgroup is set, we return immediately unable_to_parse_set_statement(lock_hostgroup); if (lock_hostgroup) { return false;