10#include <userver/engine/deadline.hpp>
11#include <userver/tracing/scope_time.hpp>
12#include <userver/utils/fast_pimpl.hpp>
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>
18USERVER_NAMESPACE_BEGIN
20namespace storages::
mysql {
23class StatementFetcher;
30template <
typename DbType>
31class MappedStatementResultSet;
37class StatementResultSet
final {
39 explicit StatementResultSet(impl::StatementFetcher&& fetcher,
tracing::Span&& span);
40 StatementResultSet(infra::ConnectionPtr&& connection, impl::StatementFetcher&& fetcher,
tracing::Span&& span);
41 ~StatementResultSet();
43 StatementResultSet(
const StatementResultSet& other) =
delete;
44 StatementResultSet(StatementResultSet&& other)
noexcept;
83 template <
typename Container>
97 template <
typename Container>
112 template <
typename T>
126 template <
typename T>
141 template <
typename T>
155 template <
typename T>
167 template <
typename DbType>
168 MappedStatementResultSet<DbType>
MapFrom() &&;
174 template <
typename T>
175 friend class CursorResultSet;
177 template <
typename DbType>
178 friend class MappedStatementResultSet;
180 template <
typename Container,
typename MapFrom,
typename ExtractionTag>
181 Container DoAsContainerMapped() &&;
183 template <
typename T,
typename ExtractionTag>
184 std::optional<T> DoAsOptionalSingleRow() &&;
186 bool FetchResult(impl::io::ExtractorBase& extractor);
189 utils::FastPimpl<Impl, 72, 8> impl_;
203template <
typename DbType>
204class MappedStatementResultSet
final {
206 explicit MappedStatementResultSet(StatementResultSet&& result_set);
207 ~MappedStatementResultSet();
215 template <
typename T>
224 template <
typename T>
233 template <
typename Container>
242 template <
typename Container>
245 template <
typename T>
249 "Not implemented, just use StatementResultSet version and "
254 template <
typename T>
255 std::optional<T> AsOptionalSingleRow() && {
258 "Not implemented, just use StatementResultSet version and "
264 StatementResultSet result_set_;
269 return std::move(*
this).AsContainer<std::vector<T>>();
274 return std::move(*
this).AsContainer<std::vector<T>>(kFieldTag);
277template <
typename Container>
279 static_assert(meta::kIsRange<Container>,
"The type isn't actually a container");
280 using Row =
typename Container::value_type;
282 return std::move(*
this).DoAsContainerMapped<Container, Row,
RowTag>();
285template <
typename Container>
287 static_assert(meta::kIsRange<Container>,
"The type isn't actually a container");
288 using Row =
typename Container::value_type;
290 return std::move(*
this).DoAsContainerMapped<Container, Row,
FieldTag>();
295 auto optional_data = std::move(*
this).AsOptionalSingleRow<T>();
297 if (!optional_data.has_value()) {
298 throw std::runtime_error{
"Result set is empty"};
301 return std::move(*optional_data);
306 auto optional_data = std::move(*
this).AsOptionalSingleField<T>();
308 if (!optional_data.has_value()) {
309 throw std::runtime_error{
"Result set is empty"};
312 return std::move(*optional_data);
317 return std::move(*
this).DoAsOptionalSingleRow<T,
RowTag>();
322 return std::move(*
this).DoAsOptionalSingleRow<T,
FieldTag>();
325template <
typename Container,
typename MapFrom,
typename ExtractionTag>
326Container StatementResultSet::DoAsContainerMapped() && {
327 static_assert(meta::kIsRange<Container>,
"The type isn't actually a container");
328 using Extractor = impl::io::TypedExtractor<Container, MapFrom, ExtractionTag>;
330 Extractor extractor{};
333 std::move(*
this).FetchResult(extractor);
336 return Container{extractor.ExtractData()};
339template <
typename T,
typename ExtractionTag>
340std::optional<T> StatementResultSet::DoAsOptionalSingleRow() && {
342 if constexpr (std::is_same_v<
RowTag, ExtractionTag>) {
343 return std::move(*
this).AsVector<T>();
345 return std::move(*
this).AsVector<T>(kFieldTag);
353 if (rows.size() > 1) {
354 throw std::runtime_error{fmt::format(
"There is more than one row in result set ({} rows)", rows.size())};
357 return {std::move(rows.front())};
360template <
typename DbType>
361MappedStatementResultSet<DbType>::MappedStatementResultSet(StatementResultSet&& result_set)
362 : result_set_{std::move(result_set)} {}
364template <
typename DbType>
365MappedStatementResultSet<DbType>::~MappedStatementResultSet() =
default;
370 return std::move(*
this).
template AsContainer<std::vector<T>>();
376 return std::move(*
this).
template AsContainer<std::vector<T>>(kFieldTag);
380template <
typename Container>
382 return std::move(result_set_).DoAsContainerMapped<Container, DbType, RowTag>();
386template <
typename Container>
388 return std::move(result_set_).DoAsContainerMapped<Container, DbType, FieldTag>();
391template <
typename DbType>
392MappedStatementResultSet<DbType> StatementResultSet::
MapFrom() && {
393 return MappedStatementResultSet<DbType>{std::move(*
this)};