MySQL 9.6.0
Source Code Documentation
gtid_text_format_conv.h
Go to the documentation of this file.
1// Copyright (c) 2025, Oracle and/or its affiliates.
2//
3// This program is free software; you can redistribute it and/or modify
4// it under the terms of the GNU General Public License, version 2.0,
5// as published by the Free Software Foundation.
6//
7// This program is designed to work with certain software (including
8// but not limited to OpenSSL) that is licensed under separate terms,
9// as designated in a particular file or component or in included license
10// documentation. The authors of MySQL hereby grant you an additional
11// permission to link the program and your derivative works with the
12// separately licensed software that they have either included with
13// the program or referenced in the documentation.
14//
15// This program is distributed in the hope that it will be useful,
16// but WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18// GNU General Public License, version 2.0, for more details.
19//
20// You should have received a copy of the GNU General Public License
21// along with this program; if not, write to the Free Software
22// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23
24#ifndef MYSQL_GTIDS_STRCONV_GTID_TEXT_FORMAT_CONV_H
25#define MYSQL_GTIDS_STRCONV_GTID_TEXT_FORMAT_CONV_H
26
27/// @file
28/// Experimental API header
29
30#include "mysql/gtids/gtid.h" // Is_gtid
31#include "mysql/gtids/gtid_set.h" // Is_gtid_set
32#include "mysql/gtids/sequence_number.h" // Sequence_number
33#include "mysql/gtids/strconv/gtid_text_format.h" // Gtid_text_format
34#include "mysql/gtids/tag.h" // Is_tag
35#include "mysql/gtids/tsid.h" // Is_tsid
36#include "mysql/strconv/strconv.h" // Is_string_target
37#include "mysql/utils/return_status.h" // Return_status
38
39/// @addtogroup GroupLibsMysqlGtids
40/// @{
41
42namespace mysql::strconv {
43
44// ==== Tags ====
45
47 const mysql::gtids::Is_tag auto &tag) {
48 target.write(format, tag.string_view());
49}
50
52 mysql::gtids::Is_tag auto &tag) {
53 // Compute length.
54 auto opt_len = tag.valid_prefix_length(parser.remaining_str());
55 if (!opt_len.has_value() || *opt_len == 0) {
56 parser.set_parse_error("Invalid tag format");
57 return;
58 }
59 // Make `sv` point to the relevant substring of the input.
60 std::string_view sv;
61 if (parser.read(Fixstr_binary_format{*opt_len}, sv) !=
63 return;
64 // Copy and normalize characters.
65 [[maybe_unused]] auto ret =
66 mysql::utils::void_to_ok([&] { return tag.assign(sv); });
67 // Can't fail because this is a "valid prefix" and the tag does not allocate.
69}
70
71// ==== Tsids ====
72
74 const mysql::gtids::Is_tsid auto &tsid) {
75 target.write(format, tsid.uuid());
76 if (tsid.tag()) {
77 target.concat(format,
79 tsid.tag());
80 }
81}
82
84 mysql::gtids::Is_tsid auto &tsid) {
85 tsid.tag().clear();
86 parser
87 .fluent(format) //
88 .read(tsid.uuid()) // UUID
89 .end_optional() // remainder is optional
91 .read(tsid.tag()); // tag
92}
93
94// ==== Gtids ====
95
97 const mysql::gtids::Is_gtid auto &gtid) {
98 target.concat(format, gtid.tsid(),
100 gtid.get_sequence_number());
101}
102
104 mysql::gtids::Is_gtid auto &gtid) {
105 mysql::gtids::Sequence_number sequence_number{
107 parser
108 .fluent(format) //
109 .read(gtid.tsid()) // TSID
111 .read(sequence_number) // N
112 .check_prev_token([&] { // check range
113 if (gtid.set_sequence_number(sequence_number) !=
115 parser.set_parse_error("GTID sequence number out of range");
116 }
117 });
118}
119
120// ==== Gtid sets ====
121
123 const mysql::gtids::Is_gtid_set auto &gtid_set) {
124 std::optional<mysql::uuids::Uuid> last_uuid{};
125 for (const auto &[tsid, interval_set] : gtid_set) {
126 bool first = !last_uuid.has_value();
127 assert(first || *last_uuid != tsid.uuid() || tsid.tag());
128 if (first || *last_uuid != tsid.uuid()) {
129 if (!first)
131 target.write(format, tsid.uuid());
132 }
133 if (tsid.tag()) {
134 target.write_raw(
136 target.write(format, tsid.tag());
137 }
139 target.write(format, interval_set);
140 last_uuid = tsid.uuid();
141 }
142}
143
144template <mysql::gtids::Is_gtid_set Gtid_set_t>
146 Gtid_set_t &gtid_set) {
147 using Interval_set_t = typename Gtid_set_t::Mapped_t;
148 auto fluent = parser.fluent(format);
149
151 Interval_set_t interval_set(gtid_set.get_memory_resource());
152
153 // ":"
154 auto parse_sep = [&] {
156 };
157
158 // INTERVAL_SET
159 auto parse_interval_set = [&] {
160 fluent //
161 .read(interval_set) // parse INTERVAL_SET
162 .check_prev_token([&] { // add to output
163 if (gtid_set.inplace_union(tsid, std::move(interval_set)) !=
165 // With current boundary container implementation this is not
166 // reachable because move semantics is guaranteed: same type, same
167 // allocator, and `has_fast_insertions` implies that the storage is
168 // map-based. But it could hypothetically be reached for
169 // user-defined storage types that support fast insertions but not
170 // move semantics.
171 parser.set_oom();
172 }
173 // It is valid to call `clear` after the object has been moved-from.
174 // NOLINENEXTLINE(bugprone-use-after-move,hicpp-invalid-access-moved)
175 interval_set.clear();
176 });
177 };
178
179 // TAG_SET := (":" TAG)* (":" INTERVAL_SET)?
180 auto parse_tag_and_interval_set = [&] {
181 fluent //
182 .call_any([&] { // (":" TAG)*
183 fluent //
184 .call(parse_sep) // ":"
185 .read(tsid.tag()); // TAG
186 }) //
187 .end_optional() // may end here
188 .call(parse_sep) // ":"
189 .call(parse_interval_set); // INTERVAL_SET
190 };
191
192 // UUID_SET := UUID (TAG_SET)?
193 auto parse_uuid_and_tags_and_interval_sets = [&] {
194 fluent //
195 .read(tsid.uuid()) // UUID
196 .end_optional() // may end here
197 .call([&] { tsid.tag().clear(); }) // reset the tag
198 .call_any(parse_tag_and_interval_set); // TAG_SET
199 };
200
202
203 // ","* (UUID_SET (","+ UUID_SET)*)? ","*
204 fluent.call_repeated_with_separators(
205 parse_uuid_and_tags_and_interval_sets, // UUID_SET
209}
210
211} // namespace mysql::strconv
212
213// addtogroup GroupLibsMysqlGtids
214/// @}
215
216#endif // ifndef MYSQL_GTIDS_STRCONV_GTID_TEXT_FORMAT_CONV_H
Definition: tsid.h:90
const auto & tag() const
Definition: tsid.h:75
const mysql::uuids::Uuid & uuid() const
Definition: tsid.h:72
Object used to parse strings.
Definition: parser.h:69
Return_status_t read(const Is_parse_options auto &opt, Object_t &obj)
Parse into the given object.
Definition: parser.h:225
Fluent_parser< Format_t > fluent(const Format_t &format)
Definition: parser.h:454
void set_parse_error(const std::string_view &message)
Store a result representing that the requested object could not be parsed because the string is wrong...
Definition: parser.h:94
std::string_view remaining_str() const
Return a string_view over the remaining string.
Definition: parse_position.h:162
static Repeat_optional any()
Return a Repeat_optional object representing any number of repetitions from 0 and up (bounded only by...
Definition: repeat.h:64
True for all Gtid set types.
Definition: gtid_set.h:178
Definition: gtid.h:53
True if Test is one of the tag classes.
Definition: tag.h:192
Definition: tsid.h:50
Concept that holds for String_counter and String_writer.
Definition: string_target.h:111
Experimental API header.
Experimental API header.
Experimental API header.
Experimental API header.
Experimental API header.
Experimental API header.
struct Parser parser
std::string format(const routing_guidelines::Session_info &session_info, bool extended_session_info)
Definition: dest_metadata_cache.cc:170
uint64_t Sequence_number
The type of the sequence number component of a GTID.
Definition: sequence_number.h:39
constexpr Sequence_number sequence_number_min
The smallest allowed value for a GTID sequence number.
Definition: sequence_number.h:50
Definition: gtid_binary_format.h:41
void skip_whitespace(Parser &parser)
Move the position forward until end or non-whitespace.
Definition: whitespace.h:47
void decode_impl(const Gtid_binary_format &format, Parser &parser, mysql::gtids::Is_tag auto &tag)
Definition: gtid_binary_format_conv.h:63
void encode_impl(const Gtid_binary_format &format, Is_string_target auto &target, const mysql::gtids::Is_tag auto &tag)
Definition: gtid_binary_format_conv.h:48
@ ok
operation succeeded
Return_t void_to_ok(const Func_t &func, Args_t &&...args)
Helper that calls the given function and returns its result, or returns Return_status::ok if the func...
Definition: return_status.h:113
static mysql_service_status_t clear(reference_caching_channel channel) noexcept
Definition: component.cc:146
Experimental API header.
Experimental API header.
Format tag to identify fixed-length-string binary format.
Definition: fixstr_binary_format.h:38
Definition: gtid_text_format.h:44
static constexpr std::string_view m_uuid_uuid_separator
Definition: gtid_text_format.h:47
static constexpr std::string_view m_uuid_uuid_separator_for_output
Definition: gtid_text_format.h:52
static constexpr std::string_view m_uuid_tag_number_separator_for_output
Definition: gtid_text_format.h:61
static constexpr std::string_view m_uuid_tag_number_separator
Definition: gtid_text_format.h:56