diff --git a/include/MySQL_Session.h b/include/MySQL_Session.h index 021629c83..1dfcc48d9 100644 --- a/include/MySQL_Session.h +++ b/include/MySQL_Session.h @@ -79,7 +79,18 @@ class MySQL_Session void handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_COM_FIELD_LIST(PtrSize_t *); void handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_COM_INIT_DB(PtrSize_t *); - void handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_COM_QUERY_USE_DB(PtrSize_t *); + /** + * @brief Handles 'COM_QUERIES' holding 'USE DB' statements. + * + * @param pkt The packet being processed. + * @param query_digest The query digest returned by the 'QueryProcessor' + * holding the 'USE' statement without the initial comment. + * + * @details NOTE: This function used to be called from 'handler_special_queries'. + * But since it was change for handling 'USE' statements which are preceded by + * comments, it's called after 'QueryProcessor' has processed the query. + */ + void handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_COM_QUERY_USE_DB(PtrSize_t *pkt, const char* query_digest); void handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_COM_PING(PtrSize_t *); void handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_COM_CHANGE_USER(PtrSize_t *, bool *); diff --git a/lib/MySQL_Session.cpp b/lib/MySQL_Session.cpp index d8d9594c8..887d53437 100644 --- a/lib/MySQL_Session.cpp +++ b/lib/MySQL_Session.cpp @@ -1135,12 +1135,6 @@ bool MySQL_Session::handler_special_queries(PtrSize_t *pkt) { } } - if (session_type != PROXYSQL_SESSION_CLICKHOUSE) { - if (pkt->size>(5+4) && strncasecmp((char *)"USE ",(char *)pkt->ptr+5,4)==0) { - handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_COM_QUERY_USE_DB(pkt); - return true; - } - } if (pkt->size==SELECT_VERSION_COMMENT_LEN+5 && strncmp((char *)SELECT_VERSION_COMMENT,(char *)pkt->ptr+5,pkt->size-5)==0) { // FIXME: this doesn't return AUTOCOMMIT or IN_TRANS PtrSize_t pkt_2; @@ -3593,6 +3587,23 @@ __get_pkts_from_client: clock_gettime(CLOCK_THREAD_CPUTIME_ID,&begint); } qpo=GloQPro->process_mysql_query(this,pkt.ptr,pkt.size,&CurrentQuery); + // This block was moved from 'handler_special_queries' to support + // handling of 'USE' statements which are preceded by a comment. + // For more context check issue: #3493. + // =================================================== + if (session_type != PROXYSQL_SESSION_CLICKHOUSE) { + if (strncasecmp((char *)"USE ",CurrentQuery.get_digest_text(),4)==0) { + handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_COM_QUERY_USE_DB(&pkt, CurrentQuery.get_digest_text()); + + if (mirror == false) { + break; + } else { + handler_ret = -1; + return handler_ret; + } + } + } + // =================================================== if (qpo->max_lag_ms >= 0) { thread->status_variables.stvar[st_var_queries_with_max_lag_ms]++; } @@ -5219,12 +5230,12 @@ void MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C // this function was introduced due to isseu #718 // some application (like the one written in Perl) do not use COM_INIT_DB , but COM_QUERY with USE dbname -void MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_COM_QUERY_USE_DB(PtrSize_t *pkt) { +void MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_COM_QUERY_USE_DB(PtrSize_t *pkt, const char* query_digest) { gtid_hid=-1; proxy_debug(PROXY_DEBUG_MYSQL_COM, 5, "Got COM_QUERY with USE dbname\n"); if (session_type == PROXYSQL_SESSION_MYSQL) { __sync_fetch_and_add(&MyHGM->status.frontend_use_db, 1); - char *schemaname=strndup((char *)pkt->ptr+sizeof(mysql_hdr)+5,pkt->size-sizeof(mysql_hdr)-5); + char *schemaname=strndup(query_digest+4,strlen(query_digest)-4); char *schemanameptr=trim_spaces_and_quotes_in_place(schemaname); // handle cases like "USE `schemaname` if(schemanameptr[0]=='`' && schemanameptr[strlen(schemanameptr)-1]=='`') {