From 4b49c38ea7c075a2e99c0d4ac4b644b88da217da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Canna=C3=B2?= Date: Mon, 26 Jun 2023 14:11:22 +0000 Subject: [PATCH] Adding setparser_test2 , possible as a complete replacement of setparser_test --- .gitignore | 1 + test/tap/tests/Makefile | 8 + test/tap/tests/setparser_test2.cpp | 307 +++++++++++++++++++++++++++++ 3 files changed, 316 insertions(+) create mode 100644 test/tap/tests/setparser_test2.cpp diff --git a/.gitignore b/.gitignore index b2c1d9626..124d43e2b 100644 --- a/.gitignore +++ b/.gitignore @@ -116,6 +116,7 @@ test/tap/tap/cpp-dotenv/cpp-dotenv-* test/tap/tests/galera_1_timeout_count test/tap/tests/galera_2_timeout_no_count test/tap/tests/setparser_test +test/tap/tests/setparser_test2 test/tap/tests/reg_test_3504-change_user_libmariadb_helper test/tap/tests/reg_test_3504-change_user_libmysql_helper test/tap/tests/generate_set_session_csv diff --git a/test/tap/tests/Makefile b/test/tap/tests/Makefile index 72807857a..6b70589e3 100644 --- a/test/tap/tests/Makefile +++ b/test/tap/tests/Makefile @@ -127,6 +127,7 @@ debug: tests tests: tests-cpp tests-php tests-py \ setparser_test reg_test_3504-change_user_libmariadb_helper reg_test_3504-change_user_libmysql_helper \ + setparser_test2 setparser_test2-t \ set_testing-240.csv test_clickhouse_server_libmysql-t reg_test_stmt_resultset_err_no_rows_libmysql-t \ prepare_statement_err3024_libmysql-t prepare_statement_err3024_async-t reg_test_mariadb_stmt_store_result_libmysql-t \ reg_test_mariadb_stmt_store_result_async-t @@ -183,6 +184,13 @@ create_connection_annotation: test_connection_annotation-t.cpp setparser_test: setparser_test.cpp $(TAP_LIBDIR)/libtap.a $(RE2_PATH)/util/test.cc $(LDIR)/set_parser.cpp $(LIBPROXYSQLAR) $(LIBCOREDUMPERAR) g++ -DDEBUG setparser_test.cpp $(RE2_PATH)/util/test.cc $(INCLUDEDIRS) $(LDIRS) $(OPT) -std=c++11 -lproxysql $(MYLIBS) -ltap -ldl -lpthread $(WASAN) $(LIBCOREDUMPERAR) -o setparser_test -DGITVERSION=\"$(GIT_VERSION)\" +setparser_test2-t: setparser_test2 + rm setparser_test2-t || true + ln -s setparser_test2 setparser_test2-t + +setparser_test2: setparser_test2.cpp $(TAP_LIBDIR)/libtap.a $(LDIR)/set_parser.cpp $(LIBPROXYSQLAR) $(LIBCOREDUMPERAR) + g++ -DDEBUG setparser_test2.cpp $(LDIR)/set_parser.cpp $(INCLUDEDIRS) $(LDIRS) $(OPT) -std=c++11 -lproxysql $(MYLIBS) -ltap -ldl -lpthread $(WASAN) $(LIBCOREDUMPERAR) -o setparser_test2 -DGITVERSION=\"$(GIT_VERSION)\" + reg_test_3504-change_user_libmariadb_helper: reg_test_3504-change_user_helper.cpp $(CXX) -DDEBUG reg_test_3504-change_user_helper.cpp $(INCLUDEDIRS) $(LDIRS) $(OPT) $(MYLIBS) -lpthread -ldl -std=c++11 -ltap $(STATIC_LIBS) -o reg_test_3504-change_user_libmariadb_helper -DGITVERSION=\"$(GIT_VERSION)\" diff --git a/test/tap/tests/setparser_test2.cpp b/test/tap/tests/setparser_test2.cpp new file mode 100644 index 000000000..fe5dd6358 --- /dev/null +++ b/test/tap/tests/setparser_test2.cpp @@ -0,0 +1,307 @@ +/** + * @file setparser_test.cpp + * @brief Test file for unit testing 'SetParser' type, responsible of parsing + * non-trivial 'SET' statements. This test is executed via the wrapper tap test + * 'setparser_test-t'. + * This file is an extension of ../../set_parser_test/setparsertest.cpp + */ + +// NOTE: Avoids the definition of 'global_variables glovars' in 'proxysql_structs.h' +#define PROXYSQL_EXTERN +// NOTE: Avoids definition of 'proxy_sqlite3_*' functions as 'extern' +#define MAIN_PROXY_SQLITE3 + +#include "command_line.h" +#include "tap.h" + +#include + +#include "re2/re2.h" +#include "re2/regexp.h" +#include "util/test.h" +#include "set_parser.h" +#include +#include +#include +#include +#include + +// ******************************************************************************************* +/** + * TODO: This should be fixed once we have improved include hierarchy. All the following + * includes are required to avoid the following linker error related to 'GloMyLdapAuth': + * + * ``` + * /usr/bin/ld: ../../../lib/libproxysql.a(ProxySQL_GloVars.oo): in function `ProxySQL_GlobalVariables::generate_global_checksum()': + * /home/javjarfer/Projects/proxysql_v2.2.0/lib/ProxySQL_GloVars.cpp:374: undefined reference to `GloMyLdapAuth' + * ``` + * + * For now we just declare it locally to avoid the linking error. + */ +#include "openssl/ssl.h" +#include "mysql.h" +#include "proxysql_structs.h" +#include "sqlite3db.h" +#include "MySQL_LDAP_Authentication.hpp" + +using namespace std; + +MySQL_LDAP_Authentication *GloMyLdapAuth = nullptr; +// ****************************************************************************************** + +bool iequals(const std::string& a, const std::string& b) +{ + unsigned int sz = a.size(); + if (b.size() != sz) + return false; + for (unsigned int i = 0; i < sz; ++i) + if (tolower(a[i]) != tolower(b[i])) + return false; + return true; +} + + +void printMap(const std::string query, std::map> map) { + std::cout << "Query: " << query << endl; + for (const auto& entry : map) { + std::cout << " - Key: " << entry.first << endl; + + for (const auto& value : entry.second) { + std::cout << " + Value: " << value << endl; + } + } +} + + +struct Expected { + const char* var; + std::vector values; + Expected(const char* var, std::vector values): var(var), values(values){}; +}; + +struct Test { + const char* query; + std::vector results; +}; + +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"}) } }, + { "SET SQL_MODE = TRADITIONAL", { Expected("sql_mode", {"TRADITIONAL"}) } }, + { "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')"}) } }, + { "SET @@sql_mode = REPLACE(REPLACE(REPLACE(@@sql_mode, 'ONLY_FULL_GROUP_BY,', ''),',ONLY_FULL_GROUP_BY', ''),'ONLY_FULL_GROUP_BY', '')" , { Expected("sql_mode", {"REPLACE(REPLACE(REPLACE(@@sql_mode, 'ONLY_FULL_GROUP_BY,', ''),',ONLY_FULL_GROUP_BY', ''),'ONLY_FULL_GROUP_BY', '')"}) } }, + { "SET @@sql_mode = REPLACE( REPLACE( REPLACE( @@sql_mode, 'ONLY_FULL_GROUP_BY,', ''),',ONLY_FULL_GROUP_BY', ''),'ONLY_FULL_GROUP_BY', '')" , { Expected("sql_mode", {"REPLACE( REPLACE( REPLACE( @@sql_mode, 'ONLY_FULL_GROUP_BY,', ''),',ONLY_FULL_GROUP_BY', ''),'ONLY_FULL_GROUP_BY', '')"}) } }, +// { "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 SQL_MODE=IFNULL(@@sql_mode,'')", { Expected("sql_mode", { "IFNULL(@@sql_mode,'')" } ) } }, + { "SET SQL_MODE=IFNULL(@old_sql_mode,'')", { Expected("sql_mode", { "IFNULL(@old_sql_mode,'')" } ) } }, + { "SET SQL_MODE=IFNULL(@OLD_SQL_MODE,'')", { Expected("sql_mode", { "IFNULL(@OLD_SQL_MODE,'')" } ) } }, + // Complex queries involving 'SELECT' and surrounding parenthesis should be parsed properly + { "SET sql_mode=(SELECT CONCAT(@@sql_mode, ',PIPES_AS_CONCAT,NO_ENGINE_SUBSTITUTION'))", { Expected("sql_mode", { "(SELECT CONCAT(@@sql_mode, ',PIPES_AS_CONCAT,NO_ENGINE_SUBSTITUTION'))" } ) } }, + { "SET sql_mode=(SELECT CONCAT(@@sql_mode, ',PIPES_AS_CONCAT,NO_ENGINE_SUBSTITUTION')), time_zone = '+00:00', NAMES utf8mb4 COLLATE utf8mb4_unicode_ci", + { + Expected("sql_mode", { "(SELECT CONCAT(@@sql_mode, ',PIPES_AS_CONCAT,NO_ENGINE_SUBSTITUTION'))" } ), + Expected("time_zone", { "+00:00" } ), + Expected("names", {"utf8mb4", "utf8mb4_unicode_ci"} ) + } + }, + // Empty set of 'sql_mode' should result into an empty value + { "SET sql_mode=''", { Expected("sql_mode", { "" } ) } }, + // Invalid 'non-matching' versions of 'sql_mode' should result into 'non-matching' + { "SET sql_mode=(SELECT CONCA(@@sql_mode, ',PIPES_AS_CONCAT,NO_ENGINE_SUBSTITUTION'))", {} }, + { "SET sql_mode=(SELECT CONCAT(@sql_mode, ',PIPES_AS_CONCAT,NO_ENGINE_SUBSTITUTION'))", {} }, + { "SET sql_mode=(SELECT CONCAT(@@sql_mode, ',PIPES_AS_CONCAT[,NO_ENGINE_SUBSTITUTION'))", {} }, + { "SET sql_mode=(SELCT CONCAT(@@sql_mode, ',PIPES_AS_CONCAT[,NO_ENGINE_SUBSTITUTION'))", {} } +}; + +void TestParse(const Test* tests, int ntests, const std::string& title) { + for (int i = 0; i < ntests; i++) { + std::map> data; + for(auto it = std::begin(tests[i].results); it != std::end(tests[i].results); ++it) { + data[it->var] = it->values; + } + + SetParser parser(tests[i].query); + std::map> result = parser.parse1(); + + cout << endl; + printMap("result", result); + cout << endl; + printMap("expected", data); + cout << endl; + + CHECK_EQ(result.size(), data.size()); + ok(result.size() == data.size() , "Sizes match: %lu, %lu" , result.size() , data.size()); + CHECK(std::equal(std::begin(result), std::end(result), std::begin(data))); + ok(std::equal(std::begin(result), std::end(result), std::begin(data)) == true, "Elements match"); + } +} + +/* +TEST(TestParse, SET_SQL_MODE) { + TestParse(sql_mode, arraysize(sql_mode), "sql_mode"); +} +*/ +static Test time_zone[] = { + { "SET @@time_zone = 'Europe/Paris'", { Expected("time_zone", {"Europe/Paris"}) } }, + { "SET @@time_zone = '+00:00'", { Expected("time_zone", {"+00:00"}) } }, + { "SET @@time_zone = \"Europe/Paris\"", { Expected("time_zone", {"Europe/Paris"}) } }, + { "SET @@time_zone = \"+00:00\"", { Expected("time_zone", {"+00:00"}) } }, + { "SET @@time_zone = @OLD_TIME_ZONE", { Expected("time_zone", {"@OLD_TIME_ZONE"}) } }, + { "SET @@TIME_ZONE = @OLD_TIME_ZONE", { Expected("time_zone", {"@OLD_TIME_ZONE"}) } }, +}; + +/* +TEST(TestParse, SET_TIME_ZONE) { + TestParse(time_zone, arraysize(time_zone), "time_zone"); +} +*/ + +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"}) } }, +}; + +/* +TEST(TestParse, SET_SESSION_TRACK_GTIDS) { + TestParse(session_track_gtids, arraysize(session_track_gtids), "session_track_gtids"); +} +*/ + +static Test character_set_results[] = { + { "SET @@character_set_results = utf8", { Expected("character_set_results", {"utf8"}) } }, + { "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"}) } }, +}; + +static Test names[] = { + { "SET NAMES utf8", { Expected("names", {"utf8"}) } }, + { "SET NAMES 'utf8'", { Expected("names", {"utf8"}) } }, + { "SET NAMES \"utf8\"", { Expected("names", {"utf8"}) } }, + { "SET NAMES utf8 COLLATE unicode_ci", { Expected("names", {"utf8", "unicode_ci"}) } }, +}; + +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"}) } }, +}; + +static Test multiple[] = { + { "SET time_zone = 'Europe/Paris', sql_mode = 'TRADITIONAL'", { Expected("time_zone", {"Europe/Paris"}), Expected("sql_mode", {"TRADITIONAL"}) } }, + { "SET time_zone = 'Europe/Paris', sql_mode = IFNULL(NULL,\"STRICT_TRANS_TABLES\")", { Expected("time_zone", {"Europe/Paris"}), Expected("sql_mode", {"IFNULL(NULL,\"STRICT_TRANS_TABLES\")"}) } }, + { "SET sql_mode = 'TRADITIONAL', NAMES 'utf8 COLLATE 'unicode_ci'", { Expected("sql_mode", {"TRADITIONAL"}), Expected("names", {"utf8", "unicode_ci"}) } }, + { "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'", + { + Expected("character_set_results", { "null" } ), + Expected("names", { "latin7" } ), + Expected("character_set_client", { "utf8mb4" } ), + } + }, + { "SET character_set_results=NULL, NAMES latin7, character_set_client='utf8mb4'", + { + Expected("character_set_results", { "NULL" } ), + Expected("names", { "latin7" } ), + Expected("character_set_client", { "utf8mb4" } ), + } + }, + { "set character_set_results=null,names latin7,character_set_client='utf8mb4'", + { + Expected("character_set_results", { "null" } ), + Expected("names", { "latin7" } ), + Expected("character_set_client", { "utf8mb4" } ), + } + }, + { "SET character_set_results=NULL,NAMES latin7,character_set_client='utf8mb4'", + { + Expected("character_set_results", { "NULL" } ), + Expected("names", { "latin7" } ), + Expected("character_set_client", { "utf8mb4" } ), + } + }, +}; + + +int main(int argc, char** argv) { + CommandLine cl; + + if(cl.getEnv()) + return exit_status(); + + unsigned int p = 0; + p += arraysize(sql_mode); + p += arraysize(time_zone); + p += arraysize(session_track_gtids); + p += arraysize(character_set_results); + p += arraysize(names); + p += arraysize(various); + p += arraysize(multiple); + p *= 2; + plan(p); + TestParse(sql_mode, arraysize(sql_mode), "sql_mode"); + TestParse(time_zone, arraysize(time_zone), "time_zone"); + TestParse(session_track_gtids, arraysize(session_track_gtids), "session_track_gtids"); + TestParse(character_set_results, arraysize(character_set_results), "character_set_results"); + TestParse(names, arraysize(names), "names"); + TestParse(various, arraysize(various), "various"); + TestParse(multiple, arraysize(multiple), "multiple"); + return exit_status(); +}