use separate function for set names verification

pull/2650/head
val 6 years ago
parent 5a33e9763d
commit 246a9d828a

@ -21,6 +21,7 @@ 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_server_variable(MySQL_Session* session, int idx, uint32_t client_hash, uint32_t server_hash);
bool verify_set_names(MySQL_Session* session);
bool logbin_update_server_variable(MySQL_Session* session, int idx, int &_rc);
class MySQL_Variables {
@ -38,6 +39,7 @@ public:
uint32_t client_get_hash(MySQL_Session* session, int idx) const;
void server_set_value(MySQL_Session* session, int idx, const char* value);
void server_set_hash_and_value(MySQL_Session* session, int idx, const char* value, uint32_t hash);
const char* server_get_value(MySQL_Session* session, int idx) const;
inline uint32_t server_get_hash(MySQL_Session* session, int idx) const;

@ -3553,6 +3553,11 @@ handler_again:
goto handler_again;
}
// Optimize network traffic when we can use 'SET NAMES'
if (verify_set_names(this)) {
goto handler_again;
}
for (auto i = 0; i < SQL_NAME_LAST; i++) {
if(!myconn->var_absent[i] && mysql_variables.verify_variable(this, i)) {
goto handler_again;

@ -74,6 +74,20 @@ bool MySQL_Variables::client_set_hash_and_value(MySQL_Session* session, int idx,
return true;
}
void MySQL_Variables::server_set_hash_and_value(MySQL_Session* session, int idx, const char* value, uint32_t hash) {
if (!session || !session->mybe || !session->mybe->server_myds || !session->mybe->server_myds->myconn || !value) {
proxy_warning("Session validation failed\n");
return;
}
session->mybe->server_myds->myconn->var_hash[idx] = hash;
if (session->mybe->server_myds->myconn->variables[idx].value) {
free(session->mybe->server_myds->myconn->variables[idx].value);
}
session->mybe->server_myds->myconn->variables[idx].value = strdup(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");
@ -336,61 +350,75 @@ bool update_server_variable(MySQL_Session* session, int idx, int &_rc) {
return ret;
}
bool verify_set_names(MySQL_Session* session) {
uint32_t client_charset_hash = mysql_variables.client_get_hash(session, SQL_CHARACTER_SET_CLIENT);
uint32_t results_charset_hash = mysql_variables.client_get_hash(session, SQL_CHARACTER_SET_RESULTS);
if (client_charset_hash != results_charset_hash)
return false;
uint32_t connection_charset_hash = mysql_variables.client_get_hash(session, SQL_CHARACTER_SET_CONNECTION);
if (client_charset_hash != connection_charset_hash)
return false;
uint32_t collation_hash = mysql_variables.client_get_hash(session, SQL_COLLATION_CONNECTION);
if (client_charset_hash != collation_hash)
return false;
if (client_charset_hash != mysql_variables.server_get_hash(session, SQL_CHARACTER_SET_CLIENT) ||
results_charset_hash != mysql_variables.server_get_hash(session, SQL_CHARACTER_SET_RESULTS) ||
connection_charset_hash != mysql_variables.server_get_hash(session, SQL_CHARACTER_SET_CONNECTION) ||
collation_hash != mysql_variables.server_get_hash(session, SQL_COLLATION_CONNECTION)) {
switch(session->status) { // this switch can be replaced with a simple previous_status.push(status), but it is here for readibility
case PROCESSING_QUERY:
session->previous_status.push(PROCESSING_QUERY);
break;
case PROCESSING_STMT_PREPARE:
session->previous_status.push(PROCESSING_STMT_PREPARE);
break;
case PROCESSING_STMT_EXECUTE:
session->previous_status.push(PROCESSING_STMT_EXECUTE);
break;
default:
proxy_error("Wrong status %d\n", session->status);
assert(0);
break;
}
session->set_status(SETTING_SET_NAMES);
uint32_t hash = mysql_variables.client_get_hash(session, SQL_CHARACTER_SET_CLIENT);
const char* value = mysql_variables.client_get_value(session, SQL_CHARACTER_SET_CLIENT);
mysql_variables.server_set_hash_and_value(session, SQL_CHARACTER_SET_CLIENT, value, hash);
mysql_variables.server_set_hash_and_value(session, SQL_CHARACTER_SET_RESULTS, value, hash);
mysql_variables.server_set_hash_and_value(session, SQL_CHARACTER_SET_CONNECTION, value, hash);
mysql_variables.server_set_hash_and_value(session, SQL_COLLATION_CONNECTION, value, hash);
mysql_variables.client_set_hash_and_value(session, SQL_CHARACTER_SET, value, hash);
mysql_variables.server_set_hash_and_value(session, SQL_CHARACTER_SET, value, hash);
return true;
}
return false;
}
inline bool verify_server_variable(MySQL_Session* session, int idx, uint32_t client_hash, uint32_t server_hash) {
if (client_hash != server_hash) {
uint32_t client_charset_hash = mysql_variables.client_get_hash(session, SQL_CHARACTER_SET_CLIENT);
uint32_t results_charset_hash = mysql_variables.client_get_hash(session, SQL_CHARACTER_SET_RESULTS);
uint32_t connection_charset_hash = mysql_variables.client_get_hash(session, SQL_CHARACTER_SET_CONNECTION);
uint32_t collation_hash = mysql_variables.client_get_hash(session, SQL_COLLATION_CONNECTION);
bool process_charset_variable = ((idx == SQL_CHARACTER_SET_CLIENT) || (idx == SQL_CHARACTER_SET_RESULTS) || (idx == SQL_CHARACTER_SET_CONNECTION) || (idx == SQL_COLLATION_CONNECTION));
bool is_set_names_hash = ((client_charset_hash == results_charset_hash) && (client_charset_hash == connection_charset_hash) && (client_charset_hash == collation_hash));
if (process_charset_variable && is_set_names_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:
session->previous_status.push(PROCESSING_QUERY);
break;
case PROCESSING_STMT_PREPARE:
session->previous_status.push(PROCESSING_STMT_PREPARE);
break;
case PROCESSING_STMT_EXECUTE:
session->previous_status.push(PROCESSING_STMT_EXECUTE);
break;
default:
proxy_error("Wrong status %d\n", session->status);
assert(0);
break;
}
session->set_status(SETTING_SET_NAMES);
mysql_variables.server_set_value(session, SQL_CHARACTER_SET_CLIENT, mysql_variables.client_get_value(session, SQL_CHARACTER_SET_CLIENT));
mysql_variables.server_set_value(session, SQL_CHARACTER_SET_RESULTS, mysql_variables.client_get_value(session, SQL_CHARACTER_SET_RESULTS));
mysql_variables.server_set_value(session, SQL_CHARACTER_SET_CONNECTION, mysql_variables.client_get_value(session, SQL_CHARACTER_SET_CONNECTION));
mysql_variables.server_set_value(session, SQL_COLLATION_CONNECTION, mysql_variables.client_get_value(session, SQL_COLLATION_CONNECTION));
mysql_variables.client_set_value(session, SQL_CHARACTER_SET, mysql_variables.client_get_value(session, SQL_CHARACTER_SET_CLIENT));
mysql_variables.server_set_value(session, SQL_CHARACTER_SET, mysql_variables.client_get_value(session, SQL_CHARACTER_SET_CLIENT));
return true;
} else {
switch(session->status) { // this switch can be replaced with a simple previous_status.push(status), but it is here for readibility
case PROCESSING_QUERY:
session->previous_status.push(PROCESSING_QUERY);
break;
case PROCESSING_STMT_PREPARE:
session->previous_status.push(PROCESSING_STMT_PREPARE);
break;
case PROCESSING_STMT_EXECUTE:
session->previous_status.push(PROCESSING_STMT_EXECUTE);
break;
default:
proxy_error("Wrong status %d\n", session->status);
assert(0);
break;
}
session->set_status(mysql_tracked_variables[idx].status);
mysql_variables.server_set_value(session, idx, mysql_variables.client_get_value(session, idx));
return true;
switch(session->status) { // this switch can be replaced with a simple previous_status.push(status), but it is here for readibility
case PROCESSING_QUERY:
session->previous_status.push(PROCESSING_QUERY);
break;
case PROCESSING_STMT_PREPARE:
session->previous_status.push(PROCESSING_STMT_PREPARE);
break;
case PROCESSING_STMT_EXECUTE:
session->previous_status.push(PROCESSING_STMT_EXECUTE);
break;
default:
proxy_error("Wrong status %d\n", session->status);
assert(0);
break;
}
session->set_status(mysql_tracked_variables[idx].status);
mysql_variables.server_set_value(session, idx, mysql_variables.client_get_value(session, idx));
return true;
}
return false;
}

Loading…
Cancel
Save