diff --git a/include/proxysql_structs.h b/include/proxysql_structs.h index 9b53a2e3a..396275122 100644 --- a/include/proxysql_structs.h +++ b/include/proxysql_structs.h @@ -143,6 +143,7 @@ enum session_status { PROCESSING_QUERY, CHANGING_SCHEMA, CHANGING_CHARSET, + SETTING_CHARSET, CHANGING_AUTOCOMMIT, CHANGING_USER_CLIENT, CHANGING_USER_SERVER, diff --git a/lib/MySQL_Session.cpp b/lib/MySQL_Session.cpp index d0727a742..1059acc3c 100644 --- a/lib/MySQL_Session.cpp +++ b/lib/MySQL_Session.cpp @@ -1564,7 +1564,7 @@ void MySQL_Session::handler_again___new_thread_to_kill_connection() { bool MySQL_Session::handler_again___verify_backend_charset() { proxy_debug(PROXY_DEBUG_MYSQL_CONNECTION, 5, "Session %p , client charset: %d , backend charset: %d\n", this, client_myds->myconn->options.charset, mybe->server_myds->myconn->mysql->charset->nr); - if (client_myds->myconn->options.charset != mybe->server_myds->myconn->mysql->charset->nr) { + if (client_myds->myconn->options.charset != mybe->server_myds->myconn->mysql->charset->nr || client_myds->myconn->options.charset_action != mybe->server_myds->myconn->options.charset_action) { //previous_status.push(PROCESSING_QUERY); switch(status) { // this switch can be replaced with a simple previous_status.push(status), but it is here for readibility case PROCESSING_QUERY: @@ -1580,7 +1580,13 @@ bool MySQL_Session::handler_again___verify_backend_charset() { assert(0); break; } - NEXT_IMMEDIATE_NEW(CHANGING_CHARSET); + if (client_myds->myconn->options.charset_action == NAMES) { + NEXT_IMMEDIATE_NEW(CHANGING_CHARSET); + } else if (client_myds->myconn->options.charset_action == CHARSET) { + NEXT_IMMEDIATE_NEW(SETTING_CHARSET); + } else { + assert(0); + } } return false; } @@ -2528,8 +2534,8 @@ bool MySQL_Session::handler_again___status_SETTING_ISOLATION_LEVEL(int *_rc) { bool MySQL_Session::handler_again___status_SETTING_CHARSET(int *_rc) { bool ret=false; assert(mybe->server_myds->myconn); - - const MARIADB_CHARSET_INFO * c = proxysql_find_charset_nr(mybe->server_myds->myconn->options.charset); + mybe->server_myds->myconn->set_charset(client_myds->myconn->options.charset, CHARSET); + const MARIADB_CHARSET_INFO * c = proxysql_find_charset_nr(client_myds->myconn->options.charset); ret = handler_again___status_SETTING_GENERIC_VARIABLE(_rc, (char *)"CHARSET", (char*)c->csname, false, true); return ret; } @@ -2901,7 +2907,7 @@ bool MySQL_Session::handler_again___status_CHANGING_CHARSET(int *_rc) { MySQL_Connection *myconn=myds->myconn; myds->DSS=STATE_MARIADB_QUERY; enum session_status st=status; - if (myconn->options.charset_action == NAMES) { + if (client_myds->myconn->options.charset_action == NAMES) { if (myds->mypolls==NULL) { thread->mypolls.add(POLLIN|POLLOUT, mybe->server_myds->fd, mybe->server_myds, thread->curtime); } @@ -2953,8 +2959,7 @@ bool MySQL_Session::handler_again___status_CHANGING_CHARSET(int *_rc) { // rc==1 , nothing to do for now } } - } else if (myconn->options.charset_action == CHARSET) { - handler_again___status_SETTING_CHARSET(_rc); + } else if (client_myds->myconn->options.charset_action == CHARSET) { myds->DSS = STATE_MARIADB_GENERIC; st=previous_status.top(); previous_status.pop(); @@ -4380,6 +4385,17 @@ handler_again: } } break; + case SETTING_CHARSET: + { + int rc=0; + if (handler_again___status_SETTING_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_SQL_LOG_BIN: { @@ -6002,6 +6018,19 @@ bool MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C client_myds->myconn->set_charset(c->nr, CHARSET); exit_after_SetParse = true; } + if (exit_after_SetParse) { + if (command_type == _MYSQL_COM_QUERY) { + client_myds->DSS=STATE_QUERY_SENT_NET; + uint16_t setStatus = (nTrx ? SERVER_STATUS_IN_TRANS : 0 ); + if (autocommit) setStatus |= SERVER_STATUS_AUTOCOMMIT; + client_myds->myprot.generate_pkt_OK(true,NULL,NULL,1,0,0,setStatus,0,NULL); + client_myds->DSS=STATE_SLEEP; + status=WAITING_CLIENT_DATA; + RequestEnd(NULL); + l_free(pkt->size,pkt->ptr); + return true; + } + } } else { unable_to_parse_set_statement(lock_hostgroup); return false;