diff --git a/include/MySQL_Session.h b/include/MySQL_Session.h index 4d3b4e146..073a60fbe 100644 --- a/include/MySQL_Session.h +++ b/include/MySQL_Session.h @@ -114,6 +114,9 @@ class MySQL_Session 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_character_set_results(); + bool handler_again___verify_backend_session_track_gtids(); 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 *); diff --git a/include/proxysql_structs.h b/include/proxysql_structs.h index 10e59034d..8c77bfa96 100644 --- a/include/proxysql_structs.h +++ b/include/proxysql_structs.h @@ -152,6 +152,9 @@ enum session_status { SETTING_SQL_LOG_BIN, SETTING_SQL_MODE, SETTING_TIME_ZONE, + SETTING_ISOLATION_LEVEL, + SETTING_CHARACTER_SET_RESULTS, + SETTING_SESSION_TRACK_GTIDS, FAST_FORWARD, PROCESSING_STMT_PREPARE, PROCESSING_STMT_EXECUTE, diff --git a/lib/MySQL_Session.cpp b/lib/MySQL_Session.cpp index 790c0cf3d..c365d73b4 100644 --- a/lib/MySQL_Session.cpp +++ b/lib/MySQL_Session.cpp @@ -1649,6 +1649,134 @@ bool MySQL_Session::handler_again___verify_backend_time_zone() { return false; } +bool MySQL_Session::handler_again___verify_backend_isolation_level() { + if (mybe->server_myds->myconn->options.isolation_level_int==0) { + // it is the first time we use this backend. Set isolation_level to default + if (mybe->server_myds->myconn->options.isolation_level) { + free(mybe->server_myds->myconn->options.isolation_level); + mybe->server_myds->myconn->options.isolation_level=NULL; + } + mybe->server_myds->myconn->options.isolation_level=strdup(mysql_thread___default_isolation_level); + uint32_t isolation_level_int=SpookyHash::Hash32(mybe->server_myds->myconn->options.isolation_level,strlen(mybe->server_myds->myconn->options.isolation_level),10); + mybe->server_myds->myconn->options.isolation_level_int=isolation_level_int; + } + if (client_myds->myconn->options.isolation_level_int) { + if (client_myds->myconn->options.isolation_level_int != mybe->server_myds->myconn->options.isolation_level_int) { + { + mybe->server_myds->myconn->options.isolation_level_int = client_myds->myconn->options.isolation_level_int; + if (mybe->server_myds->myconn->options.isolation_level) { + free(mybe->server_myds->myconn->options.isolation_level); + mybe->server_myds->myconn->options.isolation_level=NULL; + if (client_myds->myconn->options.isolation_level) { + mybe->server_myds->myconn->options.isolation_level=strdup(client_myds->myconn->options.isolation_level); + } + } + } + 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_ISOLATION_LEVEL); + } + } + return false; +} + +bool MySQL_Session::handler_again___verify_backend_character_set_results() { + if (mybe->server_myds->myconn->options.character_set_results_int==0) { + // it is the first time we use this backend. Set character_set_results to default + if (mybe->server_myds->myconn->options.character_set_results) { + free(mybe->server_myds->myconn->options.character_set_results); + mybe->server_myds->myconn->options.character_set_results=NULL; + } + mybe->server_myds->myconn->options.character_set_results=strdup(mysql_thread___default_character_set_results); + uint32_t character_set_results_int=SpookyHash::Hash32(mybe->server_myds->myconn->options.character_set_results,strlen(mybe->server_myds->myconn->options.character_set_results),10); + mybe->server_myds->myconn->options.character_set_results_int=character_set_results_int; + } + if (client_myds->myconn->options.character_set_results_int) { + if (client_myds->myconn->options.character_set_results_int != mybe->server_myds->myconn->options.character_set_results_int) { + { + mybe->server_myds->myconn->options.character_set_results_int = client_myds->myconn->options.character_set_results_int; + if (mybe->server_myds->myconn->options.character_set_results) { + free(mybe->server_myds->myconn->options.character_set_results); + mybe->server_myds->myconn->options.character_set_results=NULL; + if (client_myds->myconn->options.character_set_results) { + mybe->server_myds->myconn->options.character_set_results=strdup(client_myds->myconn->options.character_set_results); + } + } + } + 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_CHARACTER_SET_RESULTS); + } + } + return false; +} + +bool MySQL_Session::handler_again___verify_backend_session_track_gtids() { + if (mybe->server_myds->myconn->options.session_track_gtids_int==0) { + // it is the first time we use this backend. Set session_track_gtids to default + if (mybe->server_myds->myconn->options.session_track_gtids) { + free(mybe->server_myds->myconn->options.session_track_gtids); + mybe->server_myds->myconn->options.session_track_gtids=NULL; + } + mybe->server_myds->myconn->options.session_track_gtids=strdup(mysql_thread___default_session_track_gtids); + uint32_t session_track_gtids_int=SpookyHash::Hash32(mybe->server_myds->myconn->options.session_track_gtids,strlen(mybe->server_myds->myconn->options.session_track_gtids),10); + mybe->server_myds->myconn->options.session_track_gtids_int=session_track_gtids_int; + } + if (client_myds->myconn->options.session_track_gtids_int) { + if (client_myds->myconn->options.session_track_gtids_int != mybe->server_myds->myconn->options.session_track_gtids_int) { + { + mybe->server_myds->myconn->options.session_track_gtids_int = client_myds->myconn->options.session_track_gtids_int; + if (mybe->server_myds->myconn->options.session_track_gtids) { + free(mybe->server_myds->myconn->options.session_track_gtids); + mybe->server_myds->myconn->options.session_track_gtids=NULL; + if (client_myds->myconn->options.session_track_gtids) { + mybe->server_myds->myconn->options.session_track_gtids=strdup(client_myds->myconn->options.session_track_gtids); + } + } + } + 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_SESSION_TRACK_GTIDS); + } + } + return false; +} bool MySQL_Session::handler_again___verify_init_connect() { if (mybe->server_myds->myconn->options.init_connect_sent==false) { diff --git a/lib/MySQL_Thread.cpp b/lib/MySQL_Thread.cpp index 922d78dc9..9cd64b7c4 100644 --- a/lib/MySQL_Thread.cpp +++ b/lib/MySQL_Thread.cpp @@ -2146,6 +2146,45 @@ bool MySQL_Threads_Handler::set_variable(char *name, char *value) { // this is t return true; } + if (!strcasecmp(name,"default_isolation_level")) { + if (variables.default_isolation_level) free(variables.default_isolation_level); + variables.default_isolation_level=NULL; + if (vallen) { + if (strcmp(value,"(null)")) + variables.default_isolation_level=strdup(value); + } + if (variables.default_isolation_level==NULL) { + variables.default_isolation_level=strdup((char *)MYSQL_DEFAULT_ISOLATION_LEVEL); // default + } + return true; + } + + if (!strcasecmp(name,"default_character_set_results")) { + if (variables.default_character_set_results) free(variables.default_character_set_results); + variables.default_character_set_results=NULL; + if (vallen) { + if (strcmp(value,"(null)")) + variables.default_character_set_results=strdup(value); + } + if (variables.default_character_set_results==NULL) { + variables.default_character_set_results=strdup((char *)MYSQL_DEFAULT_CHARACTER_SET_RESULTS); // default + } + return true; + } + + if (!strcasecmp(name,"default_session_track_gtids")) { + if (variables.default_session_track_gtids) free(variables.default_session_track_gtids); + variables.default_session_track_gtids=NULL; + if (vallen) { + if (strcmp(value,"(null)")) + variables.default_session_track_gtids=strdup(value); + } + if (variables.default_session_track_gtids==NULL) { + variables.default_session_track_gtids=strdup((char *)MYSQL_DEFAULT_SESSION_TRACK_GTIDS); // default + } + return true; + } + if (!strcasecmp(name,"keep_multiplexing_variables")) { if (vallen) { free(variables.keep_multiplexing_variables); @@ -2935,6 +2974,28 @@ MySQL_Session * MySQL_Thread::create_new_session_and_client_data_stream(int _fd) 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 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); + return sess; }