diff --git a/include/MySQL_Variables.h b/include/MySQL_Variables.h index 9e5fdef28..76c8b93b9 100644 --- a/include/MySQL_Variables.h +++ b/include/MySQL_Variables.h @@ -33,6 +33,7 @@ public: virtual ~MySQL_Variables(); bool client_set_value(MySQL_Session* session, int idx, const std::string& value); + bool client_set_hash_and_value(MySQL_Session* session, int idx, const std::string& value, uint32_t hash); const char* client_get_value(MySQL_Session* session, int idx) const; uint32_t client_get_hash(MySQL_Session* session, int idx) const; diff --git a/lib/MySQL_Variables.cpp b/lib/MySQL_Variables.cpp index 22eaae76a..f714d64e4 100644 --- a/lib/MySQL_Variables.cpp +++ b/lib/MySQL_Variables.cpp @@ -58,6 +58,15 @@ bool MySQL_Variables::on_connect_to_backend(MySQL_Session* session) { return true; } + +bool MySQL_Variables::client_set_hash_and_value(MySQL_Session* session, int idx, const std::string& value, uint32_t hash) { + session->client_myds->myconn->var_hash[idx] = hash; + if (session->client_myds->myconn->variables[idx].value) { + free(session->client_myds->myconn->variables[idx].value); + } + session->client_myds->myconn->variables[idx].value = strdup(value.c_str()); +} + 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"); @@ -74,17 +83,17 @@ bool MySQL_Variables::client_set_value(MySQL_Session* session, int idx, const st // SET NAMES command from client if (value == "1") { 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)); + mysql_variables.client_set_hash_and_value(session, SQL_CHARACTER_SET_RESULTS, mysql_variables.client_get_value(session, SQL_CHARACTER_SET), mysql_variables.client_get_hash(session, SQL_CHARACTER_SET)); + mysql_variables.client_set_hash_and_value(session, SQL_CHARACTER_SET_CLIENT, mysql_variables.client_get_value(session, SQL_CHARACTER_SET), mysql_variables.client_get_hash(session, SQL_CHARACTER_SET)); + mysql_variables.client_set_hash_and_value(session, SQL_CHARACTER_SET_CONNECTION, mysql_variables.client_get_value(session, SQL_CHARACTER_SET), mysql_variables.client_get_hash(session, SQL_CHARACTER_SET)); + mysql_variables.client_set_hash_and_value(session, SQL_COLLATION_CONNECTION, mysql_variables.client_get_value(session, SQL_CHARACTER_SET), mysql_variables.client_get_hash(session, SQL_CHARACTER_SET)); } } // SET CHARSET command from client else if (value == "2") { 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_hash_and_value(session, SQL_CHARACTER_SET_RESULTS, mysql_variables.client_get_value(session, SQL_CHARACTER_SET), mysql_variables.client_get_hash(session, SQL_CHARACTER_SET)); + mysql_variables.client_set_hash_and_value(session, SQL_CHARACTER_SET_CLIENT, mysql_variables.client_get_value(session, SQL_CHARACTER_SET), mysql_variables.client_get_hash(session, SQL_CHARACTER_SET)); } if (mysql_variables.client_get_value(session, SQL_CHARACTER_SET_DATABASE)) { const MARIADB_CHARSET_INFO *ci = NULL; @@ -105,15 +114,6 @@ bool MySQL_Variables::client_set_value(MySQL_Session* session, int idx, const st mysql_variables.client_set_value(session, SQL_COLLATION_CONNECTION, ss.str()); } } - // SET NAMES during handshake etc. - else if (value == "3") { - 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)); - } - } } session->client_myds->myconn->var_hash[idx] = SpookyHash::Hash32(value.c_str(),strlen(value.c_str()),10); diff --git a/lib/mysql_connection.cpp b/lib/mysql_connection.cpp index d23b93ee8..e50e4d11e 100644 --- a/lib/mysql_connection.cpp +++ b/lib/mysql_connection.cpp @@ -611,7 +611,19 @@ void MySQL_Connection::connect_start() { proxy_error("Not existing charset number %s\n", mysql_thread___default_variables[SQL_CHARACTER_SET]); assert(0); } - set_charset(c->nr, CONNECT_START); + { + /* We are connecting to backend setting charset in mysql_options. + * Client already has sent us a character set and client connection variables have been already set. + * Now we store this charset in server connection variables to avoid updating this variables on backend. + */ + std::stringstream ss; + ss << c->nr; + + mysql_variables.server_set_value(myds->sess, SQL_CHARACTER_SET_RESULTS, ss.str().c_str()); + mysql_variables.server_set_value(myds->sess, SQL_CHARACTER_SET_CLIENT, ss.str().c_str()); + mysql_variables.server_set_value(myds->sess, SQL_CHARACTER_SET_CONNECTION, ss.str().c_str()); + mysql_variables.server_set_value(myds->sess, SQL_COLLATION_CONNECTION, ss.str().c_str()); + } mysql_options(mysql, MYSQL_SET_CHARSET_NAME, c->csname); unsigned long client_flags = 0; //if (mysql_thread___client_found_rows)