From 48eff16cdcca411b06d15a274519876d2e501bb2 Mon Sep 17 00:00:00 2001 From: Rene Cannao Date: Sun, 7 Jul 2024 16:21:21 +0000 Subject: [PATCH] Template for handler_special_queries_STATUS() --- include/Base_Session.h | 1 + include/MySQL_Session.h | 2 +- include/PgSQL_Session.h | 2 +- lib/Base_Session.cpp | 99 +++++++++++++++++++++++++++++++++++++++++ lib/MySQL_Session.cpp | 6 +-- lib/PgSQL_Session.cpp | 6 +-- 6 files changed, 108 insertions(+), 8 deletions(-) diff --git a/include/Base_Session.h b/include/Base_Session.h index 92ef0f15f..c53e655c5 100644 --- a/include/Base_Session.h +++ b/include/Base_Session.h @@ -113,6 +113,7 @@ class Base_Session { virtual void SQLite3_to_MySQL(SQLite3_result*, char*, int, MySQL_Protocol*, bool in_transaction = false, bool deprecate_eof_active = false) = 0; bool has_any_backend(); void reset_all_backends(); + bool handler_special_queries_STATUS(PtrSize_t*); }; #endif // CLASS_BASE_SESSION_H diff --git a/include/MySQL_Session.h b/include/MySQL_Session.h index 6272e1375..438ca8227 100644 --- a/include/MySQL_Session.h +++ b/include/MySQL_Session.h @@ -156,7 +156,7 @@ class MySQL_Session: public Base_Session::reset_all_backends(); template void Base_Session::reset_all_backends(); +template bool Base_Session::handler_special_queries_STATUS(_PtrSize_t*); +template bool Base_Session::handler_special_queries_STATUS(_PtrSize_t*); + template Base_Session::Base_Session() { }; @@ -370,3 +378,94 @@ void Base_Session::reset_all_backends() { delete mybe; } }; + + + +/** + * @brief Handles special queries executed by the STATUS command in mysql cli . + * Specifically: + * "select DATABASE(), USER() limit 1" + * "select @@character_set_client, @@character_set_connection, @@character_set_server, @@character_set_database limit 1" + * See Github issues 4396 and 4426 + * + * @param PtrSize_t The packet from the client + * + * @return True if the queries are handled + * + * @note even if this function uses templates, perhaps is relevant only for MySQL client and not PostgreSQL + */ +template +bool Base_Session::handler_special_queries_STATUS(PtrSize_t* pkt) { + if (pkt->size == (SELECT_DB_USER_LEN + 5)) { + if (strncasecmp(SELECT_DB_USER, (char*)pkt->ptr + 5, SELECT_DB_USER_LEN) == 0) { + SQLite3_result* resultset = new SQLite3_result(2); + resultset->add_column_definition(SQLITE_TEXT, "DATABASE()"); + resultset->add_column_definition(SQLITE_TEXT, "USER()"); + char* pta[2]; + pta[0] = client_myds->myconn->userinfo->username; + pta[1] = client_myds->myconn->userinfo->schemaname; + resultset->add_row(pta); + bool deprecate_eof_active = client_myds->myconn->options.client_flag & CLIENT_DEPRECATE_EOF; + SQLite3_to_MySQL(resultset, NULL, 0, &client_myds->myprot, false, deprecate_eof_active); + delete resultset; + l_free(pkt->size, pkt->ptr); + return true; + } + } + + if (pkt->size == (SELECT_CHARSET_STATUS_LEN + 5)) { + if (strncasecmp(SELECT_CHARSET_STATUS, (char*)pkt->ptr + 5, SELECT_CHARSET_STATUS_LEN) == 0) { + SQLite3_result* resultset = new SQLite3_result(4); + resultset->add_column_definition(SQLITE_TEXT, "@@character_set_client"); + resultset->add_column_definition(SQLITE_TEXT, "@@character_set_connection"); + resultset->add_column_definition(SQLITE_TEXT, "@@character_set_server"); + resultset->add_column_definition(SQLITE_TEXT, "@@character_set_database"); + + // here we do a bit back and forth to and from JSON to reuse existing code instead of writing new code. + // This is not great for performance, but this query is rarely executed. + string vals[4]; + json j = {}; + json& jc = j["conn"]; + if constexpr (std::is_same_v) { + MySQL_Connection * conn = client_myds->myconn; + conn->variables[SQL_CHARACTER_SET_CLIENT].fill_client_internal_session(jc, SQL_CHARACTER_SET_CLIENT); + conn->variables[SQL_CHARACTER_SET_CONNECTION].fill_client_internal_session(jc, SQL_CHARACTER_SET_CONNECTION); + conn->variables[SQL_CHARACTER_SET_DATABASE].fill_client_internal_session(jc, SQL_CHARACTER_SET_DATABASE); + } else if constexpr (std::is_same_v) { + PgSQL_Connection * conn = client_myds->myconn; + conn->variables[SQL_CHARACTER_SET_CLIENT].fill_client_internal_session(jc, SQL_CHARACTER_SET_CLIENT); + conn->variables[SQL_CHARACTER_SET_CONNECTION].fill_client_internal_session(jc, SQL_CHARACTER_SET_CONNECTION); + conn->variables[SQL_CHARACTER_SET_DATABASE].fill_client_internal_session(jc, SQL_CHARACTER_SET_DATABASE); + } else { + assert(0); + } + + // @@character_set_client + vals[0] = jc[mysql_tracked_variables[SQL_CHARACTER_SET_CLIENT].internal_variable_name]; + // @@character_set_connection + vals[1] = jc[mysql_tracked_variables[SQL_CHARACTER_SET_CONNECTION].internal_variable_name]; + // @@character_set_server + if constexpr (std::is_same_v) { + vals[2] = string(mysql_thread___default_variables[SQL_CHARACTER_SET]); + } else if constexpr (std::is_same_v) { + vals[2] = string(mysql_thread___default_variables[SQL_CHARACTER_SET]); + } else { + assert(0); + } + // @@character_set_database + vals[3] = jc[mysql_tracked_variables[SQL_CHARACTER_SET_DATABASE].internal_variable_name]; + + const char* pta[4]; + for (int i = 0; i < 4; i++) { + pta[i] = vals[i].c_str(); + } + resultset->add_row(pta); + bool deprecate_eof_active = client_myds->myconn->options.client_flag & CLIENT_DEPRECATE_EOF; + SQLite3_to_MySQL(resultset, NULL, 0, &client_myds->myprot, false, deprecate_eof_active); + delete resultset; + l_free(pkt->size, pkt->ptr); + return true; + } + } + return false; +} diff --git a/lib/MySQL_Session.cpp b/lib/MySQL_Session.cpp index 435e15820..d41d9f935 100644 --- a/lib/MySQL_Session.cpp +++ b/lib/MySQL_Session.cpp @@ -29,9 +29,9 @@ using json = nlohmann::json; #define SELECT_VERSION_COMMENT "select @@version_comment limit 1" #define SELECT_VERSION_COMMENT_LEN 32 -#define SELECT_DB_USER "select DATABASE(), USER() limit 1" +//#define SELECT_DB_USER "select DATABASE(), USER() limit 1" #define SELECT_DB_USER_LEN 33 -#define SELECT_CHARSET_STATUS "select @@character_set_client, @@character_set_connection, @@character_set_server, @@character_set_database limit 1" +//#define SELECT_CHARSET_STATUS "select @@character_set_client, @@character_set_connection, @@character_set_server, @@character_set_database limit 1" #define SELECT_CHARSET_STATUS_LEN 115 #define PROXYSQL_VERSION_COMMENT "\x01\x00\x00\x01\x01\x27\x00\x00\x02\x03\x64\x65\x66\x00\x00\x00\x11\x40\x40\x76\x65\x72\x73\x69\x6f\x6e\x5f\x63\x6f\x6d\x6d\x65\x6e\x74\x00\x0c\x21\x00\x18\x00\x00\x00\xfd\x00\x00\x1f\x00\x00\x05\x00\x00\x03\xfe\x00\x00\x02\x00\x0b\x00\x00\x04\x0a(ProxySQL)\x05\x00\x00\x05\xfe\x00\x00\x02\x00" #define PROXYSQL_VERSION_COMMENT_LEN 81 @@ -1309,7 +1309,6 @@ void MySQL_Session::return_proxysql_internal(PtrSize_t *pkt) { } l_free(pkt->size,pkt->ptr); } -#endif // 0 /** * @brief Handles special queries executed by the STATUS command in mysql cli . @@ -1376,6 +1375,7 @@ bool MySQL_Session::handler_special_queries_STATUS(PtrSize_t *pkt) { } return false; } +#endif // 0 bool MySQL_Session::handler_special_queries(PtrSize_t *pkt) { bool deprecate_eof_active = client_myds->myconn->options.client_flag & CLIENT_DEPRECATE_EOF; diff --git a/lib/PgSQL_Session.cpp b/lib/PgSQL_Session.cpp index d228b6a16..ad3e463a5 100644 --- a/lib/PgSQL_Session.cpp +++ b/lib/PgSQL_Session.cpp @@ -30,9 +30,9 @@ using json = nlohmann::json; #define SELECT_VERSION_COMMENT "select @@version_comment limit 1" #define SELECT_VERSION_COMMENT_LEN 32 -#define SELECT_DB_USER "select DATABASE(), USER() limit 1" +//#define SELECT_DB_USER "select DATABASE(), USER() limit 1" #define SELECT_DB_USER_LEN 33 -#define SELECT_CHARSET_STATUS "select @@character_set_client, @@character_set_connection, @@character_set_server, @@character_set_database limit 1" +//#define SELECT_CHARSET_STATUS "select @@character_set_client, @@character_set_connection, @@character_set_server, @@character_set_database limit 1" #define SELECT_CHARSET_STATUS_LEN 115 #define PROXYSQL_VERSION_COMMENT "\x01\x00\x00\x01\x01\x27\x00\x00\x02\x03\x64\x65\x66\x00\x00\x00\x11\x40\x40\x76\x65\x72\x73\x69\x6f\x6e\x5f\x63\x6f\x6d\x6d\x65\x6e\x74\x00\x0c\x21\x00\x18\x00\x00\x00\xfd\x00\x00\x1f\x00\x00\x05\x00\x00\x03\xfe\x00\x00\x02\x00\x0b\x00\x00\x04\x0a(ProxySQL)\x05\x00\x00\x05\xfe\x00\x00\x02\x00" #define PROXYSQL_VERSION_COMMENT_LEN 81 @@ -1289,7 +1289,6 @@ void PgSQL_Session::return_proxysql_internal(PtrSize_t* pkt) { } l_free(pkt->size, pkt->ptr); } -#endif // 0 /** * @brief Handles special queries executed by the STATUS command in pgsql cli . @@ -1355,6 +1354,7 @@ bool PgSQL_Session::handler_special_queries_STATUS(PtrSize_t* pkt) { } return false; } +#endif // 0 bool PgSQL_Session::handler_special_queries(PtrSize_t* pkt) { bool deprecate_eof_active = client_myds->myconn->options.client_flag & CLIENT_DEPRECATE_EOF;