MySQL 9.3.0
Source Code Documentation
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
mysql_row.h
Go to the documentation of this file.
1/*
2 Copyright (c) 2021, 2025, Oracle and/or its affiliates.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is designed to work with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have either included with
14 the program or referenced in the documentation.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24*/
25
26#ifndef ROUTER_SRC_REST_MRS_SRC_HELPER_MYSQL_ROW_H_
27#define ROUTER_SRC_REST_MRS_SRC_HELPER_MYSQL_ROW_H_
28
29#include <cassert>
30#include <cstdlib>
31#include <map>
32#include <optional>
33#include <set>
34#include <string>
35#include <type_traits>
36
39
40#include "helper/mysql_time.h"
41#include "helper/optional.h"
42
43namespace helper {
44
45class MySQLRow {
46 public:
49 /* Always do the assertion. */
51 /* Do the assertion only after `end` call. */
53 };
54
55 public:
56 MySQLRow(const ResultRow &row, MYSQL_FIELD *fields, unsigned number,
57 Verification must_call_end = kCheckAtDestructor)
58 : row_{row},
59 fields_{fields},
60 no_of_fields_{number},
61 unserialize_ended_{kCheckAtDestructor == must_call_end} {}
62
64 // At the end of execution "field_index_" contains array index to next
65 // field to read. Thus it may be interpreted as number of consumed fields.
66 //
67 // If the assert fails it means that Query fetched more fields that
68 // the user-code unserialized (missing `unserialize` calls).
69 //
70 // If the user code had finished fetching data, and there are still
71 // unserialized fields/data, then the user code should call
72 // `skip` to mark that those fields will be not unserialized.
73 assert(!unserialize_ended_ ||
75 "Number of consumed fields should be equal to number or provided "
76 "fields."));
77 }
78
79 void end() { unserialize_ended_ = true; }
80
81 void skip(uint32_t to_skip = 1) { field_index_ += to_skip; }
82
83 template <typename FieldType>
84 void unserialize(FieldType *out_field) {
85 assert((no_of_fields_ == 0 || field_index_ < no_of_fields_) &&
86 "Index out of boundary.");
87 auto in_value = row_[field_index_++];
88
89 convert(field_index_ - 1, out_field, in_value);
90 }
91
92 template <typename FieldType>
93 void unserialize(FieldType *out_field, FieldType value_default) {
94 assert((no_of_fields_ == 0 || field_index_ < no_of_fields_) &&
95 "Index out of boundary.");
96 auto in_value = row_[field_index_++];
97
98 if (in_value)
99 convert(field_index_ - 1, out_field, in_value);
100 else
101 *out_field = value_default;
102 }
103
104 template <typename FieldType, typename Converter>
105 void unserialize_with_converter(FieldType *out_field,
106 const Converter &converter) {
107 assert((no_of_fields_ == 0 || field_index_ < no_of_fields_) &&
108 "Index out of boundary.");
109 auto in_value = row_[field_index_++];
110
111 converter(out_field, in_value);
112 }
113
114 template <typename FieldType, typename Converter>
115 void unserialize_with_converter(std::optional<FieldType> *out_field,
116 const Converter &converter) {
117 assert((no_of_fields_ == 0 || field_index_ < no_of_fields_) &&
118 "Index out of boundary.");
119 auto in_value = row_[field_index_++];
120
121 out_field->reset();
122
123 if (in_value) {
124 FieldType v;
125 converter(&v, in_value);
126 *out_field = v;
127 }
128 }
129
130 template <typename FieldType, typename Converter>
132 const Converter &converter) {
133 assert((no_of_fields_ == 0 || field_index_ < no_of_fields_) &&
134 "Index out of boundary.");
135 auto in_value = row_[field_index_++];
136
137 out_field->reset();
138
139 if (in_value) {
140 FieldType r;
141 converter(&r, in_value);
142 *out_field = std::move(r);
143 }
144 }
145
146 template <typename FieldType>
147 void unserialize(std::optional<FieldType> *out_field) {
148 assert((no_of_fields_ == 0 || field_index_ < no_of_fields_) &&
149 "Index out of boundary.");
150 auto in_value = row_[field_index_++];
151
152 out_field->reset();
153
154 if (in_value) {
155 FieldType out_value;
156 convert(field_index_ - 1, &out_value, in_value);
157 *out_field = std::move(out_value);
158 }
159 }
160
161 template <typename FieldType>
163 assert((no_of_fields_ == 0 || field_index_ < no_of_fields_) &&
164 "Index out of boundary.");
165 auto in_value = row_[field_index_++];
166
167 out_field->reset();
168
169 if (in_value) {
170 FieldType out_value;
171 convert(field_index_ - 1, &out_value, in_value);
172 *out_field = std::move(out_value);
173 }
174 }
175
176 static void set_from_string(std::set<std::string> *out, const char *in) {
177 out->clear();
178
179 if (!in) return;
180
181 for (const auto &s : mysql_harness::split_string(in, ',', false)) {
182 out->insert(s);
183 }
184 }
185
186 private:
187 template <typename T>
189 unsigned field_index, T *out_value, const char *in_value) {
190 auto ptr = reinterpret_cast<std::underlying_type_t<T> *>(out_value);
191 convert(field_index, ptr, in_value);
192 }
193
194 void convert(unsigned field_index, bool *out_value, const char *in_value) {
195 if (!in_value) {
196 *out_value = {};
197 return;
198 }
199
200 if (fields_) {
201 if (field_index < no_of_fields_) {
202 if (fields_[field_index].type == MYSQL_TYPE_BIT) {
203 *out_value = *reinterpret_cast<const uint8_t *>(in_value) != 0;
204 return;
205 }
206 }
207 }
208 if (isalpha(in_value[0])) {
209 static std::map<std::string, bool> conversion{
210 {"false", false}, {"FALSE", false}, {"true", true}, {"TRUE", true}};
211
212 *out_value = conversion[in_value];
213 return;
214 }
215
216 *out_value = atoi(in_value);
217 }
218
219 void convert([[maybe_unused]] unsigned field_index, std::string *out_value,
220 const char *in_value) {
221 if (in_value)
222 *out_value = in_value;
223 else
224 *out_value = "";
225 }
226
227 void convert([[maybe_unused]] unsigned field_index, uint32_t *out_value,
228 const char *in_value) {
229 if (in_value)
230 *out_value = std::stoul(in_value);
231 else
232 *out_value = 0;
233 }
234
235 void convert([[maybe_unused]] unsigned field_index, int32_t *out_value,
236 const char *in_value) {
237 if (in_value)
238 *out_value = atoi(in_value);
239 else
240 *out_value = 0;
241 }
242
243 void convert([[maybe_unused]] unsigned field_index, uint64_t *out_value,
244 const char *in_value) {
245 char *out_value_end;
246 *out_value = strtoull(in_value, &out_value_end, 10);
247 }
248
249 void convert([[maybe_unused]] unsigned field_index,
250 std::vector<uint64_t> *out_value, const char *v) {
251 char *endptr = const_cast<char *>(v);
252 while (v && *v != 0) {
253 out_value->push_back(strtoull(v, &endptr, 10));
254
255 while (endptr && !(isalnum(*endptr) || *endptr == '-') && *endptr != 0)
256 ++endptr;
257 v = endptr;
258 }
259 }
260
261 void convert([[maybe_unused]] unsigned field_index,
262 helper::DateTime *out_value, const char *in_value) {
263 out_value->from_string(in_value);
264 }
265
266 public:
267 uint32_t field_index_{0};
272};
273
274} // namespace helper
275
276#endif // ROUTER_SRC_REST_MRS_SRC_HELPER_MYSQL_ROW_H_
Definition: mysql_time.h:38
void from_string(const std::string &text_time)
Definition: mysql_time.h:44
Definition: mysql_row.h:45
void convert(unsigned field_index, uint64_t *out_value, const char *in_value)
Definition: mysql_row.h:243
void unserialize_with_converter(FieldType *out_field, const Converter &converter)
Definition: mysql_row.h:105
Verification
Definition: mysql_row.h:48
@ kEndCallRequired
Definition: mysql_row.h:52
@ kCheckAtDestructor
Definition: mysql_row.h:50
~MySQLRow()
Definition: mysql_row.h:63
bool unserialize_ended_
Definition: mysql_row.h:271
unsigned no_of_fields_
Definition: mysql_row.h:270
std::enable_if< std::is_enum< T >::value >::type convert(unsigned field_index, T *out_value, const char *in_value)
Definition: mysql_row.h:188
void unserialize_with_converter(std::optional< FieldType > *out_field, const Converter &converter)
Definition: mysql_row.h:115
uint32_t field_index_
Definition: mysql_row.h:267
void unserialize(helper::Optional< FieldType > *out_field)
Definition: mysql_row.h:162
void end()
Definition: mysql_row.h:79
void convert(unsigned field_index, bool *out_value, const char *in_value)
Definition: mysql_row.h:194
void convert(unsigned field_index, std::string *out_value, const char *in_value)
Definition: mysql_row.h:219
void unserialize(FieldType *out_field)
Definition: mysql_row.h:84
void convert(unsigned field_index, int32_t *out_value, const char *in_value)
Definition: mysql_row.h:235
MySQLRow(const ResultRow &row, MYSQL_FIELD *fields, unsigned number, Verification must_call_end=kCheckAtDestructor)
Definition: mysql_row.h:56
void unserialize_with_converter(helper::Optional< FieldType > *out_field, const Converter &converter)
Definition: mysql_row.h:131
const ResultRow & row_
Definition: mysql_row.h:268
void unserialize(std::optional< FieldType > *out_field)
Definition: mysql_row.h:147
void convert(unsigned field_index, uint32_t *out_value, const char *in_value)
Definition: mysql_row.h:227
void unserialize(FieldType *out_field, FieldType value_default)
Definition: mysql_row.h:93
void skip(uint32_t to_skip=1)
Definition: mysql_row.h:81
void convert(unsigned field_index, helper::DateTime *out_value, const char *in_value)
Definition: mysql_row.h:261
void convert(unsigned field_index, std::vector< uint64_t > *out_value, const char *v)
Definition: mysql_row.h:249
static void set_from_string(std::set< std::string > *out, const char *in)
Definition: mysql_row.h:176
MYSQL_FIELD * fields_
Definition: mysql_row.h:269
Lightweight implementation of optional.
Definition: optional.h:39
void reset()
Definition: optional.h:79
Definition: mysql_session.h:310
@ MYSQL_TYPE_BIT
Definition: field_types.h:72
#define T
Definition: jit_executor_value.cc:373
Definition: cache.h:33
ValueType value(const std::optional< ValueType > &v)
Definition: gtid.h:83
bool isalpha(const char &ch)
Definition: parsing_helpers.h:37
HARNESS_EXPORT std::vector< std::string > split_string(const std::string_view &data, const char delimiter, bool allow_empty=true)
Splits a string using a delimiter.
Definition: string_utils.cc:37
const mysql_service_registry_t * r
Definition: pfs_example_plugin_employee.cc:86
required string type
Definition: replication_group_member_actions.proto:34
Definition: mysql.h:121