From b0ca1a030f054aa452fb44daeae0db6cadce60f7 Mon Sep 17 00:00:00 2001 From: val Date: Wed, 8 Apr 2020 08:22:55 +0000 Subject: [PATCH] make MySQL_Variables a global variable --- include/MySQL_Protocol.h | 3 ++ include/MySQL_Session.h | 5 +- include/MySQL_Thread.h | 3 ++ include/MySQL_Variables.h | 29 +++++----- lib/MySQL_Protocol.cpp | 8 +-- lib/MySQL_Session.cpp | 73 +++++++++++++------------ lib/MySQL_Thread.cpp | 7 ++- lib/MySQL_Variables.cpp | 110 +++++++++++++++++++------------------- lib/mysql_connection.cpp | 12 ++--- src/main.cpp | 1 + 10 files changed, 128 insertions(+), 123 deletions(-) diff --git a/include/MySQL_Protocol.h b/include/MySQL_Protocol.h index 3f21e173b..69ea80509 100644 --- a/include/MySQL_Protocol.h +++ b/include/MySQL_Protocol.h @@ -3,9 +3,12 @@ #include "proxysql.h" #include "cpp.h" +#include "MySQL_Variables.h" #define RESULTSET_BUFLEN 16300 +extern MySQL_Variables mysql_variables; + class MySQL_ResultSet { private: public: diff --git a/include/MySQL_Session.h b/include/MySQL_Session.h index c35bb1d9a..5b1a51d6c 100644 --- a/include/MySQL_Session.h +++ b/include/MySQL_Session.h @@ -1,13 +1,13 @@ #ifndef __CLASS_MYSQL_SESSION_H #define __CLASS_MYSQL_SESSION_H -#include "MySQL_Variables.h" #include "proxysql.h" #include "cpp.h" +#include "MySQL_Variables.h" #include "../deps/json/json.hpp" using json = nlohmann::json; -class MySQL_Variables; +extern class MySQL_Variables mysql_variables; enum proxysql_session_type { PROXYSQL_SESSION_MYSQL, @@ -151,7 +151,6 @@ class MySQL_Session MySQL_Data_Stream *client_myds; MySQL_Data_Stream *server_myds; char * default_schema; - std::unique_ptr mysql_variables {nullptr}; //this pointer is always initialized inside handler(). // it is an attempt to start simplifying the complexing of handler() diff --git a/include/MySQL_Thread.h b/include/MySQL_Thread.h index 116305d63..07becbefd 100644 --- a/include/MySQL_Thread.h +++ b/include/MySQL_Thread.h @@ -3,6 +3,7 @@ #define ____CLASS_STANDARD_MYSQL_THREAD_H #include "proxysql.h" #include "cpp.h" +#include "MySQL_Variables.h" #ifdef IDLE_THREADS #include #endif // IDLE_THREADS @@ -22,6 +23,8 @@ #define MYSQL_DEFAULT_NET_WRITE_TIMEOUT "60" #define MYSQL_DEFAULT_MAX_JOIN_SIZE "18446744073709551615" +extern class MySQL_Variables mysql_variables; + #ifdef IDLE_THREADS typedef struct __attribute__((aligned(64))) _conn_exchange_t { pthread_mutex_t mutex_idles; diff --git a/include/MySQL_Variables.h b/include/MySQL_Variables.h index 87a1757a5..faad16941 100644 --- a/include/MySQL_Variables.h +++ b/include/MySQL_Variables.h @@ -20,31 +20,30 @@ typedef bool (*update_var)(MySQL_Session* session, int idx, int &_rc); bool validate_charset(MySQL_Session* session, int idx, int &_rc); bool update_server_variable(MySQL_Session* session, int idx, int &_rc); -bool verify_variable(MySQL_Session* session, int idx, uint32_t client_hash, uint32_t server_hash); +bool verify_server_variable(MySQL_Session* session, int idx, uint32_t client_hash, uint32_t server_hash); bool logbin_update_server_variable(MySQL_Session* session, int idx, int &_rc); class MySQL_Variables { - MySQL_Session* session; - - verify_var verifiers[SQL_NAME_LAST]; - update_var updaters[SQL_NAME_LAST]; + static verify_var verifiers[SQL_NAME_LAST]; + static update_var updaters[SQL_NAME_LAST]; public: + MySQL_Variables(); + bool is_connected_to_backend; - MySQL_Variables(MySQL_Session* session); virtual ~MySQL_Variables(); - bool client_set_value(int idx, const std::string& value); - const char* client_get_value(int idx) const; - uint32_t client_get_hash(int idx) const; + bool client_set_value(MySQL_Session* session, int idx, const std::string& value); + const char* client_get_value(MySQL_Session* session, int idx) const; + uint32_t client_get_hash(MySQL_Session* session, int idx) const; - void server_set_value(int idx, const char* value); - const char* server_get_value(int idx) const; - inline uint32_t server_get_hash(int idx) const; + void server_set_value(MySQL_Session* session, int idx, const char* value); + const char* server_get_value(MySQL_Session* session, int idx) const; + inline uint32_t server_get_hash(MySQL_Session* session, int idx) const; - bool verify_variable(int idx) const; - bool update_variable(session_status status, int &_rc); - bool on_connect_to_backend(mysql_variable_st* tracked_variables); + bool verify_variable(MySQL_Session* session, int idx) const; + bool update_variable(MySQL_Session* session, session_status status, int &_rc); + bool on_connect_to_backend(MySQL_Session* session, mysql_variable_st* tracked_variables); }; #endif // #ifndef MYSQL_VARIABLES_H diff --git a/lib/MySQL_Protocol.cpp b/lib/MySQL_Protocol.cpp index 8f9e23623..b66d602cb 100644 --- a/lib/MySQL_Protocol.cpp +++ b/lib/MySQL_Protocol.cpp @@ -1977,10 +1977,10 @@ __exit_do_auth: /* We are processing handshake from client. Client sends us a character set it will use in communication. * we store this character set in the client's variables to use later in multiplexing with different backends */ - sess->mysql_variables->client_set_value(SQL_CHARACTER_SET_RESULTS, ss.str().c_str()); - sess->mysql_variables->client_set_value(SQL_CHARACTER_SET_CLIENT, ss.str().c_str()); - sess->mysql_variables->client_set_value(SQL_CHARACTER_SET_CONNECTION, ss.str().c_str()); - sess->mysql_variables->client_set_value(SQL_COLLATION_CONNECTION, ss.str().c_str()); + mysql_variables.client_set_value(sess, SQL_CHARACTER_SET_RESULTS, ss.str().c_str()); + mysql_variables.client_set_value(sess, SQL_CHARACTER_SET_CLIENT, ss.str().c_str()); + mysql_variables.client_set_value(sess, SQL_CHARACTER_SET_CONNECTION, ss.str().c_str()); + mysql_variables.client_set_value(sess, SQL_COLLATION_CONNECTION, ss.str().c_str()); } // enable compression if (capabilities & CLIENT_COMPRESS) { diff --git a/lib/MySQL_Session.cpp b/lib/MySQL_Session.cpp index c870d27b1..bd7188816 100644 --- a/lib/MySQL_Session.cpp +++ b/lib/MySQL_Session.cpp @@ -496,7 +496,6 @@ void MySQL_Session::init() { mybes= new PtrArray(4); sess_STMTs_meta=new MySQL_STMTs_meta(); SLDH=new StmtLongDataHandler(); - mysql_variables = std::unique_ptr(new MySQL_Variables(this)); } void MySQL_Session::reset() { @@ -1969,7 +1968,7 @@ bool MySQL_Session::handler_again___status_SETTING_SQL_LOG_BIN(int *_rc) { if (myconn->async_state_machine==ASYNC_IDLE) { char *q=(char *)"SET SQL_LOG_BIN=%s"; query=(char *)malloc(strlen(q)+8); - sprintf(query,q,mysql_variables->client_get_value(SQL_LOG_BIN)); + sprintf(query,q,mysql_variables.client_get_value(this, SQL_LOG_BIN)); query_length=strlen(query); } int rc=myconn->async_send_simple_command(myds->revents,query,query_length); @@ -1978,12 +1977,12 @@ bool MySQL_Session::handler_again___status_SETTING_SQL_LOG_BIN(int *_rc) { query=NULL; } if (rc==0) { - if (!strcmp("0", mysql_variables->client_get_value(SQL_LOG_BIN)) || !strcasecmp("OFF", mysql_variables->client_get_value(SQL_LOG_BIN))) { + if (!strcmp("0", mysql_variables.client_get_value(this, SQL_LOG_BIN)) || !strcasecmp("OFF", mysql_variables.client_get_value(this, SQL_LOG_BIN))) { // pay attention here. set_status_sql_log_bin0 sets it sql_log_bin is ZERO // sql_log_bin=0 => true // sql_log_bin=1 => false myconn->set_status_sql_log_bin0(true); - } else if (!strcmp("1", mysql_variables->client_get_value(SQL_LOG_BIN)) || !strcasecmp("ON", mysql_variables->client_get_value(SQL_LOG_BIN))) { + } else if (!strcmp("1", mysql_variables.client_get_value(this, SQL_LOG_BIN)) || !strcasecmp("ON", mysql_variables.client_get_value(this, SQL_LOG_BIN))) { myconn->set_status_sql_log_bin0(false); } myds->revents|=POLLOUT; // we also set again POLLOUT to send a query immediately! @@ -3382,9 +3381,9 @@ handler_again: goto handler_again; } - if (mysql_variables->is_connected_to_backend) { + if (mysql_variables.is_connected_to_backend) { for (auto i = 0; i < SQL_NAME_LAST; i++) { - if(mysql_tracked_variables[i].special_handling && mysql_variables->verify_variable(i)) { + if(mysql_tracked_variables[i].special_handling && mysql_variables.verify_variable(this, i)) { goto handler_again; } } @@ -3912,7 +3911,7 @@ handler_again: case SETTING_WSREP_SYNC_WAIT: for (auto i = 0; i < SQL_NAME_LAST; i++) { int rc = 0; - if (mysql_variables->update_variable(status, rc)) { + if (mysql_variables.update_variable(this, status, rc)) { goto handler_again; } if (rc == -1) { @@ -4714,11 +4713,11 @@ bool MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C if (rc && ( i==0 || i==1) ) { //fprintf(stderr,"sql_log_bin=%d\n", i); if (i == 1) { - if (!mysql_variables->client_set_value(SQL_LOG_BIN, "1")) + if (!mysql_variables.client_set_value(this, SQL_LOG_BIN, "1")) return false; } else if (i == 0) { - if (!mysql_variables->client_set_value(SQL_LOG_BIN, "0")) + if (!mysql_variables.client_set_value(this, SQL_LOG_BIN, "0")) return false; } @@ -4833,8 +4832,8 @@ bool MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C } proxy_debug(PROXY_DEBUG_MYSQL_COM, 5, "Processing SET SQL Mode value %s\n", value1.c_str()); uint32_t sql_mode_int=SpookyHash::Hash32(value1.c_str(),value1.length(),10); - if (mysql_variables->client_get_hash(SQL_SQL_MODE) != sql_mode_int) { - if (!mysql_variables->client_set_value(SQL_SQL_MODE, value1.c_str())) { + if (mysql_variables.client_get_hash(this, SQL_SQL_MODE) != sql_mode_int) { + if (!mysql_variables.client_set_value(this, SQL_SQL_MODE, value1.c_str())) { return false; } proxy_debug(PROXY_DEBUG_MYSQL_COM, 8, "Changing connection SQL Mode to %s\n", value1.c_str()); @@ -4845,8 +4844,8 @@ bool MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C if ((strcasecmp(value1.c_str(),"0")==0) || (strcasecmp(value1.c_str(),"1")==0)) { proxy_debug(PROXY_DEBUG_MYSQL_COM, 7, "Processing SET wsrep_sync_wait value %s\n", value1.c_str()); uint32_t wsrep_sync_wait_int=SpookyHash::Hash32(value1.c_str(),value1.length(),10); - if (mysql_variables->client_get_hash(SQL_WSREP_SYNC_WAIT) != wsrep_sync_wait_int) { - if (!mysql_variables->client_set_value(SQL_WSREP_SYNC_WAIT, value1.c_str())) + if (mysql_variables.client_get_hash(this, SQL_WSREP_SYNC_WAIT) != wsrep_sync_wait_int) { + if (!mysql_variables.client_set_value(this, SQL_WSREP_SYNC_WAIT, value1.c_str())) return false; proxy_debug(PROXY_DEBUG_MYSQL_COM, 5, "Changing connection session_track_gtids to %s\n", value1.c_str()); } @@ -4889,12 +4888,12 @@ bool MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C unable_to_parse_set_statement(lock_hostgroup); return false; } - if (mysql_variables->client_get_hash(idx) != var_value_int) { + if (mysql_variables.client_get_hash(this, idx) != var_value_int) { if (__tmp_value == 0) { - if (!mysql_variables->client_set_value(idx, "OFF")) + if (!mysql_variables.client_set_value(this, idx, "OFF")) return false; } else { - if (!mysql_variables->client_set_value(idx, "ON")) + if (!mysql_variables.client_set_value(this, idx, "ON")) return false; } proxy_debug(PROXY_DEBUG_MYSQL_COM, 5, "Changing connection %s to %s\n", var.c_str(), value1.c_str()); @@ -4970,8 +4969,8 @@ bool MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C } proxy_debug(PROXY_DEBUG_MYSQL_COM, 5, "Processing SET Time Zone value %s\n", value1.c_str()); uint32_t time_zone_int=SpookyHash::Hash32(value1.c_str(),value1.length(),10); - if (mysql_variables->client_get_hash(SQL_TIME_ZONE) != time_zone_int) { - if (!mysql_variables->client_set_value(SQL_TIME_ZONE, value1.c_str())) + if (mysql_variables.client_get_hash(this, SQL_TIME_ZONE) != time_zone_int) { + if (!mysql_variables.client_set_value(this, SQL_TIME_ZONE, value1.c_str())) return false; proxy_debug(PROXY_DEBUG_MYSQL_COM, 8, "Changing connection Time zone to %s\n", value1.c_str()); } @@ -4981,8 +4980,8 @@ bool MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C if ((strcasecmp(value1.c_str(),"OWN_GTID")==0) || (strcasecmp(value1.c_str(),"OFF")==0)) { proxy_debug(PROXY_DEBUG_MYSQL_COM, 7, "Processing SET session_track_gtids value %s\n", value1.c_str()); uint32_t session_track_gtids_int=SpookyHash::Hash32(value1.c_str(),value1.length(),10); - if (mysql_variables->client_get_hash(SQL_SESSION_TRACK_GTIDS) != session_track_gtids_int) { - if (!mysql_variables->client_set_value(SQL_SESSION_TRACK_GTIDS, value1.c_str())) + if (mysql_variables.client_get_hash(this, SQL_SESSION_TRACK_GTIDS) != session_track_gtids_int) { + if (!mysql_variables.client_set_value(this, SQL_SESSION_TRACK_GTIDS, value1.c_str())) return false; proxy_debug(PROXY_DEBUG_MYSQL_COM, 5, "Changing connection session_track_gtids to %s\n", value1.c_str()); } @@ -5023,8 +5022,8 @@ bool MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C unable_to_parse_set_statement(lock_hostgroup); return false; } - if (mysql_variables->client_get_hash(idx) != var_value_int) { - if (!mysql_variables->client_set_value(idx, value1.c_str())) + if (mysql_variables.client_get_hash(this, idx) != var_value_int) { + if (!mysql_variables.client_set_value(this, idx, value1.c_str())) return false; proxy_debug(PROXY_DEBUG_MYSQL_COM, 5, "Changing connection %s to %s\n", var.c_str(), value1.c_str()); } @@ -5060,7 +5059,7 @@ bool MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C unable_to_parse_set_statement(lock_hostgroup); return false; } - if (mysql_variables->client_get_hash(idx) != var_value_int) { + if (mysql_variables.client_get_hash(this, idx) != var_value_int) { const MARIADB_CHARSET_INFO *ci = NULL; if (var == "character_set_results" || var == "character_set_connection" || var == "character_set_client" || var == "character_set_database") { @@ -5072,11 +5071,11 @@ bool MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C if (!ci) { if (var == "character_set_results") { if (!strcasecmp("NULL", value1.c_str())) { - if (!mysql_variables->client_set_value(idx, "NULL")) { + if (!mysql_variables.client_set_value(this, idx, "NULL")) { return false; } } else if (!strcasecmp("binary", value1.c_str())) { - if (!mysql_variables->client_set_value(idx, "binary")) { + if (!mysql_variables.client_set_value(this, idx, "binary")) { return false; } } else { @@ -5091,18 +5090,18 @@ bool MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C * and vice versa */ if (var == "collation_connection") { - if (!mysql_variables->client_set_value(SQL_CHARACTER_SET_CONNECTION, ss.str().c_str())) + if (!mysql_variables.client_set_value(this, SQL_CHARACTER_SET_CONNECTION, ss.str().c_str())) return false; } if (var == "character_set_connection") { - if (!mysql_variables->client_set_value(SQL_COLLATION_CONNECTION, ss.str().c_str())) + if (!mysql_variables.client_set_value(this, SQL_COLLATION_CONNECTION, ss.str().c_str())) return false; } /* this is explicit statement from client. we do not multiplex, therefor we must * remember client's choice in the client's variable for future use in verifications, multiplexing etc. */ - if (!mysql_variables->client_set_value(idx, ss.str().c_str())) + if (!mysql_variables.client_set_value(this, idx, ss.str().c_str())) return false; proxy_debug(PROXY_DEBUG_MYSQL_COM, 5, "Changing connection %s to %s\n", var.c_str(), value1.c_str()); } @@ -5159,8 +5158,8 @@ bool MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C if (pos != std::string::npos) value1[pos] = ' '; uint32_t isolation_level_int=SpookyHash::Hash32(value1.c_str(),value1.length(),10); - if (mysql_variables->client_get_hash(SQL_ISOLATION_LEVEL) != isolation_level_int) { - if (!mysql_variables->client_set_value(SQL_ISOLATION_LEVEL, value1.c_str())) + if (mysql_variables.client_get_hash(this, SQL_ISOLATION_LEVEL) != isolation_level_int) { + if (!mysql_variables.client_set_value(this, SQL_ISOLATION_LEVEL, value1.c_str())) return false; proxy_debug(PROXY_DEBUG_MYSQL_COM, 8, "Changing connection TX ISOLATION to %s\n", value1.c_str()); } @@ -5207,8 +5206,8 @@ bool MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C delete opt2; if (rc) { uint32_t sql_mode_int=SpookyHash::Hash32(s1.c_str(),s1.length(),10); - if (mysql_variables->client_get_hash(SQL_SQL_MODE) != sql_mode_int) { - if (!mysql_variables->client_set_value(SQL_SQL_MODE, s1.c_str())) + if (mysql_variables.client_get_hash(this, SQL_SQL_MODE) != sql_mode_int) { + if (!mysql_variables.client_set_value(this, SQL_SQL_MODE, s1.c_str())) return false; std::size_t found_at = s1.find("@"); if (found_at != std::string::npos) { @@ -5276,8 +5275,8 @@ bool MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C std::string value1 = *values; proxy_debug(PROXY_DEBUG_MYSQL_COM, 5, "Processing SET SESSION TRANSACTION ISOLATION LEVEL value %s\n", value1.c_str()); uint32_t isolation_level_int=SpookyHash::Hash32(value1.c_str(),value1.length(),10); - if (mysql_variables->client_get_hash(SQL_ISOLATION_LEVEL) != isolation_level_int) { - if (!mysql_variables->client_set_value(SQL_ISOLATION_LEVEL, value1.c_str())) + if (mysql_variables.client_get_hash(this, SQL_ISOLATION_LEVEL) != isolation_level_int) { + if (!mysql_variables.client_set_value(this, SQL_ISOLATION_LEVEL, value1.c_str())) return false; proxy_debug(PROXY_DEBUG_MYSQL_COM, 8, "Changing connection TRANSACTION ISOLATION LEVEL to %s\n", value1.c_str()); } @@ -5286,8 +5285,8 @@ bool MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C std::string value1 = *values; proxy_debug(PROXY_DEBUG_MYSQL_COM, 5, "Processing SET SESSION TRANSACTION READ value %s\n", value1.c_str()); uint32_t transaction_read_int=SpookyHash::Hash32(value1.c_str(),value1.length(),10); - if (mysql_variables->client_get_hash(SQL_TRANSACTION_READ) != transaction_read_int) { - if (!mysql_variables->client_set_value(SQL_TRANSACTION_READ, value1.c_str())) + if (mysql_variables.client_get_hash(this, SQL_TRANSACTION_READ) != transaction_read_int) { + if (!mysql_variables.client_set_value(this, SQL_TRANSACTION_READ, value1.c_str())) return false; proxy_debug(PROXY_DEBUG_MYSQL_COM, 8, "Changing connection TRANSACTION READ to %s\n", value1.c_str()); } @@ -5733,7 +5732,7 @@ void MySQL_Session::handler___client_DSS_QUERY_SENT___server_DSS_NOT_INITIALIZED status=CONNECTING_SERVER; mybe->server_myds->myconn->reusable=true; } else { - mysql_variables->on_connect_to_backend(mysql_tracked_variables); + mysql_variables.on_connect_to_backend(this, mysql_tracked_variables); proxy_debug(PROXY_DEBUG_MYSQL_CONNECTION, 5, "Sess=%p -- MySQL Connection found = %p\n", this, mybe->server_myds->myconn); mybe->server_myds->assign_fd_from_mysql_conn(); mybe->server_myds->myds_type=MYDS_BACKEND; diff --git a/lib/MySQL_Thread.cpp b/lib/MySQL_Thread.cpp index ecc690154..6d1a1491a 100644 --- a/lib/MySQL_Thread.cpp +++ b/lib/MySQL_Thread.cpp @@ -14,7 +14,6 @@ #include "StatCounters.h" #include "MySQL_PreparedStatement.h" #include "MySQL_Logger.hpp" -#include "MySQL_Variables.h" #ifdef DEBUG MySQL_Session *sess_stopat; @@ -3309,7 +3308,7 @@ MySQL_Session * MySQL_Thread::create_new_session_and_client_data_stream(int _fd) } std::stringstream ss; ss << ci->nr; - sess->mysql_variables->client_set_value(i, ss.str()); + mysql_variables.client_set_value(sess, i, ss.str()); } else if (i == SQL_COLLATION_CONNECTION) { const MARIADB_CHARSET_INFO *ci = NULL; ci = proxysql_find_charset_collate(mysql_thread___default_variables[i]); @@ -3320,9 +3319,9 @@ MySQL_Session * MySQL_Thread::create_new_session_and_client_data_stream(int _fd) } std::stringstream ss; ss << ci->nr; - sess->mysql_variables->client_set_value(i, ss.str()); + mysql_variables.client_set_value(sess, i, ss.str()); } else { - sess->mysql_variables->client_set_value(i, mysql_thread___default_variables[i]); + mysql_variables.client_set_value(sess, i, mysql_thread___default_variables[i]); } } diff --git a/lib/MySQL_Variables.cpp b/lib/MySQL_Variables.cpp index 6df1ef235..ba026ac8d 100644 --- a/lib/MySQL_Variables.cpp +++ b/lib/MySQL_Variables.cpp @@ -7,9 +7,11 @@ #include -MySQL_Variables::MySQL_Variables(MySQL_Session* _session) : session(_session), is_connected_to_backend(false) { - assert(_session); +verify_var MySQL_Variables::verifiers[SQL_NAME_LAST]; +update_var MySQL_Variables::updaters[SQL_NAME_LAST]; + +MySQL_Variables::MySQL_Variables() { for (auto i = 0; i < SQL_NAME_LAST; i++) { switch(i) { case SQL_SAFE_UPDATES: @@ -28,22 +30,22 @@ MySQL_Variables::MySQL_Variables(MySQL_Session* _session) : session(_session), i case SQL_NET_WRITE_TIMEOUT: case SQL_MAX_JOIN_SIZE: case SQL_WSREP_SYNC_WAIT: - verifiers[i] = ::verify_variable; - updaters[i] = update_server_variable; + MySQL_Variables::verifiers[i] = verify_server_variable; + MySQL_Variables::updaters[i] = update_server_variable; break; case SQL_LOG_BIN: - verifiers[i] = ::verify_variable; - updaters[i] = logbin_update_server_variable; + MySQL_Variables::verifiers[i] = verify_server_variable; + MySQL_Variables::updaters[i] = logbin_update_server_variable; break; default: - updaters[i] = NULL; + MySQL_Variables::updaters[i] = NULL; } } } MySQL_Variables::~MySQL_Variables() {} -bool MySQL_Variables::on_connect_to_backend(mysql_variable_st *tracked_variables) { +bool MySQL_Variables::on_connect_to_backend(MySQL_Session* session, mysql_variable_st *tracked_variables) { if (!session || !session->mybe || !session->mybe->server_myds || !session->mybe->server_myds->myconn) return false; auto be_version = session->mybe->server_myds->myconn->mysql->server_version; @@ -77,7 +79,7 @@ bool MySQL_Variables::on_connect_to_backend(mysql_variable_st *tracked_variables return true; } -bool MySQL_Variables::client_set_value(int idx, const std::string& value) { +bool MySQL_Variables::client_set_value(MySQL_Session* session, int idx, const std::string& value) { if (!session || !session->client_myds || !session->client_myds->myconn) { proxy_warning("Session validation failed\n"); return false; @@ -92,20 +94,20 @@ bool MySQL_Variables::client_set_value(int idx, const std::string& value) { case SQL_CHARACTER_ACTION: // SET NAMES command from client if (value == "1") { - if (session->mysql_variables->client_get_value(SQL_CHARACTER_SET)) { - session->mysql_variables->client_set_value(SQL_CHARACTER_SET_RESULTS, session->mysql_variables->client_get_value(SQL_CHARACTER_SET)); - session->mysql_variables->client_set_value(SQL_CHARACTER_SET_CLIENT, session->mysql_variables->client_get_value(SQL_CHARACTER_SET)); - session->mysql_variables->client_set_value(SQL_CHARACTER_SET_CONNECTION, session->mysql_variables->client_get_value(SQL_CHARACTER_SET)); - session->mysql_variables->client_set_value(SQL_COLLATION_CONNECTION, session->mysql_variables->client_get_value(SQL_CHARACTER_SET)); + if (mysql_variables.client_get_value(session, SQL_CHARACTER_SET)) { + mysql_variables.client_set_value(session, SQL_CHARACTER_SET_RESULTS, mysql_variables.client_get_value(session, SQL_CHARACTER_SET)); + mysql_variables.client_set_value(session, SQL_CHARACTER_SET_CLIENT, mysql_variables.client_get_value(session, SQL_CHARACTER_SET)); + mysql_variables.client_set_value(session, SQL_CHARACTER_SET_CONNECTION, mysql_variables.client_get_value(session, SQL_CHARACTER_SET)); + mysql_variables.client_set_value(session, SQL_COLLATION_CONNECTION, mysql_variables.client_get_value(session, SQL_CHARACTER_SET)); } } // SET CHARSET command from client else if (value == "2") { - if (session->mysql_variables->client_get_value(SQL_CHARACTER_SET)) { - session->mysql_variables->client_set_value(SQL_CHARACTER_SET_RESULTS, session->mysql_variables->client_get_value(SQL_CHARACTER_SET)); - session->mysql_variables->client_set_value(SQL_CHARACTER_SET_CLIENT, session->mysql_variables->client_get_value(SQL_CHARACTER_SET)); + if (mysql_variables.client_get_value(session, SQL_CHARACTER_SET)) { + mysql_variables.client_set_value(session, SQL_CHARACTER_SET_RESULTS, mysql_variables.client_get_value(session, SQL_CHARACTER_SET)); + mysql_variables.client_set_value(session, SQL_CHARACTER_SET_CLIENT, mysql_variables.client_get_value(session, SQL_CHARACTER_SET)); } - if (session->mysql_variables->client_get_value(SQL_CHARACTER_SET_DATABASE)) { + if (mysql_variables.client_get_value(session, SQL_CHARACTER_SET_DATABASE)) { const MARIADB_CHARSET_INFO *ci = NULL; ci = proxysql_find_charset_name(mysql_tracked_variables[SQL_CHARACTER_SET_CONNECTION].default_value); @@ -113,7 +115,7 @@ bool MySQL_Variables::client_set_value(int idx, const std::string& value) { std::stringstream ss; ss << nr; - session->mysql_variables->client_set_value(SQL_CHARACTER_SET_CONNECTION, ss.str()); + mysql_variables.client_set_value(session, SQL_CHARACTER_SET_CONNECTION, ss.str()); ci = proxysql_find_charset_collate(mysql_tracked_variables[SQL_COLLATION_CONNECTION].default_value); nr = ci->nr; @@ -121,16 +123,16 @@ bool MySQL_Variables::client_set_value(int idx, const std::string& value) { ss.clear(); ss << nr; - session->mysql_variables->client_set_value(SQL_COLLATION_CONNECTION, ss.str()); + mysql_variables.client_set_value(session, SQL_COLLATION_CONNECTION, ss.str()); } } // SET NAMES during handshake etc. else if (value == "3") { - if (session->mysql_variables->server_get_value(SQL_CHARACTER_SET)) { - session->mysql_variables->client_set_value(SQL_CHARACTER_SET_RESULTS, session->mysql_variables->server_get_value(SQL_CHARACTER_SET)); - session->mysql_variables->client_set_value(SQL_CHARACTER_SET_CLIENT, session->mysql_variables->server_get_value(SQL_CHARACTER_SET)); - session->mysql_variables->client_set_value(SQL_CHARACTER_SET_CONNECTION, session->mysql_variables->server_get_value(SQL_CHARACTER_SET)); - session->mysql_variables->client_set_value(SQL_COLLATION_CONNECTION, session->mysql_variables->server_get_value(SQL_CHARACTER_SET)); + if (mysql_variables.server_get_value(session, SQL_CHARACTER_SET)) { + mysql_variables.client_set_value(session, SQL_CHARACTER_SET_RESULTS, mysql_variables.server_get_value(session, SQL_CHARACTER_SET)); + mysql_variables.client_set_value(session, SQL_CHARACTER_SET_CLIENT, mysql_variables.server_get_value(session, SQL_CHARACTER_SET)); + mysql_variables.client_set_value(session, SQL_CHARACTER_SET_CONNECTION, mysql_variables.server_get_value(session, SQL_CHARACTER_SET)); + mysql_variables.client_set_value(session, SQL_COLLATION_CONNECTION, mysql_variables.server_get_value(session, SQL_CHARACTER_SET)); } } } @@ -144,17 +146,17 @@ bool MySQL_Variables::client_set_value(int idx, const std::string& value) { return true; } -const char* MySQL_Variables::client_get_value(int idx) const { +const char* MySQL_Variables::client_get_value(MySQL_Session* session, int idx) const { if (!session || !session->client_myds || !session->client_myds->myconn) return NULL; return session->client_myds->myconn->variables[idx].value; } -uint32_t MySQL_Variables::client_get_hash(int idx) const { +uint32_t MySQL_Variables::client_get_hash(MySQL_Session* session, int idx) const { if (!session || !session->client_myds || !session->client_myds->myconn) return 0; return session->client_myds->myconn->var_hash[idx]; } -void MySQL_Variables::server_set_value(int idx, const char* value) { +void MySQL_Variables::server_set_value(MySQL_Session* session, int idx, const char* value) { if (!session || !session->mybe || !session->mybe->server_myds || !session->mybe->server_myds->myconn || !value) return; session->mybe->server_myds->myconn->var_hash[idx] = SpookyHash::Hash32(value,strlen(value),10); @@ -164,17 +166,17 @@ void MySQL_Variables::server_set_value(int idx, const char* value) { session->mybe->server_myds->myconn->variables[idx].value = strdup(value); } -const char* MySQL_Variables::server_get_value(int idx) const { +const char* MySQL_Variables::server_get_value(MySQL_Session* session, int idx) const { if (!session || !session->mybe || !session->mybe->server_myds || !session->mybe->server_myds->myconn) return NULL; return session->mybe->server_myds->myconn->variables[idx].value; } -uint32_t MySQL_Variables::server_get_hash(int idx) const { +uint32_t MySQL_Variables::server_get_hash(MySQL_Session* session, int idx) const { if (!session || !session->mybe || !session->mybe->server_myds || !session->mybe->server_myds->myconn) return 0; return session->mybe->server_myds->myconn->var_hash[idx]; } -bool MySQL_Variables::update_variable(session_status status, int &_rc) { +bool MySQL_Variables::update_variable(MySQL_Session* session, session_status status, int &_rc) { int idx = SQL_NAME_LAST; for (int i=0; iclient_myds->myconn->var_hash[idx]; @@ -207,11 +209,11 @@ bool validate_charset(MySQL_Session* session, int idx, int &_rc) { const char* not_supported_collation = NULL; unsigned int replace_collation_nr = 0; std::stringstream ss; - int charset = atoi(session->mysql_variables->client_get_value(idx)); + int charset = atoi(mysql_variables.client_get_value(session, idx)); if (charset >= 255 && myconn->mysql->server_version[0] != '8') { switch(mysql_thread___handle_unknown_charset) { case HANDLE_UNKNOWN_CHARSET__DISCONNECT_CLIENT: - snprintf(msg,sizeof(msg),"Can't initialize character set %s", session->mysql_variables->client_get_value(idx)); + snprintf(msg,sizeof(msg),"Can't initialize character set %s", mysql_variables.client_get_value(session, idx)); proxy_error("Can't initialize character set on %s, %d: Error %d (%s). Closing client connection %s:%d.\n", myconn->parent->address, myconn->parent->port, 2019, msg, session->client_myds->addr.addr, session->client_myds->addr.port); myds->destroy_MySQL_Connection_From_Pool(false); @@ -221,7 +223,7 @@ bool validate_charset(MySQL_Session* session, int idx, int &_rc) { case HANDLE_UNKNOWN_CHARSET__REPLACE_WITH_DEFAULT_VERBOSE: ci = proxysql_find_charset_nr(charset); if (!ci) { - proxy_error("Cannot find character set [%s]\n", session->mysql_variables->client_get_value(idx)); + proxy_error("Cannot find character set [%s]\n", mysql_variables.client_get_value(session, idx)); assert(0); } not_supported_collation = ci->name; @@ -240,11 +242,11 @@ bool validate_charset(MySQL_Session* session, int idx, int &_rc) { replace_collation_nr = ci->nr; proxy_warning("Server doesn't support collation (%s) %s. Replacing it with the configured default (%d) %s. Client %s:%d\n", - session->mysql_variables->client_get_value(idx), not_supported_collation, + mysql_variables.client_get_value(session, idx), not_supported_collation, replace_collation_nr, replace_collation, session->client_myds->addr.addr, session->client_myds->addr.port); ss << replace_collation_nr; - session->mysql_variables->client_set_value(idx, ss.str()); + mysql_variables.client_set_value(session, idx, ss.str()); _rc=0; return true; case HANDLE_UNKNOWN_CHARSET__REPLACE_WITH_DEFAULT: @@ -261,7 +263,7 @@ bool validate_charset(MySQL_Session* session, int idx, int &_rc) { replace_collation_nr = ci->nr; ss << replace_collation_nr; - session->mysql_variables->client_set_value(idx, ss.str()); + mysql_variables.client_set_value(session, idx, ss.str()); _rc=0; return true; default: @@ -294,55 +296,55 @@ bool update_server_variable(MySQL_Session* session, int idx, int &_rc) { */ if (idx==SQL_CHARACTER_SET_RESULTS) { const MARIADB_CHARSET_INFO *ci = NULL; - ci = proxysql_find_charset_nr(atoi(session->mysql_variables->client_get_value(SQL_CHARACTER_SET_RESULTS))); + ci = proxysql_find_charset_nr(atoi(mysql_variables.client_get_value(session, SQL_CHARACTER_SET_RESULTS))); if (!ci) { - if (!strcmp(session->mysql_variables->client_get_value(SQL_CHARACTER_SET_RESULTS), "NULL")) { - session->mysql_variables->server_set_value(idx, session->mysql_variables->client_get_value(idx)); + if (!strcmp(mysql_variables.client_get_value(session, SQL_CHARACTER_SET_RESULTS), "NULL")) { + mysql_variables.server_set_value(session, idx, mysql_variables.client_get_value(session, idx)); ret = session->handler_again___status_SETTING_GENERIC_VARIABLE(&_rc, set_var_name, "NULL", no_quote, st); - } else if (!strcmp(session->mysql_variables->client_get_value(SQL_CHARACTER_SET_RESULTS), "binary")) { - session->mysql_variables->server_set_value(idx, session->mysql_variables->client_get_value(idx)); + } else if (!strcmp(mysql_variables.client_get_value(session, SQL_CHARACTER_SET_RESULTS), "binary")) { + mysql_variables.server_set_value(session, idx, mysql_variables.client_get_value(session, idx)); ret = session->handler_again___status_SETTING_GENERIC_VARIABLE(&_rc, set_var_name, "binary", no_quote, st); } } else { - session->mysql_variables->server_set_value(idx, session->mysql_variables->client_get_value(idx)); + mysql_variables.server_set_value(session, idx, mysql_variables.client_get_value(session, idx)); ret = session->handler_again___status_SETTING_GENERIC_VARIABLE(&_rc, set_var_name, ci->csname, no_quote, st); } } else if (idx==SQL_COLLATION_CONNECTION) { const MARIADB_CHARSET_INFO *ci = NULL; - ci = proxysql_find_charset_nr(atoi(session->mysql_variables->client_get_value(SQL_COLLATION_CONNECTION))); + ci = proxysql_find_charset_nr(atoi(mysql_variables.client_get_value(session, SQL_COLLATION_CONNECTION))); std::stringstream ss; ss << ci->nr; - session->mysql_variables->server_set_value(idx, session->mysql_variables->client_get_value(idx)); + mysql_variables.server_set_value(session, idx, mysql_variables.client_get_value(session, idx)); ret = session->handler_again___status_SETTING_GENERIC_VARIABLE(&_rc, set_var_name, ci->name, no_quote, st); } else if (idx==SQL_CHARACTER_SET_CONNECTION) { const MARIADB_CHARSET_INFO *ci = NULL; - ci = proxysql_find_charset_nr(atoi(session->mysql_variables->client_get_value(SQL_CHARACTER_SET_CONNECTION))); + ci = proxysql_find_charset_nr(atoi(mysql_variables.client_get_value(session, SQL_CHARACTER_SET_CONNECTION))); unsigned int nr = ci->nr; std::stringstream ss; ss << nr; - session->mysql_variables->server_set_value(idx, session->mysql_variables->client_get_value(idx)); + mysql_variables.server_set_value(session, idx, mysql_variables.client_get_value(session, idx)); ret = session->handler_again___status_SETTING_GENERIC_VARIABLE(&_rc, set_var_name, ci->csname, no_quote, st); } else if (idx==SQL_CHARACTER_SET_CLIENT || idx==SQL_CHARACTER_SET_DATABASE) { const MARIADB_CHARSET_INFO *ci = NULL; - ci = proxysql_find_charset_nr(atoi(session->mysql_variables->client_get_value(idx))); + ci = proxysql_find_charset_nr(atoi(mysql_variables.client_get_value(session, idx))); std::stringstream ss; ss << ci->nr; - session->mysql_variables->server_set_value(idx, session->mysql_variables->client_get_value(idx)); + mysql_variables.server_set_value(session, idx, mysql_variables.client_get_value(session, idx)); ret = session->handler_again___status_SETTING_GENERIC_VARIABLE(&_rc, set_var_name, ci->csname, no_quote, st); } else { - session->mysql_variables->server_set_value(idx, session->mysql_variables->client_get_value(idx)); - ret = session->handler_again___status_SETTING_GENERIC_VARIABLE(&_rc, set_var_name, session->mysql_variables->server_get_value(idx), no_quote, st); + mysql_variables.server_set_value(session, idx, mysql_variables.client_get_value(session, idx)); + ret = session->handler_again___status_SETTING_GENERIC_VARIABLE(&_rc, set_var_name, mysql_variables.server_get_value(session, idx), no_quote, st); } return ret; } -inline bool verify_variable(MySQL_Session* session, int idx, uint32_t client_hash, uint32_t server_hash) { +inline bool verify_server_variable(MySQL_Session* session, int idx, uint32_t client_hash, uint32_t server_hash) { if (client_hash != server_hash) { switch(session->status) { // this switch can be replaced with a simple previous_status.push(status), but it is here for readibility case PROCESSING_QUERY: @@ -360,7 +362,7 @@ inline bool verify_variable(MySQL_Session* session, int idx, uint32_t client_has break; } session->set_status(mysql_tracked_variables[idx].status); - session->mysql_variables->server_set_value(idx, session->mysql_variables->client_get_value(idx)); + mysql_variables.server_set_value(session, idx, mysql_variables.client_get_value(session, idx)); return true; } return false; diff --git a/lib/mysql_connection.cpp b/lib/mysql_connection.cpp index 0c5a84fa0..35c346fdd 100644 --- a/lib/mysql_connection.cpp +++ b/lib/mysql_connection.cpp @@ -406,14 +406,14 @@ unsigned int MySQL_Connection::set_charset(unsigned int _c, enum charset_action // SQL_CHARACTER_SET should be set befor setting SQL_CHRACTER_ACTION std::stringstream ss; ss << _c; - myds->sess->mysql_variables->client_set_value(SQL_CHARACTER_SET, ss.str()); + mysql_variables.client_set_value(myds->sess, SQL_CHARACTER_SET, ss.str()); // When SQL_CHARACTER_ACTION is set character set variables are set according to // SQL_CHRACTER_SET value ss.str(std::string()); ss.clear(); ss << action; - myds->sess->mysql_variables->client_set_value(SQL_CHARACTER_ACTION, ss.str()); + mysql_variables.client_set_value(myds->sess, SQL_CHARACTER_ACTION, ss.str()); return _c; } @@ -590,7 +590,7 @@ void MySQL_Connection::connect_start() { mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, (void *)&timeout); /* Take client character set and use it to connect to backend */ if (myds && myds->sess) { - csname = myds->sess->mysql_variables->client_get_value(SQL_CHARACTER_SET); + csname = mysql_variables.client_get_value(myds->sess, SQL_CHARACTER_SET); } const MARIADB_CHARSET_INFO * c = NULL; @@ -731,12 +731,12 @@ void MySQL_Connection::set_autocommit_cont(short event) { void MySQL_Connection::set_names_start() { PROXY_TRACE(); - const MARIADB_CHARSET_INFO * c = proxysql_find_charset_nr(atoi(myds->sess->mysql_variables->client_get_value(SQL_CHARACTER_SET))); + const MARIADB_CHARSET_INFO * c = proxysql_find_charset_nr(atoi(mysql_variables.client_get_value(myds->sess, SQL_CHARACTER_SET))); if (!c) { - proxy_error("Not existing charset number %u\n", atoi(myds->sess->mysql_variables->client_get_value(SQL_CHARACTER_SET))); + proxy_error("Not existing charset number %u\n", atoi(mysql_variables.client_get_value(myds->sess, SQL_CHARACTER_SET))); assert(0); } - async_exit_status = mysql_set_character_set_start(&interr,mysql, NULL, atoi(myds->sess->mysql_variables->client_get_value(SQL_CHARACTER_SET))); + async_exit_status = mysql_set_character_set_start(&interr,mysql, NULL, atoi(mysql_variables.client_get_value(myds->sess, SQL_CHARACTER_SET))); } void MySQL_Connection::set_names_cont(short event) { diff --git a/src/main.cpp b/src/main.cpp index 0b5000915..6bc9c778a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -718,6 +718,7 @@ MySQL_Monitor *GloMyMon; std::thread *MyMon_thread = NULL; MySQL_Logger *GloMyLogger; +MySQL_Variables mysql_variables; SQLite3_Server *GloSQLite3Server; #ifdef PROXYSQLCLICKHOUSE