Skip to content

Commit

Permalink
Merge pull request #4427 from sysown/v2.x-4396
Browse files Browse the repository at this point in the history
Handle STATUS command without backends
  • Loading branch information
renecannao authored Jan 19, 2024
2 parents 26738b4 + e958946 commit acf2b7b
Showing 3 changed files with 80 additions and 1 deletion.
1 change: 1 addition & 0 deletions include/MySQL_Session.h
Original file line number Diff line number Diff line change
@@ -133,6 +133,7 @@ class MySQL_Session

void return_proxysql_internal(PtrSize_t *);
bool handler_special_queries(PtrSize_t *);
bool handler_special_queries_STATUS(PtrSize_t *);
/**
* @brief Handles 'COMMIT|ROLLBACK' commands.
* @details Forwarding the packet is required when there are active transactions. Since we are limited to
1 change: 1 addition & 0 deletions include/sqlite3db.h
Original file line number Diff line number Diff line change
@@ -155,6 +155,7 @@ class SQLite3_result {
void add_column_definition(int a, const char *b);
int add_row(sqlite3_stmt *stmt, bool skip=false);
int add_row(char **_fields);
int add_row(const char **_fields) { return add_row((char **)_fields); }
int add_row(SQLite3_row *old_row);
int add_row(const char* _field, ...);
SQLite3_result(sqlite3_stmt *stmt);
79 changes: 78 additions & 1 deletion lib/MySQL_Session.cpp
Original file line number Diff line number Diff line change
@@ -25,7 +25,10 @@

#define SELECT_VERSION_COMMENT "select @@version_comment limit 1"
#define SELECT_VERSION_COMMENT_LEN 32

#define SELECT_DB_USER "select DATABASE(), USER() limit 1"
#define SELECT_DB_USER_LEN 33
#define SELECT_CHARSET_STATUS "select @@character_set_client, @@character_set_connection, @@character_set_server, @@character_set_database limit 1"
#define SELECT_CHARSET_STATUS_LEN 115
#define PROXYSQL_VERSION_COMMENT "\x01\x00\x00\x01\x01\x27\x00\x00\x02\x03\x64\x65\x66\x00\x00\x00\x11\x40\x40\x76\x65\x72\x73\x69\x6f\x6e\x5f\x63\x6f\x6d\x6d\x65\x6e\x74\x00\x0c\x21\x00\x18\x00\x00\x00\xfd\x00\x00\x1f\x00\x00\x05\x00\x00\x03\xfe\x00\x00\x02\x00\x0b\x00\x00\x04\x0a(ProxySQL)\x05\x00\x00\x05\xfe\x00\x00\x02\x00"
#define PROXYSQL_VERSION_COMMENT_LEN 81

@@ -1320,9 +1323,83 @@ void MySQL_Session::return_proxysql_internal(PtrSize_t *pkt) {
l_free(pkt->size,pkt->ptr);
}

/**
* @brief Handles special queries executed by the STATUS command in mysql cli .
* Specifically:
* "select DATABASE(), USER() limit 1"
* "select @@character_set_client, @@character_set_connection, @@character_set_server, @@character_set_database limit 1"
* See Github issues 4396 and 4426
*
* @param PtrSize_t The packet from the client
*
* @return True if the queries are handled
*/
bool MySQL_Session::handler_special_queries_STATUS(PtrSize_t *pkt) {
if (pkt->size == (SELECT_DB_USER_LEN+5)) {
if (strncasecmp(SELECT_DB_USER,(char *)pkt->ptr+5, SELECT_DB_USER_LEN)==0) {
SQLite3_result *resultset = new SQLite3_result(2);
resultset->add_column_definition(SQLITE_TEXT,"DATABASE()");
resultset->add_column_definition(SQLITE_TEXT,"USER()");
char *pta[2];
pta[0] = client_myds->myconn->userinfo->username;
pta[1] = client_myds->myconn->userinfo->schemaname;
resultset->add_row(pta);
bool deprecate_eof_active = client_myds->myconn->options.client_flag & CLIENT_DEPRECATE_EOF;
SQLite3_to_MySQL(resultset, NULL, 0, &client_myds->myprot, false, deprecate_eof_active);
delete resultset;
l_free(pkt->size,pkt->ptr);
return true;
}
}
if (pkt->size == (SELECT_CHARSET_STATUS_LEN+5)) {
if (strncasecmp(SELECT_CHARSET_STATUS,(char *)pkt->ptr+5, SELECT_CHARSET_STATUS_LEN)==0) {
SQLite3_result *resultset = new SQLite3_result(4);
resultset->add_column_definition(SQLITE_TEXT,"@@character_set_client");
resultset->add_column_definition(SQLITE_TEXT,"@@character_set_connection");
resultset->add_column_definition(SQLITE_TEXT,"@@character_set_server");
resultset->add_column_definition(SQLITE_TEXT,"@@character_set_database");

string vals[4];
json j = {};
MySQL_Connection *conn = client_myds->myconn;
// here we do a bit back and forth to and from JSON to reuse existing code instead of writing new code.
// This is not great for performance, but this query is rarely executed.
conn->variables[SQL_CHARACTER_SET_CLIENT].fill_client_internal_session(j, SQL_CHARACTER_SET_CLIENT);
conn->variables[SQL_CHARACTER_SET_CONNECTION].fill_client_internal_session(j, SQL_CHARACTER_SET_CONNECTION);
conn->variables[SQL_CHARACTER_SET_DATABASE].fill_client_internal_session(j, SQL_CHARACTER_SET_DATABASE);

vals[0] = j["conn"][mysql_tracked_variables[SQL_CHARACTER_SET_CLIENT].internal_variable_name];
vals[1] = j["conn"][mysql_tracked_variables[SQL_CHARACTER_SET_CONNECTION].internal_variable_name];
vals[2] = string(mysql_thread___default_variables[SQL_CHARACTER_SET]);
vals[3] = j["conn"][mysql_tracked_variables[SQL_CHARACTER_SET_DATABASE].internal_variable_name];

const char *pta[4];
for (int i=0; i<4; i++) {
pta[i] = vals[i].c_str();
}
resultset->add_row(pta);
bool deprecate_eof_active = client_myds->myconn->options.client_flag & CLIENT_DEPRECATE_EOF;
SQLite3_to_MySQL(resultset, NULL, 0, &client_myds->myprot, false, deprecate_eof_active);
delete resultset;
l_free(pkt->size,pkt->ptr);
return true;
}
}
return false;
}

bool MySQL_Session::handler_special_queries(PtrSize_t *pkt) {
bool deprecate_eof_active = client_myds->myconn->options.client_flag & CLIENT_DEPRECATE_EOF;

if (
(pkt->size == (SELECT_DB_USER_LEN+5))
||
(pkt->size == (SELECT_CHARSET_STATUS_LEN+5))
) {
if (handler_special_queries_STATUS(pkt) == true) {
return true;
}
}
if (pkt->size>(5+18) && strncasecmp((char *)"PROXYSQL INTERNAL ",(char *)pkt->ptr+5,18)==0) {
return_proxysql_internal(pkt);
return true;

0 comments on commit acf2b7b

Please sign in to comment.