diff --git a/include/proxysql_structs.h b/include/proxysql_structs.h index 9ccdc7098..82a5ceed0 100644 --- a/include/proxysql_structs.h +++ b/include/proxysql_structs.h @@ -191,6 +191,7 @@ enum mysql_variable_name { SQL_OPTIMIZER_PRUNE_LEVEL, SQL_OPTIMIZER_SEARCH_DEPTH, SQL_OPTIMIZER_SWITCH, + SQL_OPTIMIZER_USE_CONDITION_SELECTIVITY, SQL_PROFILING, SQL_QUERY_CACHE_TYPE, SQL_SORT_BUFFER_SIZE, @@ -1135,6 +1136,7 @@ mysql_variable_st mysql_tracked_variables[] { { SQL_OPTIMIZER_PRUNE_LEVEL, SETTING_VARIABLE, false, false, true, false, (char *)"optimizer_prune_level", NULL, (char *)"" , false} , { SQL_OPTIMIZER_SEARCH_DEPTH, SETTING_VARIABLE, false, false, true, false, (char *)"optimizer_search_depth", NULL, (char *)"" , false} , { SQL_OPTIMIZER_SWITCH, SETTING_VARIABLE, true, false, false, false, (char *)"optimizer_switch", NULL, (char *)"" , false} , + { SQL_OPTIMIZER_USE_CONDITION_SELECTIVITY, SETTING_VARIABLE, false, false, true, false, (char*)"optimizer_use_condition_selectivity", NULL, (char*)"" , false} , { SQL_PROFILING, SETTING_VARIABLE, true, false, false, true, ( char *)"profiling", NULL, (char *)"" , false} , { SQL_QUERY_CACHE_TYPE, SETTING_VARIABLE, false, false, true, true, ( char *)"query_cache_type", NULL, (char *)"" , false} , // note that this variable can act both as boolean AND a number. See https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_query_cache_type { SQL_SORT_BUFFER_SIZE, SETTING_VARIABLE, false, false, true, false, (char *)"sort_buffer_size", NULL, (char *)"18446744073709551615" , false} , diff --git a/lib/MySQL_Session.cpp b/lib/MySQL_Session.cpp index 966270e3a..5b6994d73 100644 --- a/lib/MySQL_Session.cpp +++ b/lib/MySQL_Session.cpp @@ -97,6 +97,7 @@ static const std::set mysql_variables_numeric = { "max_sort_length", "optimizer_prune_level", "optimizer_search_depth", + "optimizer_use_condition_selectivity", "query_cache_type", "sort_buffer_size", "sql_select_limit", diff --git a/lib/MySQL_Thread.cpp b/lib/MySQL_Thread.cpp index 4993b14af..63021edeb 100644 --- a/lib/MySQL_Thread.cpp +++ b/lib/MySQL_Thread.cpp @@ -2900,7 +2900,7 @@ bool MySQL_Thread::init() { match_regexes[0] = NULL; // NOTE: historically we used match_regexes[0] for SET SQL_LOG_BIN . Not anymore std::stringstream ss; - ss << "^SET (|SESSION |@@|@@session.)`?(" << mysql_variables.variables_regexp << "SESSION_TRACK_GTIDS|TX_ISOLATION)`?( *)(:|)=( *)"; + ss << "^SET (|SESSION |@@|@@session.|@@local.)`?(" << 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_connection.cpp b/lib/mysql_connection.cpp index 81646e719..08a218d2f 100644 --- a/lib/mysql_connection.cpp +++ b/lib/mysql_connection.cpp @@ -2344,16 +2344,22 @@ bool MySQL_Connection::IsKeepMultiplexEnabledVariables(char *query_digest_text) } else { return false; } - //filter @@session. and @@ + //filter @@session., @@local. and @@ char *match=NULL; char* last_pos=NULL; const int at_session_offset = strlen("@@session."); + const int at_local_offset = strlen("@@local."); // Alias of session const int double_at_offset = strlen("@@"); while (query_digest_text_filter_select && (match = strcasestr(query_digest_text_filter_select,"@@session."))) { memmove(match, match + at_session_offset, strlen(match) - at_session_offset); last_pos = match + strlen(match) - at_session_offset; *last_pos = '\0'; } + while (query_digest_text_filter_select && (match = strcasestr(query_digest_text_filter_select, "@@local."))) { + memmove(match, match + at_local_offset, strlen(match) - at_local_offset); + last_pos = match + strlen(match) - at_local_offset; + *last_pos = '\0'; + } while (query_digest_text_filter_select && (match = strcasestr(query_digest_text_filter_select,"@@"))) { memmove(match, match + double_at_offset, strlen(match) - double_at_offset); last_pos = match + strlen(match) - double_at_offset; diff --git a/lib/set_parser.cpp b/lib/set_parser.cpp index f73f8f649..2942e1f55 100644 --- a/lib/set_parser.cpp +++ b/lib/set_parser.cpp @@ -33,7 +33,7 @@ std::map> SetParser::parse1() { std::map> result; -#define SESSION_P1 "(?:|SESSION +|@@|@@session.)" +#define SESSION_P1 "(?:|SESSION +|@@|@@session.|@@local.)" #define VAR_P1 "`?(@\\w+|\\w+)`?" //#define VAR_VALUE "((?:[\\w/\\d:\\+\\-]|,)+)" //#define VAR_VALUE "((?:CONCAT\\((?:(REPLACE|CONCAT)\\()+@@sql_mode,(?:(?:'|\\w|,| |\"|\\))+(?:\\)))|(?:[@\\w/\\d:\\+\\-]|,)+|(?:)))" diff --git a/test/tap/tests/generate_set_session_csv.cpp b/test/tap/tests/generate_set_session_csv.cpp index 48e5e4e63..009bbfe3f 100644 --- a/test/tap/tests/generate_set_session_csv.cpp +++ b/test/tap/tests/generate_set_session_csv.cpp @@ -234,6 +234,9 @@ int main() { vars["optimizer_switch"]->add(std::vector {"'index_merge_union=off'", "`index_merge_union=on`", "\"index_merge_union=off\""}); vars["optimizer_switch"]->add(std::vector {"'semijoin=off'", "`semijoin=on`", "\"semijoin=off\""}); + vars["optimizer_use_condition_selectivity"] = new variable("optimizer_use_condition_selectivity", true, true, false); + vars["optimizer_use_condition_selectivity"]->add({1, 2, 3, 4, 5}, 0); + vars["lc_time_names"] = new variable("lc_time_names", true, false, false); vars["lc_time_names"]->add(std::vector {"en_US", "'en_US'", "`en_US`", "\"en_US\""}); vars["lc_time_names"]->add(std::vector {"en_GB", "'en_GB'", "`en_GB`", "\"en_GB\""}); diff --git a/test/tap/tests/setparser_test.cpp b/test/tap/tests/setparser_test.cpp index d0462f885..0d2325c93 100644 --- a/test/tap/tests/setparser_test.cpp +++ b/test/tap/tests/setparser_test.cpp @@ -79,6 +79,7 @@ static Test sql_mode[] = { { "SET @@sql_mode = 'TRADITIONAL'", { Expected("sql_mode", {"TRADITIONAL"}) } }, { "SET SESSION sql_mode = 'TRADITIONAL'", { Expected("sql_mode", {"TRADITIONAL"}) } }, { "SET @@session.sql_mode = 'TRADITIONAL'", { Expected("sql_mode", {"TRADITIONAL"}) } }, + { "SET @@local.sql_mode = 'TRADITIONAL'", { Expected("sql_mode", {"TRADITIONAL"}) } }, { "SET sql_mode = 'TRADITIONAL'", { Expected("sql_mode", {"TRADITIONAL"}) } }, { "SET SQL_MODE ='TRADITIONAL'", { Expected("sql_mode", {"TRADITIONAL"}) } }, { "SET SQL_MODE = \"TRADITIONAL\"", { Expected("sql_mode", {"TRADITIONAL"}) } }, @@ -86,6 +87,7 @@ static Test sql_mode[] = { { "set sql_mode = IFNULL(NULL,\"STRICT_TRANS_TABLES\")", { Expected("sql_mode", {"IFNULL(NULL,\"STRICT_TRANS_TABLES\")"}) } }, { "set sql_mode = IFNULL(NULL,'STRICT_TRANS_TABLES')", { Expected("sql_mode", {"IFNULL(NULL,'STRICT_TRANS_TABLES')"}) } }, { "SET @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ', STRICT_ALL_TABLES'), ', NO_AUTO_VALUE_ON_ZERO')", { Expected("sql_mode", {"CONCAT(CONCAT(@@sql_mode, ', STRICT_ALL_TABLES'), ', NO_AUTO_VALUE_ON_ZERO')"}) } }, + { "SET @@LOCAL.sql_mode = CONCAT(CONCAT(@@sql_mode, ', STRICT_ALL_TABLES'), ', NO_AUTO_VALUE_ON_ZERO')", { Expected("sql_mode", {"CONCAT(CONCAT(@@sql_mode, ', STRICT_ALL_TABLES'), ', NO_AUTO_VALUE_ON_ZERO')"}) } }, { "set session sql_mode = 'ONLY_FULL_GROUP_BY'" , { Expected("sql_mode", {"ONLY_FULL_GROUP_BY"}) } }, { "SET sql_mode = 'NO_ZERO_DATE,STRICT_ALL_TABLES,ONLY_FULL_GROUP_BY'" , { Expected("sql_mode", {"NO_ZERO_DATE,STRICT_ALL_TABLES,ONLY_FULL_GROUP_BY"}) } }, { "SET @@sql_mode = CONCAT(@@sql_mode, ',', 'ONLY_FULL_GROUP_BY')" , { Expected("sql_mode", {"CONCAT(@@sql_mode, ',', 'ONLY_FULL_GROUP_BY')"}) } }, @@ -153,9 +155,11 @@ static Test session_track_gtids[] = { { "SET @@session_track_gtids = OFF", { Expected("session_track_gtids", {"OFF"}) } }, { "SET @@session_track_gtids = OWN_GTID", { Expected("session_track_gtids", {"OWN_GTID"}) } }, { "SET @@SESSION.session_track_gtids = OWN_GTID", { Expected("session_track_gtids", {"OWN_GTID"}) } }, + { "SET @@LOCAL.session_track_gtids = OWN_GTID", { Expected("session_track_gtids", {"OWN_GTID"}) } }, { "SET SESSION session_track_gtids = OWN_GTID", { Expected("session_track_gtids", {"OWN_GTID"}) } }, { "SET @@session_track_gtids = ALL_GTIDS", { Expected("session_track_gtids", {"ALL_GTIDS"}) } }, { "SET @@SESSION.session_track_gtids = ALL_GTIDS", { Expected("session_track_gtids", {"ALL_GTIDS"}) } }, + { "SET @@LOCAL.session_track_gtids = ALL_GTIDS", { Expected("session_track_gtids", {"ALL_GTIDS"}) } }, { "SET SESSION session_track_gtids = ALL_GTIDS", { Expected("session_track_gtids", {"ALL_GTIDS"}) } }, }; @@ -168,6 +172,7 @@ static Test character_set_results[] = { { "SET @@character_set_results = NULL", { Expected("character_set_results", {"NULL"}) } }, { "SET character_set_results = NULL", { Expected("character_set_results", {"NULL"}) } }, { "SET @@session.character_set_results = NULL", { Expected("character_set_results", {"NULL"}) } }, + { "SET @@local.character_set_results = NULL", { Expected("character_set_results", {"NULL"}) } }, { "SET session character_set_results = NULL", { Expected("character_set_results", {"NULL"}) } }, }; @@ -187,19 +192,25 @@ TEST(TestParse, SET_NAMES) { } static Test various[] = { { "SET @@SESSION.SQL_SELECT_LIMIT= DEFAULT", { Expected("sql_select_limit", {"DEFAULT"}) } }, + { "SET @@LOCAL.SQL_SELECT_LIMIT= DEFAULT", { Expected("sql_select_limit", {"DEFAULT"}) } }, { "SET @@SQL_SELECT_LIMIT= DEFAULT", { Expected("sql_select_limit", {"DEFAULT"}) } }, { "SET SESSION SQL_SELECT_LIMIT = DEFAULT", { Expected("sql_select_limit", {"DEFAULT"}) } }, { "SET @@SESSION.SQL_SELECT_LIMIT= 1234", { Expected("sql_select_limit", {"1234"}) } }, + { "SET @@LOCAL.SQL_SELECT_LIMIT= 1234", { Expected("sql_select_limit", {"1234"}) } }, { "SET @@SQL_SELECT_LIMIT= 1234", { Expected("sql_select_limit", {"1234"}) } }, { "SET SESSION SQL_SELECT_LIMIT = 1234", { Expected("sql_select_limit", {"1234"}) } }, { "SET @@SESSION.SQL_SELECT_LIMIT= 1234", { Expected("sql_select_limit", {"1234"}) } }, + { "SET @@LOCAL.SQL_SELECT_LIMIT= 1234", { Expected("sql_select_limit", {"1234"}) } }, { "SET @@SESSION.SQL_SELECT_LIMIT= @old_sql_select_limit", { Expected("sql_select_limit", {"@old_sql_select_limit"}) } }, + { "SET @@LOCAL.SQL_SELECT_LIMIT= @old_sql_select_limit", { Expected("sql_select_limit", {"@old_sql_select_limit"}) } }, { "SET SQL_SELECT_LIMIT= @old_sql_select_limit", { Expected("sql_select_limit", {"@old_sql_select_limit"}) } }, { "SET @@SESSION.sql_auto_is_null = 0", { Expected("sql_auto_is_null", {"0"}) } }, + { "SET @@LOCAL.sql_auto_is_null = 0", { Expected("sql_auto_is_null", {"0"}) } }, { "SET SESSION sql_auto_is_null = 1", { Expected("sql_auto_is_null", {"1"}) } }, { "SET sql_auto_is_null = OFF", { Expected("sql_auto_is_null", {"OFF"}) } }, { "SET @@sql_auto_is_null = ON", { Expected("sql_auto_is_null", {"ON"}) } }, { "SET @@SESSION.sql_safe_updates = 0", { Expected("sql_safe_updates", {"0"}) } }, + { "SET @@LOCAL.sql_safe_updates = 0", { Expected("sql_safe_updates", {"0"}) } }, { "SET SESSION sql_safe_updates = 1", { Expected("sql_safe_updates", {"1"}) } }, { "SET SQL_SAFE_UPDATES = OFF", { Expected("sql_safe_updates", {"OFF"}) } }, { "SET @@sql_safe_updates = ON", { Expected("sql_safe_updates", {"ON"}) } }, @@ -216,12 +227,20 @@ static Test multiple[] = { { "SET @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'), @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483", { Expected("sql_mode", {"CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO')"}), Expected("sql_auto_is_null", {"0"}), Expected("wait_timeout", {"2147483"}) } }, + { "SET @@LOCAL.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'), @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483", + { Expected("sql_mode", {"CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO')"}), Expected("sql_auto_is_null", {"0"}), + Expected("wait_timeout", {"2147483"}) } }, { "set autocommit=1, sql_mode = concat(@@sql_mode,',STRICT_TRANS_TABLES')", { Expected("autocommit", {"1"}), Expected("sql_mode", {"concat(@@sql_mode,',STRICT_TRANS_TABLES')"}) } }, { "SET NAMES utf8, @@SESSION.sql_mode = CONCAT(REPLACE(REPLACE(REPLACE(@@sql_mode, 'STRICT_TRANS_TABLES', ''), 'STRICT_ALL_TABLES', ''), 'TRADITIONAL', ''), ',NO_AUTO_VALUE_ON_ZERO'), @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 3600", { Expected("names", {"utf8"}), Expected("sql_mode", {"CONCAT(REPLACE(REPLACE(REPLACE(@@sql_mode, 'STRICT_TRANS_TABLES', ''), 'STRICT_ALL_TABLES', ''), 'TRADITIONAL', ''), ',NO_AUTO_VALUE_ON_ZERO')"}), Expected("sql_auto_is_null", {"0"}), Expected("wait_timeout", {"3600"}) } }, + { "SET NAMES utf8, @@LOCAL.sql_mode = CONCAT(REPLACE(REPLACE(REPLACE(@@sql_mode, 'STRICT_TRANS_TABLES', ''), 'STRICT_ALL_TABLES', ''), 'TRADITIONAL', ''), ',NO_AUTO_VALUE_ON_ZERO'), @@LOCAL.sql_auto_is_null = 0, @@LOCAL.wait_timeout = 3600", + { Expected("names", {"utf8"}), Expected("sql_mode", {"CONCAT(REPLACE(REPLACE(REPLACE(@@sql_mode, 'STRICT_TRANS_TABLES', ''), 'STRICT_ALL_TABLES', ''), 'TRADITIONAL', ''), ',NO_AUTO_VALUE_ON_ZERO')"}), Expected("sql_auto_is_null", {"0"}), + Expected("wait_timeout", {"3600"}) } }, { "set autocommit=1, session_track_schema=1, sql_mode = concat(@@sql_mode,',STRICT_TRANS_TABLES'), @@SESSION.net_write_timeout=7200", { Expected("autocommit", {"1"}), Expected("session_track_schema", {"1"}), Expected("sql_mode", {"concat(@@sql_mode,',STRICT_TRANS_TABLES')"}), Expected("net_write_timeout", {"7200"}) } }, + { "set autocommit=1, session_track_schema=1, sql_mode = concat(@@sql_mode,',STRICT_TRANS_TABLES'), @@LOCAL.net_write_timeout=7200", { Expected("autocommit", {"1"}), Expected("session_track_schema", {"1"}), Expected("sql_mode", {"concat(@@sql_mode,',STRICT_TRANS_TABLES')"}), + Expected("net_write_timeout", {"7200"}) } }, // Mutiple set queries involving 'NULL' values should be properly parsed with and without spaces { "set character_set_results=null, names latin7, character_set_client='utf8mb4'", {