12#include <fmt/format.h>
14#include <userver/storages/postgres/detail/typed_rows.hpp>
15#include <userver/storages/postgres/exceptions.hpp>
16#include <userver/storages/postgres/io/supported_types.hpp>
17#include <userver/storages/postgres/row.hpp>
19#include <userver/compiler/demangle.hpp>
20#include <userver/logging/log.hpp>
22USERVER_NAMESPACE_BEGIN
184template <
typename T,
typename ExtractionTag>
202 using size_type = std::size_t;
203 using difference_type = std::ptrdiff_t;
204 static constexpr size_type npos = std::numeric_limits<size_type>::max();
211 using value_type =
Row;
212 using reference = value_type;
213 using pointer = const_iterator;
216 explicit ResultSet(std::shared_ptr<detail::ResultWrapper> pimpl) : pimpl_{std::move(pimpl)} {}
220 bool IsEmpty()
const {
return Size() == 0; }
222 size_type RowsAffected()
const;
223 std::string CommandStatus()
const;
229 const_iterator cbegin()
const&;
230 const_iterator begin()
const& {
return cbegin(); }
231 const_iterator cend()
const&;
232 const_iterator end()
const& {
return cend(); }
235 const_iterator cbegin()
const&& =
delete;
236 const_iterator begin()
const&& =
delete;
237 const_iterator cend()
const&& =
delete;
238 const_iterator end()
const&& =
delete;
242 const_reverse_iterator crbegin()
const&;
243 const_reverse_iterator rbegin()
const& {
return crbegin(); }
244 const_reverse_iterator crend()
const&;
245 const_reverse_iterator rend()
const& {
return crend(); }
247 const_reverse_iterator crbegin()
const&& =
delete;
248 const_reverse_iterator rbegin()
const&& =
delete;
249 const_reverse_iterator crend()
const&& =
delete;
250 const_reverse_iterator rend()
const&& =
delete;
253 reference Front()
const&;
254 reference Back()
const&;
256 reference Front()
const&& =
delete;
257 reference Back()
const&& =
delete;
263 reference operator[](size_type index)
const&& =
delete;
269 size_type FieldCount()
const;
279 template <
typename T>
281 template <
typename T>
282 auto AsSetOf(
RowTag)
const;
283 template <
typename T>
288 template <
typename Container>
290 template <
typename Container>
291 Container AsContainer(
RowTag)
const;
296 template <
typename T>
298 template <
typename T>
299 auto AsSingleRow(
RowTag)
const;
300 template <
typename T>
307 template <
typename T>
309 template <
typename T>
310 std::optional<T> AsOptionalSingleRow(
RowTag)
const;
311 template <
typename T>
312 std::optional<T> AsOptionalSingleRow(
FieldTag)
const;
315 friend class detail::ConnectionImpl;
316 void FillBufferCategories(
const UserTypes& types);
317 void SetBufferCategoriesFrom(
const ResultSet&);
319 template <
typename T,
typename Tag>
320 friend class TypedResultSet;
321 friend class ConnectionImpl;
323 std::shared_ptr<detail::ResultWrapper> pimpl_;
328 return AsSetOf<T>(kFieldTag);
333 detail::AssertSaneTypeToDeserialize<T>();
334 using ValueType = std::decay_t<T>;
335 io::
traits::AssertIsValidRowType<ValueType>();
336 return TypedResultSet<T,
RowTag>{*
this};
341 detail::AssertSaneTypeToDeserialize<T>();
342 using ValueType = std::decay_t<T>;
343 detail::AssertRowTypeIsMappedToPgOrIsCompositeType<ValueType>();
344 if (FieldCount() > 1) {
347 return TypedResultSet<T,
FieldTag>{*
this};
350template <
typename Container>
352 detail::AssertSaneTypeToDeserialize<Container>();
353 using ValueType =
typename Container::value_type;
355 if constexpr (io::
traits::kCanReserve<Container>) {
358 auto res = AsSetOf<ValueType>();
360 auto inserter = io::
traits::Inserter(c);
361 auto row_it = res.begin();
362 for (std::size_t i = 0; i < res.Size(); ++i, ++row_it, ++inserter) {
369template <
typename Container>
371 detail::AssertSaneTypeToDeserialize<Container>();
372 using ValueType =
typename Container::value_type;
374 if constexpr (io::
traits::kCanReserve<Container>) {
377 auto res = AsSetOf<ValueType>(kRowTag);
379 auto inserter = io::
traits::Inserter(c);
380 auto row_it = res.begin();
381 for (std::size_t i = 0; i < res.Size(); ++i, ++row_it, ++inserter) {
390 return AsSingleRow<T>(kFieldTag);
395 detail::AssertSaneTypeToDeserialize<T>();
399 return Front().As<T>(kRowTag);
404 detail::AssertSaneTypeToDeserialize<T>();
408 return Front().As<T>(kFieldTag);
413 return AsOptionalSingleRow<T>(kFieldTag);
418 return IsEmpty() ? std::nullopt : std::optional<T>{AsSingleRow<T>(kRowTag)};
423 return IsEmpty() ? std::nullopt : std::optional<T>{AsSingleRow<T>(kFieldTag)};
561template <
typename T,
typename ExtractionTag>
562class TypedResultSet {
565 using difference_type =
ResultSet::difference_type;
566 static constexpr size_type npos =
ResultSet::npos;
567 static constexpr ExtractionTag kExtractTag{};
571 using const_iterator = detail::ConstTypedRowIterator<T, ExtractionTag, detail::IteratorDirection::kForward>;
572 using const_reverse_iterator = detail::ConstTypedRowIterator<T, ExtractionTag, detail::IteratorDirection::kReverse>;
574 using value_type = T;
575 using pointer = const_iterator;
580 using reference = value_type;
582 using reference = std::add_const_t<value_type>;
586 explicit TypedResultSet(
ResultSet result) : result_{std::move(result)} {}
590 bool IsEmpty()
const {
return Size() == 0; }
597 const_iterator cbegin()
const& {
return const_iterator{result_.pimpl_, 0}; }
598 const_iterator begin()
const& {
return cbegin(); }
599 const_iterator cend()
const& {
return const_iterator{result_.pimpl_,
Size()}; }
600 const_iterator end()
const& {
return cend(); }
601 const_iterator cbegin()
const&& { ReportMisuse(); }
602 const_iterator begin()
const&& { ReportMisuse(); }
603 const_iterator cend()
const&& { ReportMisuse(); }
604 const_iterator end()
const&& { ReportMisuse(); }
608 const_reverse_iterator crbegin()
const& {
return const_reverse_iterator(result_.pimpl_,
Size() - 1); }
609 const_reverse_iterator rbegin()
const& {
return crbegin(); }
610 const_reverse_iterator crend()
const& {
return const_reverse_iterator(result_.pimpl_, npos); }
611 const_reverse_iterator rend()
const& {
return crend(); }
612 const_reverse_iterator crbegin()
const&& { ReportMisuse(); }
613 const_reverse_iterator rbegin()
const&& { ReportMisuse(); }
614 const_reverse_iterator crend()
const&& { ReportMisuse(); }
615 const_reverse_iterator rend()
const&& { ReportMisuse(); }
620 reference
operator[](size_type index)
const& {
return result_
[index
].
template As<value_type>(kExtractTag); }
622 reference operator[](size_type)
const&& { ReportMisuse(); }
625 [[noreturn]]
static void ReportMisuse() {
626 static_assert(!
sizeof(T),
"keep the TypedResultSet before using, please");