6#include <initializer_list> 
   15#include <fmt/format.h> 
   17#include <userver/storages/postgres/exceptions.hpp> 
   18#include <userver/storages/postgres/io/supported_types.hpp> 
   19#include <userver/storages/postgres/postgres_fwd.hpp> 
   21#include <userver/storages/postgres/detail/const_data_iterator.hpp> 
   23#include <userver/compiler/demangle.hpp> 
   24#include <userver/logging/log.hpp> 
   26USERVER_NAMESPACE_BEGIN
 
  212  RowDescription(detail::ResultWrapperPtr res) : res_{std::move(res)} {}
 
  220  detail::ResultWrapperPtr res_;
 
  225template <
typename T, 
typename ExtractionTag>
 
  228class FieldView 
final {
 
  230  using size_type = std::size_t;
 
  232  FieldView(
const detail::ResultWrapper& res, size_type row_index,
 
  233            size_type field_index)
 
  234      : res_{res}, row_index_{row_index}, field_index_{field_index} {}
 
  236  template <
typename T>
 
  237  size_type To(T&& val) 
const {
 
  238    using ValueType = 
typename std::decay<T>::type;
 
  239    auto fb = GetBuffer();
 
  240    return ReadNullable(fb, std::forward<T>(val),
 
  246  std::string_view Name() 
const;
 
  247  const io::TypeBufferCategory& GetTypeBufferCategories() 
const;
 
  249  template <
typename T>
 
  251                         std::true_type) 
const {
 
  252    using ValueType = 
typename std::decay<T>::type;
 
  255      NullSetter::SetNull(val);
 
  257      Read(fb, std::forward<T>(val));
 
  262  template <
typename T>
 
  263  size_type ReadNullable(
const io::
FieldBuffer& buffer, T&& val,
 
  264                         std::false_type) 
const {
 
  265    if (buffer.is_null) {
 
  266      throw FieldValueIsNull{field_index_, Name(), val};
 
  268      Read(buffer, std::forward<T>(val));
 
  270    return buffer.length;
 
  273  template <
typename T>
 
  275    using ValueType = 
typename std::decay<T>::type;
 
  276    io::
traits::CheckParser<ValueType>();
 
  278      io::ReadBuffer(buffer, std::forward<T>(val), GetTypeBufferCategories());
 
  281          fmt::format(
" (ResultSet error while reading field #{} name `{}`)",
 
  282                      field_index_, Name()));
 
  287  const detail::ResultWrapper& res_;
 
  288  const size_type row_index_;
 
  289  const size_type field_index_;
 
  295  using size_type = std::size_t;
 
  297  size_type RowIndex() 
const { 
return row_index_; }
 
  298  size_type FieldIndex() 
const { 
return field_index_; }
 
  306  Oid GetTypeOid() 
const;
 
  316  template <
typename T>
 
  317  size_type 
To(T&& val) 
const {
 
  318    return FieldView{*res_, row_index_, field_index_}.To(std::forward<T>(val));
 
  323  template <
typename T>
 
  324  void Coalesce(T& val, 
const T& default_val) 
const {
 
  334  template <
typename T>
 
  335  typename std::decay<T>::
type As() 
const {
 
  343  template <
typename T>
 
  345    if (IsNull()) 
return default_val;
 
  349  const io::TypeBufferCategory& GetTypeBufferCategories() 
const;
 
  356  Field(detail::ResultWrapperPtr res, size_type row, size_type col)
 
  357      : res_{std::move(res)}, row_index_{row}, field_index_{col} {}
 
  361  bool IsValid() 
const;
 
  362  int Compare(
const Field& rhs) 
const;
 
  363  std::ptrdiff_t Distance(
const Field& rhs) 
const;
 
  364  Field& Advance(std::ptrdiff_t);
 
  368  detail::ResultWrapperPtr res_;
 
  369  size_type row_index_{0};
 
  370  size_type field_index_{0};
 
  378  ConstFieldIterator() = 
default;
 
  383  ConstFieldIterator(detail::ResultWrapperPtr res, size_type row, size_type col)
 
  384      : ConstDataIterator(std::move(res), row, col) {}
 
  392  ReverseConstFieldIterator() = 
default;
 
  397  ReverseConstFieldIterator(detail::ResultWrapperPtr res, size_type row,
 
  399      : ConstDataIterator(std::move(res), row, col) {}
 
  411  using size_type = std::size_t;
 
  415  using value_type = 
Field;
 
  416  using reference = 
Field;
 
  417  using pointer = const_iterator;
 
  420  size_type RowIndex() 
const { 
return row_index_; }
 
  430  const_iterator cbegin() 
const;
 
  431  const_iterator begin() 
const { 
return cbegin(); }
 
  432  const_iterator cend() 
const;
 
  433  const_iterator end() 
const { 
return cend(); }
 
  437  const_reverse_iterator crbegin() 
const;
 
  438  const_reverse_iterator rbegin() 
const { 
return crbegin(); }
 
  439  const_reverse_iterator crend() 
const;
 
  440  const_reverse_iterator rend() 
const { 
return crend(); }
 
  449  reference 
operator[](
const std::string& name) 
const;
 
  472  template <
typename T>
 
  473  void To(T&& val) 
const;
 
  477  template <
typename T>
 
  483  template <
typename T>
 
  487  template <
typename... T>
 
  488  void To(T&&... val) 
const;
 
  500  template <
typename T, 
typename... Y>
 
  505  template <
typename T>
 
  514  template <
typename T>
 
  522  template <
typename... T>
 
  523  void To(
const std::initializer_list<std::string>& names, T&&... val) 
const;
 
  524  template <
typename... T>
 
  525  std::tuple<T...> As(
const std::initializer_list<std::string>& names) 
const;
 
  529  template <
typename... T>
 
  530  void To(
const std::initializer_list<size_type>& indexes, T&&... val) 
const;
 
  531  template <
typename... T>
 
  532  std::tuple<T...> As(
const std::initializer_list<size_type>& indexes) 
const;
 
  535  size_type IndexOfName(
const std::string&) 
const;
 
  537  FieldView GetFieldView(size_type index) 
const;
 
  544  Row(detail::ResultWrapperPtr res, size_type row)
 
  545      : res_{std::move(res)}, row_index_{row} {}
 
  549  bool IsValid() 
const;
 
  550  int Compare(
const Row& rhs) 
const;
 
  551  std::ptrdiff_t Distance(
const Row& rhs) 
const;
 
  552  Row& Advance(std::ptrdiff_t);
 
  555  detail::ResultWrapperPtr res_;
 
  556  size_type row_index_{0};
 
  564  ConstRowIterator() = 
default;
 
  569  ConstRowIterator(detail::ResultWrapperPtr res, size_type row)
 
  570      : ConstDataIterator(std::move(res), row) {}
 
  578  ReverseConstRowIterator() = 
default;
 
  583  ReverseConstRowIterator(detail::ResultWrapperPtr res, size_type row)
 
  584      : ConstDataIterator(std::move(res), row) {}
 
  602  using size_type = std::size_t;
 
  603  using difference_type = std::ptrdiff_t;
 
  604  static constexpr size_type npos = std::numeric_limits<size_type>::max();
 
  611  using value_type = 
Row;
 
  612  using reference = value_type;
 
  613  using pointer = const_iterator;
 
  616  explicit ResultSet(std::shared_ptr<detail::ResultWrapper> pimpl)
 
  617      : pimpl_{std::move(pimpl)} {}
 
  621  bool IsEmpty() 
const { 
return Size() == 0; }
 
  623  size_type RowsAffected() 
const;
 
  624  std::string CommandStatus() 
const;
 
  630  const_iterator cbegin() 
const&;
 
  631  const_iterator begin() 
const& { 
return cbegin(); }
 
  632  const_iterator cend() 
const&;
 
  633  const_iterator end() 
const& { 
return cend(); }
 
  636  const_iterator cbegin() 
const&& = 
delete;
 
  637  const_iterator begin() 
const&& = 
delete;
 
  638  const_iterator cend() 
const&& = 
delete;
 
  639  const_iterator end() 
const&& = 
delete;
 
  643  const_reverse_iterator crbegin() 
const&;
 
  644  const_reverse_iterator rbegin() 
const& { 
return crbegin(); }
 
  645  const_reverse_iterator crend() 
const&;
 
  646  const_reverse_iterator rend() 
const& { 
return crend(); }
 
  648  const_reverse_iterator crbegin() 
const&& = 
delete;
 
  649  const_reverse_iterator rbegin() 
const&& = 
delete;
 
  650  const_reverse_iterator crend() 
const&& = 
delete;
 
  651  const_reverse_iterator rend() 
const&& = 
delete;
 
  654  reference Front() 
const&;
 
  655  reference Back() 
const&;
 
  657  reference Front() 
const&& = 
delete;
 
  658  reference Back() 
const&& = 
delete;
 
  664  reference operator[](size_type index) 
const&& = 
delete;
 
  670  size_type FieldCount() 
const;
 
  680  template <
typename T>
 
  682  template <
typename T>
 
  683  auto AsSetOf(
RowTag) 
const;
 
  684  template <
typename T>
 
  689  template <
typename Container>
 
  691  template <
typename Container>
 
  692  Container AsContainer(
RowTag) 
const;
 
  697  template <
typename T>
 
  699  template <
typename T>
 
  700  auto AsSingleRow(
RowTag) 
const;
 
  701  template <
typename T>
 
  708  template <
typename T>
 
  710  template <
typename T>
 
  711  std::optional<T> AsOptionalSingleRow(
RowTag) 
const;
 
  712  template <
typename T>
 
  713  std::optional<T> AsOptionalSingleRow(
FieldTag) 
const;
 
  716  friend class detail::ConnectionImpl;
 
  717  void FillBufferCategories(
const UserTypes& types);
 
  718  void SetBufferCategoriesFrom(
const ResultSet&);
 
  720  template <
typename T, 
typename Tag>
 
  721  friend class TypedResultSet;
 
  722  friend class ConnectionImpl;
 
  724  std::shared_ptr<detail::ResultWrapper> pimpl_;
 
  730struct IsOptionalFromOptional : std::false_type {};
 
  733struct IsOptionalFromOptional<std::optional<std::optional<T>>>
 
  737struct IsOneVariant : std::false_type {};
 
  740struct IsOneVariant<std::variant<T>> : std::true_type {};
 
  742template <
typename... Args>
 
  743constexpr void AssertSaneTypeToDeserialize() {
 
  745      !(IsOptionalFromOptional<
 
  746            std::remove_const_t<std::remove_reference_t<Args>>>::value ||
 
  748      "Attempt to get an optional<optional<T>> was detected. Such " 
  749      "optional-from-optional types are very error prone, obfuscate code and " 
  750      "are ambiguous to deserialize. Change the type to just optional<T>");
 
  753            std::remove_const_t<std::remove_reference_t<Args>>>::value ||
 
  755      "Attempt to get an variant<T> was detected. Such variant from one type " 
  756      "obfuscates code. Change the type to just T");
 
  761template <
typename IndexTuple, 
typename... T>
 
  762struct RowDataExtractorBase;
 
  764template <std::size_t... Indexes, 
typename... T>
 
  765struct RowDataExtractorBase<std::index_sequence<Indexes...>, T...> {
 
  766  static void ExtractValues(
const Row& row, T&&... val) {
 
  767    static_assert(
sizeof...(Indexes) == 
sizeof...(T));
 
  769    std::size_t field_index = 0;
 
  770    const auto perform = [&](
auto&& arg) {
 
  771      row.GetFieldView(field_index++).To(std::forward<
decltype(arg)>(arg));
 
  773    (perform(std::forward<T>(val)), ...);
 
  775  static void ExtractTuple(
const Row& row, std::tuple<T...>& val) {
 
  776    static_assert(
sizeof...(Indexes) == 
sizeof...(T));
 
  778    std::size_t field_index = 0;
 
  779    const auto perform = [&](
auto& arg) {
 
  780      row.GetFieldView(field_index++).To(arg);
 
  782    (perform(std::get<Indexes>(val)), ...);
 
  784  static void ExtractTuple(
const Row& row, std::tuple<T...>&& val) {
 
  785    static_assert(
sizeof...(Indexes) == 
sizeof...(T));
 
  787    std::size_t field_index = 0;
 
  788    const auto perform = [&](
auto& arg) {
 
  789      row.GetFieldView(field_index++).To(arg);
 
  791    (perform(std::get<Indexes>(val)), ...);
 
  794  static void ExtractValues(
const Row& row,
 
  795                            const std::initializer_list<std::string>& names,
 
  797    (row[*(names.begin() + Indexes)].To(std::forward<T>(val)), ...);
 
  799  static void ExtractTuple(
const Row& row,
 
  800                           const std::initializer_list<std::string>& names,
 
  801                           std::tuple<T...>& val) {
 
  802    std::tuple<T...> tmp{row[*(names.begin() + Indexes)].
template As<T>()...};
 
  806  static void ExtractValues(
const Row& row,
 
  807                            const std::initializer_list<std::size_t>& indexes,
 
  809    (row[*(indexes.begin() + Indexes)].To(std::forward<T>(val)), ...);
 
  811  static void ExtractTuple(
const Row& row,
 
  812                           const std::initializer_list<std::size_t>& indexes,
 
  813                           std::tuple<T...>& val) {
 
  814    std::tuple<T...> tmp{row[*(indexes.begin() + Indexes)].
template As<T>()...};
 
  819template <
typename... T>
 
  820struct RowDataExtractor
 
  821    : RowDataExtractorBase<std::index_sequence_for<T...>, T...> {};
 
  824struct TupleDataExtractor;
 
  825template <
typename... T>
 
  826struct TupleDataExtractor<std::tuple<T...>>
 
  827    : RowDataExtractorBase<std::index_sequence_for<T...>, T...> {};
 
  830template <
typename RowType>
 
  831constexpr void AssertRowTypeIsMappedToPgOrIsCompositeType() {
 
  834      io::
traits::kIsMappedToPg<RowType> ||
 
  835          io::
traits::kIsCompositeType<RowType>,
 
  836      "Row type must be mapped to pg type(CppToUserPg) or one of the " 
  838      "1. primitive type. " 
  840      "3. Aggregation type. See std::aggregation. " 
  841      "4. Has a Introspect method that makes the std::tuple from your " 
  843      "For more info see `uPg: Typed PostgreSQL results` chapter in docs.");
 
  850  To(std::forward<T>(val), kFieldTag);
 
  855  detail::AssertSaneTypeToDeserialize<T>();
 
  857  using ValueType = std::decay_t<T>;
 
  858  io::traits::AssertIsValidRowType<ValueType>();
 
  859  using RowType = io::RowType<ValueType>;
 
  860  using TupleType = 
typename RowType::TupleType;
 
  861  constexpr auto tuple_size = RowType::size;
 
  862  if (tuple_size > Size()) {
 
  863    throw InvalidTupleSizeRequested(Size(), tuple_size);
 
  864  } 
else if (tuple_size < Size()) {
 
  866        << 
"Row size is greater that the number of data members in " 
  871  detail::TupleDataExtractor<TupleType>::ExtractTuple(
 
  872      *
this, RowType::GetTuple(std::forward<T>(val)));
 
  877  detail::AssertSaneTypeToDeserialize<T>();
 
  878  using ValueType = std::decay_t<T>;
 
  879  detail::AssertRowTypeIsMappedToPgOrIsCompositeType<ValueType>();
 
  887  (*
this)
[0
].To(std::forward<T>(val));
 
  890template <
typename... T>
 
  892  detail::AssertSaneTypeToDeserialize<T...>();
 
  893  if (
sizeof...(T) > 
Size()) {
 
  896  detail::RowDataExtractor<T...>::ExtractValues(*
this, std::forward<T>(val)...);
 
  899template <
typename T, 
typename... Y>
 
  901  if constexpr (
sizeof...(Y) > 0) {
 
  902    std::tuple<T, Y...> res;
 
  906    return As<T>(kFieldTag);
 
  910template <
typename... T>
 
  911void Row::
To(
const std::initializer_list<std::string>& names,
 
  913  detail::AssertSaneTypeToDeserialize<T...>();
 
  914  if (
sizeof...(T) != names.size()) {
 
  915    throw FieldTupleMismatch(names.size(), 
sizeof...(T));
 
  917  detail::RowDataExtractor<T...>::ExtractValues(*
this, names,
 
  918                                                std::forward<T>(val)...);
 
  921template <
typename... T>
 
  922std::tuple<T...> 
Row::As(
 
  923    const std::initializer_list<std::string>& names) 
const {
 
  924  if (
sizeof...(T) != names.size()) {
 
  925    throw FieldTupleMismatch(names.size(), 
sizeof...(T));
 
  927  std::tuple<T...> res;
 
  928  detail::RowDataExtractor<T...>::ExtractTuple(*
this, names, res);
 
  932template <
typename... T>
 
  933void Row::
To(
const std::initializer_list<size_type>& indexes,
 
  935  detail::AssertSaneTypeToDeserialize<T...>();
 
  936  if (
sizeof...(T) != indexes.size()) {
 
  937    throw FieldTupleMismatch(indexes.size(), 
sizeof...(T));
 
  939  detail::RowDataExtractor<T...>::ExtractValues(*
this, indexes,
 
  940                                                std::forward<T>(val)...);
 
  943template <
typename... T>
 
  944std::tuple<T...> 
Row::As(
 
  945    const std::initializer_list<size_type>& indexes) 
const {
 
  946  if (
sizeof...(T) != indexes.size()) {
 
  947    throw FieldTupleMismatch(indexes.size(), 
sizeof...(T));
 
  949  std::tuple<T...> res;
 
  950  detail::RowDataExtractor<T...>::ExtractTuple(*
this, indexes, res);
 
  956  return AsSetOf<T>(kFieldTag);
 
  961  detail::AssertSaneTypeToDeserialize<T>();
 
  962  using ValueType = std::decay_t<T>;
 
  963  io::traits::AssertIsValidRowType<ValueType>();
 
  964  return TypedResultSet<T, 
RowTag>{*
this};
 
  969  detail::AssertSaneTypeToDeserialize<T>();
 
  970  using ValueType = std::decay_t<T>;
 
  971  detail::AssertRowTypeIsMappedToPgOrIsCompositeType<ValueType>();
 
  972  if (FieldCount() > 1) {
 
  976  return TypedResultSet<T, 
FieldTag>{*
this};
 
  979template <
typename Container>
 
  981  detail::AssertSaneTypeToDeserialize<Container>();
 
  982  using ValueType = 
typename Container::value_type;
 
  984  if constexpr (
io::
traits::kCanReserve<Container>) {
 
  987  auto res = AsSetOf<ValueType>();
 
  989  auto inserter = 
io::
traits::Inserter(c);
 
  990  auto row_it = res.begin();
 
  991  for (std::size_t i = 0; i < res.Size(); ++i, ++row_it, ++inserter) {
 
  998template <
typename Container>
 
 1000  detail::AssertSaneTypeToDeserialize<Container>();
 
 1001  using ValueType = 
typename Container::value_type;
 
 1003  if constexpr (
io::
traits::kCanReserve<Container>) {
 
 1006  auto res = AsSetOf<ValueType>(kRowTag);
 
 1008  auto inserter = 
io::
traits::Inserter(c);
 
 1009  auto row_it = res.begin();
 
 1010  for (std::size_t i = 0; i < res.Size(); ++i, ++row_it, ++inserter) {
 
 1011    *inserter = *row_it;
 
 1017template <
typename T>
 
 1019  return AsSingleRow<T>(kFieldTag);
 
 1022template <
typename T>
 
 1024  detail::AssertSaneTypeToDeserialize<T>();
 
 1028  return Front().As<T>(kRowTag);
 
 1031template <
typename T>
 
 1033  detail::AssertSaneTypeToDeserialize<T>();
 
 1037  return Front().As<T>(kFieldTag);
 
 1040template <
typename T>
 
 1042  return AsOptionalSingleRow<T>(kFieldTag);
 
 1045template <
typename T>
 
 1047  return IsEmpty() ? std::nullopt : std::optional<T>{AsSingleRow<T>(kRowTag)};
 
 1050template <
typename T>
 
 1052  return IsEmpty() ? std::nullopt : std::optional<T>{AsSingleRow<T>(kFieldTag)};
 
 1057USERVER_NAMESPACE_END
 
 1059#include <userver/storages/postgres/typed_result_set.hpp>