Skip to content

Commit b5d1299

Browse files
PS-10679 fix: cannot parse GTID set with multiple UUIDs if no space after a coma before start of next UUID (#102)
https://perconadev.atlassian.net/browse/PS-10679 Fixed an issue with "binsrv::gtids::gtid_set' parser not being able to accept GTIDs without spaces between UUID groups. 'gtid_set_test' unit test (BOOST_TEST_MODULE GtidSetTests) extended with additional test case 'GtidSetWhitespaces' that checks for 'binsrv::gtids::gtid_set' -> 'std::string' -> 'binsrv::gtids::gtid_set roundtrip' with removed whitespaces.
1 parent 8429ba2 commit b5d1299

2 files changed

Lines changed: 58 additions & 4 deletions

File tree

src/binsrv/gtids/gtid_set.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ class gtid_set_parser {
8080
<optionally_tagged_interval> ::= (<tag> ':')? <gno> ('-' <gno>)?
8181
<tag> ::= [a-zA-Z_][a-zA-Z0-9_]{0,31}
8282
<gno> ::= [0-9]+
83-
<space> ::= [ \t\r\n\f\v]+
83+
<space> ::= [ \t\r\n\f\v]*
8484
*/
8585

8686
gtid_set *result_gtids_;
@@ -252,10 +252,8 @@ class gtid_set_parser {
252252
parse_optionally_tagged_intervals(remainder);
253253
}
254254

255-
// <space> ::= [ \t\r\n\f\v]+
255+
// <space> ::= [ \t\r\n\f\v]*
256256
static void parse_space(std::string_view &remainder) {
257-
util::parse_character_predicate(remainder, space_predicate);
258-
259257
char character{};
260258
while (util::parse_character_predicate_ex(remainder, space_predicate,
261259
character)) {

tests/gtid_set_test.cpp

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -665,3 +665,59 @@ BOOST_AUTO_TEST_CASE(GtidSetStreamOperatorMixed) {
665665
boost::lexical_cast<binsrv::gtids::gtid_set>(gtids_str)};
666666
BOOST_CHECK_EQUAL(gtids, restored_gtids);
667667
}
668+
669+
BOOST_AUTO_TEST_CASE(GtidSetWhitespaces) {
670+
const binsrv::gtids::uuid first_uuid{first_uuid_sv};
671+
const binsrv::gtids::uuid second_uuid{second_uuid_sv};
672+
673+
const binsrv::gtids::tag first_tag{first_tag_sv};
674+
const binsrv::gtids::tag second_tag{second_tag_sv};
675+
676+
binsrv::gtids::gtid_set gtids{};
677+
// NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers)
678+
gtids += binsrv::gtids::gtid{first_uuid, 101ULL};
679+
gtids += binsrv::gtids::gtid{first_uuid, 102ULL};
680+
gtids += binsrv::gtids::gtid{first_uuid, 103ULL};
681+
gtids += binsrv::gtids::gtid{first_uuid, 105ULL};
682+
683+
gtids += binsrv::gtids::gtid{first_uuid, first_tag, 111ULL};
684+
gtids += binsrv::gtids::gtid{first_uuid, first_tag, 112ULL};
685+
gtids += binsrv::gtids::gtid{first_uuid, first_tag, 113ULL};
686+
gtids += binsrv::gtids::gtid{first_uuid, first_tag, 115ULL};
687+
688+
gtids += binsrv::gtids::gtid{first_uuid, second_tag, 121ULL};
689+
gtids += binsrv::gtids::gtid{first_uuid, second_tag, 122ULL};
690+
gtids += binsrv::gtids::gtid{first_uuid, second_tag, 123ULL};
691+
gtids += binsrv::gtids::gtid{first_uuid, second_tag, 125ULL};
692+
693+
gtids += binsrv::gtids::gtid{second_uuid, 201ULL};
694+
gtids += binsrv::gtids::gtid{second_uuid, 202ULL};
695+
gtids += binsrv::gtids::gtid{second_uuid, 203ULL};
696+
gtids += binsrv::gtids::gtid{second_uuid, 205ULL};
697+
698+
gtids += binsrv::gtids::gtid{second_uuid, first_tag, 211ULL};
699+
gtids += binsrv::gtids::gtid{second_uuid, first_tag, 212ULL};
700+
gtids += binsrv::gtids::gtid{second_uuid, first_tag, 213ULL};
701+
gtids += binsrv::gtids::gtid{second_uuid, first_tag, 215ULL};
702+
703+
gtids += binsrv::gtids::gtid{second_uuid, second_tag, 221ULL};
704+
gtids += binsrv::gtids::gtid{second_uuid, second_tag, 222ULL};
705+
gtids += binsrv::gtids::gtid{second_uuid, second_tag, 223ULL};
706+
gtids += binsrv::gtids::gtid{second_uuid, second_tag, 225ULL};
707+
// NOLINTEND(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers)
708+
709+
auto gtids_str{boost::lexical_cast<std::string>(gtids)};
710+
// erasing all space characters from the GTIDs string
711+
712+
// looks like a misconfiguration in clang-tyidy-19 that doesn't know that
713+
// std::erase() for std::string is located in the <string> system header
714+
715+
// TODO: re-check this when switching to clang-20
716+
717+
// NOLINTNEXTLINE(misc-include-cleaner)
718+
std::erase(gtids_str, ' ');
719+
BOOST_CHECK(gtids_str.find(' ') == std::string::npos);
720+
const auto restored_gtids{
721+
boost::lexical_cast<binsrv::gtids::gtid_set>(gtids_str)};
722+
BOOST_CHECK_EQUAL(gtids, restored_gtids);
723+
}

0 commit comments

Comments
 (0)