Implementation of the session variables array

- SQL_SAFE_UPDATES
- SQL_SELECT_LIMIT
- SQL_SQL_MODE
- SQL_TIME_ZONE
- CHARACTER_SET_RESULTS
- SQL_TRANSACTION_ISOLATION
- SQL_TRANSACTION_READ
- SQL_SESSION_TRACK_GTIDS
- SQL_SQL_AUTO_IS_NULL
pull/2582/head
Valentin Rakush 6 years ago committed by val
parent 70b9f25937
commit 1fb5c9cf06

@ -6,6 +6,8 @@
#include "../deps/json/json.hpp"
using json = nlohmann::json;
class MySQL_Variables;
enum proxysql_session_type {
PROXYSQL_SESSION_MYSQL,
PROXYSQL_SESSION_ADMIN,
@ -70,7 +72,6 @@ class MySQL_Session
{
private:
int handler_ret;
std::stack<enum session_status> previous_status;
void handler___status_CONNECTING_CLIENT___STATE_SERVER_HANDSHAKE(PtrSize_t *, bool *);
void handler___status_CHANGING_USER_CLIENT___STATE_CLIENT_HANDSHAKE(PtrSize_t *, bool *);
@ -106,13 +107,13 @@ 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_sql_mode();
bool handler_again___verify_backend_time_zone();
bool handler_again___verify_backend_isolation_level();
bool handler_again___verify_backend_transaction_read();
@ -120,8 +121,6 @@ class MySQL_Session
bool handler_again___verify_backend_character_set_results();
bool handler_again___verify_backend_session_track_gtids();
bool handler_again___verify_backend_sql_auto_is_null();
bool handler_again___verify_backend_sql_select_limit();
bool handler_again___verify_backend_sql_safe_updates();
bool handler_again___verify_backend_collation_connection();
bool handler_again___verify_backend_net_write_timeout();
bool handler_again___verify_backend_max_join_size();
@ -145,7 +144,6 @@ class MySQL_Session
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_SETTING_GENERIC_VARIABLE(int *_rc, char *var_name, char *var_value, bool no_quote=false, bool set_transaction=false);
bool handler_again___status_CHANGING_SCHEMA(int *);
bool handler_again___status_CONNECTING_SERVER(int *);
bool handler_again___status_CHANGING_USER_SERVER(int *);
@ -157,6 +155,8 @@ 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);
std::stack<enum session_status> previous_status;
void * operator new(size_t);
void operator delete(void *);
@ -178,6 +178,7 @@ class MySQL_Session
MySQL_Data_Stream *client_myds;
MySQL_Data_Stream *server_myds;
char * default_schema;
std::unique_ptr<MySQL_Variables> mysql_variables;
//this pointer is always initialized inside handler().
// it is an attempt to start simplifying the complexing of handler()

@ -0,0 +1,52 @@
#ifndef MYSQL_VARIABLES_H
#define MYSQL_VARIABLES_H
#include "proxysql.h"
#include "cpp.h"
#include <cstdint>
#include <vector>
#include <memory>
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;
};
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);
};
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];
MySQL_Variables(MySQL_Session* session);
virtual ~MySQL_Variables();
void client_set_value(int idx, const char* value);
const char* client_get_value(int idx);
uint32_t client_get_hash(int idx);
void server_set_value(int idx, const char* value);
const char* server_get_value(int idx);
uint32_t server_get_hash(int idx);
bool verify_variable(int idx);
bool update_variable(int &_rc);
};
#endif // #ifndef MYSQL_VARIABLES_H

