Polishing and cleanup

- cleanup code
- performance optimization
- use default value for connection
pull/2650/head
val 6 years ago
parent 61c1913334
commit 3e790c9083

@ -1,5 +1,6 @@
#ifndef __CLASS_MYSQL_SESSION_H
#define __CLASS_MYSQL_SESSION_H
#include "MySQL_Variables.h"
#include "proxysql.h"
#include "cpp.h"
@ -107,35 +108,19 @@ class MySQL_Session
int handler_again___status_RESETTING_CONNECTION();
void handler_again___new_thread_to_kill_connection();
// bool handler_again___verify_backend(int var);
bool handler_again___verify_backend_charset();
bool handler_again___verify_init_connect();
bool handler_again___verify_ldap_user_variable();
bool handler_again___verify_backend_autocommit();
bool handler_again___verify_backend_user_schema();
bool handler_again___verify_backend_sql_log_bin();
bool handler_again___verify_backend_tx_isolation();
bool handler_again___verify_backend_multi_statement();
bool handler_again___verify_backend__generic_variable(uint32_t *be_int, char **be_var, char *def, uint32_t *fe_int, char *fe_var, enum session_status next_sess_status);
bool handler_again___verify_backend_user_schema();
bool handler_again___status_SETTING_INIT_CONNECT(int *);
bool handler_again___status_SETTING_LDAP_USER_VARIABLE(int *);
bool handler_again___status_SETTING_SQL_LOG_BIN(int *);
bool handler_again___status_SETTING_SQL_MODE(int *);
bool handler_again___status_SETTING_TIME_ZONE(int *);
bool handler_again___status_SETTING_ISOLATION_LEVEL(int *);
bool handler_again___status_SETTING_TRANSACTION_READ(int *);
bool handler_again___status_SETTING_TX_ISOLATION(int *);
bool handler_again___status_SETTING_CHARACTER_SET_RESULTS(int *);
bool handler_again___status_SETTING_SESSION_TRACK_GTIDS(int *);
bool handler_again___status_SETTING_MULTI_STMT(int *_rc);
bool handler_again___status_SETTING_SQL_AUTO_IS_NULL(int *);
bool handler_again___status_SETTING_COLLATION_CONNECTION(int *);
bool handler_again___status_SETTING_NET_WRITE_TIMEOUT(int *);
bool handler_again___status_SETTING_MAX_JOIN_SIZE(int *);
bool handler_again___status_CHANGING_SCHEMA(int *);
bool handler_again___status_CONNECTING_SERVER(int *);
bool handler_again___status_CHANGING_USER_SERVER(int *);
bool handler_again___status_CHANGING_AUTOCOMMIT(int *);
bool handler_again___status_SETTING_MULTI_STMT(int *_rc);
void init();
void reset();
void add_ldap_comment_to_pkt(PtrSize_t *);
@ -143,7 +128,7 @@ class MySQL_Session
public:
bool handler_again___status_SETTING_GENERIC_VARIABLE(int *_rc, const char *var_name, const char *var_value, bool no_quote=false, bool set_transaction=false);
bool handler_again___status_CHANGING_CHARSET(int *);
bool handler_again___status_SETTING_SQL_LOG_BIN(int *);
std::stack<enum session_status> previous_status;
void * operator new(size_t);
void operator delete(void *);
@ -166,7 +151,7 @@ class MySQL_Session
MySQL_Data_Stream *client_myds;
MySQL_Data_Stream *server_myds;
char * default_schema;
std::unique_ptr<MySQL_Variables> mysql_variables;
std::unique_ptr<MySQL_Variables> mysql_variables {nullptr};
//this pointer is always initialized inside handler().
// it is an attempt to start simplifying the complexing of handler()

@ -10,43 +10,41 @@
class MySQL_Session;
class Updater {
public:
virtual bool verify_variables(MySQL_Session* session, int idx) = 0;
virtual bool update_server_variable(MySQL_Session* session, int idx, int &_rc) = 0;
virtual ~Updater();
};
extern const MARIADB_CHARSET_INFO * proxysql_find_charset_nr(unsigned int nr);
extern MARIADB_CHARSET_INFO * proxysql_find_charset_name(const char *name);
extern MARIADB_CHARSET_INFO * proxysql_find_charset_collate(const char *collatename);
extern void print_backtrace(void);
class Generic_Updater : public Updater {
public:
bool verify_variables(MySQL_Session* session, int idx);
bool update_server_variable(MySQL_Session* session, int idx, int &_rc);
};
typedef bool (*verify_var)(MySQL_Session* session, int idx, uint32_t client_hash, uint32_t server_hash);
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 logbin_update_server_variable(MySQL_Session* session, int idx, int &_rc);
class MySQL_Variables {
MySQL_Session* session;
public:
bool verify_generic_variable(uint32_t *be_int, char **be_var, char *def, uint32_t *fe_int, char *fe_var, enum session_status next_sess_status);
static int session_by_var[SQL_NAME_LAST];
static int var_by_session[NONE];
static bool quotes[SQL_NAME_LAST];
static bool set_transaction[SQL_NAME_LAST];
Updater* updaters[SQL_NAME_LAST];
verify_var verifiers[SQL_NAME_LAST];
update_var updaters[SQL_NAME_LAST];
public:
bool is_connected_to_backend;
MySQL_Variables(MySQL_Session* session);
virtual ~MySQL_Variables();
void client_set_value(int idx, const std::string& value);
const char* client_get_value(int idx);
uint32_t client_get_hash(int idx);
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;
void server_set_value(int idx, const char* value);
const char* server_get_value(int idx);
uint32_t server_get_hash(int idx);
const char* server_get_value(int idx) const;
inline uint32_t server_get_hash(int idx) const;
bool verify_variable(int idx);
bool verify_variable(int idx) const;
bool update_variable(session_status status, int &_rc);
bool on_connect_to_backend(mysql_variable_st* tracked_variables);
};
#endif // #ifndef MYSQL_VARIABLES_H

