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;
77 template <
typename Container>
89 template <
typename Container>
102 template <
typename T>
114 template <
typename T>
127 template <
typename T>
139 template <
typename T>
149 template <
typename DbType>
150 MappedStatementResultSet<DbType>
MapFrom() &&;
156 template <
typename T>
157 friend class CursorResultSet;
159 template <
typename DbType>
160 friend class MappedStatementResultSet;
162 template <
typename Container,
typename MapFrom,
typename ExtractionTag>
163 Container DoAsContainerMapped() &&;
165 template <
typename T,
typename ExtractionTag>
166 std::optional<T> DoAsOptionalSingleRow() &&;
168 bool FetchResult(impl::io::ExtractorBase& extractor);
171 utils::FastPimpl<Impl, 72, 8> impl_;
185template <
typename DbType>
186class MappedStatementResultSet
final {
188 explicit MappedStatementResultSet(StatementResultSet&& result_set);
189 ~MappedStatementResultSet();
197 template <
typename T>
206 template <
typename T>
215 template <
typename Container>
224 template <
typename Container>
227 template <
typename T>
231 "Not implemented, just use StatementResultSet version and "
236 template <
typename T>
237 std::optional<T> AsOptionalSingleRow() && {
240 "Not implemented, just use StatementResultSet version and "
246 StatementResultSet result_set_;
251 return std::move(*
this).AsContainer<std::vector<T>>();
256 return std::move(*
this).AsContainer<std::vector<T>>(kFieldTag);
259template <
typename Container>
261 static_assert(meta::kIsRange<Container>,
"The type isn't actually a container");
262 using Row =
typename Container::value_type;
264 return std::move(*
this).DoAsContainerMapped<Container, Row,
RowTag>();
267template <
typename Container>
269 static_assert(meta::kIsRange<Container>,
"The type isn't actually a container");
270 using Row =
typename Container::value_type;
272 return std::move(*
this).DoAsContainerMapped<Container, Row,
FieldTag>();
277 auto optional_data = std::move(*
this).AsOptionalSingleRow<T>();
279 if (!optional_data.has_value()) {
280 throw std::runtime_error{
"Result set is empty"};
283 return std::move(*optional_data);
288 auto optional_data = std::move(*
this).AsOptionalSingleField<T>();
290 if (!optional_data.has_value()) {
291 throw std::runtime_error{
"Result set is empty"};
294 return std::move(*optional_data);
299 return std::move(*
this).DoAsOptionalSingleRow<T,
RowTag>();
304 return std::move(*
this).DoAsOptionalSingleRow<T,
FieldTag>();
307template <
typename Container,
typename MapFromType,
typename ExtractionTag>
308Container StatementResultSet::DoAsContainerMapped() && {
309 static_assert(meta::kIsRange<Container>,
"The type isn't actually a container");
310 using Extractor = impl::io::TypedExtractor<Container, MapFromType, ExtractionTag>;
312 Extractor extractor{};
315 std::move(*
this).FetchResult(extractor);
318 return Container{extractor.ExtractData()};
321template <
typename T,
typename ExtractionTag>
322std::optional<T> StatementResultSet::DoAsOptionalSingleRow() && {
324 if constexpr (std::is_same_v<
RowTag, ExtractionTag>) {
325 return std::move(*
this).AsVector<T>();
327 return std::move(*
this).AsVector<T>(kFieldTag);
335 if (rows.size() > 1) {
336 throw std::runtime_error{fmt::format(
"There is more than one row in result set ({} rows)", rows.size())};
339 return {std::move(rows.front())};
342template <
typename DbType>
343MappedStatementResultSet<DbType>::MappedStatementResultSet(StatementResultSet&& result_set)
344 : result_set_{std::move(result_set)}
347template <
typename DbType>
348MappedStatementResultSet<DbType>::~MappedStatementResultSet() =
default;
352std::vector<T> MappedStatementResultSet<DbType>::
AsVector() && {
353 return std::move(*
this).
template AsContainer<std::vector<T>>();
359 return std::move(*
this).
template AsContainer<std::vector<T>>(kFieldTag);
363template <
typename Container>
365 return std::move(result_set_).
template DoAsContainerMapped<Container, DbType,
RowTag>();
369template <
typename Container>
371 return std::move(result_set_).
template DoAsContainerMapped<Container, DbType,
FieldTag>();
374template <
typename DbType>
375MappedStatementResultSet<DbType> StatementResultSet::
MapFrom() && {
376 return MappedStatementResultSet<DbType>{std::move(*
this)};