Skip to content

Commit

Permalink
Merge pull request #4629 from sysown/v2.x-4628
Browse files Browse the repository at this point in the history
Removing trailing semicolon from `USE` #4628
  • Loading branch information
renecannao committed Aug 29, 2024
2 parents 5d2c1ba + c76dda6 commit bd7bd35
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 14 deletions.
2 changes: 1 addition & 1 deletion include/set_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class SetParser {
// First implemenation of the parser for TRANSACTION ISOLATION LEVEL and TRANSACTION READ/WRITE
std::map<std::string, std::vector<std::string>> parse2();
std::string parse_character_set();
std::string parse_USE_query();
std::string parse_USE_query(std::string& errmsg);
std::string remove_comments(const std::string& q);
#ifdef DEBUG
// built-in testing
Expand Down
11 changes: 9 additions & 2 deletions lib/MySQL_Session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6139,7 +6139,8 @@ void MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C
__sync_fetch_and_add(&MyHGM->status.frontend_use_db, 1);
string nq=string((char *)pkt->ptr+sizeof(mysql_hdr)+1,pkt->size-sizeof(mysql_hdr)-1);
SetParser parser(nq);
string schemaname = parser.parse_USE_query();
string errmsg = "";
string schemaname = parser.parse_USE_query(errmsg);
if (schemaname != "") {
client_myds->myconn->userinfo->set_schemaname((char *)schemaname.c_str(),schemaname.length());
if (mirror==false) {
Expand All @@ -6156,6 +6157,9 @@ void MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C
l_free(pkt->size,pkt->ptr);
client_myds->setDSS_STATE_QUERY_SENT_NET();
std::string msg = "Unable to parse: " + nq;
if (errmsg != "") {
msg = errmsg + ": " + nq;
}
client_myds->myprot.generate_pkt_ERR(true,NULL,NULL,client_myds->pkt_sid+1,1148,(char *)"42000", msg.c_str());
RequestEnd(NULL);
}
Expand Down Expand Up @@ -6475,7 +6479,10 @@ bool MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C
RE2::GlobalReplace(&nq,(char *)"^/\\*!\\d\\d\\d\\d\\d SET(.*)\\*/",(char *)"SET\\1");
RE2::GlobalReplace(&nq,(char *)"(?U)/\\*.*\\*/",(char *)"");
// remove trailing space and semicolon if present. See issue#4380
nq.erase(nq.find_last_not_of(" ;") + 1);
size_t pos = nq.find_last_not_of(" ;");
if (pos != nq.npos) {
nq.erase(pos + 1); // remove trailing spaces and semicolumns
}
/*
// we do not threat SET SQL_LOG_BIN as a special case
if (match_regexes && match_regexes[0]->match(dig)) {
Expand Down
43 changes: 32 additions & 11 deletions lib/set_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

using namespace std;

#define MULTI_STATEMENTS_USE "Unable to parse multi-statements command with USE statement"

static void remove_quotes(string& v) {
if (v.length() > 2) {
Expand Down Expand Up @@ -118,7 +119,10 @@ VALGRIND_ENABLE_ERROR_REPORTING;
} else if (strcasecmp("transaction_read_only", value4.c_str()) == 0) {
value4 = "tx_read_only";
}
value5.erase(value5.find_last_not_of(" \n\r\t,")+1);
size_t pos = value5.find_last_not_of(" \n\r\t,");
if (pos != value5.npos) {
value5.erase(pos+1);
}
key = value4;
if (value5 == "''" || value5 == "\"\"") {
op.push_back("");
Expand Down Expand Up @@ -404,7 +408,10 @@ VALGRIND_ENABLE_ERROR_REPORTING;
} else if (strcasecmp("transaction_read_only", value4.c_str()) == 0) {
value4 = "tx_read_only";
}
value5.erase(value5.find_last_not_of(" \n\r\t,")+1);
size_t pos = value5.find_last_not_of(" \n\r\t,");
if (pos != value5.npos) {
value5.erase(pos+1);
}
key = value4;
if (value5 == "''" || value5 == "\"\"") {
op.push_back("");
Expand Down Expand Up @@ -508,7 +515,7 @@ std::string SetParser::parse_character_set() {
return value4;
}

std::string SetParser::parse_USE_query() {
std::string SetParser::parse_USE_query(std::string& errmsg) {
#ifdef DEBUG
proxy_debug(PROXY_DEBUG_MYSQL_QUERY_PROCESSOR, 4, "Parsing query %s\n", query.c_str());
#endif // DEBUG
Expand All @@ -518,6 +525,10 @@ std::string SetParser::parse_USE_query() {
opt2.set_longest_match(false);

std::string dbname = remove_comments(query);
size_t pos = dbname.find_last_not_of(" ;");
if (pos != dbname.npos) {
dbname.erase(pos + 1); // remove trailing spaces and semicolumns
}
re2::RE2 re0("^\\s*", opt2);
re2::RE2::Replace(&dbname, re0, "");
if (dbname.size() >= 4) {
Expand All @@ -537,18 +548,22 @@ std::string SetParser::parse_USE_query() {
dbname.erase(0, 1);
// Remove the last character
dbname.erase(dbname.length() - 1);
return dbname;
}
}
} else {
return dbname;
}
} else {
dbname = "";
}
} else {
return "";
dbname = "";
}

return "";
if (dbname.find_first_of(';') != std::string::npos) {
errmsg = MULTI_STATEMENTS_USE;
dbname = "";
}

return dbname;
}


Expand Down Expand Up @@ -638,18 +653,24 @@ void SetParser::test_parse_USE_query() {
{"USE/*+ placeholder_comment */`test_use_comment-5`", "test_use_comment-5"},
{"/* comment */USE`test_use_comment-6`", "test_use_comment-6"},
{"USE`test_use_comment-7`", "test_use_comment-7"},
{"USE test_use_comment-7 ;", "test_use_comment-7"},
{"USE`test_use_comment-2` ; ", "test_use_comment-2"},
{"USE`test_use_comment-2` ; -- comment", "test_use_comment-2"},
{"USE test_use_comment-7 /* comment */ ; ", "test_use_comment-7"},
{"USE /* comment */ test_use_comment-7 ; ", "test_use_comment-7"},
{"USE dbame ; SELECT 1", ""},
};

// Run tests for each pair
for (const auto& p : testCases) {
set_query(p.first);
std::string dbname = parse_USE_query();
std::string errmsg = "";
std::string dbname = parse_USE_query(errmsg);
if (dbname != p.second) {
// we call parse_USE_query() again just to make it easier to create a breakpoint
std::string s = parse_USE_query();
std::string s = parse_USE_query(errmsg);
assert(s == p.second);
}
}

}
#endif // DEBUG

0 comments on commit bd7bd35

Please sign in to comment.