userver
C++ Async Framework
Toggle main menu visibility
Loading...
Searching...
No Matches
statement_result_set.hpp
Go to the documentation of this file.
1
#
pragma
once
2
3
/// @file userver/storages/mysql/statement_result_set.hpp
4
5
#
include
<
optional
>
6
#
include
<
vector
>
7
8
#
include
<
fmt
/
format
.
h
>
9
10
#
include
<
userver
/
engine
/
deadline
.
hpp
>
11
#
include
<
userver
/
tracing
/
scope_time
.
hpp
>
12
#
include
<
userver
/
utils
/
fast_pimpl
.
hpp
>
13
14
#
include
<
userver
/
storages
/
mysql
/
execution_result
.
hpp
>
15
#
include
<
userver
/
storages
/
mysql
/
impl
/
io
/
extractor
.
hpp
>
16
#
include
<
userver
/
storages
/
mysql
/
impl
/
tracing_tags
.
hpp
>
17
18
USERVER_NAMESPACE_BEGIN
19
20
namespace
storages::
mysql
{
21
22
namespace
impl {
23
class
StatementFetcher;
24
}
25
26
namespace
infra {
27
class
ConnectionPtr;
28
}
29
30
template
<
typename
DbType>
31
class
MappedStatementResultSet
;
32
33
/// @brief A wrapper for statement execution result.
34
///
35
/// This type can't be constructed in user code and is always retrieved from
36
/// storages::mysql::Cluster or storages::mysql::Transaction methods.
37
class
StatementResultSet
final
{
38
public
:
39
explicit
StatementResultSet(impl::StatementFetcher&& fetcher,
tracing
::Span&& span);
40
StatementResultSet(infra::ConnectionPtr&& connection, impl::StatementFetcher&& fetcher,
tracing
::Span&& span);
41
~StatementResultSet();
42
43
StatementResultSet(
const
StatementResultSet& other) =
delete
;
44
StatementResultSet(StatementResultSet&& other)
noexcept
;
45
46
/// @brief Parse statement result set as std::vector<T>.
47
/// `T` is expected to be an aggregate of supported types.
48
/// See @ref scripts/docs/en/userver/mysql/supported_types.md for better understanding of
49
/// `T` requirements.
50
///
51
/// UINVARIANTs on columns count mismatch or types mismatch.
52
///
53
/// @snippet mysql/tests/statement_result_set.cpp uMySQL usage sample - StatementResultSet AsVector
54
template
<
typename
T>
55
std::vector<T>
AsVector
() &&;
56
57
/// @brief Parse statement result set as std::vector<T>.
58
/// Result set is expected to have a single column, `T` is expected to be one
59
/// of supported types.
60
/// See @ref scripts/docs/en/userver/mysql/supported_types.md for supported typed.
61
///
62
/// UINVARIANTs on columns count not being equal to 1 or type mismatch.
63
///
64
/// @snippet mysql/tests/statement_result_set.cpp uMySQL usage sample - StatementResultSet AsVectorFieldTag
65
template
<
typename
T>
66
std::vector<T>
AsVector
(
FieldTag
) &&;
67
68
/// @brief Parse statement result set as Container<T>.
69
/// `T` is expected to be an aggregate of supported types, `Container` is
70
/// expected to meet std::Container requirements.
71
/// See @ref scripts/docs/en/userver/mysql/supported_types.md for better understanding of
72
/// `Container::value_type` requirements.
73
///
74
/// UINVARIANTs on columns count mismatch or types mismatch.
75
///
76
/// @snippet mysql/tests/statement_result_set.cpp uMySQL usage sample - StatementResultSet AsContainer
77
template
<
typename
Container>
78
Container
AsContainer
() &&;
79
80
/// @brief Parse statement result as Container<T>.
81
/// Result set is expected to have a single column, `T` is expected to be one
82
/// of supported types,
83
/// `Container` is expected to meed std::Container requirements.
84
/// See @ref scripts/docs/en/userver/mysql/supported_types.md for supported types.
85
///
86
/// UINVARIANTs on columns count not being equal to 1 or type mismatch.
87
///
88
/// @snippet mysql/tests/statement_result_set.cpp uMySQL usage sample - StatementResultSet AsContainerFieldTag
89
template
<
typename
Container>
90
Container
AsContainer
(
FieldTag
) &&;
91
92
/// @brief Parse statement result as T.
93
/// Result set is expected to have a single row, `T` is expected to be an
94
/// aggregate of supported types.
95
/// See @ref scripts/docs/en/userver/mysql/supported_types.md for better understanding of
96
/// `T` requirements.
97
///
98
/// UINVARIANTs on columns count mismatch or types mismatch.
99
/// throws if result set is empty or contains more than one row.
100
///
101
/// @snippet mysql/tests/statement_result_set.cpp uMySQL usage sample - StatementResultSet AsSingleRow
102
template
<
typename
T>
103
T
AsSingleRow
() &&;
104
105
/// @brief Parse statement result as T.
106
/// Result set is expected to have a single row and a single column,
107
/// `T` is expected to be one of supported types.
108
/// See @ref scripts/docs/en/userver/mysql/supported_types.md for supported types.
109
///
110
/// UINVARIANTs on columns count not being equal to 1 or type mismatch.
111
/// throws if result set is empty of contains more than one row.
112
///
113
/// @snippet mysql/tests/statement_result_set.cpp uMySQL usage sample - StatementResultSet AsSingleField
114
template
<
typename
T>
115
T
AsSingleField
() &&;
116
117
/// @brief Parse statement result as std::optional<T>.
118
/// Result set is expected to have not more than one row,
119
/// `T` is expected to be an aggregate of supported types.
120
/// See @ref scripts/docs/en/userver/mysql/supported_types.md for better understanding of
121
/// `T` requirements.
122
///
123
/// UINVARIANTs on columns count mismatch or types mismatch.
124
/// throws if result set contains more than one row.
125
///
126
/// @snippet mysql/tests/statement_result_set.cpp uMySQL usage sample - StatementResultSet AsOptionalSingleRow
127
template
<
typename
T>
128
std::optional<T>
AsOptionalSingleRow
() &&;
129
130
/// @brief Parse statement result as T.
131
/// Result set is expected to have not more than one row,
132
/// `T` is expected to be one of supported types.
133
/// See @ref scripts/docs/en/userver/mysql/supported_types.md for supported types.
134
///
135
/// UINVARIANTs on columns count not being equal to 1 or type mismatch.
136
/// throws if result set contains more than one row.
137
///
138
/// @snippet mysql/tests/statement_result_set.cpp uMySQL usage sample - StatementResultSet AsOptionalSingleField
139
template
<
typename
T>
140
std::optional<T>
AsOptionalSingleField
() &&;
141
142
/// @brief Converts to an interface for on-the-flight mapping
143
/// statement result set from `DbType`.
144
/// `DbType` is expected to be an aggregate of supported types.
145
/// See @ref scripts/docs/en/userver/mysql/supported_types.md for better understanding of
146
/// `DbType` requirements.
147
///
148
/// @snippet mysql/tests/statement_result_set.cpp uMySQL usage sample - StatementResultSet MapFrom
149
template
<
typename
DbType>
150
MappedStatementResultSet
<DbType>
MapFrom
() &&;
151
152
/// @brief Get statement execution metadata.
153
ExecutionResult
AsExecutionResult
() &&;
154
155
private
:
156
template
<
typename
T>
157
friend
class
CursorResultSet;
158
159
template
<
typename
DbType>
160
friend
class
MappedStatementResultSet
;
161
162
template
<
typename
Container,
typename
MapFrom,
typename
ExtractionTag>
163
Container DoAsContainerMapped() &&;
164
165
template
<
typename
T,
typename
ExtractionTag>
166
std::optional<T> DoAsOptionalSingleRow() &&;
167
168
bool
FetchResult(impl::io::ExtractorBase& extractor);
169
170
struct
Impl;
171
utils
::FastPimpl<Impl, 72, 8> impl_;
172
};
173
174
/// @brief An interface for on-the-flight mapping statement result set from
175
/// DbType into whatever type you provide without additional allocations.
176
///
177
/// `DbType` is expected to be either an aggregate of supported types or a
178
/// supported type itself for methods taking `FieldTag`; DbType is expected
179
/// to match DB representation - same amount of columns (1 for `FieldTag`
180
/// overload) and matching types.
181
///
182
/// You are expected to provide a converter function
183
/// `T Convert(DbType&&, storages::mysql::convert:To<T>)` in either
184
/// T's namespace or `storages::mysql::convert` namespace
185
template
<
typename
DbType>
186
class
MappedStatementResultSet
final
{
187
public
:
188
explicit
MappedStatementResultSet(StatementResultSet&& result_set);
189
~MappedStatementResultSet();
190
191
/// @brief Parse statement result set as std::vector<T> using provided
192
/// converter function.
193
/// See @ref scripts/docs/en/userver/mysql/supported_types.md for better
194
/// understanding of `T` requirements.
195
///
196
/// UINVARIANTs on columns count mismatch or types mismatch for `DbType`.
197
template
<
typename
T>
198
std::vector<T>
AsVector
() &&;
199
200
/// @brief Parse statement result set as std::vector<T> using provided
201
/// converter function.
202
/// See @ref scripts/docs/en/userver/mysql/supported_types.md for supported
203
/// types.
204
///
205
/// UINVARIANTs on columns count not being 1 or types mismatch for DbType.
206
template
<
typename
T>
207
std::vector<T>
AsVector
(
FieldTag
) &&;
208
209
/// @brief Parse statement result set as Container<T> using provided
210
/// converter function.
211
/// See @ref scripts/docs/en/userver/mysql/supported_types.md for better
212
/// understanding of `Container::value_type` requirements.
213
///
214
/// UINVARIANTs on columns count mismatch or types mismatch for `DbType`.
215
template
<
typename
Container>
216
Container
AsContainer
() &&;
217
218
/// @brief Parse statement result set as Container<T> using provided
219
/// converter function.
220
/// See @ref scripts/docs/en/userver/mysql/supported_types.md for supported
221
/// types.
222
///
223
/// UINVARIANTs on columns count not being 1 or types mismatch for DbType.
224
template
<
typename
Container>
225
Container
AsContainer
(
FieldTag
) &&;
226
227
template
<
typename
T>
228
T AsSingleRow() && {
229
static_assert
(
230
!
sizeof
(T),
231
"Not implemented, just use StatementResultSet version and "
232
"convert yourself."
233
);
234
}
235
236
template
<
typename
T>
237
std::optional<T> AsOptionalSingleRow() && {
238
static_assert
(
239
!
sizeof
(T),
240
"Not implemented, just use StatementResultSet version and "
241
"convert yourself."
242
);
243
}
244
245
private
:
246
StatementResultSet result_set_;
247
};
248
249
template
<
typename
T>
250
std::vector<T> StatementResultSet::
AsVector
() && {
251
return
std::move(*
this
).AsContainer<std::vector<T>>();
252
}
253
254
template
<
typename
T>
255
std::vector<T> StatementResultSet::
AsVector
(
FieldTag
) && {
256
return
std::move(*
this
).AsContainer<std::vector<T>>(kFieldTag);
257
}
258
259
template
<
typename
Container>
260
Container StatementResultSet::
AsContainer
() && {
261
static_assert
(meta::
kIsRange
<Container>,
"The type isn't actually a container"
);
262
using
Row =
typename
Container::value_type;
263
264
return
std::move(*
this
).DoAsContainerMapped<Container, Row,
RowTag
>();
265
}
266
267
template
<
typename
Container>
268
Container StatementResultSet::
AsContainer
(
FieldTag
) && {
269
static_assert
(meta::
kIsRange
<Container>,
"The type isn't actually a container"
);
270
using
Row =
typename
Container::value_type;
271
272
return
std::move(*
this
).DoAsContainerMapped<Container, Row,
FieldTag
>();
273
}
274
275
template
<
typename
T>
276
T StatementResultSet::
AsSingleRow
() && {
277
auto
optional_data = std::move(*
this
).AsOptionalSingleRow<T>();
278
279
if
(!optional_data.has_value()) {
280
throw
std::runtime_error{
"Result set is empty"
};
281
}
282
283
return
std::move(*optional_data);
284
}
285
286
template
<
typename
T>
287
T StatementResultSet::
AsSingleField
() && {
288
auto
optional_data = std::move(*
this
).AsOptionalSingleField<T>();
289
290
if
(!optional_data.has_value()) {
291
throw
std::runtime_error{
"Result set is empty"
};
292
}
293
294
return
std::move(*optional_data);
295
}
296
297
template
<
typename
T>
298
std::optional<T> StatementResultSet::
AsOptionalSingleRow
() && {
299
return
std::move(*
this
).DoAsOptionalSingleRow<T,
RowTag
>();
300
}
301
302
template
<
typename
T>
303
std::optional<T> StatementResultSet::
AsOptionalSingleField
() && {
304
return
std::move(*
this
).DoAsOptionalSingleRow<T,
FieldTag
>();
305
}
306
307
template
<
typename
Container,
typename
MapFromType,
typename
ExtractionTag>
308
Container StatementResultSet::DoAsContainerMapped() && {
309
static_assert
(meta::
kIsRange
<Container>,
"The type isn't actually a container"
);
310
using
Extractor = impl::io::TypedExtractor<Container, MapFromType, ExtractionTag>;
311
312
Extractor extractor{};
313
314
tracing
::
ScopeTime
fetch
{
impl::tracing::kFetchScope
}
;
315
std::move(*
this
).FetchResult(extractor);
316
fetch
.
Reset
(
)
;
317
318
return
Container{extractor.ExtractData()};
319
}
320
321
template
<
typename
T,
typename
ExtractionTag>
322
std::optional<T> StatementResultSet::DoAsOptionalSingleRow() && {
323
auto
rows = [
this
] {
324
if
constexpr
(std::is_same_v<
RowTag
, ExtractionTag>) {
325
return
std::move(*
this
).AsVector<T>();
326
}
else
{
327
return
std::move(*
this
).AsVector<T>(kFieldTag);
328
}
329
}();
330
331
if
(rows.empty()) {
332
return
std::nullopt;
333
}
334
335
if
(rows.size() > 1) {
336
throw
std::runtime_error{fmt::format(
"There is more than one row in result set ({} rows)"
, rows.size())};
337
}
338
339
return
{std::move(rows.front())};
340
}
341
342
template
<
typename
DbType>
343
MappedStatementResultSet
<DbType>::MappedStatementResultSet(StatementResultSet&& result_set)
344
: result_set_{std::move(result_set)}
345
{}
346
347
template
<
typename
DbType>
348
MappedStatementResultSet
<DbType>::~MappedStatementResultSet() =
default
;
349
350
template
<
typename
DbType
>
351
template
<
typename
T>
352
std::vector<T>
MappedStatementResultSet
<DbType>::
AsVector
() && {
353
return
std::move(*
this
).
template
AsContainer<std::vector<T>>();
354
}
355
356
template
<
typename
DbType
>
357
template
<
typename
T>
358
std::vector<T>
MappedStatementResultSet
<DbType>::
AsVector
(
FieldTag
) && {
359
return
std::move(*
this
).
template
AsContainer<std::vector<T>>(kFieldTag);
360
}
361
362
template
<
typename
DbType
>
363
template
<
typename
Container>
364
Container
MappedStatementResultSet
<DbType>::
AsContainer
() && {
365
return
std::move(result_set_).
template
DoAsContainerMapped<Container, DbType,
RowTag
>();
366
}
367
368
template
<
typename
DbType
>
369
template
<
typename
Container>
370
Container
MappedStatementResultSet
<DbType>::
AsContainer
(
FieldTag
) && {
371
return
std::move(result_set_).
template
DoAsContainerMapped<Container, DbType,
FieldTag
>();
372
}
373
374
template
<
typename
DbType>
375
MappedStatementResultSet
<DbType> StatementResultSet::
MapFrom
() && {
376
return
MappedStatementResultSet
<DbType>{std::move(*
this
)};
377
}
378
379
}
// namespace storages::mysql
380
381
USERVER_NAMESPACE_END
userver
storages
mysql
statement_result_set.hpp
Generated on
for userver by
Doxygen
1.17.0