Skip to content

Commit bd7bd35

Browse files
authored
Merge pull request #4629 from sysown/v2.x-4628
Removing trailing semicolon from `USE` #4628
2 parents 5d2c1ba + c76dda6 commit bd7bd35

File tree

3 files changed

+42
-14
lines changed

3 files changed

+42
-14
lines changed

include/set_parser.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ class SetParser {
4242
// First implemenation of the parser for TRANSACTION ISOLATION LEVEL and TRANSACTION READ/WRITE
4343
std::map<std::string, std::vector<std::string>> parse2();
4444
std::string parse_character_set();
45-
std::string parse_USE_query();
45+
std::string parse_USE_query(std::string& errmsg);
4646
std::string remove_comments(const std::string& q);
4747
#ifdef DEBUG
4848
// built-in testing

lib/MySQL_Session.cpp

+9-2
Original file line numberDiff line numberDiff line change
@@ -6139,7 +6139,8 @@ void MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C
61396139
__sync_fetch_and_add(&MyHGM->status.frontend_use_db, 1);
61406140
string nq=string((char *)pkt->ptr+sizeof(mysql_hdr)+1,pkt->size-sizeof(mysql_hdr)-1);
61416141
SetParser parser(nq);
6142-
string schemaname = parser.parse_USE_query();
6142+
string errmsg = "";
6143+
string schemaname = parser.parse_USE_query(errmsg);
61436144
if (schemaname != "") {
61446145
client_myds->myconn->userinfo->set_schemaname((char *)schemaname.c_str(),schemaname.length());
61456146
if (mirror==false) {
@@ -6156,6 +6157,9 @@ void MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C
61566157
l_free(pkt->size,pkt->ptr);
61576158
client_myds->setDSS_STATE_QUERY_SENT_NET();
61586159
std::string msg = "Unable to parse: " + nq;
6160+
if (errmsg != "") {
6161+
msg = errmsg + ": " + nq;
6162+
}
61596163
client_myds->myprot.generate_pkt_ERR(true,NULL,NULL,client_myds->pkt_sid+1,1148,(char *)"42000", msg.c_str());
61606164
RequestEnd(NULL);
61616165
}
@@ -6475,7 +6479,10 @@ bool MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C
64756479
RE2::GlobalReplace(&nq,(char *)"^/\\*!\\d\\d\\d\\d\\d SET(.*)\\*/",(char *)"SET\\1");
64766480
RE2::GlobalReplace(&nq,(char *)"(?U)/\\*.*\\*/",(char *)"");
64776481
// remove trailing space and semicolon if present. See issue#4380
6478-
nq.erase(nq.find_last_not_of(" ;") + 1);
6482+
size_t pos = nq.find_last_not_of(" ;");
6483+
if (pos != nq.npos) {
6484+
nq.erase(pos + 1); // remove trailing spaces and semicolumns
6485+
}
64796486
/*
64806487
// we do not threat SET SQL_LOG_BIN as a special case
64816488
if (match_regexes && match_regexes[0]->match(dig)) {

lib/set_parser.cpp

+32-11
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
using namespace std;
1313

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

1516
static void remove_quotes(string& v) {
1617
if (v.length() > 2) {
@@ -118,7 +119,10 @@ VALGRIND_ENABLE_ERROR_REPORTING;
118119
} else if (strcasecmp("transaction_read_only", value4.c_str()) == 0) {
119120
value4 = "tx_read_only";
120121
}
121-
value5.erase(value5.find_last_not_of(" \n\r\t,")+1);
122+
size_t pos = value5.find_last_not_of(" \n\r\t,");
123+
if (pos != value5.npos) {
124+
value5.erase(pos+1);
125+
}
122126
key = value4;
123127
if (value5 == "''" || value5 == "\"\"") {
124128
op.push_back("");
@@ -404,7 +408,10 @@ VALGRIND_ENABLE_ERROR_REPORTING;
404408
} else if (strcasecmp("transaction_read_only", value4.c_str()) == 0) {
405409
value4 = "tx_read_only";
406410
}
407-
value5.erase(value5.find_last_not_of(" \n\r\t,")+1);
411+
size_t pos = value5.find_last_not_of(" \n\r\t,");
412+
if (pos != value5.npos) {
413+
value5.erase(pos+1);
414+
}
408415
key = value4;
409416
if (value5 == "''" || value5 == "\"\"") {
410417
op.push_back("");
@@ -508,7 +515,7 @@ std::string SetParser::parse_character_set() {
508515
return value4;
509516
}
510517

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

520527
std::string dbname = remove_comments(query);
528+
size_t pos = dbname.find_last_not_of(" ;");
529+
if (pos != dbname.npos) {
530+
dbname.erase(pos + 1); // remove trailing spaces and semicolumns
531+
}
521532
re2::RE2 re0("^\\s*", opt2);
522533
re2::RE2::Replace(&dbname, re0, "");
523534
if (dbname.size() >= 4) {
@@ -537,18 +548,22 @@ std::string SetParser::parse_USE_query() {
537548
dbname.erase(0, 1);
538549
// Remove the last character
539550
dbname.erase(dbname.length() - 1);
540-
return dbname;
541551
}
542552
}
543-
} else {
544-
return dbname;
545553
}
554+
} else {
555+
dbname = "";
546556
}
547557
} else {
548-
return "";
558+
dbname = "";
549559
}
550560

551-
return "";
561+
if (dbname.find_first_of(';') != std::string::npos) {
562+
errmsg = MULTI_STATEMENTS_USE;
563+
dbname = "";
564+
}
565+
566+
return dbname;
552567
}
553568

554569

@@ -638,18 +653,24 @@ void SetParser::test_parse_USE_query() {
638653
{"USE/*+ placeholder_comment */`test_use_comment-5`", "test_use_comment-5"},
639654
{"/* comment */USE`test_use_comment-6`", "test_use_comment-6"},
640655
{"USE`test_use_comment-7`", "test_use_comment-7"},
656+
{"USE test_use_comment-7 ;", "test_use_comment-7"},
657+
{"USE`test_use_comment-2` ; ", "test_use_comment-2"},
658+
{"USE`test_use_comment-2` ; -- comment", "test_use_comment-2"},
659+
{"USE test_use_comment-7 /* comment */ ; ", "test_use_comment-7"},
660+
{"USE /* comment */ test_use_comment-7 ; ", "test_use_comment-7"},
661+
{"USE dbame ; SELECT 1", ""},
641662
};
642663

643664
// Run tests for each pair
644665
for (const auto& p : testCases) {
645666
set_query(p.first);
646-
std::string dbname = parse_USE_query();
667+
std::string errmsg = "";
668+
std::string dbname = parse_USE_query(errmsg);
647669
if (dbname != p.second) {
648670
// we call parse_USE_query() again just to make it easier to create a breakpoint
649-
std::string s = parse_USE_query();
671+
std::string s = parse_USE_query(errmsg);
650672
assert(s == p.second);
651673
}
652674
}
653-
654675
}
655676
#endif // DEBUG

0 commit comments

Comments
 (0)