Adding ability to parse some variables based ontheir attributes

Expanded mysql_variable_st to include is_number and is_bool
pull/2675/head
René Cannaò 6 years ago
parent 54ee4e9b69
commit 3454c625c2

@ -46,6 +46,8 @@ public:
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_Connection *myconn);
bool parse_variable_boolean(MySQL_Session *sess, int idx, string &value1, bool& exit_after_SetParse, bool* lock_hostgroup);
bool parse_variable_number(MySQL_Session *sess, int idx, string &value1, bool& exit_after_SetParse, bool* lock_hostgroup);
};
#endif // #ifndef MYSQL_VARIABLES_H

@ -206,6 +206,8 @@ typedef struct {
bool quote; // if the variable needs to be quoted
bool set_transaction; // if related to SET TRANSACTION statement . if false , it will be execute "SET varname = varvalue" . If true, "SET varname varvalue"
bool special_handling; // if true, some special handling is required
bool is_number; // if true, the variable is a number. Special cases should be checked
bool is_bool; // if true, the variable is a boolean. Special cases should be checked
char * set_variable_name; // what variable name (or string) will be used when setting it to backend
char * internal_variable_name; // variable name as displayed in admin , WITHOUT "default_"
char * default_value; // default value
@ -969,29 +971,45 @@ extern __thread unsigned int g_seed;
// field_3: if the variable needs to be quoted
// field_4: if related to SET TRANSACTION statement . if false , it will be execute "SET varname = varvalue" . If true, "SET varname varvalue"
// field_5: if true, some special handling is required
// field_6: what variable name (or string) will be used when setting it to backend
// field_7: variable name as displayed in admin , WITHOUT "default_"
// field_8: default value
// field_6: if true, the variable is a number. Special cases should be checked
// field_7: if true, the variable is a boolean. Special cases should be checked
// field_8: what variable name (or string) will be used when setting it to backend
// field_9: variable name as displayed in admin , WITHOUT "default_"
// field_10: default value
/*
typedef struct {
enum variable_name idx; // index number
enum session_status status; // what status should be changed after setting this variables
bool quote; // if the variable needs to be quoted
bool set_transaction; // if related to SET TRANSACTION statement . if false , it will be execute "SET varname = varvalue" . If true, "SET varname varvalue"
bool special_handling; // if true, some special handling is required
bool is_number; // if true, the variable is a number. Special cases should be checked
bool is_bool; // if true, the variable is a boolean. Special cases should be checked
char * set_variable_name; // what variable name (or string) will be used when setting it to backend
char * internal_variable_name; // variable name as displayed in admin , WITHOUT "default_"
char * default_value; // default value
} mysql_variable_st;
*/
mysql_variable_st mysql_tracked_variables[] {
{ SQL_CHARACTER_SET, SETTING_CHARSET, false, true, false, (char *)"CHARSET", (char *)"CHARSET", (char *)"UTF8" } , // should be before SQL_CHARACTER_SET_RESULTS
{ SQL_CHARACTER_ACTION, NONE, false, false, false, (char *)"action", (char *)"action", (char *)"1" } ,
{ SQL_SET_NAMES, SETTING_SET_NAMES,false, false, false, (char *)"names", (char *)"names", (char *)"DEFAULT" } ,
{ SQL_SAFE_UPDATES, SETTING_VARIABLE, true, false, true, (char *)"sql_safe_updates", (char *)"sql_safe_updates", (char *)"OFF" } ,
{ SQL_SELECT_LIMIT, SETTING_VARIABLE, false, false, true, (char *)"sql_select_limit", (char *)"sql_select_limit", (char *)"DEFAULT" } ,
{ SQL_SQL_MODE, SETTING_VARIABLE, true, false, true, (char *)"sql_mode" , (char *)"sql_mode" , (char *)"" } ,
{ SQL_TIME_ZONE, SETTING_VARIABLE, true, false, true, (char *)"time_zone", (char *)"time_zone", (char *)"SYSTEM" } ,
{ SQL_CHARACTER_SET_RESULTS, SETTING_VARIABLE, false, false, true, (char *)"character_set_results", (char *)"character_set_results", (char *)"UTF8" } ,
{ SQL_CHARACTER_SET_CONNECTION, SETTING_VARIABLE, false, false, true, (char *)"character_set_connection", (char *)"character_set_connection", (char *)"UTF8" } ,
{ SQL_CHARACTER_SET_CLIENT, SETTING_VARIABLE, false, false, true, (char *)"character_set_client", (char *)"character_set_client", (char *)"UTF8" } ,
{ SQL_CHARACTER_SET_DATABASE, SETTING_VARIABLE, false, false, true, (char *)"character_set_database", (char *)"character_set_database", (char *)"UTF8" } ,
{ SQL_ISOLATION_LEVEL, SETTING_ISOLATION_LEVEL, false, true, true, (char *)"SESSION TRANSACTION ISOLATION LEVEL", (char *)"isolation_level", (char *)"READ COMMITTED" } ,
{ SQL_TRANSACTION_READ, SETTING_TRANSACTION_READ, false, true, true, (char *)"SESSION TRANSACTION READ", (char *)"transaction_read", (char *)"WRITE" } ,
{ SQL_SQL_AUTO_IS_NULL, SETTING_VARIABLE, true, false, true, (char *)"sql_auto_is_null", (char *)"sql_auto_is_null", (char *)"OFF" } ,
{ SQL_COLLATION_CONNECTION, SETTING_VARIABLE, true, false, true, (char *)"collation_connection", (char *)"collation_connection", (char *)"utf8_general_ci" } ,
{ SQL_NET_WRITE_TIMEOUT, SETTING_VARIABLE, false, false, true, (char *)"net_write_timeout", (char *)"net_write_timeout", (char *)"60" } ,
{ SQL_MAX_JOIN_SIZE, SETTING_VARIABLE, false, false, true, (char *)"max_join_size", (char *)"max_join_size", (char *)"18446744073709551615" } ,
{ SQL_LOG_BIN, SETTING_VARIABLE, false, false, true, (char *)"sql_log_bin", (char *)"sql_log_bin", (char *)"1" } ,
{ SQL_WSREP_SYNC_WAIT, SETTING_VARIABLE, false, false, true, (char *)"wsrep_sync_wait", (char *)"wsrep_sync_wait", (char *)"0" } ,
{ SQL_CHARACTER_SET, SETTING_CHARSET, false, true, false, false, false, (char *)"CHARSET", (char *)"CHARSET", (char *)"UTF8" } , // should be before SQL_CHARACTER_SET_RESULTS
{ SQL_CHARACTER_ACTION, NONE, false, false, false, false, false, (char *)"action", (char *)"action", (char *)"1" } ,
{ SQL_SET_NAMES, SETTING_SET_NAMES, false, false, false, false, false, (char *)"names", (char *)"names", (char *)"DEFAULT" } ,
{ SQL_SAFE_UPDATES, SETTING_VARIABLE, true, false, true, false, true, (char *)"sql_safe_updates", (char *)"sql_safe_updates", (char *)"OFF" } ,
{ SQL_SELECT_LIMIT, SETTING_VARIABLE, false, false, true, true, false, (char *)"sql_select_limit", (char *)"sql_select_limit", (char *)"DEFAULT" } ,
{ SQL_SQL_MODE, SETTING_VARIABLE, true, false, true, false, false, (char *)"sql_mode" , (char *)"sql_mode" , (char *)"" } ,
{ SQL_TIME_ZONE, SETTING_VARIABLE, true, false, true, false, false, (char *)"time_zone", (char *)"time_zone", (char *)"SYSTEM" } ,
{ SQL_CHARACTER_SET_RESULTS, SETTING_VARIABLE, false, false, true, false, false, (char *)"character_set_results", (char *)"character_set_results", (char *)"UTF8" } ,
{ SQL_CHARACTER_SET_CONNECTION, SETTING_VARIABLE, false, false, true, false, false, (char *)"character_set_connection", (char *)"character_set_connection", (char *)"UTF8" } ,
{ SQL_CHARACTER_SET_CLIENT, SETTING_VARIABLE, false, false, true, false, false, (char *)"character_set_client", (char *)"character_set_client", (char *)"UTF8" } ,
{ SQL_CHARACTER_SET_DATABASE, SETTING_VARIABLE, false, false, true, false, false, (char *)"character_set_database", (char *)"character_set_database", (char *)"UTF8" } ,
{ SQL_ISOLATION_LEVEL, SETTING_ISOLATION_LEVEL, false, true, true, false, false, (char *)"SESSION TRANSACTION ISOLATION LEVEL", (char *)"isolation_level", (char *)"READ COMMITTED" } ,
{ SQL_TRANSACTION_READ, SETTING_TRANSACTION_READ, false, true, true, false, false, (char *)"SESSION TRANSACTION READ", (char *)"transaction_read", (char *)"WRITE" } ,
{ SQL_SQL_AUTO_IS_NULL, SETTING_VARIABLE, true, false, true, false, true, (char *)"sql_auto_is_null", (char *)"sql_auto_is_null", (char *)"OFF" } ,
{ SQL_COLLATION_CONNECTION, SETTING_VARIABLE, true, false, true, false, false, (char *)"collation_connection", (char *)"collation_connection", (char *)"utf8_general_ci" } ,
{ SQL_NET_WRITE_TIMEOUT, SETTING_VARIABLE, false, false, true, true, false, (char *)"net_write_timeout", (char *)"net_write_timeout", (char *)"60" } ,
{ SQL_MAX_JOIN_SIZE, SETTING_VARIABLE, false, false, true, true, false, (char *)"max_join_size", (char *)"max_join_size", (char *)"18446744073709551615" } ,
{ SQL_LOG_BIN, SETTING_VARIABLE, false, false, true, false, false, (char *)"sql_log_bin", (char *)"sql_log_bin", (char *)"1" } ,
{ SQL_WSREP_SYNC_WAIT, SETTING_VARIABLE, false, false, true, false, false, (char *)"wsrep_sync_wait", (char *)"wsrep_sync_wait", (char *)"0" } ,
};
#else
extern mysql_variable_st mysql_tracked_variables[];

@ -5036,54 +5036,36 @@ bool MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C
unable_to_parse_set_statement(lock_hostgroup);
return false;
}
// the following two blocks of code will be simplified later
} else if ((var == "sql_auto_is_null") || (var == "sql_safe_updates")) {
std::string value1 = *values;
proxy_debug(PROXY_DEBUG_MYSQL_COM, 5, "Processing SET %s value %s\n", var.c_str(), value1.c_str());
int __tmp_value = -1;
if (
(strcasecmp(value1.c_str(),(char *)"0")==0) ||
(strcasecmp(value1.c_str(),(char *)"false")==0) ||
(strcasecmp(value1.c_str(),(char *)"off")==0)
) {
__tmp_value = 0;
} else {
if (
(strcasecmp(value1.c_str(),(char *)"1")==0) ||
(strcasecmp(value1.c_str(),(char *)"true")==0) ||
(strcasecmp(value1.c_str(),(char *)"on")==0)
) {
__tmp_value = 1;
}
}
if (__tmp_value >= 0) {
proxy_debug(PROXY_DEBUG_MYSQL_COM, 7, "Processing SET %s value %s\n", var.c_str(), value1.c_str());
uint32_t var_value_int=SpookyHash::Hash32(value1.c_str(),value1.length(),10);
int idx = SQL_NAME_LAST;
for (int i = 0 ; i < SQL_NAME_LAST ; i++) {
if (!strcmp(var.c_str(), mysql_tracked_variables[i].set_variable_name)) {
int idx = SQL_NAME_LAST;
for (int i = 0 ; i < SQL_NAME_LAST ; i++) {
if (mysql_tracked_variables[i].is_bool) {
if (!strcasecmp(var.c_str(), mysql_tracked_variables[i].set_variable_name)) {
idx = mysql_tracked_variables[i].idx;
break;
}
}
if (idx == SQL_NAME_LAST) {
proxy_error("Variable %s not found in mysql_tracked_variables[]\n", var.c_str());
unable_to_parse_set_statement(lock_hostgroup);
}
if (idx != SQL_NAME_LAST) {
if (mysql_variables.parse_variable_boolean(this,idx, *values, exit_after_SetParse, lock_hostgroup)==false) {
return false;
}
if (mysql_variables.client_get_hash(this, idx) != var_value_int) {
if (__tmp_value == 0) {
if (!mysql_variables.client_set_value(this, idx, "OFF"))
return false;
} else {
if (!mysql_variables.client_set_value(this, idx, "ON"))
return false;
}
} else if ( (var == "sql_select_limit") || (var == "net_write_timeout") || (var == "max_join_size") ) {
int idx = SQL_NAME_LAST;
for (int i = 0 ; i < SQL_NAME_LAST ; i++) {
if (mysql_tracked_variables[i].is_number) {
if (!strcasecmp(var.c_str(), mysql_tracked_variables[i].set_variable_name)) {
idx = mysql_tracked_variables[i].idx;
break;
}
proxy_debug(PROXY_DEBUG_MYSQL_COM, 5, "Changing connection %s to %s\n", var.c_str(), value1.c_str());
}
exit_after_SetParse = true;
} else {
unable_to_parse_set_statement(lock_hostgroup);
return false;
}
if (idx != SQL_NAME_LAST) {
if (mysql_variables.parse_variable_number(this,idx, *values, exit_after_SetParse, lock_hostgroup)==false) {
return false;
}
}
} else if (var == "autocommit") {
std::string value1 = *values;
@ -5175,48 +5157,6 @@ bool MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C
unable_to_parse_set_statement(lock_hostgroup);
return false;
}
} else if ( (var == "sql_select_limit") || (var == "net_write_timeout") || (var == "max_join_size") ) {
std::string value1 = *values;
int vl = strlen(value1.c_str());
const char *v = value1.c_str();
bool only_digit_chars = true;
for (int i=0; i<vl && only_digit_chars==true; i++) {
if (is_digit(v[i])==0) {
only_digit_chars=false;
}
}
if (!only_digit_chars) {
if (var == "sql_select_limit") { // only sql_select_limit allows value "default"
if (strcasecmp(v,"default")==0) {
only_digit_chars = true;
}
}
}
if (only_digit_chars) {
proxy_debug(PROXY_DEBUG_MYSQL_COM, 7, "Processing SET %s value %s\n", var.c_str(), value1.c_str());
uint32_t var_value_int=SpookyHash::Hash32(value1.c_str(),value1.length(),10);
int idx = SQL_NAME_LAST;
for (int i = 0 ; i < SQL_NAME_LAST ; i++) {
if (!strcasecmp(var.c_str(), mysql_tracked_variables[i].set_variable_name)) {
idx = mysql_tracked_variables[i].idx;
break;
}
}
if (idx == SQL_NAME_LAST) {
proxy_error("Variable %s not found in mysql_tracked_variables[]\n", var.c_str());
unable_to_parse_set_statement(lock_hostgroup);
return false;
}
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());
}
exit_after_SetParse = true;
} else {
unable_to_parse_set_statement(lock_hostgroup);
return false;
}
} else if ( (var == "character_set_results") || ( var == "collation_connection" ) ||
(var == "character_set_connection") || (var == "character_set_client") ||
(var == "character_set_database")) {

@ -7,6 +7,14 @@
#include <sstream>
static inline char is_digit(char c) {
if(c >= '0' && c <= '9')
return 1;
return 0;
}
verify_var MySQL_Variables::verifiers[SQL_NAME_LAST];
update_var MySQL_Variables::updaters[SQL_NAME_LAST];
@ -452,3 +460,77 @@ bool logbin_update_server_variable(MySQL_Session* session, int idx, int &_rc) {
return session->handler_again___status_SETTING_SQL_LOG_BIN(&_rc);
}
bool MySQL_Variables::parse_variable_boolean(MySQL_Session *sess, int idx, string& value1, bool& exit_after_SetParse, bool * lock_hostgroup) {
proxy_debug(PROXY_DEBUG_MYSQL_COM, 5, "Processing SET %s value %s\n", mysql_tracked_variables[idx].set_variable_name, value1.c_str());
int __tmp_value = -1;
if (
(strcasecmp(value1.c_str(),(char *)"0")==0) ||
(strcasecmp(value1.c_str(),(char *)"false")==0) ||
(strcasecmp(value1.c_str(),(char *)"off")==0)
) {
__tmp_value = 0;
} else {
if (
(strcasecmp(value1.c_str(),(char *)"1")==0) ||
(strcasecmp(value1.c_str(),(char *)"true")==0) ||
(strcasecmp(value1.c_str(),(char *)"on")==0)
) {
__tmp_value = 1;
}
}
if (__tmp_value >= 0) {
proxy_debug(PROXY_DEBUG_MYSQL_COM, 7, "Processing SET %s value %s\n", mysql_tracked_variables[idx].set_variable_name, value1.c_str());
uint32_t var_value_int=SpookyHash::Hash32(value1.c_str(),value1.length(),10);
if (mysql_variables.client_get_hash(sess, idx) != var_value_int) {
if (__tmp_value == 0) {
if (!mysql_variables.client_set_value(sess, idx, "OFF"))
return false;
} else {
if (!mysql_variables.client_set_value(sess, idx, "ON"))
return false;
}
proxy_debug(PROXY_DEBUG_MYSQL_COM, 5, "Changing connection %s to %s\n", mysql_tracked_variables[idx].set_variable_name, value1.c_str());
}
exit_after_SetParse = true;
} else {
sess->unable_to_parse_set_statement(lock_hostgroup);
return false;
}
return true;
}
bool MySQL_Variables::parse_variable_number(MySQL_Session *sess, int idx, string& value1, bool& exit_after_SetParse, bool * lock_hostgroup) {
int vl = strlen(value1.c_str());
const char *v = value1.c_str();
bool only_digit_chars = true;
for (int i=0; i<vl && only_digit_chars==true; i++) {
if (is_digit(v[i])==0) {
only_digit_chars=false;
}
}
if (!only_digit_chars) {
if (strcasecmp(mysql_tracked_variables[idx].set_variable_name,(char *)"sql_select_limit")==0) { // only sql_select_limit allows value "default"
if (strcasecmp(v,"default")==0) {
only_digit_chars = true;
}
}
}
if (only_digit_chars) {
proxy_debug(PROXY_DEBUG_MYSQL_COM, 7, "Processing SET %s value %s\n", mysql_tracked_variables[idx].set_variable_name, value1.c_str());
uint32_t var_value_int=SpookyHash::Hash32(value1.c_str(),value1.length(),10);
if (mysql_variables.client_get_hash(sess, idx) != var_value_int) {
if (!mysql_variables.client_set_value(sess, idx, value1.c_str()))
return false;
proxy_debug(PROXY_DEBUG_MYSQL_COM, 5, "Changing connection %s to %s\n", mysql_tracked_variables[idx].set_variable_name, value1.c_str());
}
exit_after_SetParse = true;
} else {
sess->unable_to_parse_set_statement(lock_hostgroup);
return false;
}
return true;
}

Loading…
Cancel
Save