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
 
   23class StatementFetcher;
 
   30template <
typename DbType>
 
   31class MappedStatementResultSet;
 
   37class StatementResultSet 
final {
 
   39  explicit StatementResultSet(impl::StatementFetcher&& fetcher,
 
   41  StatementResultSet(infra::ConnectionPtr&& connection,
 
   42                     impl::StatementFetcher&& fetcher, 
tracing::Span&& span);
 
   43  ~StatementResultSet();
 
   45  StatementResultSet(
const StatementResultSet& other) = 
delete;
 
   46  StatementResultSet(StatementResultSet&& other) 
noexcept;
 
   85  template <
typename Container>
 
   99  template <
typename Container>
 
  114  template <
typename T>
 
  128  template <
typename T>
 
  143  template <
typename T>
 
  157  template <
typename T>
 
  169  template <
typename DbType>
 
  170  MappedStatementResultSet<DbType> 
MapFrom() &&;
 
  176  template <
typename T>
 
  177  friend class CursorResultSet;
 
  179  template <
typename DbType>
 
  180  friend class MappedStatementResultSet;
 
  182  template <
typename Container, 
typename MapFrom, 
typename ExtractionTag>
 
  183  Container DoAsContainerMapped() &&;
 
  185  template <
typename T, 
typename ExtractionTag>
 
  186  std::optional<T> DoAsOptionalSingleRow() &&;
 
  188  bool FetchResult(impl::io::ExtractorBase& extractor);
 
  191  utils::FastPimpl<Impl, 72, 8> impl_;
 
  205template <
typename DbType>
 
  206class MappedStatementResultSet 
final {
 
  208  explicit MappedStatementResultSet(StatementResultSet&& result_set);
 
  209  ~MappedStatementResultSet();
 
  217  template <
typename T>
 
  226  template <
typename T>
 
  235  template <
typename Container>
 
  244  template <
typename Container>
 
  247  template <
typename T>
 
  249    static_assert(!
sizeof(T),
 
  250                  "Not implemented, just use StatementResultSet version and " 
  251                  "convert yourself.");
 
  254  template <
typename T>
 
  255  std::optional<T> AsOptionalSingleRow() && {
 
  256    static_assert(!
sizeof(T),
 
  257                  "Not implemented, just use StatementResultSet version and " 
  258                  "convert yourself.");
 
  262  StatementResultSet result_set_;
 
  267  return std::move(*
this).AsContainer<std::vector<T>>();
 
  272  return std::move(*
this).AsContainer<std::vector<T>>(kFieldTag);
 
  275template <
typename Container>
 
  277  static_assert(meta::kIsRange<Container>,
 
  278                "The type isn't actually a container");
 
  279  using Row = 
typename Container::value_type;
 
  281  return std::move(*
this).DoAsContainerMapped<Container, Row, 
RowTag>();
 
  284template <
typename Container>
 
  286  static_assert(meta::kIsRange<Container>,
 
  287                "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>,
 
  328                "The type isn't actually a container");
 
  329  using Extractor = impl::io::TypedExtractor<Container, MapFrom, ExtractionTag>;
 
  331  Extractor extractor{};
 
  334  std::move(*
this).FetchResult(extractor);
 
  337  return Container{extractor.ExtractData()};
 
  340template <
typename T, 
typename ExtractionTag>
 
  341std::optional<T> StatementResultSet::DoAsOptionalSingleRow() && {
 
  343    if constexpr (std::is_same_v<
RowTag, ExtractionTag>) {
 
  344      return std::move(*
this).AsVector<T>();
 
  346      return std::move(*
this).AsVector<T>(kFieldTag);
 
  354  if (rows.size() > 1) {
 
  355    throw std::runtime_error{fmt::format(
 
  356        "There is more than one row in result set ({} rows)", rows.size())};
 
  359  return {std::move(rows.front())};
 
  362template <
typename DbType>
 
  363MappedStatementResultSet<DbType>::MappedStatementResultSet(
 
  364    StatementResultSet&& result_set)
 
  365    : result_set_{std::move(result_set)} {}
 
  367template <
typename DbType>
 
  368MappedStatementResultSet<DbType>::~MappedStatementResultSet() = 
default;
 
  373  return std::move(*
this).
template AsContainer<std::vector<T>>();
 
  379  return std::move(*
this).
template AsContainer<std::vector<T>>(kFieldTag);
 
  383template <
typename Container>
 
  385  return std::move(result_set_)
 
  386      .DoAsContainerMapped<Container, DbType, RowTag>();
 
  390template <
typename Container>
 
  392  return std::move(result_set_)
 
  393      .DoAsContainerMapped<Container, DbType, FieldTag>();
 
  396template <
typename DbType>
 
  397MappedStatementResultSet<DbType> StatementResultSet::
MapFrom() && {
 
  398  return MappedStatementResultSet<DbType>{std::move(*
this)};