@ -4,6 +4,9 @@
#include "proxysql.h"
#include "cpp.h"
#include "../deps/json/json.hpp"
using json = nlohmann::json;
#define STATUS_MYSQL_CONNECTION_TRANSACTION 0x00000001
#define STATUS_MYSQL_CONNECTION_COMPRESSION 0x00000002
#define STATUS_MYSQL_CONNECTION_USER_VARIABLE 0x00000004
@ -16,6 +19,16 @@
#define STATUS_MYSQL_CONNECTION_FOUND_ROWS 0x00000200
#define STATUS_MYSQL_CONNECTION_NO_BACKSLASH_ESCAPES 0x00000400
class Variable {
public:
char *value;
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];
static const char proxysql_internal_session_name[SQL_NAME_LAST][64];
};
enum charset_action {
UNKNOWN,
NAMES,
@ -46,18 +59,6 @@ class MySQL_Connection {
public:
struct {
char *server_version;
char *sql_mode;
char *time_zone;
uint32_t sql_mode_int;
uint32_t time_zone_int;
uint32_t character_set_results_int;
uint32_t isolation_level_int;
uint32_t transaction_read_int;
uint32_t tx_isolation_int;
uint32_t session_track_gtids_int;
uint32_t sql_auto_is_null_int;
uint32_t sql_select_limit_int;
uint32_t sql_safe_updates_int;
uint32_t collation_connection_int;
uint32_t net_write_timeout_int;
uint32_t max_join_size_int;
@ -67,29 +68,12 @@ class MySQL_Connection {
unsigned int compression_min_length;
char *init_connect;
bool init_connect_sent;
char * character_set_results;
char * isolation_level;
char * transaction_read;
char * tx_isolation;
char * session_track_gtids;
char * sql_auto_is_null;
char * sql_select_limit;
char * sql_safe_updates;
char * collation_connection;
char * net_write_timeout;
char * max_join_size;
bool isolation_level_sent;
bool tx_isolation_sent;
bool transaction_read_sent;
bool character_set_results_sent;
bool session_track_gtids_sent;
bool sql_auto_is_null_sent;
bool sql_select_limit_sent;
bool sql_safe_updates_sent;
bool collation_connection_sent;
bool net_write_timeout_sent;
bool max_join_size_sent;
bool sql_mode_sent;
char *ldap_user_variable;
char *ldap_user_variable_value;
bool ldap_user_variable_sent;
@ -101,6 +85,7 @@ class MySQL_Connection {
bool autocommit;
bool no_backslash_escapes;
} options;
Variable variables[SQL_NAME_LAST];
struct {
unsigned long length;
char *ptr;

@ -146,6 +146,22 @@ enum MySQL_DS_type {
};
enum variable_name {
SQL_SAFE_UPDATES,
SQL_SELECT_LIMIT,
SQL_SQL_MODE,
SQL_TIME_ZONE,
SQL_CHARACTER_SET_RESULTS,
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,*/
SQL_NAME_LAST
};
enum session_status {
CONNECTING_CLIENT,
CONNECTING_SERVER,
@ -168,7 +184,6 @@ enum session_status {
SETTING_TIME_ZONE,
SETTING_ISOLATION_LEVEL,
SETTING_TRANSACTION_READ,
SETTING_TX_ISOLATION,
SETTING_CHARACTER_SET_RESULTS,
SETTING_SESSION_TRACK_GTIDS,
SETTING_SQL_AUTO_IS_NULL,

@ -95,7 +95,7 @@ default: libproxysql.a
_OBJ = c_tokenizer.o
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
_OBJ_CXX = ProxySQL_GloVars.oo network.oo debug.oo configfile.oo Query_Cache.oo SpookyV2.oo MySQL_Authentication.oo gen_utils.oo sqlite3db.oo mysql_connection.oo MySQL_HostGroups_Manager.oo mysql_data_stream.oo MySQL_Thread.oo MySQL_Session.oo MySQL_Protocol.oo mysql_backend.oo Query_Processor.oo ProxySQL_Admin.oo ProxySQL_Config.oo ProxySQL_Restapi.oo MySQL_Monitor.oo MySQL_Logger.oo thread.oo MySQL_PreparedStatement.oo ProxySQL_Cluster.oo ClickHouse_Authentication.oo ClickHouse_Server.oo ProxySQL_Statistics.oo Chart_bundle_js.oo ProxySQL_HTTP_Server.oo ProxySQL_RESTAPI_Server.oo font-awesome.min.css.oo main-bundle.min.css.oo set_parser.oo
_OBJ_CXX = ProxySQL_GloVars.oo network.oo debug.oo configfile.oo Query_Cache.oo SpookyV2.oo MySQL_Authentication.oo gen_utils.oo sqlite3db.oo mysql_connection.oo MySQL_HostGroups_Manager.oo mysql_data_stream.oo MySQL_Thread.oo MySQL_Session.oo MySQL_Protocol.oo mysql_backend.oo Query_Processor.oo ProxySQL_Admin.oo ProxySQL_Config.oo ProxySQL_Restapi.oo MySQL_Monitor.oo MySQL_Logger.oo thread.oo MySQL_PreparedStatement.oo ProxySQL_Cluster.oo ClickHouse_Authentication.oo ClickHouse_Server.oo ProxySQL_Statistics.oo Chart_bundle_js.oo ProxySQL_HTTP_Server.oo ProxySQL_RESTAPI_Server.oo font-awesome.min.css.oo main-bundle.min.css.oo set_parser.oo MySQL_Variables.oo
OBJ_CXX = $(patsubst %,$(ODIR)/%,$(_OBJ_CXX))
HEADERS = ../include/*.h ../include/*.hpp

@ -3082,12 +3082,12 @@ SQLite3_result * MySQL_HostGroups_Manager::SQL3_Free_Connections() {
pta[6] = strdup(conn->options.init_connect);
}
pta[7] = NULL;
if (conn->options.time_zone) {
pta[7] = strdup(conn->options.time_zone);
if (conn->variables[SQL_TIME_ZONE].value) {
pta[7] = strdup(conn->variables[SQL_TIME_ZONE].value);
}
pta[8] = NULL;
if (conn->options.sql_mode) {
pta[8] = strdup(conn->options.sql_mode);
if (conn->variables[SQL_SQL_MODE].value) {
pta[8] = strdup(conn->variables[SQL_SQL_MODE].value);
}
sprintf(buf,"%d", conn->options.autocommit);
pta[9]=strdup(buf);

@ -14,6 +14,7 @@
#include "MySQL_LDAP_Authentication.hpp"
#include "MySQL_Protocol.h"
#include "SQLite3_Server.h"
#include "MySQL_Variables.h"
#include "libinjection.h"
@ -495,6 +496,7 @@ void MySQL_Session::init() {
mybes= new PtrArray(4);
sess_STMTs_meta=new MySQL_STMTs_meta();
SLDH=new StmtLongDataHandler();
mysql_variables = std::unique_ptr<MySQL_Variables>(new MySQL_Variables(this));
}
void MySQL_Session::reset() {
@ -957,16 +959,9 @@ void MySQL_Session::generate_proxysql_internal_session_json(json &j) {
j["client"]["DSS"] = client_myds->DSS;
j["default_schema"] = ( default_schema ? default_schema : "" );
j["transaction_persistent"] = transaction_persistent;
j["conn"]["sql_mode"] = ( client_myds->myconn->options.sql_mode ? client_myds->myconn->options.sql_mode : "") ;
j["conn"]["time_zone"] = ( client_myds->myconn->options.time_zone ? client_myds->myconn->options.time_zone : "") ;
j["conn"]["isolation_level"] = ( client_myds->myconn->options.isolation_level ? client_myds->myconn->options.isolation_level : "") ;
j["conn"]["transaction_read"] = ( client_myds->myconn->options.transaction_read ? client_myds->myconn->options.transaction_read : "") ;
j["conn"]["tx_isolation"] = ( client_myds->myconn->options.tx_isolation ? client_myds->myconn->options.tx_isolation : "") ;
j["conn"]["character_set_results"] = ( client_myds->myconn->options.character_set_results ? client_myds->myconn->options.character_set_results : "") ;
j["conn"]["session_track_gtids"] = ( client_myds->myconn->options.session_track_gtids ? client_myds->myconn->options.session_track_gtids : "") ;
j["conn"]["sql_auto_is_null"] = ( client_myds->myconn->options.sql_auto_is_null ? client_myds->myconn->options.sql_auto_is_null : "") ;
j["conn"]["sql_select_limit"] = ( client_myds->myconn->options.sql_select_limit ? client_myds->myconn->options.sql_select_limit : "") ;
j["conn"]["sql_safe_updates"] = ( client_myds->myconn->options.sql_safe_updates ? client_myds->myconn->options.sql_safe_updates : "") ;
for (auto idx = 0; idx < SQL_NAME_LAST; idx++) {
client_myds->myconn->variables[idx].fill_client_internal_session(j, idx);
}
j["conn"]["collation_connection"] = ( client_myds->myconn->options.collation_connection ? client_myds->myconn->options.collation_connection : "") ;
j["conn"]["net_write_timeout"] = ( client_myds->myconn->options.net_write_timeout ? client_myds->myconn->options.net_write_timeout : "") ;
j["conn"]["max_join_size"] = ( client_myds->myconn->options.max_join_size ? client_myds->myconn->options.max_join_size : "") ;
@ -1003,6 +998,9 @@ void MySQL_Session::generate_proxysql_internal_session_json(json &j) {
j["backends"][i]["stream"]["DSS"] = _myds->DSS;
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);
}
sprintf(buff,"%p",_myconn);
j["backends"][i]["conn"]["address"] = buff;
j["backends"][i]["conn"]["auto_increment_delay_token"] = _myconn->auto_increment_delay_token;
@ -1011,17 +1009,6 @@ void MySQL_Session::generate_proxysql_internal_session_json(json &j) {
j["backends"][i]["conn"]["questions"] = _myconn->statuses.questions;
j["backends"][i]["conn"]["myconnpoll_get"] = _myconn->statuses.myconnpoll_get;
j["backends"][i]["conn"]["myconnpoll_put"] = _myconn->statuses.myconnpoll_put;
j["backends"][i]["conn"]["sql_mode"] = ( _myconn->options.sql_mode ? _myconn->options.sql_mode : "") ;
j["backends"][i]["conn"]["sql_mode_sent"] = _myds->myconn->options.sql_mode_sent;
j["backends"][i]["conn"]["time_zone"] = ( _myconn->options.time_zone ? _myconn->options.time_zone : "") ;
j["backends"][i]["conn"]["isolation_level"] = ( _myconn->options.isolation_level ? _myconn->options.isolation_level : "") ;
j["backends"][i]["conn"]["tx_isolation"] = ( _myconn->options.tx_isolation ? _myconn->options.tx_isolation : "") ;
j["backends"][i]["conn"]["transaction_read"] = ( _myconn->options.transaction_read ? _myconn->options.transaction_read : "") ;
j["backends"][i]["conn"]["character_set_results"] = ( _myconn->options.character_set_results ? _myconn->options.character_set_results : "") ;
j["backends"][i]["conn"]["session_track_gtids"] = ( _myconn->options.session_track_gtids ? _myconn->options.session_track_gtids : "") ;
j["backends"][i]["conn"]["sql_auto_is_null"] = ( _myconn->options.sql_auto_is_null ? _myconn->options.sql_auto_is_null : "") ;
j["backends"][i]["conn"]["sql_select_limit"] = ( _myconn->options.sql_select_limit ? _myconn->options.sql_select_limit : "") ;
j["backends"][i]["conn"]["sql_safe_updates"] = ( _myconn->options.sql_safe_updates ? _myconn->options.sql_safe_updates : "") ;
j["backends"][i]["conn"]["collation_connection"] = ( _myconn->options.collation_connection ? _myconn->options.collation_connection : "") ;
j["backends"][i]["conn"]["net_write_timeout"] = ( _myconn->options.net_write_timeout ? _myconn->options.net_write_timeout : "") ;
j["backends"][i]["conn"]["max_join_size"] = ( _myconn->options.max_join_size ? _myconn->options.max_join_size : "") ;
@ -1645,45 +1632,6 @@ bool MySQL_Session::handler_again___verify_backend_sql_log_bin() {
return false;
}
bool MySQL_Session::handler_again___verify_backend_sql_mode() {
bool ret = false;
proxy_debug(PROXY_DEBUG_MYSQL_CONNECTION, 5, "Session %p , client: %s , backend: %s\n", this, client_myds->myconn->options.sql_mode, mybe->server_myds->myconn->options.sql_mode);
ret = handler_again___verify_backend__generic_variable(
&mybe->server_myds->myconn->options.sql_mode_int,
&mybe->server_myds->myconn->options.sql_mode,
mysql_thread___default_sql_mode,
&client_myds->myconn->options.sql_mode_int,
client_myds->myconn->options.sql_mode,
SETTING_SQL_MODE
);
return ret;
/*
// for sql_mode we also set sql_mode_sent . Doesn't seem used tho.
// snippet, for reference
if (
(client_myds->myconn->options.sql_mode_int != mybe->server_myds->myconn->options.sql_mode_int)
||
(mybe->server_myds->myconn->options.sql_mode_sent == false)
) {
mybe->server_myds->myconn->options.sql_mode_sent = true;
*/
}
bool MySQL_Session::handler_again___verify_backend_time_zone() {
bool ret = false;
proxy_debug(PROXY_DEBUG_MYSQL_CONNECTION, 5, "Session %p , client: %s , backend: %s\n", this, client_myds->myconn->options.time_zone, mybe->server_myds->myconn->options.time_zone);
ret = handler_again___verify_backend__generic_variable(
&mybe->server_myds->myconn->options.time_zone_int,
&mybe->server_myds->myconn->options.time_zone,
mysql_thread___default_time_zone,
&client_myds->myconn->options.time_zone_int,
client_myds->myconn->options.time_zone,
SETTING_TIME_ZONE
);
return ret;
}
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
@ -1732,115 +1680,10 @@ bool MySQL_Session::handler_again___verify_backend__generic_variable(uint32_t *b
return false;
}
bool MySQL_Session::handler_again___verify_backend_isolation_level() {
bool ret = false;
proxy_debug(PROXY_DEBUG_MYSQL_CONNECTION, 5, "Session %p , client: %s , backend: %s\n", this, client_myds->myconn->options.isolation_level, mybe->server_myds->myconn->options.isolation_level);
ret = handler_again___verify_backend__generic_variable(
&mybe->server_myds->myconn->options.isolation_level_int,
&mybe->server_myds->myconn->options.isolation_level,
mysql_thread___default_isolation_level,
&client_myds->myconn->options.isolation_level_int,
client_myds->myconn->options.isolation_level,
SETTING_ISOLATION_LEVEL
);
return ret;
}
bool MySQL_Session::handler_again___verify_backend_transaction_read() {
bool ret = false;
proxy_debug(PROXY_DEBUG_MYSQL_CONNECTION, 5, "Session %p , client: %s , backend: %s\n", this, client_myds->myconn->options.transaction_read, mybe->server_myds->myconn->options.transaction_read);
ret = handler_again___verify_backend__generic_variable(
&mybe->server_myds->myconn->options.transaction_read_int,
&mybe->server_myds->myconn->options.transaction_read,
mysql_thread___default_transaction_read,
&client_myds->myconn->options.transaction_read_int,
client_myds->myconn->options.transaction_read,
SETTING_TRANSACTION_READ
);
return ret;
}
bool MySQL_Session::handler_again___verify_backend_tx_isolation() {
bool ret = false;
proxy_debug(PROXY_DEBUG_MYSQL_CONNECTION, 5, "Session %p , client: %s , backend: %s\n", this, client_myds->myconn->options.tx_isolation, mybe->server_myds->myconn->options.tx_isolation);
ret = handler_again___verify_backend__generic_variable(
&mybe->server_myds->myconn->options.tx_isolation_int,
&mybe->server_myds->myconn->options.tx_isolation,
mysql_thread___default_tx_isolation,
&client_myds->myconn->options.tx_isolation_int,
client_myds->myconn->options.tx_isolation,
SETTING_TX_ISOLATION
);
return ret;
}
bool MySQL_Session::handler_again___verify_backend_character_set_results() {
bool ret = false;
proxy_debug(PROXY_DEBUG_MYSQL_CONNECTION, 5, "Session %p , client: %s , backend: %s\n", this, client_myds->myconn->options.character_set_results, mybe->server_myds->myconn->options.character_set_results);
ret = handler_again___verify_backend__generic_variable(
&mybe->server_myds->myconn->options.character_set_results_int,
&mybe->server_myds->myconn->options.character_set_results,
mysql_thread___default_character_set_results,
&client_myds->myconn->options.character_set_results_int,
client_myds->myconn->options.character_set_results,
SETTING_CHARACTER_SET_RESULTS
);
return ret;
}
bool MySQL_Session::handler_again___verify_backend_session_track_gtids() {
bool ret = false;
proxy_debug(PROXY_DEBUG_MYSQL_CONNECTION, 5, "Session %p , client: %s , backend: %s\n", this, client_myds->myconn->options.session_track_gtids, mybe->server_myds->myconn->options.session_track_gtids);
ret = handler_again___verify_backend__generic_variable(
&mybe->server_myds->myconn->options.session_track_gtids_int,
&mybe->server_myds->myconn->options.session_track_gtids,
mysql_thread___default_session_track_gtids,
&client_myds->myconn->options.session_track_gtids_int,
client_myds->myconn->options.session_track_gtids,
SETTING_SESSION_TRACK_GTIDS
);
return ret;
}
bool MySQL_Session::handler_again___verify_backend_sql_auto_is_null() {
bool ret = false;
proxy_debug(PROXY_DEBUG_MYSQL_CONNECTION, 5, "Session %p , client: %s , backend: %s\n", this, client_myds->myconn->options.sql_auto_is_null, mybe->server_myds->myconn->options.sql_auto_is_null);
ret = handler_again___verify_backend__generic_variable(
&mybe->server_myds->myconn->options.sql_auto_is_null_int,
&mybe->server_myds->myconn->options.sql_auto_is_null,
mysql_thread___default_sql_auto_is_null,
&client_myds->myconn->options.sql_auto_is_null_int,
client_myds->myconn->options.sql_auto_is_null,
SETTING_SQL_AUTO_IS_NULL
);
return ret;
}
bool MySQL_Session::handler_again___verify_backend_sql_select_limit() {
bool ret = false;
proxy_debug(PROXY_DEBUG_MYSQL_CONNECTION, 5, "Session %p , client: %s , backend: %s\n", this, client_myds->myconn->options.sql_select_limit, mybe->server_myds->myconn->options.sql_select_limit);
ret = handler_again___verify_backend__generic_variable(
&mybe->server_myds->myconn->options.sql_select_limit_int,
&mybe->server_myds->myconn->options.sql_select_limit,
mysql_thread___default_sql_select_limit,
&client_myds->myconn->options.sql_select_limit_int,
client_myds->myconn->options.sql_select_limit,
SETTING_SQL_SELECT_LIMIT
);
return ret;
}
bool MySQL_Session::handler_again___verify_backend_sql_safe_updates() {
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, client_myds->myconn->options.sql_safe_updates, mybe->server_myds->myconn->options.sql_safe_updates);
ret = handler_again___verify_backend__generic_variable(
&mybe->server_myds->myconn->options.sql_safe_updates_int,
&mybe->server_myds->myconn->options.sql_safe_updates,
mysql_thread___default_sql_safe_updates,
&client_myds->myconn->options.sql_safe_updates_int,
client_myds->myconn->options.sql_safe_updates,
SETTING_SQL_SAFE_UPDATES
);
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;
}
@ -2340,13 +2183,6 @@ bool MySQL_Session::handler_again___status_SETTING_SQL_LOG_BIN(int *_rc) {
return ret;
}
bool MySQL_Session::handler_again___status_SETTING_SQL_MODE(int *_rc) {
bool ret=false;
assert(mybe->server_myds->myconn);
ret = handler_again___status_SETTING_GENERIC_VARIABLE(_rc, (char *)"SQL_MODE", mybe->server_myds->myconn->options.sql_mode);
return ret;
}
/* FIXME: this old code hardcoded the handling of issue 1738
// this seems unnecessary/redundant
// leaving the code for further reference, to be removed later
@ -2453,7 +2289,7 @@ bool MySQL_Session::handler_again___status_SETTING_SQL_MODE(int *_rc) {
}
*/
bool MySQL_Session::handler_again___status_SETTING_GENERIC_VARIABLE(int *_rc, char *var_name, char *var_value, bool no_quote, bool set_transaction) {
bool MySQL_Session::handler_again___status_SETTING_GENERIC_VARIABLE(int *_rc, const char *var_name, const char *var_value, bool no_quote, bool set_transaction) {
bool ret = false;
assert(mybe->server_myds->myconn);
MySQL_Data_Stream *myds=mybe->server_myds;
@ -2576,20 +2412,6 @@ bool MySQL_Session::handler_again___status_SETTING_GENERIC_VARIABLE(int *_rc, ch
return ret;
}
bool MySQL_Session::handler_again___status_SETTING_TIME_ZONE(int *_rc) {
bool ret=false;
assert(mybe->server_myds->myconn);
ret = handler_again___status_SETTING_GENERIC_VARIABLE(_rc, (char *)"TIME_ZONE", mybe->server_myds->myconn->options.time_zone);
return ret;
}
bool MySQL_Session::handler_again___status_SETTING_ISOLATION_LEVEL(int *_rc) {
bool ret=false;
assert(mybe->server_myds->myconn);
ret = handler_again___status_SETTING_GENERIC_VARIABLE(_rc, (char *)"SESSION TRANSACTION ISOLATION LEVEL", mybe->server_myds->myconn->options.isolation_level, false, true);
return ret;
}
bool MySQL_Session::handler_again___status_SETTING_MULTI_STMT(int *_rc) {
assert(mybe->server_myds->myconn);
MySQL_Data_Stream *myds=mybe->server_myds;
@ -2621,52 +2443,17 @@ bool MySQL_Session::handler_again___status_SETTING_CHARSET(int *_rc) {
return ret;
}
bool MySQL_Session::handler_again___status_SETTING_TRANSACTION_READ(int *_rc) {
bool ret=false;
assert(mybe->server_myds->myconn);
ret = handler_again___status_SETTING_GENERIC_VARIABLE(_rc, (char *)"SESSION TRANSACTION READ", mybe->server_myds->myconn->options.transaction_read, false, true);
return ret;
}
bool MySQL_Session::handler_again___status_SETTING_TX_ISOLATION(int *_rc) {
bool ret=false;
assert(mybe->server_myds->myconn);
ret = handler_again___status_SETTING_GENERIC_VARIABLE(_rc, (char *)"TX_ISOLATION", mybe->server_myds->myconn->options.tx_isolation, false, false);
return ret;
}
bool MySQL_Session::handler_again___status_SETTING_CHARACTER_SET_RESULTS(int *_rc) {
bool ret=false;
assert(mybe->server_myds->myconn);
ret = handler_again___status_SETTING_GENERIC_VARIABLE(_rc, (char *)"CHARACTER_SET_RESULTS", mybe->server_myds->myconn->options.character_set_results, true);
return ret;
}
bool MySQL_Session::handler_again___status_SETTING_SESSION_TRACK_GTIDS(int *_rc) {
bool ret=false;
assert(mybe->server_myds->myconn);
ret = handler_again___status_SETTING_GENERIC_VARIABLE(_rc, (char *)"SESSION_TRACK_GTIDS", mybe->server_myds->myconn->options.session_track_gtids, true);
return ret;
}
bool MySQL_Session::handler_again___status_SETTING_SQL_AUTO_IS_NULL(int *_rc) {
bool ret=false;
assert(mybe->server_myds->myconn);
ret = handler_again___status_SETTING_GENERIC_VARIABLE(_rc, (char *)"SQL_AUTO_IS_NULL", mybe->server_myds->myconn->options.sql_auto_is_null, true);
return ret;
}
bool MySQL_Session::handler_again___status_SETTING_SQL_SELECT_LIMIT(int *_rc) {
bool ret=false;
assert(mybe->server_myds->myconn);
ret = handler_again___status_SETTING_GENERIC_VARIABLE(_rc, (char *)"SQL_SELECT_LIMIT", mybe->server_myds->myconn->options.sql_select_limit, true);
ret = handler_again___status_SETTING_GENERIC_VARIABLE(_rc, (char *)"SQL_SELECT_LIMIT", mysql_variables->server_get_value(SQL_SELECT_LIMIT), true);
return ret;
}
bool MySQL_Session::handler_again___status_SETTING_SQL_SAFE_UPDATES(int *_rc) {
bool ret=false;
assert(mybe->server_myds->myconn);
ret = handler_again___status_SETTING_GENERIC_VARIABLE(_rc, (char *)"SQL_SAFE_UPDATES", mybe->server_myds->myconn->options.sql_safe_updates, true);
ret = handler_again___status_SETTING_GENERIC_VARIABLE(_rc, (char *)"SQL_SAFE_UPDATES", mysql_variables->server_get_value(SQL_SAFE_UPDATES), true);
return ret;
}
@ -3996,40 +3783,17 @@ handler_again:
goto handler_again;
}
if (locked_on_hostgroup == -1 || locked_on_hostgroup_and_all_variables_set == false ) {
if (handler_again___verify_backend_charset()) {
goto handler_again;
}
if (handler_again___verify_backend_sql_log_bin()) {
goto handler_again;
}
if (handler_again___verify_backend_sql_mode()) {
goto handler_again;
}
if (handler_again___verify_backend_time_zone()) {
goto handler_again;
}
if (handler_again___verify_backend_isolation_level()) {
goto handler_again;
}
if (handler_again___verify_backend_transaction_read()) {
goto handler_again;
}
if (handler_again___verify_backend_tx_isolation()) {
goto handler_again;
}
if (handler_again___verify_backend_character_set_results()) {
goto handler_again;
}
if (handler_again___verify_backend_session_track_gtids()) {
goto handler_again;
}
if (handler_again___verify_backend_sql_auto_is_null()) {
goto handler_again;
}
if (handler_again___verify_backend_sql_select_limit()) {
goto handler_again;
for (auto i = 0; i < SQL_NAME_LAST; i++) {
if(mysql_variables->verify_variable(i))
goto handler_again;
}
if (handler_again___verify_backend_sql_safe_updates()) {
if (handler_again___verify_backend_sql_log_bin()) {
goto handler_again;
}
if (handler_again___verify_backend_collation_connection()) {
@ -4581,120 +4345,20 @@ handler_again:
break;
case SETTING_SQL_MODE:
{
int rc=0;
if (handler_again___status_SETTING_SQL_MODE(&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_SELECT_LIMIT:
case SETTING_SQL_SAFE_UPDATES:
case SETTING_TIME_ZONE:
{
int rc=0;
if (handler_again___status_SETTING_TIME_ZONE(&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_CHARACTER_SET_RESULTS:
case SETTING_ISOLATION_LEVEL:
{
int rc=0;
if (handler_again___status_SETTING_ISOLATION_LEVEL(&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_TRANSACTION_READ:
{
int rc=0;
if (handler_again___status_SETTING_TRANSACTION_READ(&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_TX_ISOLATION:
{
int rc=0;
if (handler_again___status_SETTING_TX_ISOLATION(&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_CHARACTER_SET_RESULTS:
{
int rc=0;
if (handler_again___status_SETTING_CHARACTER_SET_RESULTS(&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_SESSION_TRACK_GTIDS:
{
int rc=0;
if (handler_again___status_SETTING_SESSION_TRACK_GTIDS(&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_AUTO_IS_NULL:
{
int rc=0;
if (handler_again___status_SETTING_SQL_AUTO_IS_NULL(&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_SELECT_LIMIT:
{
int rc=0;
if (handler_again___status_SETTING_SQL_SELECT_LIMIT(&rc))
goto handler_again; // we changed status
if (rc==-1) { // we have an error we can't handle
handler_ret = -1;
return handler_ret;
for (auto i = 0; i < SQL_NAME_LAST; i++) {
int rc = 0;
if (mysql_variables->update_variable(rc)) {
goto handler_again;
}
}
break;
case SETTING_SQL_SAFE_UPDATES:
{
int rc=0;
if (handler_again___status_SETTING_SQL_SAFE_UPDATES(&rc))
goto handler_again; // we changed status
if (rc==-1) { // we have an error we can't handle
if (rc == -1) {
handler_ret = -1;
return handler_ret;
}
@ -5640,17 +5304,9 @@ 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 (client_myds->myconn->options.sql_mode_int != sql_mode_int) {
//fprintf(stderr,"sql_mode_int='%u'\n", sql_mode_int);
client_myds->myconn->options.sql_mode_int = sql_mode_int;
if (client_myds->myconn->options.sql_mode) {
free(client_myds->myconn->options.sql_mode);
}
if (mysql_variables->client_get_hash(SQL_SQL_MODE) != sql_mode_int) {
mysql_variables->client_set_value(SQL_SQL_MODE, value1.c_str());
proxy_debug(PROXY_DEBUG_MYSQL_COM, 8, "Changing connection SQL Mode to %s\n", value1.c_str());
client_myds->myconn->options.sql_mode=strdup(value1.c_str());
if (strcasestr(value1.c_str(), (char *)"NO_BACKSLASH_ESCAPES")) {
//goto __exit_set_destination_hostgroup;
}
}
exit_after_SetParse = true;
} else if (var == "sql_auto_is_null") {
@ -5675,13 +5331,9 @@ bool MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C
if (__tmp_value >= 0) {
proxy_debug(PROXY_DEBUG_MYSQL_COM, 7, "Processing SET sql_auto_is_null value %s\n", value1.c_str());
uint32_t sql_auto_is_null_int=SpookyHash::Hash32(value1.c_str(),value1.length(),10);
if (client_myds->myconn->options.sql_auto_is_null_int != sql_auto_is_null_int) {
client_myds->myconn->options.sql_auto_is_null_int = sql_auto_is_null_int;
if (client_myds->myconn->options.sql_auto_is_null) {
free(client_myds->myconn->options.sql_auto_is_null);
}
if (mysql_variables->client_get_hash(SQL_SQL_AUTO_IS_NULL) != sql_auto_is_null_int) {
mysql_variables->client_set_value(SQL_SQL_AUTO_IS_NULL, value1.c_str());
proxy_debug(PROXY_DEBUG_MYSQL_COM, 5, "Changing connection sql_auto_is_null to %s\n", value1.c_str());
client_myds->myconn->options.sql_auto_is_null=strdup(value1.c_str());
}
exit_after_SetParse = true;
} else {
@ -5710,13 +5362,9 @@ bool MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C
if (__tmp_value >= 0) {
proxy_debug(PROXY_DEBUG_MYSQL_COM, 7, "Processing SET sql_safe_updates value %s\n", value1.c_str());
uint32_t sql_safe_updates_int=SpookyHash::Hash32(value1.c_str(),value1.length(),10);
if (client_myds->myconn->options.sql_safe_updates_int != sql_safe_updates_int) {
client_myds->myconn->options.sql_safe_updates_int = sql_safe_updates_int;
if (client_myds->myconn->options.sql_safe_updates) {
free(client_myds->myconn->options.sql_safe_updates);
}
if (mysql_variables->client_get_hash(SQL_SAFE_UPDATES) != sql_safe_updates_int) {
mysql_variables->client_set_value(SQL_SAFE_UPDATES, value1.c_str());
proxy_debug(PROXY_DEBUG_MYSQL_COM, 5, "Changing connection sql_safe_updates to %s\n", value1.c_str());
client_myds->myconn->options.sql_safe_updates=strdup(value1.c_str());
}
exit_after_SetParse = true;
} else {
@ -5789,14 +5437,9 @@ 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 (client_myds->myconn->options.time_zone_int != time_zone_int) {
//fprintf(stderr,"time_zone_int='%u'\n", time_zone_int);
client_myds->myconn->options.time_zone_int = time_zone_int;
if (client_myds->myconn->options.time_zone) {
free(client_myds->myconn->options.time_zone);
}
if (mysql_variables->client_get_hash(SQL_TIME_ZONE) != time_zone_int) {
mysql_variables->client_set_value(SQL_TIME_ZONE, value1.c_str());
proxy_debug(PROXY_DEBUG_MYSQL_COM, 8, "Changing connection Time zone to %s\n", value1.c_str());
client_myds->myconn->options.time_zone=strdup(value1.c_str());
}
exit_after_SetParse = true;
} else if (var == "session_track_gtids") {
@ -5804,13 +5447,9 @@ bool MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C
if ((strcasecmp(value1.c_str(),"OWN_GTID")==0) || (strcasecmp(value1.c_str(),"OFF")==0)) {
proxy_debug(PROXY_DEBUG_MYSQL_COM, 7, "Processing SET session_track_gtids value %s\n", value1.c_str());
uint32_t session_track_gtids_int=SpookyHash::Hash32(value1.c_str(),value1.length(),10);
if (client_myds->myconn->options.session_track_gtids_int != session_track_gtids_int) {
client_myds->myconn->options.session_track_gtids_int = session_track_gtids_int;
if (client_myds->myconn->options.session_track_gtids) {
free(client_myds->myconn->options.session_track_gtids);
}
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());
proxy_debug(PROXY_DEBUG_MYSQL_COM, 5, "Changing connection session_track_gtids to %s\n", value1.c_str());
client_myds->myconn->options.session_track_gtids=strdup(value1.c_str());
}
exit_after_SetParse = true;
} else {
@ -5887,13 +5526,9 @@ bool MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C
if (only_digit_chars) {
proxy_debug(PROXY_DEBUG_MYSQL_COM, 7, "Processing SET sql_select_limit value %s\n", value1.c_str());
uint32_t sql_select_limit_int=SpookyHash::Hash32(value1.c_str(),value1.length(),10);
if (client_myds->myconn->options.sql_select_limit_int != sql_select_limit_int) {
client_myds->myconn->options.sql_select_limit_int = sql_select_limit_int;
if (client_myds->myconn->options.sql_select_limit) {
free(client_myds->myconn->options.sql_select_limit);
}
if (mysql_variables->client_get_hash(SQL_SELECT_LIMIT) != sql_select_limit_int) {
mysql_variables->client_set_value(SQL_SELECT_LIMIT, value1.c_str());
proxy_debug(PROXY_DEBUG_MYSQL_COM, 5, "Changing connection sql_select_limit to %s\n", value1.c_str());
client_myds->myconn->options.sql_select_limit=strdup(value1.c_str());
}
exit_after_SetParse = true;
} else {
@ -5939,13 +5574,9 @@ bool MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C
if (only_normal_chars) {
proxy_debug(PROXY_DEBUG_MYSQL_COM, 7, "Processing SET character_set_results value %s\n", value1.c_str());
uint32_t character_set_results_int=SpookyHash::Hash32(value1.c_str(),value1.length(),10);
if (client_myds->myconn->options.character_set_results_int != character_set_results_int) {
client_myds->myconn->options.character_set_results_int = character_set_results_int;
if (client_myds->myconn->options.character_set_results) {
free(client_myds->myconn->options.character_set_results);
}
if (mysql_variables->client_get_hash(SQL_CHARACTER_SET_RESULTS) != character_set_results_int) {
mysql_variables->client_set_value(SQL_CHARACTER_SET_RESULTS, value1.c_str());
proxy_debug(PROXY_DEBUG_MYSQL_COM, 5, "Changing connection character_set_results to %s\n", value1.c_str());
client_myds->myconn->options.character_set_results=strdup(value1.c_str());
}
exit_after_SetParse = true;
} else {
@ -5995,15 +5626,13 @@ bool MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C
} else if (var == "tx_isolation") {
std::string value1 = *values;
proxy_debug(PROXY_DEBUG_MYSQL_COM, 5, "Processing SET tx_isolation value %s\n", value1.c_str());
uint32_t tx_isolation_int=SpookyHash::Hash32(value1.c_str(),value1.length(),10);
if (client_myds->myconn->options.tx_isolation_int != tx_isolation_int) {
//fprintf(stderr,"sql_mode_int='%u'\n", sql_mode_int);
client_myds->myconn->options.tx_isolation_int = tx_isolation_int;
if (client_myds->myconn->options.tx_isolation) {
free(client_myds->myconn->options.tx_isolation);
}
auto pos = value1.find('-');
if (pos != std::string::npos)
value1[pos] = ' ';
uint32_t isolation_level_int=SpookyHash::Hash32(value1.c_str(),value1.length(),10);
if (mysql_variables->client_get_hash(SQL_ISOLATION_LEVEL) != isolation_level_int) {
mysql_variables->client_set_value(SQL_ISOLATION_LEVEL, value1.c_str());
proxy_debug(PROXY_DEBUG_MYSQL_COM, 8, "Changing connection TX ISOLATION to %s\n", value1.c_str());
client_myds->myconn->options.tx_isolation=strdup(value1.c_str());
}
exit_after_SetParse = true;
} else {
@ -6048,12 +5677,8 @@ bool MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C
delete opt2;
if (rc) {
uint32_t sql_mode_int=SpookyHash::Hash32(s1.c_str(),s1.length(),10);
if (client_myds->myconn->options.sql_mode_int != sql_mode_int) {
client_myds->myconn->options.sql_mode_int = sql_mode_int;
if (client_myds->myconn->options.sql_mode) {
free(client_myds->myconn->options.sql_mode);
}
client_myds->myconn->options.sql_mode=strdup(s1.c_str());
if (mysql_variables->client_get_hash(SQL_SQL_MODE) != sql_mode_int) {
mysql_variables->client_set_value(SQL_SQL_MODE, s1.c_str());
std::size_t found_at = s1.find("@");
if (found_at != std::string::npos) {
char *v1 = strdup(s1.c_str());
@ -6120,26 +5745,18 @@ bool MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C
std::string value1 = *values;
proxy_debug(PROXY_DEBUG_MYSQL_COM, 5, "Processing SET SESSION TRANSACTION ISOLATION LEVEL value %s\n", value1.c_str());
uint32_t isolation_level_int=SpookyHash::Hash32(value1.c_str(),value1.length(),10);
if (client_myds->myconn->options.isolation_level_int != isolation_level_int) {
client_myds->myconn->options.isolation_level_int = isolation_level_int;
if (client_myds->myconn->options.isolation_level) {
free(client_myds->myconn->options.isolation_level);
}
if (mysql_variables->client_get_hash(SQL_ISOLATION_LEVEL) != isolation_level_int) {
mysql_variables->client_set_value(SQL_ISOLATION_LEVEL, value1.c_str());
proxy_debug(PROXY_DEBUG_MYSQL_COM, 8, "Changing connection TRANSACTION ISOLATION LEVEL to %s\n", value1.c_str());
client_myds->myconn->options.isolation_level=strdup(value1.c_str());
}
exit_after_SetParse = true;
} else if (var == "read") {
std::string value1 = *values;
proxy_debug(PROXY_DEBUG_MYSQL_COM, 5, "Processing SET SESSION TRANSACTION READ value %s\n", value1.c_str());
uint32_t transaction_read_int=SpookyHash::Hash32(value1.c_str(),value1.length(),10);
if (client_myds->myconn->options.transaction_read_int != transaction_read_int) {
client_myds->myconn->options.transaction_read_int = transaction_read_int;
if (client_myds->myconn->options.transaction_read) {
free(client_myds->myconn->options.transaction_read);
}
if (mysql_variables->client_get_hash(SQL_TRANSACTION_READ) != transaction_read_int) {
mysql_variables->client_set_value(SQL_TRANSACTION_READ, value1.c_str());
proxy_debug(PROXY_DEBUG_MYSQL_COM, 8, "Changing connection TRANSACTION READ to %s\n", value1.c_str());
client_myds->myconn->options.transaction_read=strdup(value1.c_str());
}
exit_after_SetParse = true;
} else {

@ -14,6 +14,7 @@
#include "StatCounters.h"
#include "MySQL_PreparedStatement.h"
#include "MySQL_Logger.hpp"
#include "MySQL_Variables.h"
#ifdef DEBUG
MySQL_Session *sess_stopat;
@ -3567,69 +3568,16 @@ 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);
// fix bug 1253 : initialize time_zone
uint32_t time_zone_int=SpookyHash::Hash32(mysql_thread___default_time_zone,strlen(mysql_thread___default_time_zone),10);
sess->client_myds->myconn->options.time_zone_int = time_zone_int;
if (sess->client_myds->myconn->options.time_zone) {
free(sess->client_myds->myconn->options.time_zone);
}
sess->client_myds->myconn->options.time_zone=strdup(mysql_thread___default_time_zone);
uint32_t isolation_level_int=SpookyHash::Hash32(mysql_thread___default_isolation_level,strlen(mysql_thread___default_isolation_level),10);
sess->client_myds->myconn->options.isolation_level_int = isolation_level_int;
if (sess->client_myds->myconn->options.isolation_level) {
free(sess->client_myds->myconn->options.isolation_level);
}
sess->client_myds->myconn->options.isolation_level=strdup(mysql_thread___default_isolation_level);
uint32_t tx_isolation_int=SpookyHash::Hash32(mysql_thread___default_tx_isolation,strlen(mysql_thread___default_tx_isolation),10);
sess->client_myds->myconn->options.tx_isolation_int = tx_isolation_int;
if (sess->client_myds->myconn->options.tx_isolation) {
free(sess->client_myds->myconn->options.tx_isolation);
}
sess->client_myds->myconn->options.tx_isolation=strdup(mysql_thread___default_tx_isolation);
uint32_t transaction_read_int=SpookyHash::Hash32(mysql_thread___default_transaction_read,strlen(mysql_thread___default_transaction_read),10);
sess->client_myds->myconn->options.transaction_read_int = transaction_read_int;
if (sess->client_myds->myconn->options.transaction_read) {
free(sess->client_myds->myconn->options.transaction_read);
}
sess->client_myds->myconn->options.transaction_read=strdup(mysql_thread___default_transaction_read);
uint32_t character_set_results_int=SpookyHash::Hash32(mysql_thread___default_character_set_results,strlen(mysql_thread___default_character_set_results),10);
sess->client_myds->myconn->options.character_set_results_int = character_set_results_int;
if (sess->client_myds->myconn->options.character_set_results) {
free(sess->client_myds->myconn->options.character_set_results);
}
sess->client_myds->myconn->options.character_set_results=strdup(mysql_thread___default_character_set_results);
uint32_t session_track_gtids_int=SpookyHash::Hash32(mysql_thread___default_session_track_gtids,strlen(mysql_thread___default_session_track_gtids),10);
sess->client_myds->myconn->options.session_track_gtids_int = session_track_gtids_int;
if (sess->client_myds->myconn->options.session_track_gtids) {
free(sess->client_myds->myconn->options.session_track_gtids);
}
sess->client_myds->myconn->options.session_track_gtids=strdup(mysql_thread___default_session_track_gtids);
uint32_t sql_auto_is_null_int=SpookyHash::Hash32(mysql_thread___default_sql_auto_is_null,strlen(mysql_thread___default_sql_auto_is_null),10);
sess->client_myds->myconn->options.sql_auto_is_null_int = sql_auto_is_null_int;
if (sess->client_myds->myconn->options.sql_auto_is_null) {
free(sess->client_myds->myconn->options.sql_auto_is_null);
}
sess->client_myds->myconn->options.sql_auto_is_null=strdup(mysql_thread___default_sql_auto_is_null);
uint32_t sql_select_limit_int=SpookyHash::Hash32(mysql_thread___default_sql_select_limit,strlen(mysql_thread___default_sql_select_limit),10);
sess->client_myds->myconn->options.sql_select_limit_int = sql_select_limit_int;
if (sess->client_myds->myconn->options.sql_select_limit) {
free(sess->client_myds->myconn->options.sql_select_limit);
}
sess->client_myds->myconn->options.sql_select_limit=strdup(mysql_thread___default_sql_select_limit);
uint32_t sql_safe_updates_int=SpookyHash::Hash32(mysql_thread___default_sql_safe_updates,strlen(mysql_thread___default_sql_safe_updates),10);
sess->client_myds->myconn->options.sql_safe_updates_int = sql_safe_updates_int;
if (sess->client_myds->myconn->options.sql_safe_updates) {
free(sess->client_myds->myconn->options.sql_safe_updates);
}
sess->client_myds->myconn->options.sql_safe_updates=strdup(mysql_thread___default_sql_safe_updates);
sess->mysql_variables->client_set_value(SQL_SELECT_LIMIT, mysql_thread___default_sql_select_limit);
sess->mysql_variables->client_set_value(SQL_SAFE_UPDATES, mysql_thread___default_sql_safe_updates);
sess->mysql_variables->client_set_value(SQL_SQL_MODE, mysql_thread___default_sql_mode);
sess->mysql_variables->client_set_value(SQL_TIME_ZONE, mysql_thread___default_time_zone);
sess->mysql_variables->client_set_value(SQL_CHARACTER_SET_RESULTS, mysql_thread___default_character_set_results);
sess->mysql_variables->client_set_value(SQL_ISOLATION_LEVEL, mysql_thread___default_isolation_level);
sess->mysql_variables->client_set_value(SQL_TRANSACTION_READ, mysql_thread___default_transaction_read);
sess->mysql_variables->client_set_value(SQL_SESSION_TRACK_GTIDS, mysql_thread___default_session_track_gtids);
sess->mysql_variables->client_set_value(SQL_SQL_AUTO_IS_NULL, mysql_thread___default_sql_auto_is_null);
uint32_t collation_connection_int=SpookyHash::Hash32(mysql_thread___default_collation_connection,strlen(mysql_thread___default_collation_connection),10);
sess->client_myds->myconn->options.collation_connection_int = collation_connection_int;

@ -0,0 +1,230 @@
#include "MySQL_Variables.h"
#include "proxysql.h"
#include "MySQL_Session.h"
#include "MySQL_Data_Stream.h"
#include "SpookyV2.h"
int MySQL_Variables::session_by_var[SQL_NAME_LAST] = {
SETTING_SQL_SAFE_UPDATES,
SETTING_SQL_SELECT_LIMIT,
SETTING_SQL_MODE,
SETTING_TIME_ZONE,
SETTING_CHARACTER_SET_RESULTS,
SETTING_ISOLATION_LEVEL,
SETTING_TRANSACTION_READ,
SETTING_SESSION_TRACK_GTIDS,
SETTING_SQL_AUTO_IS_NULL
/* SETTING_COLLATION_CONNECTION,
SETTING_NET_WRITE_TIMEOUT,
SETTING_MAX_JOIN_SIZE*/
};
bool MySQL_Variables::quotes[SQL_NAME_LAST] = {
true, // SQL_SAFE_UPDATES
true, // SQL_SELECT_LIMIT
false, // SQL_MODE
false, // SQL_TIME_ZONE
true, // CHARACTER_SET_RESULTS
false, // ISOLATION_LEVEL
false, // TRANSACTION_READ
true, // SESSION_TRACK_GTIDS
true // SQL_AUTO_IS_NULL
/* false, // COLLATION_CONNECTION
true, // NET_WRITE_TIMEOUT
true // MAX_JOIN_SIZE*/
};
bool MySQL_Variables::set_transaction[SQL_NAME_LAST] = {
false, // SQL_SAFE_UPDATES
false, // SQL_SELECT_LIMIT
false, // SQL_MODE
false, // SQL_TIME_ZONE
false, // CHARACTER_SET_RESULTS
true, // ISOLATION_LEVEL
true, // TRANSACTION_READ
false, // SESSION_TRACK_GTIDS
false // SQL_AUTO_IS_NULL
/* false, // COLLATION_CONNECTION
false, // NET_WRITE_TIMEOUT
false // MAX_JOIN_SIZE */
};
int MySQL_Variables::var_by_session[NONE] = {
SQL_NAME_LAST,
SQL_NAME_LAST,
SQL_NAME_LAST,
SQL_NAME_LAST,
SQL_NAME_LAST,
SQL_NAME_LAST,
SQL_NAME_LAST,
SQL_NAME_LAST,
SQL_NAME_LAST,
SQL_NAME_LAST,
SQL_NAME_LAST,
SQL_NAME_LAST,
SQL_NAME_LAST,
SQL_NAME_LAST,
SQL_NAME_LAST,
SQL_NAME_LAST,
SQL_NAME_LAST,
SQL_SQL_MODE,
SQL_TIME_ZONE,
SQL_ISOLATION_LEVEL,
SQL_TRANSACTION_READ,
SQL_CHARACTER_SET_RESULTS,
SQL_SESSION_TRACK_GTIDS,
SQL_SQL_AUTO_IS_NULL,
SQL_SELECT_LIMIT,
SQL_SAFE_UPDATES,
SQL_NAME_LAST,
SQL_NAME_LAST,
SQL_NAME_LAST,
SQL_NAME_LAST,
SQL_NAME_LAST,
SQL_NAME_LAST,
SQL_NAME_LAST
};
MySQL_Variables::MySQL_Variables(MySQL_Session* _session) {
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_ISOLATION_LEVEL:
case SQL_TRANSACTION_READ:
case SQL_SESSION_TRACK_GTIDS:
case SQL_SQL_AUTO_IS_NULL:
updaters[i] = new Generic_Updater();
break;
default:
proxy_error("Wrong variable index\n");
assert(0);
}
}
}
MySQL_Variables::~MySQL_Variables() {
for (auto u : updaters)
delete u;
}
void MySQL_Variables::client_set_value(int idx, const char* value) {
session->client_myds->myconn->variables[idx].hash = SpookyHash::Hash32(value,strlen(value),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);
}
const char* MySQL_Variables::client_get_value(int idx) {
return session->client_myds->myconn->variables[idx].value;
}
uint32_t MySQL_Variables::client_get_hash(int idx) {
return session->client_myds->myconn->variables[idx].hash;
}
void MySQL_Variables::server_set_value(int idx, const char* value) {
session->mybe->server_myds->myconn->variables[idx].hash = SpookyHash::Hash32(value,strlen(value),10);
if (session->mybe->server_myds->myconn->variables[idx].value) {
free(session->mybe->server_myds->myconn->variables[idx].value);
}
session->mybe->server_myds->myconn->variables[idx].value = strdup(value);
}
const char* MySQL_Variables::server_get_value(int idx) {
return session->mybe->server_myds->myconn->variables[idx].value;
}
uint32_t MySQL_Variables::server_get_hash(int idx) {
return session->mybe->server_myds->myconn->variables[idx].hash;
}
bool MySQL_Variables::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) {
// 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(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:
assert(0);
break;
}
session->set_status(next_sess_status);
return true;
}
}
return false;
}
bool MySQL_Variables::update_variable(int &_rc) {
auto idx = MySQL_Variables::var_by_session[session->status];
updaters[idx]->update_server_variable(session, idx, _rc);
}
bool MySQL_Variables::verify_variable(int idx) {
int rc = 0;
auto ret = updaters[idx]->verify_variables(session, idx);
if (ret)
update_variable(rc);
return ret;
}
bool Generic_Updater::verify_variables(MySQL_Session* session, int idx) {
auto ret = session->mysql_variables->verify_generic_variable(
&session->mybe->server_myds->myconn->variables[idx].hash,
&session->mybe->server_myds->myconn->variables[idx].value,
mysql_thread___default_sql_safe_updates,
&session->client_myds->myconn->variables[idx].hash,
session->client_myds->myconn->variables[idx].value,
static_cast<session_status>(MySQL_Variables::session_by_var[idx])
);
}
bool Generic_Updater::update_server_variable(MySQL_Session* session, int idx, int &_rc) {
bool q = MySQL_Variables::quotes[idx];
bool st = MySQL_Variables::set_transaction[idx];
auto ret = session->handler_again___status_SETTING_GENERIC_VARIABLE(&_rc, Variable::set_name[idx], session->mysql_variables->server_get_value(idx), q, st);
return ret;
}

@ -9,6 +9,19 @@
extern const MARIADB_CHARSET_INFO * proxysql_find_charset_nr(unsigned int nr);
const char Variable::set_name[SQL_NAME_LAST][64] = {"sql_safe_updates", "sql_select_limit", "sql_mode", "time_zone", "character_set_results", "session transaction isolation level",
"session transaction read", "session_track_gtids", "sql_auto_is_null"};
const char Variable::proxysql_internal_session_name[SQL_NAME_LAST][64] = {"sql_safe_updates", "sql_select_limit", "sql_mode", "time_zone", "character_set_results", "isolation_level",
"transaction_read", "session_track_gtids", "sql_auto_is_null"};
void Variable::fill_server_internal_session(json &j, int conn_num, int idx) {
j["backends"][conn_num]["conn"][Variable::proxysql_internal_session_name[idx]] = std::string(value);
}
void Variable::fill_client_internal_session(json &j, int idx) {
j["conn"][Variable::proxysql_internal_session_name[idx]] = value;
}
#define PROXYSQL_USE_RESULT
static int
@ -202,6 +215,12 @@ MySQL_Connection::MySQL_Connection() {
fd=-1;
status_flags=0;
last_time_used=0;
for (auto i = 0; i < SQL_NAME_LAST; i++) {
variables[i].value = NULL;
variables[i].hash = 0;
}
options.client_flag = 0;
options.compression_min_length=0;
options.server_version=NULL;
@ -210,45 +229,16 @@ MySQL_Connection::MySQL_Connection() {
options.no_backslash_escapes=false;
options.init_connect=NULL;
options.init_connect_sent=false;
options.character_set_results = NULL;
options.isolation_level = NULL;
options.tx_isolation = NULL;
options.transaction_read = NULL;
options.session_track_gtids = NULL;
options.sql_auto_is_null = NULL;
options.sql_select_limit = NULL;
options.sql_safe_updates = NULL;
options.collation_connection = NULL;
options.net_write_timeout = NULL;
options.max_join_size = NULL;
options.isolation_level_sent = false;
options.tx_isolation_sent = false;
options.transaction_read_sent = false;
options.character_set_results_sent = false;
options.session_track_gtids_sent = false;
options.sql_auto_is_null_sent = false;
options.sql_select_limit_sent = false;
options.sql_safe_updates_sent = false;
options.collation_connection_sent = false;
options.net_write_timeout_sent = false;
options.max_join_size_sent = false;
options.sql_mode_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.sql_mode=NULL; // #509
options.sql_mode_int=0; // #509
options.time_zone=NULL; // #819
options.time_zone_int=0; // #819
options.isolation_level_int=0;
options.tx_isolation_int=0;
options.transaction_read_int=0;
options.character_set_results_int=0;
options.session_track_gtids_int=0;
options.sql_auto_is_null_int=0;
options.sql_select_limit_int=0;
options.sql_safe_updates_int=0;
options.collation_connection_int=0;
options.net_write_timeout_int=0;
options.max_join_size_int=0;
@ -322,46 +312,14 @@ MySQL_Connection::~MySQL_Connection() {
if (query.stmt) {
query.stmt=NULL;
}
if (options.sql_mode) {
free(options.sql_mode);
options.sql_mode=NULL;
}
if (options.time_zone) {
free(options.time_zone);
options.time_zone=NULL;
}
if (options.isolation_level) {
free(options.isolation_level);
options.isolation_level=NULL;
}
if (options.tx_isolation) {
free(options.tx_isolation);
options.tx_isolation=NULL;
}
if (options.transaction_read) {
free(options.transaction_read);
options.transaction_read=NULL;
}
if (options.character_set_results) {
free(options.character_set_results);
options.character_set_results=NULL;
}
if (options.session_track_gtids) {
free(options.session_track_gtids);
options.session_track_gtids=NULL;
}
if (options.sql_auto_is_null) {
free(options.sql_auto_is_null);
options.sql_auto_is_null=NULL;
}
if (options.sql_select_limit) {
free(options.sql_select_limit);
options.sql_select_limit=NULL;
}
if (options.sql_safe_updates) {
free(options.sql_safe_updates);
options.sql_safe_updates=NULL;
for (auto i = 0; i < SQL_NAME_LAST; i++) {
if (variables[i].value) {
free(variables[i].value);
variables[i].value = NULL;
}
}
if (options.collation_connection) {
free(options.collation_connection);
options.collation_connection=NULL;
@ -2187,71 +2145,19 @@ void MySQL_Connection::reset() {
status_flags=0;
reusable=true;
options.last_set_autocommit=-1; // never sent
{ // bug #1160
options.sql_mode_int = 0;
if (options.sql_mode) {
free(options.sql_mode);
options.sql_mode = NULL;
options.sql_mode_sent = false;
}
options.time_zone_int = 0;
if (options.time_zone) {
free(options.time_zone);
options.time_zone = NULL;
}
}
delete local_stmts;
local_stmts=new MySQL_STMTs_local_v14(false);
creation_time = monotonic_time();
options.isolation_level_int = 0;
if (options.isolation_level) {
free (options.isolation_level);
options.isolation_level = NULL;
options.isolation_level_sent = false;
}
options.tx_isolation_int = 0;
if (options.tx_isolation) {
free (options.tx_isolation);
options.tx_isolation = NULL;
options.tx_isolation_sent = false;
}
options.transaction_read_int = 0;
if (options.transaction_read) {
free (options.transaction_read);
options.transaction_read = NULL;
options.transaction_read_sent = false;
}
options.character_set_results_int = 0;
if (options.character_set_results) {
free (options.character_set_results);
options.character_set_results = NULL;
options.character_set_results_sent = false;
}
options.session_track_gtids_int = 0;
if (options.session_track_gtids) {
free (options.session_track_gtids);
options.session_track_gtids = NULL;
options.session_track_gtids_sent = false;
}
options.sql_auto_is_null_int = 0;
if (options.sql_auto_is_null) {
free (options.sql_auto_is_null);
options.sql_auto_is_null = NULL;
options.sql_auto_is_null_sent = false;
}
options.sql_select_limit_int = 0;
if (options.sql_select_limit) {
free (options.sql_select_limit);
options.sql_select_limit = NULL;
options.sql_select_limit_sent = false;
}
options.sql_safe_updates_int = 0;
if (options.sql_safe_updates) {
free (options.sql_safe_updates);
options.sql_safe_updates = NULL;
options.sql_safe_updates_sent = false;
for (auto i = 0; i < SQL_NAME_LAST; i++) {
variables[i].hash = 0;
if (variables[i].value) {
free(variables[i].value);
variables[i].value = NULL;
}
}
options.collation_connection_int = 0;
if (options.collation_connection) {
free (options.collation_connection);

@ -12,6 +12,7 @@ PROXYSQL_PATH=../../..
PROXYSQL_IDIR=$(PROXYSQL_PATH)/include
SQLITE3_DIR=$(DEPS_PATH)/sqlite3/sqlite3
JSON_IDIR=$(DEPS_PATH)/json
RE2_PATH=$(DEPS_PATH)/re2/re2
RE2_IDIR=$(RE2_PATH)
@ -63,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)
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)
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)
@ -74,13 +75,13 @@ all: tests
.PHONY: clean
clean:
rm -f basic-t set_character_set-t charset_unsigned_int-t select_config_file-t sqlite3-t galera_1_timeout_count galera_2_timeout_no_count aurora test_set_character_results-t test_ps_large_result-t test_firewall-t || true
rm -f basic-t set_character_set-t charset_unsigned_int-t select_config_file-t sqlite3-t galera_1_timeout_count galera_2_timeout_no_count aurora test_set_character_results-t test_ps_large_result-t set_testing-t test_firewall-t || true
OPT=-O2
SRC=basic-t.cpp set_character_set-t.cpp charset_unsigned_int-t.cpp select_config_file-t.cpp sqlite3-t.cpp galera_1_timeout_count.cpp galera_2_timeout_no_count.cpp aurora.cpp test_set_character_results-t.cpp test_ps_large_result-t.cpp test_firewall-t.cpp
SRC=basic-t.cpp set_character_set-t.cpp charset_unsigned_int-t.cpp select_config_file-t.cpp sqlite3-t.cpp galera_1_timeout_count.cpp galera_2_timeout_no_count.cpp aurora.cpp test_set_character_results-t.cpp test_ps_large_result-t.cpp set_testing-t.cpp test_firewall-t.cpp
tests: basic-t set_character_set-t charset_unsigned_int-t select_config_file-t sqlite3-t test_set_character_results-t test_ps_large_result-t test_firewall-t
tests: basic-t set_character_set-t charset_unsigned_int-t select_config_file-t sqlite3-t test_set_character_results-t test_ps_large_result-t set_testing-t test_firewall-t
testgalera: galera_1_timeout_count galera_2_timeout_no_count
testaurora: aurora
@ -117,3 +118,5 @@ galera_2_timeout_no_count: galera_2_timeout_no_count.cpp $(TAP_LIBDIR)/libtap.a
aurora: aurora.cpp $(TAP_LIBDIR)/libtap.a
g++ -DTEST_AURORA -DDEBUG aurora.cpp ../tap/SQLite3_Server.cpp $(INCLUDEDIRS) $(LDIRS) $(OPT) -std=c++11 $(OBJ) $(MYLIBS) -ltap -ldl -o aurora -DGITVERSION=\"$(GIT_VERSION)\"
set_testing-t: set_testing-t.cpp $(TAP_LIBDIR)/libtap.a
g++ set_testing-t.cpp -Wall $(INCLUDEDIRS) $(LDIRS) $(OPT) -std=c++11 $(MYLIBS) -ltap -pthread -O0 -ggdb -ldl -lssl -lcrypto -o set_testing-t

@ -0,0 +1,442 @@
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <mysql.h>
#include <string.h>
#include <string>
#include <time.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <sstream>
#include <iostream>
#include <fstream>
#include <mutex>
#include "json.hpp"
#include "tap.h"
#include "command_line.h"
using nlohmann::json;
struct TestCase {
std::string command;
json expected_vars;
};
std::vector<TestCase> testCases;
#define MAX_LINE 1024
int readTestCases(const std::string& fileName) {
FILE* fp = fopen(fileName.c_str(), "r");
if (!fp) return 0;
char buf[MAX_LINE], col1[MAX_LINE], col2[MAX_LINE];
int n = 0;
for(;;) {
if (fgets(buf, sizeof(buf), fp) == NULL) break;
n = sscanf(buf, " \"%[^\"]\", \"%[^\"]\"", col1, col2);
if (n == 0) break;
char *p = col2;
while(*p++) if(*p == '\'') *p = '\"';
json vars = json::parse(col2);
testCases.push_back({col1, vars});
}
fclose(fp);
return 1;
}
unsigned long long monotonic_time() {
struct timespec ts;
//clock_gettime(CLOCK_MONOTONIC_COARSE, &ts); // this is faster, but not precise
clock_gettime(CLOCK_MONOTONIC, &ts);
return (((unsigned long long) ts.tv_sec) * 1000000) + (ts.tv_nsec / 1000);
}
struct cpu_timer
{
cpu_timer() {
begin = monotonic_time();
}
~cpu_timer()
{
unsigned long long end = monotonic_time();
std::cerr << double( end - begin ) / 1000000 << " secs.\n" ;
begin=end-begin;
};
unsigned long long begin;
};
int queries_per_connections=1;
unsigned int num_threads=1;
int count=0;
char *username=NULL;
char *password=NULL;
char *host=(char *)"localhost";
int port=3306;
int multiport=1;
char *schema=(char *)"information_schema";
int silent = 0;
int sysbench = 0;
int local=0;
int queries=0;
int uniquequeries=0;
int histograms=-1;
unsigned int g_connect_OK=0;
unsigned int g_connect_ERR=0;
unsigned int g_select_OK=0;
unsigned int g_select_ERR=0;
unsigned int g_passed=0;
unsigned int g_failed=0;
unsigned int status_connections = 0;
unsigned int connect_phase_completed = 0;
unsigned int query_phase_completed = 0;
__thread int g_seed;
inline int fastrand() {
g_seed = (214013*g_seed+2531011);
return (g_seed>>16)&0x7FFF;
}
void parseResultJsonColumn(MYSQL_RES *result, json& j) {
if(!result) return;
MYSQL_ROW row;
while ((row = mysql_fetch_row(result)))
j = json::parse(row[0]);
}
void parseResult(MYSQL_RES *result, json& j) {
if(!result) return;
MYSQL_ROW row;
while ((row = mysql_fetch_row(result)))
j[row[0]] = row[1];
}
void dumpResult(MYSQL_RES *result) {
if(!result) return;
MYSQL_ROW row;
int num_fields = mysql_num_fields(result);
while ((row = mysql_fetch_row(result)))
{
for(int i = 0; i < num_fields; i++)
{
printf("%s ", row[i] ? row[i] : "NULL");
}
printf("\n");
}
}
void queryVariables(MYSQL *mysql, json& j) {
char *query = (char*)"SELECT * 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');";
if (mysql_query(mysql, query)) {
if (silent==0) {
fprintf(stderr,"%s\n", mysql_error(mysql));
}
} else {
MYSQL_RES *result = mysql_store_result(mysql);
parseResult(result, j);
mysql_free_result(result);
__sync_fetch_and_add(&g_select_OK,1);
}
}
void queryInternalStatus(MYSQL *mysql, json& j) {
char *query = (char*)"PROXYSQL INTERNAL SESSION";
if (mysql_query(mysql, query)) {
if (silent==0) {
fprintf(stderr,"%s\n", mysql_error(mysql));
}
} else {
MYSQL_RES *result = mysql_store_result(mysql);
parseResultJsonColumn(result, j);
mysql_free_result(result);
__sync_fetch_and_add(&g_select_OK,1);
}
// value types in mysql and in proxysql are different
// we should convert proxysql values to mysql format to compare
for (auto& el : j.items()) {
if (el.key() == "conn") {
std::string sql_log_bin_value;
// sql_log_bin {0|1}
if (el.value()["sql_log_bin"] == 1) {
el.value().erase("sql_log_bin");
j["conn"]["sql_log_bin"] = "ON";
}
else if (el.value()["sql_log_bin"] == 0) {
el.value().erase("sql_log_bin");
j["conn"]["sql_log_bin"] = "OFF";
}
// autocommit {true|false}
if (!el.value()["sql_auto_is_null"].dump().compare("ON") ||
!el.value()["sql_auto_is_null"].dump().compare("1") ||
!el.value()["sql_auto_is_null"].dump().compare("on") ||
el.value()["sql_auto_is_null"] == 1) {
el.value().erase("sql_auto_is_null");
j["conn"]["sql_auto_is_null"] = "ON";
}
else if (!el.value()["sql_auto_is_null"].dump().compare("OFF") ||
!el.value()["sql_auto_is_null"].dump().compare("0") ||
!el.value()["sql_auto_is_null"].dump().compare("off") ||
el.value()["sql_auto_is_null"] == 0) {
el.value().erase("sql_auto_is_null");
j["conn"]["sql_auto_is_null"] = "OFF";
}
// autocommit {true|false}
if (!el.value()["autocommit"].dump().compare("ON") ||
!el.value()["autocommit"].dump().compare("1") ||
!el.value()["autocommit"].dump().compare("on") ||
el.value()["autocommit"] == 1) {
el.value().erase("autocommit");
j["conn"]["autocommit"] = "ON";
}
else if (!el.value()["autocommit"].dump().compare("OFF") ||
!el.value()["autocommit"].dump().compare("0") ||
!el.value()["autocommit"].dump().compare("off") ||
el.value()["autocommit"] == 0) {
el.value().erase("autocommit");
j["conn"]["autocommit"] = "OFF";
}
// sql_safe_updates
if (!el.value()["sql_safe_updates"].dump().compare("\"ON\"") ||
!el.value()["sql_safe_updates"].dump().compare("\"1\"") ||
!el.value()["sql_safe_updates"].dump().compare("\"on\"") ||
el.value()["sql_safe_updates"] == 1) {
el.value().erase("sql_safe_updates");
j["conn"]["sql_safe_updates"] = "ON";
}
else if (!el.value()["sql_safe_updates"].dump().compare("\"OFF\"") ||
!el.value()["sql_safe_updates"].dump().compare("\"0\"") ||
!el.value()["sql_safe_updates"].dump().compare("\"off\"") ||
el.value()["sql_safe_updates"] == 0) {
el.value().erase("sql_safe_updates");
j["conn"]["sql_safe_updates"] = "OFF";
}
std::stringstream ss;
ss << 0xFFFFFFFFFFFFFFFF;
// sql_select_limit
if (!el.value()["sql_select_limit"].dump().compare("\"DEFAULT\"")) {
el.value().erase("sql_select_limit");
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";
}
else if (!el.value()["isolation_level"].dump().compare("\"SERIALIZABLE\"")) {
el.value().erase("isolation_level");
j["conn"]["transaction_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";
}
// 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";
}
}
}
}
void * my_conn_thread(void *arg) {
g_seed = time(NULL) ^ getpid() ^ pthread_self();
unsigned int select_OK=0;
unsigned int select_ERR=0;
int i, j;
MYSQL **mysqlconns=(MYSQL **)malloc(sizeof(MYSQL *)*count);
std::vector<json> varsperconn(count);
if (mysqlconns==NULL) {
exit(EXIT_FAILURE);
}
for (i=0; i<count; i++) {
MYSQL *mysql=mysql_init(NULL);
if (mysql==NULL) {
exit(EXIT_FAILURE);
}
MYSQL *rc=mysql_real_connect(mysql, host, username, password, schema, (local ? 0 : ( port + rand()%multiport ) ), NULL, 0);
if (rc==NULL) {
if (silent==0) {
fprintf(stderr,"%s\n", mysql_error(mysql));
}
exit(EXIT_FAILURE);
}
mysqlconns[i]=mysql;
__sync_add_and_fetch(&status_connections,1);
}
__sync_fetch_and_add(&connect_phase_completed,1);
while(__sync_fetch_and_add(&connect_phase_completed,0) != num_threads) {
}
MYSQL *mysql;
json vars;
for (j=0; j<queries; j++) {
int fr = fastrand();
int r1=fr%count;
int r2=fastrand()%testCases.size();
if (j%queries_per_connections==0) {
mysql=mysqlconns[r1];
vars = varsperconn[r1];
}
if (mysql_query(mysql, testCases[r2].command.c_str())) {
if (silent==0) {
fprintf(stderr,"%s\n", mysql_error(mysql));
}
} else {
MYSQL_RES *result = mysql_store_result(mysql);
mysql_free_result(result);
select_OK++;
__sync_fetch_and_add(&g_select_OK,1);
}
for (auto& el : testCases[r2].expected_vars.items()) {
vars[el.key()] = el.value();
}
int sleepDelay = fastrand()%100;
usleep(sleepDelay * 1000);
char query[128];
sprintf(query, "SELECT %d;", sleepDelay);
if (mysql_query(mysql,query)) {
select_ERR++;
__sync_fetch_and_add(&g_select_ERR,1);
} else {
MYSQL_RES *result = mysql_store_result(mysql);
mysql_free_result(result);
select_OK++;
__sync_fetch_and_add(&g_select_OK,1);
}
json mysql_vars;
queryVariables(mysql, mysql_vars);
json proxysql_vars;
queryInternalStatus(mysql, proxysql_vars);
bool testPassed = true;
for (auto& el : vars.items()) {
auto k = mysql_vars.find(el.key());
auto s = proxysql_vars["conn"].find(el.key());
if (k == mysql_vars.end())
fprintf(stderr, "Variable %s->%s in mysql resultset was not found.\nmysql data : %s\nproxysql data: %s\ncsv data %s\n",
el.value().dump().c_str(), el.key().c_str(), mysql_vars.dump().c_str(), proxysql_vars.dump().c_str(), vars.dump().c_str());
if (s == proxysql_vars["conn"].end())
fprintf(stderr, "Variable %s->%s in proxysql resultset was not found.\nmysql data : %s\nproxysql data: %s\ncsv data %s\n",
el.value().dump().c_str(), el.key().c_str(), mysql_vars.dump().c_str(), proxysql_vars.dump().c_str(), vars.dump().c_str());
if (k.value() != el.value() || s.value() != el.value()) {
__sync_fetch_and_add(&g_failed, 1);
testPassed = false;
fprintf(stderr, "Test failed for this case %s->%s.\n\nmysql data %s\n\n proxysql data %s\n\n csv data %s\n\n\n",
el.value().dump().c_str(), el.key().c_str(), mysql_vars.dump().c_str(), proxysql_vars.dump().c_str(), vars.dump().c_str());
}
}
ok(testPassed, "Test passed");
}
__sync_fetch_and_add(&query_phase_completed,1);
return NULL;
}
int main(int argc, char *argv[]) {
CommandLine cl;
std::string fileName("./tests/set_testing-t.csv");
if(cl.getEnv())
return exit_status();
num_threads = 10;
queries = 1000;
queries_per_connections = 10;
count = 10;
username = cl.username;
password = cl.password;
host = cl.host;
port = cl.port;
plan(queries * num_threads);
if (!readTestCases(fileName)) {
fprintf(stderr, "Cannot read %s\n", fileName.c_str());
return exit_status();
}
if (strcmp(host,"localhost")==0) {
local = 1;
}
if (uniquequeries == 0) {
if (queries) uniquequeries=queries;
}
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)
return exit_status();
for (unsigned int i=0; i<num_threads; i++) {
if ( pthread_create(&thi[i], NULL, my_conn_thread , NULL) != 0 )
perror("Thread creation");
}
for (unsigned int i=0; i<num_threads; i++) {
pthread_join(thi[i], NULL);
}
return exit_status();
}

@ -0,0 +1,29 @@
"set sql_mode=''","{'sql_mode':''}"
"SET sql_mode='PIPES_AS_CONCAT,NO_ENGINE_SUBSTITUTION'", "{'sql_mode':'PIPES_AS_CONCAT,NO_ENGINE_SUBSTITUTION'}"
"SET sql_log_bin=0", "{'sql_log_bin':'OFF'}"
"SET sql_log_bin=1", "{'sql_log_bin':'ON'}"
"SET time_zone='+01:00'","{'time_zone':'+01:00'}"
"SET time_zone='-03:00', sql_mode='ALLOW_INVALID_DATES'","{'time_zone':'-03:00', 'sql_mode':'ALLOW_INVALID_DATES'}"
"SET autocommit=0","{'autocommit':'OFF'}"
"SET time_zone='+04:00', sql_mode='NO_ENGINE_SUBSTITUTION'", "{'time_zone':'+04:00','sql_mode':'NO_ENGINE_SUBSTITUTION'}"
"SET sql_safe_updates=0", "{'sql_safe_updates':'OFF'}"
"SET sql_safe_updates=1", "{'sql_safe_updates':'ON'}"
"SET sql_select_limit=1010", "{'sql_select_limit':'1010'}"
"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 session transaction read only", "{'transaction_read_only':'ON'}"
"SET session transaction read write", "{'transaction_read_only':'OFF'}"
"SET session transaction isolation level READ COMMITTED", "{'transaction_isolation':'READ-COMMITTED'}"
"SET session transaction isolation level READ UNCOMMITTED", "{'transaction_isolation':'READ-UNCOMMITTED'}"
"SET session transaction isolation level REPEATABLE READ", "{'transaction_isolation':'REPEATABLE-READ'}"
"SET session transaction isolation level SERIALIZABLE", "{'transaction_isolation':'SERIALIZABLE'}"
"SET tx_isolation='READ-COMMITTED'", "{'transaction_isolation':'READ-COMMITTED'}"
"SET tx_isolation='READ-UNCOMMITTED'", "{'transaction_isolation':'READ-UNCOMMITTED'}"
"SET tx_isolation='REPEATABLE-READ'", "{'transaction_isolation':'REPEATABLE-READ'}"
"SET tx_isolation='SERIALIZABLE'", "{'transaction_isolation':'SERIALIZABLE'}"
"SET session_track_gtids=OFF", "{'session_track_gtids':'OFF'}"
"SET session_track_gtids=OWN_GTID", "{'session_track_gtids':'OWN_GTID'}"
"SET sql_auto_is_null=OFF", "{'sql_auto_is_null':'OFF'}"
"SET sql_auto_is_null=ON", "{'sql_auto_is_null':'ON'}"
1 set sql_mode='' {'sql_mode':''}
2 SET sql_mode='PIPES_AS_CONCAT,NO_ENGINE_SUBSTITUTION' {'sql_mode':'PIPES_AS_CONCAT,NO_ENGINE_SUBSTITUTION'}
3 SET sql_log_bin=0 {'sql_log_bin':'OFF'}
4 SET sql_log_bin=1 {'sql_log_bin':'ON'}
5 SET time_zone='+01:00' {'time_zone':'+01:00'}
6 SET time_zone='-03:00', sql_mode='ALLOW_INVALID_DATES' {'time_zone':'-03:00', 'sql_mode':'ALLOW_INVALID_DATES'}
7 SET autocommit=0 {'autocommit':'OFF'}
8 SET time_zone='+04:00', sql_mode='NO_ENGINE_SUBSTITUTION' {'time_zone':'+04:00','sql_mode':'NO_ENGINE_SUBSTITUTION'}
9 SET sql_safe_updates=0 {'sql_safe_updates':'OFF'}
10 SET sql_safe_updates=1 {'sql_safe_updates':'ON'}
11 SET sql_select_limit=1010 {'sql_select_limit':'1010'}
12 SET character_set_results='latin1' {'character_set_results':'latin1'}
13 SET character_set_results='utf8' {'character_set_results':'utf8'}
14 SET character_set_results='utf8mb4' {'character_set_results':'utf8mb4'}
15 SET session transaction read only {'transaction_read_only':'ON'}
16 SET session transaction read write {'transaction_read_only':'OFF'}
17 SET session transaction isolation level READ COMMITTED {'transaction_isolation':'READ-COMMITTED'}
18 SET session transaction isolation level READ UNCOMMITTED {'transaction_isolation':'READ-UNCOMMITTED'}
19 SET session transaction isolation level REPEATABLE READ {'transaction_isolation':'REPEATABLE-READ'}
20 SET session transaction isolation level SERIALIZABLE {'transaction_isolation':'SERIALIZABLE'}
21 SET tx_isolation='READ-COMMITTED' {'transaction_isolation':'READ-COMMITTED'}
22 SET tx_isolation='READ-UNCOMMITTED' {'transaction_isolation':'READ-UNCOMMITTED'}
23 SET tx_isolation='REPEATABLE-READ' {'transaction_isolation':'REPEATABLE-READ'}
24 SET tx_isolation='SERIALIZABLE' {'transaction_isolation':'SERIALIZABLE'}
25 SET session_track_gtids=OFF {'session_track_gtids':'OFF'}
26 SET session_track_gtids=OWN_GTID {'session_track_gtids':'OWN_GTID'}
27 SET sql_auto_is_null=OFF {'sql_auto_is_null':'OFF'}
28 SET sql_auto_is_null=ON {'sql_auto_is_null':'ON'}
Loading…
Cancel
Save