@ -22,7 +22,6 @@ using json = nlohmann::json;
class Variable {
public:
char *value = (char*)"";
uint32_t hash;
void fill_server_internal_session(json &j, int conn_num, int idx);
void fill_client_internal_session(json &j, int idx);
static const char set_name[SQL_NAME_LAST][64];
@ -60,31 +59,22 @@ class MySQL_Connection {
public:
struct {
char *server_version;
// uint32_t collation_connection_int;
// uint32_t net_write_timeout_int;
// uint32_t max_join_size_int;
uint32_t max_allowed_pkt;
uint32_t server_capabilities;
uint32_t client_flag;
unsigned int compression_min_length;
char *init_connect;
bool init_connect_sent;
// char * collation_connection;
// char * net_write_timeout;
// char * max_join_size;
// bool collation_connection_sent;
// bool net_write_timeout_sent;
// bool max_join_size_sent;
char *ldap_user_variable;
char *ldap_user_variable_value;
bool ldap_user_variable_sent;
uint8_t protocol_version;
uint8_t sql_log_bin;
int8_t last_set_autocommit;
bool autocommit;
bool no_backslash_escapes;
} options;
Variable variables[SQL_NAME_LAST];
uint32_t var_hash[SQL_NAME_LAST];
struct {
unsigned long length;
char *ptr;

@ -165,6 +165,8 @@ enum variable_name {
SQL_COLLATION_CONNECTION,
SQL_NET_WRITE_TIMEOUT,
SQL_MAX_JOIN_SIZE,
SQL_LOG_BIN,
SQL_WSREP_SYNC_WAIT,
SQL_NAME_LAST
};
@ -201,6 +203,7 @@ enum session_status {
SETTING_COLLATION_CONNECTION,
SETTING_NET_WRITE_TIMEOUT,
SETTING_MAX_JOIN_SIZE,
SETTING_WSREP_SYNC_WAIT,
SETTING_MULTI_STMT,
FAST_FORWARD,
PROCESSING_STMT_PREPARE,
@ -971,7 +974,6 @@ extern __thread bool mysql_thread___session_debug;
extern __thread unsigned int g_seed;
#endif /* PROXYSQL_EXTERN */
#ifndef MYSQL_TRACKED_VARIABLES
#define MYSQL_TRACKED_VARIABLES
#ifdef PROXYSQL_EXTERN
@ -987,21 +989,23 @@ 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_SQL_SAFE_UPDATES , true, false, false, (char *)"sql_safe_updates", (char *)"sql_safe_updates", (char *)"OFF" } ,
{ SQL_SELECT_LIMIT, SETTING_SQL_SELECT_LIMIT , false, false, false, (char *)"sql_select_limit", (char *)"sql_select_limit", (char *)"DEFAULT" } ,
{ SQL_SQL_MODE, SETTING_SQL_MODE , true, false, false, (char *)"sql_mode" , (char *)"sql_mode" , (char *)"" } ,
{ SQL_TIME_ZONE, SETTING_TIME_ZONE , true, false, false, (char *)"time_zone", (char *)"time_zone", (char *)"SYSTEM" } ,
{ SQL_CHARACTER_SET_RESULTS, SETTING_CHARACTER_SET_RESULTS, false, false, false, (char *)"character_set_results", (char *)"character_set_results", (char *)"UTF8" } ,
{ SQL_CHARACTER_SET_CONNECTION, SETTING_CHARACTER_SET_CONNECTION, false, false, false, (char *)"character_set_connection", (char *)"character_set_connection", (char *)"UTF8" } ,
{ SQL_CHARACTER_SET_CLIENT, SETTING_CHARACTER_SET_CLIENT, false, false, false, (char *)"character_set_client", (char *)"character_set_client", (char *)"UTF8" } ,
{ SQL_CHARACTER_SET_DATABASE, SETTING_CHARACTER_SET_DATABASE, false, false, false, (char *)"character_set_database", (char *)"character_set_database", (char *)"UTF8" } ,
{ SQL_SAFE_UPDATES, SETTING_SQL_SAFE_UPDATES , true, false, true, (char *)"sql_safe_updates", (char *)"sql_safe_updates", (char *)"OFF" } ,
{ SQL_SELECT_LIMIT, SETTING_SQL_SELECT_LIMIT , false, false, true, (char *)"sql_select_limit", (char *)"sql_select_limit", (char *)"DEFAULT" } ,
{ SQL_SQL_MODE, SETTING_SQL_MODE , true, false, true, (char *)"sql_mode" , (char *)"sql_mode" , (char *)"" } ,
{ SQL_TIME_ZONE, SETTING_TIME_ZONE , true, false, true, (char *)"time_zone", (char *)"time_zone", (char *)"SYSTEM" } ,
{ SQL_CHARACTER_SET_RESULTS, SETTING_CHARACTER_SET_RESULTS, false, false, true, (char *)"character_set_results", (char *)"character_set_results", (char *)"UTF8" } ,
{ SQL_CHARACTER_SET_CONNECTION, SETTING_CHARACTER_SET_CONNECTION, false, false, true, (char *)"character_set_connection", (char *)"character_set_connection", (char *)"UTF8" } ,
{ SQL_CHARACTER_SET_CLIENT, SETTING_CHARACTER_SET_CLIENT, false, false, true, (char *)"character_set_client", (char *)"character_set_client", (char *)"UTF8" } ,
{ SQL_CHARACTER_SET_DATABASE, SETTING_CHARACTER_SET_DATABASE, 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_SESSION_TRACK_GTIDS, SETTING_SESSION_TRACK_GTIDS, true, false, false, (char *)"session_track_gtids" , (char *)"session_track_gtids" , (char *)"OFF" } ,
{ SQL_SQL_AUTO_IS_NULL, SETTING_SQL_AUTO_IS_NULL, true, false, false, (char *)"sql_auto_is_null", (char *)"sql_auto_is_null", (char *)"OFF" } ,
{ SQL_COLLATION_CONNECTION, SETTING_COLLATION_CONNECTION, true, false, false, (char *)"COLLATION_CONNECTION", (char *)"collation_connection", (char *)"utf8_general_ci" } ,
{ SQL_NET_WRITE_TIMEOUT, SETTING_NET_WRITE_TIMEOUT, false, false, false, (char *)"NET_WRITE_TIMEOUT", (char *)"net_write_timeout", (char *)"60" } ,
{ SQL_MAX_JOIN_SIZE, SETTING_MAX_JOIN_SIZE, false, false, false, (char *)"MAX_JOIN_SIZE", (char *)"max_join_size", (char *)"18446744073709551615" } ,
{ SQL_SESSION_TRACK_GTIDS, SETTING_SESSION_TRACK_GTIDS, false, false, true, (char *)"session_track_gtids" , (char *)"session_track_gtids" , (char *)"OFF" } ,
{ SQL_SQL_AUTO_IS_NULL, SETTING_SQL_AUTO_IS_NULL, true, false, true, (char *)"sql_auto_is_null", (char *)"sql_auto_is_null", (char *)"OFF" } ,
{ SQL_COLLATION_CONNECTION, SETTING_COLLATION_CONNECTION, true, false, true, (char *)"COLLATION_CONNECTION", (char *)"collation_connection", (char *)"utf8_general_ci" } ,
{ SQL_NET_WRITE_TIMEOUT, SETTING_NET_WRITE_TIMEOUT, false, false, true, (char *)"NET_WRITE_TIMEOUT", (char *)"net_write_timeout", (char *)"60" } ,
{ SQL_MAX_JOIN_SIZE, SETTING_MAX_JOIN_SIZE, false, false, true, (char *)"MAX_JOIN_SIZE", (char *)"max_join_size", (char *)"18446744073709551615" } ,
{ SQL_LOG_BIN, SETTING_SQL_LOG_BIN, false, false, true, (char *)"SQL_LOG_BIN", (char *)"sql_log_bin", (char *)"1" } ,
{ SQL_WSREP_SYNC_WAIT, SETTING_WSREP_SYNC_WAIT, false, false, true, (char *)"WSREP_SYNC_WAIT", (char *)"wsrep_sync_wait", (char *)"0" } ,
};
#else
extern mysql_variable_st mysql_tracked_variables[];

@ -1982,8 +1982,6 @@ __exit_do_auth:
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());
}
if (sess->mysql_variables)
proxy_warning("TRACE : LOGIN charset server %s, client %s, handshake %d\n", sess->mysql_variables->server_get_value(SQL_CHARACTER_SET), sess->mysql_variables->client_get_value(SQL_CHARACTER_SET), charset);
// enable compression
if (capabilities & CLIENT_COMPRESS) {
if (myconn->options.server_capabilities & CLIENT_COMPRESS) {

@ -55,8 +55,7 @@ static inline char is_normal_char(char c) {
return 0;
}
extern const MARIADB_CHARSET_INFO * proxysql_find_charset_name(const char * const name);
extern MARIADB_CHARSET_INFO * proxysql_find_charset_name(const char * const name);
extern MARIADB_CHARSET_INFO * proxysql_find_charset_collate_names(const char *csname, const char *collatename);
extern const MARIADB_CHARSET_INFO * proxysql_find_charset_nr(unsigned int nr);
extern MARIADB_CHARSET_INFO * proxysql_find_charset_collate(const char *collatename);
@ -961,9 +960,10 @@ void MySQL_Session::generate_proxysql_internal_session_json(json &j) {
j["default_schema"] = ( default_schema ? default_schema : "" );
j["transaction_persistent"] = transaction_persistent;
for (auto idx = 0; idx < SQL_NAME_LAST; idx++) {
client_myds->myconn->variables[idx].fill_client_internal_session(j, idx);
if(mysql_tracked_variables[idx].special_handling) {
client_myds->myconn->variables[idx].fill_client_internal_session(j, idx);
}
}
j["conn"]["sql_log_bin"] = client_myds->myconn->options.sql_log_bin;
j["conn"]["autocommit"] = ( client_myds->myconn->options.autocommit ? "ON" : "OFF" );
j["conn"]["client_flag"]["value"] = client_myds->myconn->options.client_flag;
j["conn"]["client_flag"]["client_found_rows"] = (client_myds->myconn->options.client_flag & CLIENT_FOUND_ROWS ? 1 : 0);
@ -996,7 +996,9 @@ void MySQL_Session::generate_proxysql_internal_session_json(json &j) {
if (_myds->myconn) {
MySQL_Connection * _myconn = _myds->myconn;
for (auto idx = 0; idx < SQL_NAME_LAST; idx++) {
_myconn->variables[idx].fill_server_internal_session(j, i, idx);
if(mysql_tracked_variables[idx].special_handling) {
_myconn->variables[idx].fill_server_internal_session(j, i, idx);
}
}
sprintf(buff,"%p",_myconn);
j["backends"][i]["conn"]["address"] = buff;
@ -1007,7 +1009,6 @@ void MySQL_Session::generate_proxysql_internal_session_json(json &j) {
j["backends"][i]["conn"]["myconnpoll_get"] = _myconn->statuses.myconnpoll_get;
j["backends"][i]["conn"]["myconnpoll_put"] = _myconn->statuses.myconnpoll_put;
//j["backend"][i]["conn"]["charset"] = _myds->myconn->options.charset; // not used for backend
j["backends"][i]["conn"]["sql_log_bin"] = ( _myconn->options.sql_log_bin ? "ON" : "OFF" );
j["backends"][i]["conn"]["init_connect"] = ( _myconn->options.init_connect ? _myconn->options.init_connect : "");
j["backends"][i]["conn"]["init_connect_sent"] = _myds->myconn->options.init_connect_sent;
j["backends"][i]["conn"]["autocommit"] = ( _myds->myconn->options.autocommit ? "ON" : "OFF" );
@ -1575,85 +1576,6 @@ void MySQL_Session::handler_again___new_thread_to_kill_connection() {
// true should jump to handler_again
#define NEXT_IMMEDIATE_NEW(new_st) do { set_status(new_st); return true; } while (0)
bool MySQL_Session::handler_again___verify_backend_sql_log_bin() {
if (client_myds->myconn->options.sql_log_bin != mybe->server_myds->myconn->options.sql_log_bin) {
mybe->server_myds->myconn->options.sql_log_bin = client_myds->myconn->options.sql_log_bin;
switch(status) { // this switch can be replaced with a simple previous_status.push(status), but it is here for readibility
case PROCESSING_QUERY:
previous_status.push(PROCESSING_QUERY);
break;
case PROCESSING_STMT_PREPARE:
previous_status.push(PROCESSING_STMT_PREPARE);
break;
case PROCESSING_STMT_EXECUTE:
previous_status.push(PROCESSING_STMT_EXECUTE);
break;
default:
assert(0);
break;
}
NEXT_IMMEDIATE_NEW(SETTING_SQL_LOG_BIN);
}
return false;
}
bool MySQL_Session::handler_again___verify_backend__generic_variable(uint32_t *be_int, char **be_var, char *def, uint32_t *fe_int, char *fe_var, enum session_status next_sess_status) {
// be_int = backend int (hash)
// be_var = backend value
// def = default
// fe_int = frontend int (has)
// fe_var = frontend value
if (*be_int == 0) {
// it is the first time we use this backend. Set value to default
if (*be_var) {
free(*be_var);
*be_var = NULL;
}
*be_var = strdup(def);
uint32_t tmp_int = SpookyHash::Hash32(*be_var, strlen(*be_var), 10);
*be_int = tmp_int;
}
if (*fe_int) {
if (*fe_int != *be_int) {
{
*be_int = *fe_int;
if (*be_var) {
free(*be_var);
*be_var = NULL;
}
if (fe_var) {
*be_var = strdup(fe_var);
}
}
switch(status) { // this switch can be replaced with a simple previous_status.push(status), but it is here for readibility
case PROCESSING_QUERY:
previous_status.push(PROCESSING_QUERY);
break;
case PROCESSING_STMT_PREPARE:
previous_status.push(PROCESSING_STMT_PREPARE);
break;
case PROCESSING_STMT_EXECUTE:
previous_status.push(PROCESSING_STMT_EXECUTE);
break;
default:
assert(0);
break;
}
NEXT_IMMEDIATE_NEW(next_sess_status);
}
}
return false;
}
/*
bool MySQL_Session::handler_again___verify_backend(int var) {
bool ret = false;
proxy_debug(PROXY_DEBUG_MYSQL_CONNECTION, 5, "Session %p , client: %s , backend: %s\n", this, mysql_variables->client_get_value(var), mysql_variables->server_get_value(var));
ret = mysql_variables->verify_variable(var);
return ret;
}
*/
bool MySQL_Session::handler_again___verify_backend_multi_statement() {
if ((client_myds->myconn->options.client_flag & CLIENT_MULTI_STATEMENTS) != (mybe->server_myds->myconn->options.client_flag & CLIENT_MULTI_STATEMENTS)) {
@ -2001,8 +1923,8 @@ bool MySQL_Session::handler_again___status_SETTING_LDAP_USER_VARIABLE(int *_rc)
bool retry_conn=false;
// client error, serious
proxy_error("Detected a broken connection while setting LDAP USER VARIABLE on %s:%d hg %d : %d, %s\n", myconn->parent->address, myconn->parent->port, current_hostgroup, myerr, mysql_error(myconn->mysql));
if ((myds->myconn->reusable==true) && myds->myconn->IsActiveTransaction()==false && myds->myconn->MultiplexDisabled()==false) {
retry_conn=true;
if ((myds->myconn->reusable==true) && myds->myconn->IsActiveTransaction()==false && myds->myconn->MultiplexDisabled()==false) {
retry_conn=true;
}
myds->destroy_MySQL_Connection_From_Pool(false);
myds->fd=0;
@ -2045,9 +1967,9 @@ bool MySQL_Session::handler_again___status_SETTING_SQL_LOG_BIN(int *_rc) {
char *query=NULL;
unsigned long query_length=0;
if (myconn->async_state_machine==ASYNC_IDLE) {
char *q=(char *)"SET SQL_LOG_BIN=%d";
char *q=(char *)"SET SQL_LOG_BIN=%s";
query=(char *)malloc(strlen(q)+8);
sprintf(query,q,myconn->options.sql_log_bin);
sprintf(query,q,mysql_variables->client_get_value(SQL_LOG_BIN));
query_length=strlen(query);
}
int rc=myconn->async_send_simple_command(myds->revents,query,query_length);
@ -2056,15 +1978,15 @@ bool MySQL_Session::handler_again___status_SETTING_SQL_LOG_BIN(int *_rc) {
query=NULL;
}
if (rc==0) {
if (myconn->options.sql_log_bin==0) {
if (!strcmp("0", mysql_variables->client_get_value(SQL_LOG_BIN)) || !strcasecmp("OFF", mysql_variables->client_get_value(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 {
} else if (!strcmp("1", mysql_variables->client_get_value(SQL_LOG_BIN)) || !strcasecmp("ON", mysql_variables->client_get_value(SQL_LOG_BIN))) {
myconn->set_status_sql_log_bin0(false);
}
myds->revents|=POLLOUT; // we also set again POLLOUT to send a query immediately!
myds->revents|=POLLOUT; // we also set again POLLOUT to send a query immediately!
myds->DSS = STATE_MARIADB_GENERIC;
st=previous_status.top();
previous_status.pop();
@ -2077,9 +1999,8 @@ bool MySQL_Session::handler_again___status_SETTING_SQL_LOG_BIN(int *_rc) {
bool retry_conn=false;
// client error, serious
proxy_error("Detected a broken connection while setting SQL_LOG_BIN on %s:%d hg %d : %d, %s\n", myconn->parent->address, myconn->parent->port, current_hostgroup, myerr, mysql_error(myconn->mysql));
//if ((myds->myconn->reusable==true) && ((myds->myprot.prot_status & SERVER_STATUS_IN_TRANS)==0)) {
if ((myds->myconn->reusable==true) && myds->myconn->IsActiveTransaction()==false && myds->myconn->MultiplexDisabled()==false) {
retry_conn=true;
if ((myds->myconn->reusable==true) && myds->myconn->IsActiveTransaction()==false && myds->myconn->MultiplexDisabled()==false) {
retry_conn=true;
}
myds->destroy_MySQL_Connection_From_Pool(false);
myds->fd=0;
@ -2087,11 +2008,11 @@ bool MySQL_Session::handler_again___status_SETTING_SQL_LOG_BIN(int *_rc) {
myds->DSS=STATE_NOT_INITIALIZED;
NEXT_IMMEDIATE_NEW(CONNECTING_SERVER);
}
*_rc=-1; // an error happened, we should destroy the Session
*_rc=-1; // an error happened, we should destroy the Session
return ret;
} else {
proxy_warning("Error while setting SQL_LOG_BIN: %s:%d hg %d : %d, %s\n", myconn->parent->address, myconn->parent->port, current_hostgroup, myerr, mysql_error(myconn->mysql));
// we won't go back to PROCESSING_QUERY
// we won't go back to PROCESSING_QUERY
st=previous_status.top();
previous_status.pop();
char sqlstate[10];
@ -2162,7 +2083,6 @@ bool MySQL_Session::handler_again___status_SETTING_GENERIC_VARIABLE(int *_rc, co
query=NULL;
}
if (rc==0) {
proxy_warning("TRACE : tid [%lu] END SET VAR %s value %s\n", thread_session_id, var_name, var_value);
myds->revents|=POLLOUT; // we also set again POLLOUT to send a query immediately!
myds->DSS = STATE_MARIADB_GENERIC;
st=previous_status.top();
@ -2224,6 +2144,7 @@ bool MySQL_Session::handler_again___status_SETTING_GENERIC_VARIABLE(int *_rc, co
}
myds->fd=0;
RequestEnd(myds);
ret=true;
}
} else {
// rc==1 , nothing to do for now
@ -2318,7 +2239,6 @@ bool MySQL_Session::handler_again___status_CHANGING_SCHEMA(int *_rc) {
bool MySQL_Session::handler_again___status_CONNECTING_SERVER(int *_rc) {
proxy_warning("TRACE : CONNECTING TO SERVER\n");
//fprintf(stderr,"CONNECTING_SERVER\n");
unsigned long long curtime=monotonic_time();
thread->atomic_curtime=curtime;
@ -2364,11 +2284,6 @@ bool MySQL_Session::handler_again___status_CONNECTING_SERVER(int *_rc) {
NEXT_IMMEDIATE_NEW(WAITING_CLIENT_DATA);
}
}
proxy_warning("TRACE : HAVE CONNECTION START\n");
std::vector<int> vars = {SQL_CHARACTER_SET, SQL_CHARACTER_ACTION, SQL_CHARACTER_SET_RESULTS, SQL_CHARACTER_SET_CONNECTION, SQL_COLLATION_CONNECTION, SQL_CHARACTER_SET_CLIENT, SQL_CHARACTER_SET_DATABASE };
for (auto i : vars) {
proxy_warning("TRACE : tid [%lu] variable name %24s\tclient value [%5s]\tserver value [%5s]\n", thread_session_id, mysql_tracked_variables[i].set_variable_name, mysql_variables->client_get_value(i), mysql_variables->server_get_value(i));
}
if (mybe->server_myds->myconn==NULL) {
pause_until=thread->curtime+mysql_thread___connect_retries_delay*1000;
@ -2557,138 +2472,6 @@ bool MySQL_Session::handler_again___status_CHANGING_USER_SERVER(int *_rc) {
return false;
}
bool MySQL_Session::handler_again___status_CHANGING_CHARSET(int *_rc) {
assert(mybe->server_myds->myconn);
MySQL_Data_Stream *myds=mybe->server_myds;
MySQL_Connection *myconn=myds->myconn;
char msg[128];
const MARIADB_CHARSET_INFO *ci = NULL;
const char* replace_collation = NULL;
const char* not_supported_collation = NULL;
unsigned int replace_collation_nr = 0;
std::stringstream ss;
/* Validate that server can support client's charset */
int charset = atoi(mysql_variables->client_get_value(SQL_CHARACTER_SET));
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",mysql_variables->client_get_value(SQL_CHARACTER_SET));
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, client_myds->addr.addr, client_myds->addr.port);
myds->destroy_MySQL_Connection_From_Pool(false);
myds->fd=0;
*_rc=-1;
return false;
case HANDLE_UNKNOWN_CHARSET__REPLACE_WITH_DEFAULT_VERBOSE:
ci = proxysql_find_charset_nr(atoi(mysql_variables->client_get_value(SQL_CHARACTER_SET)));
if (!ci) {
proxy_error("Cannot find character set [%s]\n", mysql_variables->client_get_value(SQL_CHARACTER_SET));
assert(0);
}
not_supported_collation = ci->name;
ci = proxysql_find_charset_name(mysql_thread___default_variables[SQL_CHARACTER_SET]);
if (!ci) {
proxy_error("Cannot find character set [%s]\n", mysql_thread___default_variables[SQL_CHARACTER_SET]);
assert(0);
}
replace_collation = ci->name;
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",
mysql_variables->client_get_value(SQL_CHARACTER_SET), not_supported_collation,
replace_collation_nr, replace_collation, client_myds->addr.addr, client_myds->addr.port);
ss << replace_collation_nr;
mysql_variables->client_set_value(SQL_CHARACTER_SET, ss.str());
mysql_variables->client_set_value(SQL_CHARACTER_SET_RESULTS, ss.str());
mysql_variables->client_set_value(SQL_CHARACTER_SET_CLIENT, ss.str());
mysql_variables->client_set_value(SQL_CHARACTER_SET_CONNECTION, ss.str());
mysql_variables->client_set_value(SQL_COLLATION_CONNECTION, ss.str());
break;
case HANDLE_UNKNOWN_CHARSET__REPLACE_WITH_DEFAULT:
ci = proxysql_find_charset_name(mysql_thread___default_variables[SQL_CHARACTER_SET]);
if (!ci) {
proxy_error("Cannot filnd charset [%s]\n", mysql_thread___default_variables[SQL_CHARACTER_SET]);
assert(0);
}
replace_collation_nr = ci->nr;
ss << replace_collation_nr;
mysql_variables->client_set_value(SQL_CHARACTER_SET, ss.str());
break;
default:
proxy_error("Wrong configuration of the handle_unknown_charset\n");
break;
}
}
myds->DSS=STATE_MARIADB_QUERY;
enum session_status st=status;
if (myds->mypolls==NULL) {
thread->mypolls.add(POLLIN|POLLOUT, mybe->server_myds->fd, mybe->server_myds, thread->curtime);
}
int rc=myconn->async_set_names(myds->revents, atoi(mysql_variables->client_get_value(SQL_CHARACTER_SET)));
if (rc==0) {
proxy_warning("TRACE : END SET NAMES %s\n", mysql_variables->client_get_value(SQL_CHARACTER_SET));
__sync_fetch_and_add(&MyHGM->status.backend_set_names, 1);
myds->DSS = STATE_MARIADB_GENERIC;
st=previous_status.top();
previous_status.pop();
NEXT_IMMEDIATE_NEW(st);
} else {
if (rc==-1) {
// the command failed
int myerr=mysql_errno(myconn->mysql);
if (myerr >= 2000) {
if (myerr == 2019) {
ci = proxysql_find_charset_name(mysql_thread___default_variables[SQL_CHARACTER_SET]);
if (ci) replace_collation_nr = ci->nr;
proxy_error("Client trying to set a charset/collation (%u) not supported by backend (%s:%d). Changing it to %u\n", mysql_variables->client_get_value(SQL_CHARACTER_SET), myconn->parent->address, myconn->parent->port, replace_collation_nr);
ss.clear();
ss << replace_collation_nr;
mysql_variables->client_set_value(SQL_CHARACTER_SET, ss.str());
}
bool retry_conn=false;
// client error, serious
proxy_error("Detected a broken connection during SET NAMES on %s , %d : %d, %s\n", myconn->parent->address, myconn->parent->port, myerr, mysql_error(myconn->mysql));
if ((myds->myconn->reusable==true) && myds->myconn->IsActiveTransaction()==false && myds->myconn->MultiplexDisabled()==false) {
retry_conn=true;
}
myds->destroy_MySQL_Connection_From_Pool(false);
myds->fd=0;
if (retry_conn) {
myds->DSS=STATE_NOT_INITIALIZED;
//previous_status.push(PROCESSING_QUERY);
NEXT_IMMEDIATE_NEW(CONNECTING_SERVER);
}
*_rc=-1;
return false;
} else {
proxy_warning("Error during SET NAMES: %d, %s\n", myerr, mysql_error(myconn->mysql));
// we won't go back to PROCESSING_QUERY
st=previous_status.top();
previous_status.pop();
char sqlstate[10];
sprintf(sqlstate,"%s",mysql_sqlstate(myconn->mysql));
client_myds->myprot.generate_pkt_ERR(true,NULL,NULL,1,mysql_errno(myconn->mysql),sqlstate,mysql_error(myconn->mysql));
myds->destroy_MySQL_Connection_From_Pool(true);
myds->fd=0;
status=WAITING_CLIENT_DATA;
client_myds->DSS=STATE_SLEEP;
RequestEnd(myds);
}
} else {
// rc==1 , nothing to do for now
}
}
return false;
}
bool MySQL_Session::handler_again___status_CHANGING_AUTOCOMMIT(int *_rc) {
//fprintf(stderr,"CHANGING_AUTOCOMMIT\n");
assert(mybe->server_myds->myconn);
@ -3595,23 +3378,18 @@ handler_again:
}
if (locked_on_hostgroup == -1 || locked_on_hostgroup_and_all_variables_set == false ) {
// Verify and update only variables: no SET NAMES, no SET CHARSET
static const std::vector<int> variables = {SQL_SAFE_UPDATES, SQL_SELECT_LIMIT, SQL_SQL_MODE, SQL_TIME_ZONE, SQL_CHARACTER_SET_RESULTS,
SQL_CHARACTER_SET_CONNECTION, SQL_CHARACTER_SET_CLIENT, SQL_CHARACTER_SET_DATABASE, SQL_ISOLATION_LEVEL, SQL_TRANSACTION_READ,
SQL_SESSION_TRACK_GTIDS, SQL_SQL_AUTO_IS_NULL, SQL_COLLATION_CONNECTION, SQL_NET_WRITE_TIMEOUT, SQL_MAX_JOIN_SIZE };
if (handler_again___verify_backend_multi_statement()) {
goto handler_again;
}
for (auto i : variables) {
if(mysql_variables->verify_variable(i)) {
goto handler_again;
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)) {
goto handler_again;
}
}
}
if (handler_again___verify_backend_sql_log_bin()) {
goto handler_again;
}
if (handler_again___verify_backend_multi_statement()) {
goto handler_again;
}
if (locked_on_hostgroup != -1) {
locked_on_hostgroup_and_all_variables_set=true;
}
@ -4101,18 +3879,6 @@ handler_again:
}
break;
case CHANGING_CHARSET:
{
int rc=0;
if (handler_again___status_CHANGING_CHARSET(&rc))
goto handler_again; // we changed status
if (rc==-1) { // we have an error we can't handle
handler_ret = -1;
return handler_ret;
}
}
break;
case SETTING_MULTI_STMT:
{
int rc=0;
@ -4125,18 +3891,6 @@ handler_again:
}
break;
case SETTING_SQL_LOG_BIN:
{
int rc=0;
if (handler_again___status_SETTING_SQL_LOG_BIN(&rc))
goto handler_again; // we changed status
if (rc==-1) { // we have an error we can't handle
handler_ret = -1;
return handler_ret;
}
}
break;
case SETTING_SQL_MODE:
case SETTING_SQL_SELECT_LIMIT:
case SETTING_SQL_SAFE_UPDATES:
@ -4154,6 +3908,8 @@ handler_again:
case SETTING_MAX_JOIN_SIZE:
case SETTING_CHARSET:
case SETTING_SET_NAMES:
case SETTING_SQL_LOG_BIN:
case SETTING_WSREP_SYNC_WAIT:
for (auto i = 0; i < SQL_NAME_LAST; i++) {
int rc = 0;
if (mysql_variables->update_variable(status, rc)) {
@ -4957,7 +4713,15 @@ bool MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C
delete opt2;
if (rc && ( i==0 || i==1) ) {
//fprintf(stderr,"sql_log_bin=%d\n", i);
client_myds->myconn->options.sql_log_bin=i;
if (i == 1) {
if (!mysql_variables->client_set_value(SQL_LOG_BIN, "1"))
return false;
}
else if (i == 0) {
if (!mysql_variables->client_set_value(SQL_LOG_BIN, "0"))
return false;
}
#ifdef DEBUG
proxy_info("Setting SQL_LOG_BIN to %d\n", i);
#endif
@ -5070,10 +4834,27 @@ 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) {
mysql_variables->client_set_value(SQL_SQL_MODE, value1.c_str());
if (!mysql_variables->client_set_value(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());
}
exit_after_SetParse = true;
} else if (var == "wsrep_sync_wait") {
std::string value1 = *values;
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()))
return false;
proxy_debug(PROXY_DEBUG_MYSQL_COM, 5, "Changing connection session_track_gtids to %s\n", value1.c_str());
}
exit_after_SetParse = true;
} else {
unable_to_parse_set_statement(lock_hostgroup);
return false;
}
} 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());
@ -5109,10 +4890,13 @@ bool MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C
return false;
}
if (mysql_variables->client_get_hash(idx) != var_value_int) {
if (__tmp_value == 0)
mysql_variables->client_set_value(idx, "OFF");
else
mysql_variables->client_set_value(idx, "ON");
if (__tmp_value == 0) {
if (!mysql_variables->client_set_value(idx, "OFF"))
return false;
} else {
if (!mysql_variables->client_set_value(idx, "ON"))
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;
@ -5187,7 +4971,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) {
mysql_variables->client_set_value(SQL_TIME_ZONE, value1.c_str());
if (!mysql_variables->client_set_value(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());
}
exit_after_SetParse = true;
@ -5197,7 +4982,8 @@ bool MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C
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) {
mysql_variables->client_set_value(SQL_SESSION_TRACK_GTIDS, value1.c_str());
if (!mysql_variables->client_set_value(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());
}
exit_after_SetParse = true;
@ -5238,7 +5024,8 @@ bool MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C
return false;
}
if (mysql_variables->client_get_hash(idx) != var_value_int) {
mysql_variables->client_set_value(idx, value1.c_str());
if (!mysql_variables->client_set_value(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;
@ -5285,9 +5072,13 @@ 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())) {
mysql_variables->client_set_value(idx, "-1");
if (!mysql_variables->client_set_value(idx, "NULL")) {
return false;
}
} else if (!strcasecmp("binary", value1.c_str())) {
mysql_variables->client_set_value(idx, "-2");
if (!mysql_variables->client_set_value(idx, "binary")) {
return false;
}
} else {
proxy_error("Cannot find charset/collation [%s]\n", value1.c_str());
assert(0);
@ -5299,15 +5090,20 @@ bool MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C
/* changing collation_connection the character_set_connection will be changed as well
* and vice versa
*/
if (var == "collation_connection")
mysql_variables->client_set_value(SQL_CHARACTER_SET_CONNECTION, ss.str().c_str());
if (var == "character_set_connection")
mysql_variables->client_set_value(SQL_COLLATION_CONNECTION, ss.str().c_str());
if (var == "collation_connection") {
if (!mysql_variables->client_set_value(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()))
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.
*/
mysql_variables->client_set_value(idx, ss.str().c_str());
if (!mysql_variables->client_set_value(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());
}
}
@ -5364,7 +5160,8 @@ bool MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C
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) {
mysql_variables->client_set_value(SQL_ISOLATION_LEVEL, value1.c_str());
if (!mysql_variables->client_set_value(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());
}
exit_after_SetParse = true;
@ -5411,7 +5208,8 @@ bool MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C
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) {
mysql_variables->client_set_value(SQL_SQL_MODE, s1.c_str());
if (!mysql_variables->client_set_value(SQL_SQL_MODE, s1.c_str()))
return false;
std::size_t found_at = s1.find("@");
if (found_at != std::string::npos) {
char *v1 = strdup(s1.c_str());
@ -5479,7 +5277,8 @@ bool MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C
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) {
mysql_variables->client_set_value(SQL_ISOLATION_LEVEL, value1.c_str());
if (!mysql_variables->client_set_value(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());
}
exit_after_SetParse = true;
@ -5488,7 +5287,8 @@ bool MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C
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) {
mysql_variables->client_set_value(SQL_TRANSACTION_READ, value1.c_str());
if (!mysql_variables->client_set_value(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());
}
exit_after_SetParse = true;
@ -5933,16 +5733,12 @@ 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);
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;
mybe->server_myds->DSS=STATE_READY;
std::vector<int> vars = {SQL_CHARACTER_SET, SQL_CHARACTER_ACTION, SQL_CHARACTER_SET_RESULTS, SQL_CHARACTER_SET_CONNECTION, SQL_COLLATION_CONNECTION, SQL_CHARACTER_SET_CLIENT, SQL_CHARACTER_SET_DATABASE };
for (auto i : vars) {
proxy_warning("TRACE : tid [%lu], variable name %24s\tclient value [%5s]\tserver value [%5s]\n", thread_session_id, mysql_tracked_variables[i].set_variable_name, mysql_variables->client_get_value(i), mysql_variables->server_get_value(i));
}
if (session_fast_forward==true) {
status=FAST_FORWARD;
mybe->server_myds->myconn->reusable=false; // the connection cannot be usable anymore
@ -6373,8 +6169,7 @@ bool MySQL_Session::handle_command_query_kill(PtrSize_t *pkt) {
re2::RE2 *re=new RE2(pattern, *opt2);
int id=0;
string tk;
int rc;
rc=RE2::FullMatch(nq, *re, &tk, &id);
RE2::FullMatch(nq, *re, &tk, &id);
delete re;
delete opt2;
proxy_debug(PROXY_DEBUG_MYSQL_QUERY_PROCESSOR, 2, "filtered query= \"%s\"\n", qu);

@ -3296,7 +3296,6 @@ MySQL_Session * MySQL_Thread::create_new_session_and_client_data_stream(int _fd)
sess->client_myds->myprot.init(&sess->client_myds, sess->client_myds->myconn->userinfo, sess);
proxy_warning("TRACE : new_client\n");
for (int i=0; i<SQL_NAME_LAST; i++) {
if (i == SQL_CHARACTER_SET || i == SQL_CHARACTER_SET_RESULTS ||
i == SQL_CHARACTER_SET_CONNECTION || i == SQL_CHARACTER_SET_CLIENT ||
@ -3367,7 +3366,7 @@ bool MySQL_Thread::init() {
match_regexes=(Session_Regex **)malloc(sizeof(Session_Regex *)*4);
match_regexes[0]=new Session_Regex((char *)"^SET (|SESSION |@@|@@session.)SQL_LOG_BIN( *)(:|)=( *)");
match_regexes[1]=new Session_Regex((char *)"^SET (|SESSION |@@|@@session.)(SQL_MODE|TIME_ZONE|CHARACTER_SET_RESULTS|CHARACTER_SET_CLIENT|CHARACTER_SET_DATABASE|SESSION_TRACK_GTIDS|SQL_AUTO_IS_NULL|SQL_SELECT_LIMIT|SQL_SAFE_UPDATES|COLLATION_CONNECTION|CHARACTER_SET_CONNECTION|NET_WRITE_TIMEOUT|TX_ISOLATION|MAX_JOIN_SIZE( *)(:|)=( *))");
match_regexes[1]=new Session_Regex((char *)"^SET (|SESSION |@@|@@session.)(SQL_MODE|TIME_ZONE|CHARACTER_SET_RESULTS|CHARACTER_SET_CLIENT|CHARACTER_SET_DATABASE|SESSION_TRACK_GTIDS|SQL_AUTO_IS_NULL|SQL_SELECT_LIMIT|SQL_SAFE_UPDATES|COLLATION_CONNECTION|CHARACTER_SET_CONNECTION|NET_WRITE_TIMEOUT|WSREP_SYNC_WAIT|TX_ISOLATION|MAX_JOIN_SIZE( *)(:|)=( *))");
match_regexes[2]=new Session_Regex((char *)"^SET(?: +)(|SESSION +)TRANSACTION(?: +)(?:(?:(ISOLATION(?: +)LEVEL)(?: +)(REPEATABLE(?: +)READ|READ(?: +)COMMITTED|READ(?: +)UNCOMMITTED|SERIALIZABLE))|(?:(READ)(?: +)(WRITE|ONLY)))");
match_regexes[3]=new Session_Regex((char *)"^(set)(?: +)((charset)|(character +set))(?: )");

@ -7,49 +7,87 @@
#include <sstream>
extern const MARIADB_CHARSET_INFO * proxysql_find_charset_nr(unsigned int nr);
extern MARIADB_CHARSET_INFO * proxysql_find_charset_name(const char *name);
MySQL_Variables::MySQL_Variables(MySQL_Session* _session) {
MySQL_Variables::MySQL_Variables(MySQL_Session* _session) : session(_session), is_connected_to_backend(false) {
assert(_session);
session = _session;
for (auto i = 0; i < SQL_NAME_LAST; i++) {
switch(i) {
case SQL_SAFE_UPDATES:
case SQL_SELECT_LIMIT:
case SQL_SQL_MODE:
case SQL_TIME_ZONE:
case SQL_CHARACTER_SET_RESULTS:
case SQL_CHARACTER_SET_CONNECTION:
case SQL_CHARACTER_SET_CLIENT:
case SQL_CHARACTER_SET_DATABASE:
case SQL_ISOLATION_LEVEL:
case SQL_TRANSACTION_READ:
case SQL_SESSION_TRACK_GTIDS:
case SQL_SQL_AUTO_IS_NULL:
case SQL_COLLATION_CONNECTION:
case SQL_NET_WRITE_TIMEOUT:
case SQL_MAX_JOIN_SIZE:
updaters[i] = new Generic_Updater();
break;
default:
updaters[i] = NULL;
case SQL_SAFE_UPDATES:
case SQL_SELECT_LIMIT:
case SQL_SQL_MODE:
case SQL_TIME_ZONE:
case SQL_CHARACTER_SET_RESULTS:
case SQL_CHARACTER_SET_CONNECTION:
case SQL_CHARACTER_SET_CLIENT:
case SQL_CHARACTER_SET_DATABASE:
case SQL_ISOLATION_LEVEL:
case SQL_TRANSACTION_READ:
case SQL_SESSION_TRACK_GTIDS:
case SQL_SQL_AUTO_IS_NULL:
case SQL_COLLATION_CONNECTION:
case SQL_NET_WRITE_TIMEOUT:
case SQL_MAX_JOIN_SIZE:
case SQL_WSREP_SYNC_WAIT:
verifiers[i] = ::verify_variable;
updaters[i] = update_server_variable;
break;
case SQL_LOG_BIN:
verifiers[i] = ::verify_variable;
updaters[i] = logbin_update_server_variable;
break;
default:
updaters[i] = NULL;
}
}
}
MySQL_Variables::~MySQL_Variables() {
for (auto u : updaters)
delete u;
}
MySQL_Variables::~MySQL_Variables() {}
bool MySQL_Variables::on_connect_to_backend(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;
// verify mariadb
if (be_version[0] == '1') {
int idx = SQL_NAME_LAST;
for (auto i=0; i<SQL_NAME_LAST; i++) {
if (tracked_variables[i].idx == SQL_SESSION_TRACK_GTIDS) {
idx = i;
break;
}
}
tracked_variables[idx].special_handling = false;
}
// verify this is not galera cluster
// assume galera cluster has two dashes in a version
char* first_dash = strstr(be_version, "-");
if (!first_dash || !strstr(first_dash+1, "-")) {
int idx = SQL_NAME_LAST;
for (auto i=0; i<SQL_NAME_LAST; i++) {
if (tracked_variables[i].idx == SQL_WSREP_SYNC_WAIT) {
idx = i;
break;
}
}
tracked_variables[idx].special_handling = false;
}
void print_backtrace(void);
is_connected_to_backend = true;
return true;
}
void MySQL_Variables::client_set_value(int idx, const std::string& value) {
if (!session || !session->client_myds || !session->client_myds->myconn) return;
session->client_myds->myconn->variables[idx].hash = SpookyHash::Hash32(value.c_str(),strlen(value.c_str()),10);
bool MySQL_Variables::client_set_value(int idx, const std::string& value) {
if (!session || !session->client_myds || !session->client_myds->myconn) {
proxy_warning("Session validation failed\n");
return false;
}
/* Process SET NAMES and SET CHARSET commands
* The character_set_client, character_set_results, character_set_connection variables are set here
* During multiplexing/query execution these values will be used to set corresponding backend variables
* The charset used in SET NAMES and SET CHARSET is not used in setting backend chrsets
*/
switch (idx) {
case SQL_CHARACTER_ACTION:
// SET NAMES command from client
@ -68,8 +106,22 @@ void MySQL_Variables::client_set_value(int idx, const std::string& value) {
session->mysql_variables->client_set_value(SQL_CHARACTER_SET_CLIENT, session->mysql_variables->client_get_value(SQL_CHARACTER_SET));
}
if (session->mysql_variables->client_get_value(SQL_CHARACTER_SET_DATABASE)) {
session->mysql_variables->client_set_value(SQL_CHARACTER_SET_CONNECTION, session->mysql_variables->client_get_value(SQL_CHARACTER_SET_DATABASE));
session->mysql_variables->client_set_value(SQL_COLLATION_CONNECTION, session->mysql_variables->client_get_value(SQL_CHARACTER_SET_DATABASE));
const MARIADB_CHARSET_INFO *ci = NULL;
ci = proxysql_find_charset_name(mysql_tracked_variables[SQL_CHARACTER_SET_CONNECTION].default_value);
unsigned int nr = ci->nr;
std::stringstream ss;
ss << nr;
session->mysql_variables->client_set_value(SQL_CHARACTER_SET_CONNECTION, ss.str());
ci = proxysql_find_charset_collate(mysql_tracked_variables[SQL_COLLATION_CONNECTION].default_value);
nr = ci->nr;
ss.str(std::string());
ss.clear();
ss << nr;
session->mysql_variables->client_set_value(SQL_COLLATION_CONNECTION, ss.str());
}
}
// SET NAMES during handshake etc.
@ -83,25 +135,28 @@ void MySQL_Variables::client_set_value(int idx, const std::string& value) {
}
}
session->client_myds->myconn->var_hash[idx] = SpookyHash::Hash32(value.c_str(),strlen(value.c_str()),10);
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());
return true;
}
const char* MySQL_Variables::client_get_value(int idx) {
const char* MySQL_Variables::client_get_value(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) {
uint32_t MySQL_Variables::client_get_hash(int idx) const {
if (!session || !session->client_myds || !session->client_myds->myconn) return 0;
return session->client_myds->myconn->variables[idx].hash;
return session->client_myds->myconn->var_hash[idx];
}
void MySQL_Variables::server_set_value(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->variables[idx].hash = SpookyHash::Hash32(value,strlen(value),10);
session->mybe->server_myds->myconn->var_hash[idx] = SpookyHash::Hash32(value,strlen(value),10);
if (session->mybe->server_myds->myconn->variables[idx].value) {
free(session->mybe->server_myds->myconn->variables[idx].value);
@ -109,14 +164,14 @@ 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 char* MySQL_Variables::server_get_value(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) {
uint32_t MySQL_Variables::server_get_hash(int idx) const {
if (!session || !session->mybe || !session->mybe->server_myds || !session->mybe->server_myds->myconn) return 0;
return session->mybe->server_myds->myconn->variables[idx].hash;
return session->mybe->server_myds->myconn->var_hash[idx];
}
bool MySQL_Variables::update_variable(session_status status, int &_rc) {
@ -128,55 +183,111 @@ bool MySQL_Variables::update_variable(session_status status, int &_rc) {
}
}
assert(idx != SQL_NAME_LAST);
return updaters[idx]->update_server_variable(session, idx, _rc);
return updaters[idx](session, idx, _rc);
}
bool MySQL_Variables::verify_variable(int idx) {
bool MySQL_Variables::verify_variable(int idx) const {
auto ret = false;
if (updaters[idx] && updaters[idx])
ret = updaters[idx]->verify_variables(session, idx);
if (likely(verifiers[idx])) {
auto client_hash = session->client_myds->myconn->var_hash[idx];
auto server_hash = session->mybe->server_myds->myconn->var_hash[idx];
ret = verifiers[idx](session, idx, client_hash, server_hash);
}
return ret;
}
/*
* Updaters for different variables
*/
Updater::~Updater() {}
bool Generic_Updater::verify_variables(MySQL_Session* session, int idx) {
if ( !session->mysql_variables->server_get_value(idx) || strcmp(session->mysql_variables->client_get_value(idx), session->mysql_variables->server_get_value(idx))) {
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;
bool validate_charset(MySQL_Session* session, int idx, int &_rc) {
if (idx == SQL_CHARACTER_SET || idx == SQL_CHARACTER_SET_CLIENT || idx == SQL_CHARACTER_SET_RESULTS ||
idx == SQL_CHARACTER_SET_CONNECTION || idx == SQL_CHARACTER_SET_DATABASE || idx == SQL_COLLATION_CONNECTION) {
MySQL_Data_Stream *myds = session->mybe->server_myds;
MySQL_Connection *myconn = myds->myconn;
char msg[128];
const MARIADB_CHARSET_INFO *ci = NULL;
const char* replace_collation = NULL;
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));
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));
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);
myds->fd=0;
_rc=-1;
return false;
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));
assert(0);
}
not_supported_collation = ci->name;
if (idx == SQL_COLLATION_CONNECTION) {
ci = proxysql_find_charset_collate(mysql_thread___default_variables[idx]);
} else {
ci = proxysql_find_charset_name(mysql_thread___default_variables[idx]);
}
if (!ci) {
proxy_error("Cannot find character set [%s]\n", mysql_thread___default_variables[idx]);
assert(0);
}
replace_collation = ci->name;
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,
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());
_rc=0;
return true;
case HANDLE_UNKNOWN_CHARSET__REPLACE_WITH_DEFAULT:
if (idx == SQL_COLLATION_CONNECTION) {
ci = proxysql_find_charset_collate(mysql_thread___default_variables[idx]);
} else {
ci = proxysql_find_charset_name(mysql_thread___default_variables[idx]);
}
if (!ci) {
proxy_error("Cannot filnd charset [%s]\n", mysql_thread___default_variables[idx]);
assert(0);
}
replace_collation_nr = ci->nr;
ss << replace_collation_nr;
session->mysql_variables->client_set_value(idx, ss.str());
_rc=0;
return true;
default:
proxy_error("Wrong configuration of the handle_unknown_charset\n");
_rc=-1;
return false;
}
}
session->set_status(mysql_tracked_variables[idx].status);
proxy_warning("TRACE: tid [%lu] setting SERVER variable %d, value %s\n", session->thread_session_id, idx, session->mysql_variables->client_get_value(idx));
session->mysql_variables->server_set_value(idx, session->mysql_variables->client_get_value(idx));
return true;
}
return false;
_rc=0;
return true;
}
bool Generic_Updater::update_server_variable(MySQL_Session* session, int idx, int &_rc) {
bool update_server_variable(MySQL_Session* session, int idx, int &_rc) {
bool no_quote = true;
if (mysql_tracked_variables[idx].quote) no_quote = false;
bool st = mysql_tracked_variables[idx].set_transaction;
const char * set_var_name = mysql_tracked_variables[idx].set_variable_name;
bool ret = false;
/* Validating that charset is less than 255 for mysqld version <8.0
*/
if (!validate_charset(session, idx, _rc)) {
return false;
}
/* character set variables store collation id in the char* string, but we set character_set_% command
* uses character set name or collation name. This branch convert collation id to character set name
* or collation name for further execution on backend
@ -185,18 +296,11 @@ bool Generic_Updater::update_server_variable(MySQL_Session* session, int idx, in
const MARIADB_CHARSET_INFO *ci = NULL;
ci = proxysql_find_charset_nr(atoi(session->mysql_variables->client_get_value(SQL_CHARACTER_SET_RESULTS)));
/* CHARACTER_SET_RESULTS may have "NULL" and "binary" as parameter value.
* -1 - NULL
* -2 - binary
*
* TODO: current implementation is not nice. Think about nicer implementation
*/
if (!ci) {
if (!strcmp(session->mysql_variables->client_get_value(SQL_CHARACTER_SET_RESULTS), "-1")) {
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));
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), "-2")) {
} 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));
ret = session->handler_again___status_SETTING_GENERIC_VARIABLE(&_rc, set_var_name, "binary", no_quote, st);
}
@ -238,4 +342,31 @@ bool Generic_Updater::update_server_variable(MySQL_Session* session, int idx, in
return ret;
}
inline bool verify_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:
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);
session->mysql_variables->server_set_value(idx, session->mysql_variables->client_get_value(idx));
return true;
}
return false;
}
bool logbin_update_server_variable(MySQL_Session* session, int idx, int &_rc) {
return session->handler_again___status_SETTING_SQL_LOG_BIN(&_rc);
}

@ -16,22 +16,37 @@ void Variable::fill_server_internal_session(json &j, int conn_num, int idx) {
if (idx == SQL_CHARACTER_SET_RESULTS || idx == SQL_CHARACTER_SET_CONNECTION ||
idx == SQL_CHARACTER_SET_CLIENT || idx == SQL_CHARACTER_SET_DATABASE) {
const MARIADB_CHARSET_INFO *ci = NULL;
ci = proxysql_find_charset_nr(atoi(value));
if (!value)
ci = proxysql_find_charset_name(mysql_tracked_variables[idx].default_value);
else
ci = proxysql_find_charset_nr(atoi(value));
if (!ci) {
proxy_error("Cannot find charset [%s] for variables %d\n", value, idx);
assert(0);
if (idx == SQL_CHARACTER_SET_RESULTS && (!strcasecmp("NULL", value) || !strcasecmp("binary", value))) {
j["conn"][mysql_tracked_variables[idx].internal_variable_name] = (ci && ci->csname)?ci->csname:"";
}
else {
proxy_error("Cannot find charset [%s] for variables %d\n", value, idx);
assert(0);
}
}
j["backends"][conn_num]["conn"][mysql_tracked_variables[idx].internal_variable_name] = std::string((ci && ci->csname)?ci->csname:"");
} else if (idx == SQL_COLLATION_CONNECTION) {
const MARIADB_CHARSET_INFO *ci = NULL;
ci = proxysql_find_charset_nr(atoi(value));
if (!value)
ci = proxysql_find_charset_collate(mysql_tracked_variables[idx].default_value);
else
ci = proxysql_find_charset_nr(atoi(value));
if (!ci) {
proxy_error("Cannot find charset [%s] for variable %d\n", value, idx);
assert(0);
}
j["backends"][conn_num]["conn"][mysql_tracked_variables[idx].internal_variable_name] = std::string((ci && ci->name)?ci->name:"");
} else if (idx == SQL_LOG_BIN) {
if (!value)
value = mysql_tracked_variables[idx].default_value;
j["backends"][conn_num]["conn"][mysql_tracked_variables[idx].internal_variable_name] = std::string(!strcmp("1",value)?"ON":"OFF");
} else {
j["backends"][conn_num]["conn"][mysql_tracked_variables[idx].internal_variable_name] = std::string(value?value:"");
}
@ -43,8 +58,13 @@ void Variable::fill_client_internal_session(json &j, int idx) {
const MARIADB_CHARSET_INFO *ci = NULL;
ci = proxysql_find_charset_nr(atoi(value));
if (!ci) {
proxy_error("Cannot find charset [%s] for variables %d\n", value, idx);
assert(0);
if (idx == SQL_CHARACTER_SET_RESULTS && (!strcasecmp("NULL", value) || !strcasecmp("binary", value))) {
j["conn"][mysql_tracked_variables[idx].internal_variable_name] = (ci && ci->csname)?ci->csname:"";
}
else {
proxy_error("Cannot find charset [%s] for variables %d\n", value, idx);
assert(0);
}
}
j["conn"][mysql_tracked_variables[idx].internal_variable_name] = (ci && ci->csname)?ci->csname:"";
@ -57,6 +77,8 @@ void Variable::fill_client_internal_session(json &j, int idx) {
}
j["conn"][mysql_tracked_variables[idx].internal_variable_name] = (ci && ci->name)?ci->name:"";
} else if (idx == SQL_LOG_BIN) {
j["conn"][mysql_tracked_variables[idx].internal_variable_name] = !strcmp("1", value)?"ON":"OFF";
} else {
j["conn"][mysql_tracked_variables[idx].internal_variable_name] = value?value:"";
}
@ -258,7 +280,7 @@ MySQL_Connection::MySQL_Connection() {
for (auto i = 0; i < SQL_NAME_LAST; i++) {
variables[i].value = NULL;
variables[i].hash = 0;
var_hash[i] = 0;
}
options.client_flag = 0;
@ -269,19 +291,9 @@ MySQL_Connection::MySQL_Connection() {
options.no_backslash_escapes=false;
options.init_connect=NULL;
options.init_connect_sent=false;
// options.collation_connection = NULL;
// options.net_write_timeout = NULL;
// options.max_join_size = NULL;
// options.collation_connection_sent = false;
// options.net_write_timeout_sent = false;
// options.max_join_size_sent = false;
options.ldap_user_variable=NULL;
options.ldap_user_variable_value=NULL;
options.ldap_user_variable_sent=false;
options.sql_log_bin=1; // default #818
// options.collation_connection_int=0;
// options.net_write_timeout_int=0;
// options.max_join_size_int=0;
compression_pkt_id=0;
mysql_result=NULL;
query.ptr=NULL;
@ -591,7 +603,6 @@ void MySQL_Connection::connect_start() {
proxy_error("Not existing charset number %s\n", mysql_thread___default_variables[SQL_CHARACTER_SET]);
assert(0);
}
proxy_warning("TRACE : INITIAL ACTION client %s, server %s\n", myds->sess->mysql_variables->client_get_value(SQL_CHARACTER_ACTION), myds->sess->mysql_variables->server_get_value(SQL_CHARACTER_ACTION));
set_charset(c->nr, CONNECT_START);
mysql_options(mysql, MYSQL_SET_CHARSET_NAME, c->csname);
unsigned long client_flags = 0;
@ -725,7 +736,6 @@ void MySQL_Connection::set_names_start() {
proxy_error("Not existing charset number %u\n", atoi(myds->sess->mysql_variables->client_get_value(SQL_CHARACTER_SET)));
assert(0);
}
proxy_warning("TRACE : START SET NAMES %s\n", myds->sess->mysql_variables->client_get_value(SQL_CHARACTER_SET));
async_exit_status = mysql_set_character_set_start(&interr,mysql, NULL, atoi(myds->sess->mysql_variables->client_get_value(SQL_CHARACTER_SET)));
}
@ -748,7 +758,6 @@ void MySQL_Connection::set_query(char *stmt, unsigned long length) {
void MySQL_Connection::real_query_start() {
PROXY_TRACE();
async_exit_status = mysql_real_query_start(&interr , mysql, query.ptr, query.length);
proxy_warning("TRACE : START SET %s\n", query.ptr);
}
void MySQL_Connection::real_query_cont(short event) {
@ -2219,7 +2228,7 @@ void MySQL_Connection::reset() {
creation_time = monotonic_time();
for (auto i = 0; i < SQL_NAME_LAST; i++) {
variables[i].hash = 0;
var_hash[i] = 0;
if (variables[i].value) {
free(variables[i].value);
variables[i].value = NULL;

@ -0,0 +1 @@
For executing the scripts for the tests, installing the module TAP::Parser::SourceHandler::MyTAP is required.

@ -22,6 +22,7 @@ int show_variable(MYSQL *mysql, const std::string& var_name, std::string& var_va
row = mysql_fetch_row(result);
var_value = row[1];
mysql_free_result(result);
return 0;
}
int select_config_file(MYSQL* mysql, std::string& resultset) {
@ -42,59 +43,62 @@ int select_config_file(MYSQL* mysql, std::string& resultset) {
fprintf(stderr, "error\n");
}
return 0;
}
int show_admin_global_variable(MYSQL *mysql, const std::string& var_name, std::string& var_value) {
char query[128];
char query[128];
snprintf(query, sizeof(query),"select variable_value from global_variables where variable_name='%s'", var_name.c_str());
if (mysql_query(mysql, query)) {
fprintf(stderr, "Failed to execute SHOW VARIABLES LIKE : no %d, %s\n",
mysql_errno(mysql), mysql_error(mysql));
return exit_status();
}
snprintf(query, sizeof(query),"select variable_value from global_variables where variable_name='%s'", var_name.c_str());
if (mysql_query(mysql, query)) {
fprintf(stderr, "Failed to execute SHOW VARIABLES LIKE : no %d, %s\n",
mysql_errno(mysql), mysql_error(mysql));
return exit_status();
}
MYSQL_RES *result;
MYSQL_ROW row;
result = mysql_store_result(mysql);
MYSQL_RES *result;
MYSQL_ROW row;
result = mysql_store_result(mysql);
int num_fields = mysql_num_fields(result);
int num_fields = mysql_num_fields(result);
row = mysql_fetch_row(result);
var_value = row[0];
mysql_free_result(result);
row = mysql_fetch_row(result);
var_value = row[0];
mysql_free_result(result);
return 0;
}
int set_admin_global_variable(MYSQL *mysql, const std::string& var_name, const std::string& var_value) {
char query[128];
snprintf(query, sizeof(query),"update global_variables set variable_value = '%s' where variable_name='%s'", var_value.c_str(), var_name.c_str());
if (mysql_query(mysql, query)) {
fprintf(stderr, "Failed to execute SHOW VARIABLES LIKE : no %d, %s\n",
mysql_errno(mysql), mysql_error(mysql));
return exit_status();
}
char query[128];
snprintf(query, sizeof(query),"update global_variables set variable_value = '%s' where variable_name='%s'", var_value.c_str(), var_name.c_str());
if (mysql_query(mysql, query)) {
fprintf(stderr, "Failed to execute SHOW VARIABLES LIKE : no %d, %s\n",
mysql_errno(mysql), mysql_error(mysql));
return exit_status();
}
return 0;
}
int get_server_version(MYSQL *mysql, std::string& version) {
char query[128];
char query[128];
if (mysql_query(mysql, "select @@version")) {
fprintf(stderr, "Error %d, %s\n",
mysql_errno(mysql), mysql_error(mysql));
return exit_status();
}
if (mysql_query(mysql, "select @@version")) {
fprintf(stderr, "Error %d, %s\n",
mysql_errno(mysql), mysql_error(mysql));
return exit_status();
}
MYSQL_RES *result;
MYSQL_ROW row;
result = mysql_store_result(mysql);
MYSQL_RES *result;
MYSQL_ROW row;
result = mysql_store_result(mysql);
int num_fields = mysql_num_fields(result);
int num_fields = mysql_num_fields(result);
row = mysql_fetch_row(result);
version = row[0];
mysql_free_result(result);
row = mysql_fetch_row(result);
version = row[0];
mysql_free_result(result);
return 0;
return 0;
}

@ -24,7 +24,7 @@ LIBHTTPSERVER_IDIR=$(LIBHTTPSERVER_DIR)/src
LIBHTTPSERVER_LDIR=$(LIBHTTPSERVER_DIR)/build/src/.libs/
LIBCONFIG_PATH=$(DEPS_PATH)/libconfig/libconfig
LIBCONFIG_IDIR=-I$(LIBCONFIG_PATH)/lib
LIBCONFIG_IDIR=$(LIBCONFIG_PATH)/lib
LIBCONFIG_LDIR=-L$(LIBCONFIG_PATH)/lib/.libs
CURL_DIR=$(DEPS_PATH)/curl/curl
@ -64,7 +64,7 @@ EXECUTABLE=proxysql
OBJ=../../../src/obj/proxysql_global.o ../../../src/obj/main.o
INCLUDEDIRS=-I../tap -I$(RE2_PATH) -I$(IDIR) -I$(JEMALLOC_IDIR) -I$(SQLITE3_DIR) -I$(LIBHTTPSERVER_IDIR) -I$(CURL_IDIR) -I$(DAEMONPATH_IDIR) -I$(MARIADB_IDIR) -I$(SSL_IDIR) -I$(JSON_IDIR)
INCLUDEDIRS=-I../tap -I$(RE2_PATH) -I$(IDIR) -I$(JEMALLOC_IDIR) -I$(SQLITE3_DIR) -I$(LIBHTTPSERVER_IDIR) -I$(CURL_IDIR) -I$(DAEMONPATH_IDIR) -I$(MARIADB_IDIR) -I$(SSL_IDIR) -I$(JSON_IDIR) -I$(LIBCONFIG_IDIR)
LDIRS=-L$(TAP_LIBDIR) -L$(LDIR) -L$(JEMALLOC_LDIR) $(LIBCONFIG_LDIR) -L$(RE2_PATH)/obj -L$(MARIADB_LDIR) -L$(DAEMONPATH_LDIR) -L$(PCRE_LDIR) -L$(MICROHTTPD_LDIR) -L$(LIBHTTPSERVER_LDIR) -L$(LIBINJECTION_LDIR) -L$(CURL_LDIR) -L$(EV_LDIR) -L$(SSL_LDIR)
MYLIBS=-Wl,--export-dynamic -Wl,-Bstatic -lconfig -lproxysql -ldaemon -ljemalloc -lconfig++ -lre2 -lpcrecpp -lpcre -lmariadbclient -lhttpserver -lmicrohttpd -linjection -lcurl -lssl -lcrypto -lev -Wl,-Bdynamic -lgnutls -lpthread -lm -lz -lrt $(EXTRALINK)
@ -86,7 +86,7 @@ testgalera: galera_1_timeout_count galera_2_timeout_no_count
testaurora: aurora
sqlite3-t: $(TAP_LIBDIR)/libtap.a sqlite3-t.cpp
g++ sqlite3-t.cpp $(INCLUDEDIRS) $(LDIRS) $(OPT) ../../../lib/libproxysql.a $(MYLIBS) -lpthread -ldl -std=c++11 -ltap -o sqlite3-t
g++ sqlite3-t.cpp $(INCLUDEDIRS) $(LDIRS) $(OPT) $(MYLIBS) -lpthread -ldl -std=c++11 -ltap -o sqlite3-t
basic-t: $(TAP_LIBDIR)/libtap.a
g++ basic-t.cpp $(INCLUDEDIRS) $(LDIRS) $(OPT) -std=c++11 -ltap -o basic-t

@ -30,6 +30,11 @@ int main(int argc, char** argv) {
if (!mysql_real_connect(mysqlAdmin, cl.host, "admin", "admin", NULL, 6032, NULL, 0)) return exit_status();
set_admin_global_variable(mysqlAdmin, "mysql-handle_unknown_charset", "1");
set_admin_global_variable(mysqlAdmin, "mysql-default_charset", "utf8mb4");
set_admin_global_variable(mysqlAdmin, "mysql-default_character_set_client", "utf8mb4");
set_admin_global_variable(mysqlAdmin, "mysql-default_character_set_results", "utf8mb4");
set_admin_global_variable(mysqlAdmin, "mysql-default_character_set_connection", "utf8mb4");
set_admin_global_variable(mysqlAdmin, "mysql-default_character_set_database", "utf8mb4");
set_admin_global_variable(mysqlAdmin, "mysql-default_collation_connection", "utf8mb4_general_ci");
if (mysql_query(mysqlAdmin, "load mysql variables to runtime")) return exit_status();
if (mysql_query(mysqlAdmin, "save mysql variables to disk")) return exit_status();
@ -77,9 +82,6 @@ int main(int argc, char** argv) {
mysql_close(mysql_a);
//set_admin_global_variable(mysqlAdmin, "mysql-default_charset", "utf8mb4");
//set_admin_global_variable(mysqlAdmin, "mysql-default_collation_connection", "latin1_swedish_ci");
//if (mysql_query(mysqlAdmin, "load mysql variables to runtime")) return exit_status();
MYSQL* mysql_b = mysql_init(NULL);
if (!mysql_b) return exit_status();
if (!mysql_real_connect(mysql_b, cl.host, cl.username, cl.password, NULL, cl.port, NULL, 0)) return exit_status();

@ -24,38 +24,38 @@ int main(int argc, char** argv) {
return exit_status();
if (mysql_options(mysql, MYSQL_SET_CHARSET_NAME, "utf8")) {
fprintf(stderr, "File %s, line %d, Error: %s\n",
__FILE__, __LINE__, mysql_error(mysql));
fprintf(stderr, "File %s, line %d, Error: %s\n",
__FILE__, __LINE__, mysql_error(mysql));
return exit_status();
}
if (!mysql_real_connect(mysql, cl.host, cl.username, cl.password, NULL, cl.port, NULL, 0)) {
fprintf(stderr, "Failed to connect to database: Error: %s\n",
mysql_error(mysql));
fprintf(stderr, "Failed to connect to database: Error: %s\n",
mysql_error(mysql));
return exit_status();
}
if (mysql_query(mysql, "drop database if exists t1")) {
fprintf(stderr, "File %s, line %d, Error: %s\n",
__FILE__, __LINE__, mysql_error(mysql));
fprintf(stderr, "File %s, line %d, Error: %s\n",
__FILE__, __LINE__, mysql_error(mysql));
return exit_status();
}
if (mysql_query(mysql, "create database t1 charset utf8")) {
fprintf(stderr, "File %s, line %d, Error: %s\n",
__FILE__, __LINE__, mysql_error(mysql));
fprintf(stderr, "File %s, line %d, Error: %s\n",
__FILE__, __LINE__, mysql_error(mysql));
return exit_status();
}
if (mysql_query(mysql, "use t1")) {
fprintf(stderr, "File %s, line %d, Error: %s\n",
__FILE__, __LINE__, mysql_error(mysql));
fprintf(stderr, "File %s, line %d, Error: %s\n",
__FILE__, __LINE__, mysql_error(mysql));
return exit_status();
}
if (mysql_query(mysql, "set names 'utf8'")) {
fprintf(stderr, "SET CHARACTER SET 'utf8': Error: %s\n",
mysql_error(mysql));
fprintf(stderr, "SET NAMES 'utf8': Error: %s\n",
mysql_error(mysql));
return exit_status();
}

@ -15,18 +15,9 @@
#include "json.hpp"
#include "tap.h"
#include "utils.h"
#include "command_line.h"
#define MYSQL_QUERY(mysql, query) \
do { \
if (mysql_query(mysql, query)) { \
fprintf(stderr, "File %s, line %d, Error: %s\n", \
__FILE__, __LINE__, mysql_error(mysql)); \
return exit_status(); \
} \
} while(0)
std::vector<std::string> split(const std::string& s, char delimiter)
{
std::vector<std::string> tokens;
@ -108,6 +99,9 @@ int local=0;
int queries=0;
int uniquequeries=0;
int histograms=-1;
bool is_mariadb = false;
bool is_cluster = false;
unsigned int g_connect_OK=0;
unsigned int g_connect_ERR=0;
unsigned int g_select_OK=0;
@ -140,8 +134,9 @@ void parseResult(MYSQL_RES *result, json& j) {
if(!result) return;
MYSQL_ROW row;
while ((row = mysql_fetch_row(result)))
while ((row = mysql_fetch_row(result))) {
j[row[0]] = row[1];
}
}
void dumpResult(MYSQL_RES *result) {
@ -162,11 +157,27 @@ void dumpResult(MYSQL_RES *result) {
void queryVariables(MYSQL *mysql, json& j) {
std::stringstream query;
query << "SELECT /* mysql " << mysql << " */ * FROM performance_schema.session_variables WHERE variable_name IN "
" ('hostname', 'sql_log_bin', 'sql_mode', 'init_connect', 'time_zone', 'autocommit', 'sql_auto_is_null', "
" 'sql_safe_updates', 'session_track_gtids', 'max_join_size', 'net_write_timeout', 'sql_select_limit', "
" 'sql_select_limit', 'character_set_results', 'transaction_isolation', 'transaction_read_only', 'session_track_gtids', "
" 'sql_auto_is_null', 'collation_connection', 'character_set_connection', 'character_set_client', 'character_set_database');";
if (is_mariadb) {
query << "SELECT /* mysql " << mysql << " */ lower(variable_name), variable_value FROM information_schema.session_variables WHERE variable_name IN "
" ('hostname', 'sql_log_bin', 'sql_mode', 'init_connect', 'time_zone', 'autocommit', 'sql_auto_is_null', "
" 'sql_safe_updates', 'max_join_size', 'net_write_timeout', 'sql_select_limit', "
" 'sql_select_limit', 'character_set_results', 'tx_isolation', 'tx_read_only', "
" 'sql_auto_is_null', 'collation_connection', 'character_set_connection', 'character_set_client', 'character_set_database');";
}
if (is_cluster) {
query << "SELECT /* mysql " << mysql << " */ * FROM performance_schema.session_variables WHERE variable_name IN "
" ('hostname', 'sql_log_bin', 'sql_mode', 'init_connect', 'time_zone', 'autocommit', 'sql_auto_is_null', "
" 'sql_safe_updates', 'session_track_gtids', 'max_join_size', 'net_write_timeout', 'sql_select_limit', "
" 'sql_select_limit', 'character_set_results', 'transaction_isolation', 'transaction_read_only', "
" 'sql_auto_is_null', 'collation_connection', 'character_set_connection', 'character_set_client', 'character_set_database', 'wsrep_sync_wait');";
}
if (!is_mariadb && !is_cluster) {
query << "SELECT /* mysql " << mysql << " */ * FROM performance_schema.session_variables WHERE variable_name IN "
" ('hostname', 'sql_log_bin', 'sql_mode', 'init_connect', 'time_zone', 'autocommit', 'sql_auto_is_null', "
" 'sql_safe_updates', 'session_track_gtids', 'max_join_size', 'net_write_timeout', 'sql_select_limit', "
" 'sql_select_limit', 'character_set_results', 'transaction_isolation', 'transaction_read_only', "
" 'sql_auto_is_null', 'collation_connection', 'character_set_connection', 'character_set_client', 'character_set_database');";
}
//fprintf(stderr, "TRACE : QUERY 3 : variables %s\n", query.str().c_str());
if (mysql_query(mysql, query.str().c_str())) {
if (silent==0) {
@ -269,47 +280,83 @@ void queryInternalStatus(MYSQL *mysql, json& j) {
j["conn"]["sql_select_limit"] = strdup(ss.str().c_str());
}
// transaction_isolation (level)
if (!el.value()["isolation_level"].dump().compare("\"REPEATABLE READ\"")) {
el.value().erase("isolation_level");
j["conn"]["transaction_isolation"] = "REPEATABLE-READ";
}
else if (!el.value()["isolation_level"].dump().compare("\"READ COMMITTED\"")) {
el.value().erase("isolation_level");
j["conn"]["transaction_isolation"] = "READ-COMMITTED";
}
else if (!el.value()["isolation_level"].dump().compare("\"READ UNCOMMITTED\"")) {
el.value().erase("isolation_level");
j["conn"]["transaction_isolation"] = "READ-UNCOMMITTED";
if (!is_mariadb) {
// transaction_isolation (level)
if (!el.value()["isolation_level"].dump().compare("\"REPEATABLE READ\"")) {
el.value().erase("isolation_level");
j["conn"]["transaction_isolation"] = "REPEATABLE-READ";
}
else if (!el.value()["isolation_level"].dump().compare("\"READ COMMITTED\"")) {
el.value().erase("isolation_level");
j["conn"]["transaction_isolation"] = "READ-COMMITTED";
}
else if (!el.value()["isolation_level"].dump().compare("\"READ UNCOMMITTED\"")) {
el.value().erase("isolation_level");
j["conn"]["transaction_isolation"] = "READ-UNCOMMITTED";
}
else if (!el.value()["isolation_level"].dump().compare("\"SERIALIZABLE\"")) {
el.value().erase("isolation_level");
j["conn"]["transaction_isolation"] = "SERIALIZABLE";
}
}
else if (!el.value()["isolation_level"].dump().compare("\"SERIALIZABLE\"")) {
el.value().erase("isolation_level");
j["conn"]["transaction_isolation"] = "SERIALIZABLE";
else {
// transaction_isolation (level)
if (!el.value()["isolation_level"].dump().compare("\"REPEATABLE READ\"")) {
el.value().erase("isolation_level");
j["conn"]["tx_isolation"] = "REPEATABLE-READ";
}
else if (!el.value()["isolation_level"].dump().compare("\"READ COMMITTED\"")) {
el.value().erase("isolation_level");
j["conn"]["tx_isolation"] = "READ-COMMITTED";
}
else if (!el.value()["isolation_level"].dump().compare("\"READ UNCOMMITTED\"")) {
el.value().erase("isolation_level");
j["conn"]["tx_isolation"] = "READ-UNCOMMITTED";
}
else if (!el.value()["isolation_level"].dump().compare("\"SERIALIZABLE\"")) {
el.value().erase("isolation_level");
j["conn"]["tx_isolation"] = "SERIALIZABLE";
}
}
// transaction_read (write|only)
if (!el.value()["transaction_read"].dump().compare("\"ONLY\"")) {
el.value().erase("transaction_read");
j["conn"]["transaction_read_only"] = "ON";
}
else if (!el.value()["transaction_read"].dump().compare("\"WRITE\"")) {
el.value().erase("transaction_read");
j["conn"]["transaction_read_only"] = "OFF";
if (!is_mariadb) {
// transaction_read (write|only)
if (!el.value()["transaction_read"].dump().compare("\"ONLY\"")) {
el.value().erase("transaction_read");
j["conn"]["transaction_read_only"] = "ON";
}
else if (!el.value()["transaction_read"].dump().compare("\"WRITE\"")) {
el.value().erase("transaction_read");
j["conn"]["transaction_read_only"] = "OFF";
}
} else {
// transaction_read (write|only)
if (!el.value()["transaction_read"].dump().compare("\"ONLY\"")) {
el.value().erase("transaction_read");
j["conn"]["tx_read_only"] = "ON";
}
else if (!el.value()["transaction_read"].dump().compare("\"WRITE\"")) {
el.value().erase("transaction_read");
j["conn"]["tx_read_only"] = "OFF";
}
}
// session_track_gtids
if (!el.value()["session_track_gtids"].dump().compare("\"OFF\"")) {
el.value().erase("session_track_gtids");
j["conn"]["session_track_gtids"] = "OFF";
}
else if (!el.value()["session_track_gtids"].dump().compare("\"OWN_GTID\"")) {
el.value().erase("session_track_gtids");
j["conn"]["session_track_gtids"] = "OWN_GTID";
}
else if (!el.value()["session_track_gtids"].dump().compare("\"ALL_GTIDS\"")) {
el.value().erase("session_track_gtids");
j["conn"]["session_track_gtids"] = "ALL_GTIDS";
if (!is_mariadb) {
// session_track_gtids
if (!el.value()["session_track_gtids"].dump().compare("\"OFF\"")) {
el.value().erase("session_track_gtids");
j["conn"]["session_track_gtids"] = "OFF";
}
else if (!el.value()["session_track_gtids"].dump().compare("\"OWN_GTID\"")) {
el.value().erase("session_track_gtids");
j["conn"]["session_track_gtids"] = "OWN_GTID";
}
else if (!el.value()["session_track_gtids"].dump().compare("\"ALL_GTIDS\"")) {
el.value().erase("session_track_gtids");
j["conn"]["session_track_gtids"] = "ALL_GTIDS";
}
}
}
}
}
@ -377,7 +424,34 @@ void * my_conn_thread(void *arg) {
}
for (auto& el : testCases[r2].expected_vars.items()) {
vars[el.key()] = el.value();
if (el.key() == "transaction_isolation") {
if (is_mariadb) {
vars["tx_isolation"] = el.value();
}
else {
vars[el.key()] = el.value();
}
}
else if (el.key() == "session_track_gtids") {
if (!is_mariadb) {
vars[el.key()] = el.value();
}
}
else if (el.key() == "wsrep_sync_wait") {
if (is_cluster) {
vars[el.key()] = el.value();
}
}
else if (el.key() == "transaction_read_only") {
if (is_mariadb) {
vars["tx_read_only"] = el.value();
} else {
vars[el.key()] = el.value();
}
}
else {
vars[el.key()] = el.value();
}
}
int sleepDelay = fastrand()%100;
@ -460,6 +534,39 @@ int main(int argc, char *argv[]) {
MYSQL_QUERY(mysqladmin, "update global_variables set variable_value='true' where variable_name='mysql-enforce_autocommit_on_reads'");
MYSQL_QUERY(mysqladmin, "load mysql variables to runtime");
mysql_close(mysqladmin);
MYSQL* mysql = mysql_init(NULL);
if (!mysql)
return exit_status();
if (!mysql_real_connect(mysql, cl.host, cl.username, cl.password, NULL, cl.port, NULL, 0)) {
fprintf(stderr, "File %s, line %d, Error: %s\n",
__FILE__, __LINE__, mysql_error(mysql));
return exit_status();
}
MYSQL_QUERY(mysql, "select @@version");
MYSQL_RES *result = mysql_store_result(mysql);
MYSQL_ROW row;
while ((row = mysql_fetch_row(result)))
{
if (strstr(row[0], "Maria")) {
is_mariadb = true;
}
else {
is_mariadb = false;
}
char* first_dash = strstr(row[0], "-");
if (!first_dash || !strstr(first_dash+1, "-")) {
is_cluster = false;
} else {
is_cluster = true;
}
}
mysql_free_result(result);
mysql_close(mysql);
num_threads = 10;
queries = 1000;
queries_per_connections = 10;
@ -484,7 +591,6 @@ int main(int argc, char *argv[]) {
if (uniquequeries) {
uniquequeries=(int)sqrt(uniquequeries);
}
mysql_library_init(0, NULL, NULL);
pthread_t *thi=(pthread_t *)malloc(sizeof(pthread_t)*num_threads);
if (thi==NULL)

@ -1,10 +1,10 @@
"set character_set_results='utf8'; set names latin7; set character_set_client='utf8mb4';", "{'character_set_results':'latin7', 'collation_connection':'latin7_general_ci', 'character_set_connection':'latin7', 'character_set_client':'utf8mb4'}"
"set character_set_results='null'; set names latin7; set character_set_client='utf8mb4';", "{'character_set_results':'latin7', 'collation_connection':'latin7_general_ci', 'character_set_connection':'latin7', 'character_set_client':'utf8mb4'}"
"set character_set_client='utf8mb4'; set charset utf8; set character_set_connection='latin1';", "{'character_set_results':'utf8', 'collation_connection':'latin1_swedish_ci', 'character_set_connection':'latin1', 'character_set_client':'utf8'}"
"set character_set_database='utf8'; set character_set_connection='utf8mb4'; set charset utf8; set character_set_client='latin1';", "{'character_set_database':'utf8', 'character_set_results':'utf8', 'collation_connection':'utf8_general_ci', 'character_set_connection':'utf8', 'character_set_client':'latin1'}"
"set character_set_connection='utf8mb4'; set charset utf8; set character_set_client='latin1'; set collation_connection='latin1_swedish_ci';", "{'character_set_results':'utf8', 'collation_connection':'latin1_swedish_ci', 'character_set_connection':'latin1', 'character_set_client':'latin1'}""set names latin7", "{'character_set_results':'latin7', 'collation_connection':'latin7_general_ci', 'character_set_connection':'latin7', 'character_set_client':'latin7'}"
"set names latin2", "{'character_set_results':'latin2', 'collation_connection':'latin2_general_ci', 'character_set_connection':'latin2', 'character_set_client':'latin2'}"
"set names utf8mb4", "{'character_set_results':'utf8mb4', 'collation_connection':'utf8mb4_general_ci', 'character_set_connection':'utf8mb4', 'character_set_client':'utf8mb4'}"
"set names utf8; set character_set_connection='utf8mb4'; set character_set_database='latin1'; set charset utf8;", "{'character_set_results':'utf8', 'collation_connection':'latin1_swedish_ci', 'character_set_connection':'latin1', 'character_set_client':'utf8', 'character_set_database':'latin1'}"
"set names utf8; set character_set_connection='utf8mb4'; set character_set_database='latin1'; set charset utf8;", "{'character_set_results':'utf8', 'collation_connection':'utf8_general_ci', 'character_set_connection':'utf8', 'character_set_client':'utf8', 'character_set_database':'latin1'}"
"set character_set_client='utf8mb4'; set names utf8; set character_set_connection='latin1';", "{'character_set_results':'utf8', 'collation_connection':'latin1_swedish_ci', 'character_set_connection':'latin1', 'character_set_client':'utf8'}"
"set character_set_database='latin1'; set character_set_connection='utf8mb4'; set names utf8; set character_set_client='latin1';", "{'character_set_database':'latin1', 'character_set_results':'utf8', 'collation_connection':'utf8_general_ci', 'character_set_connection':'utf8', 'character_set_client':'latin1'}"
"set character_set_connection='utf8mb4'; set names utf8; set character_set_client='latin1'; set collation_connection='latin1_swedish_ci';", "{'character_set_results':'utf8', 'collation_connection':'latin1_swedish_ci', 'character_set_connection':'latin1', 'character_set_client':'latin1'}""set names latin7", "{'character_set_results':'latin7', 'collation_connection':'latin7_general_ci', 'character_set_connection':'latin7', 'character_set_client':'latin7'}"
@ -19,6 +19,8 @@
"SET character_set_connection='utf8'", "{'character_set_connection':'utf8', 'collation_connection':'utf8_general_ci'}"
"SET character_set_connection='utf8mb4'", "{'character_set_connection':'utf8mb4', 'collation_connection':'utf8mb4_general_ci'}"
"SET character_set_results='latin1'", "{'character_set_results':'latin1'}"
"SET character_set_results='binary'", "{'character_set_results':'binary'}"
"SET character_set_results='NULL'", "{'character_set_results':''}"
"SET character_set_results='utf8'", "{'character_set_results':'utf8'}"
"SET character_set_results='utf8mb4'", "{'character_set_results':'utf8mb4'}"
"SET character_set_client='latin1'", "{'character_set_client':'latin1'}"
@ -27,9 +29,8 @@
"SET character_set_database='latin1'", "{'character_set_database':'latin1'}"
"SET character_set_database='utf8'", "{'character_set_database':'utf8'}"
"SET character_set_database='utf8mb4'", "{'character_set_database':'utf8mb4'}"
"SET character_set_results='latin1'", "{'character_set_results':'latin1'}"
"SET character_set_results='utf8'", "{'character_set_results':'utf8'}"
"SET character_set_results='utf8mb4'", "{'character_set_results':'utf8mb4'}"
"SET sql_log_bin=1", "{'sql_log_bin':'ON'}"
"SET sql_log_bin=0", "{'sql_log_bin':'OFF'}"
"set sql_mode=''","{'sql_mode':''}"
"SET sql_mode='PIPES_AS_CONCAT,NO_ENGINE_SUBSTITUTION'", "{'sql_mode':'PIPES_AS_CONCAT,NO_ENGINE_SUBSTITUTION'}"
"SET time_zone='+01:00'","{'time_zone':'+01:00'}"
@ -63,3 +64,5 @@
"set max_join_size=20000", "{'max_join_size':'20000'}"
"set max_join_size=10000", "{'max_join_size':'10000'}"
"set max_join_size=18446744073709551615", "{'max_join_size':'18446744073709551615'}"
"set wsrep_sync_wait=1", "{'wsrep_sync_wait':'1'}"
"set wsrep_sync_wait=0", "{'wsrep_sync_wait':'0'}"

Can't render this file because it has a wrong number of fields in line 4.
Loading…
Cancel
Save