9#include <boost/pfr/core.hpp>
11#include <userver/storages/clickhouse/impl/block_wrapper_fwd.hpp>
12#include <userver/storages/clickhouse/impl/iterators_helper.hpp>
13#include <userver/storages/clickhouse/io/columns/column_wrapper.hpp>
14#include <userver/storages/clickhouse/io/io_fwd.hpp>
16USERVER_NAMESPACE_BEGIN
22template <
typename MappedType>
23class ColumnsMapper
final {
25 explicit ColumnsMapper(
clickhouse::impl::BlockWrapper& block) : block_{block} {}
27 template <
typename Field, size_t Index>
28 void operator()(Field& field, std::integral_constant<size_t, Index> i) {
29 using ColumnType = std::tuple_element_t<Index, MappedType>;
30 static_assert(std::is_same_v<Field,
typename ColumnType::container_type>);
32 auto column = ColumnType{io::columns::GetWrappedColumn(block_, i)};
33 field.reserve(column.Size());
34 for (
auto& it : column) field.push_back(std::move(it));
41template <
typename Row>
42class RowsMapper
final {
44 using MappedType =
typename CppToClickhouse<Row>::mapped_type;
45 explicit RowsMapper(
clickhouse::impl::BlockWrapperPtr&& block) : block_{block.release()} {
46 IteratorsHelperT::Init(begin_iterators_, end_iterators_, *block_);
48 ~RowsMapper() =
default;
50 using IteratorsTupleT = clickhouse::impl::IteratorsTupleT<MappedType>;
52 class Iterator
final {
54 using iterator_category = std::forward_iterator_tag;
55 using difference_type = std::ptrdiff_t;
56 using value_type = Row;
57 using reference = value_type&;
58 using pointer = value_type*;
61 Iterator(IteratorsTupleT iterators);
63 Iterator operator++(
int);
64 Iterator& operator++();
65 reference operator*()
const;
66 pointer operator->()
const;
68 bool operator==(
const Iterator& other)
const;
69 bool operator!=(
const Iterator& other)
const;
71 friend class IteratorsTester;
74 Row& UpdateValue()
const;
76 class FieldMapper
final {
78 FieldMapper(
const IteratorsTupleT& iterators) : iterators_{iterators} {}
80 template <
typename Field, size_t Index>
81 void operator()(Field& field, [[maybe_unused]] std::integral_constant<size_t, Index> i)
const {
82 if constexpr (kCanMoveFromIterators) {
83 field = std::move(*std::get<Index>(iterators_));
85 field = *std::get<Index>(iterators_);
90 const IteratorsTupleT& iterators_;
93 IteratorsTupleT iterators_;
94 mutable std::optional<Row> current_value_ = std::nullopt;
97 Iterator begin()
const {
return Iterator{begin_iterators_}; }
98 Iterator end()
const {
return Iterator{end_iterators_}; }
100 friend class IteratorsTester;
103 template <
typename TypesTuple>
104 struct IteratorValuesAreNoexceptMovable;
106 template <
typename... Ts>
107 struct IteratorValuesAreNoexceptMovable<std::tuple<Ts...>>
108 : std::conjunction<std::is_nothrow_move_constructible<
typename Ts::iterator::value_type>...> {};
110 static constexpr auto kCanMoveFromIterators = IteratorValuesAreNoexceptMovable<MappedType>::value;
112 using IteratorsHelperT = clickhouse::impl::IteratorsHelper<MappedType>;
115 IteratorsTupleT begin_iterators_{};
116 IteratorsTupleT end_iterators_{};
119template <
typename Row>
120RowsMapper<Row>::Iterator::Iterator(IteratorsTupleT iterators) : iterators_{std::move(iterators)} {}
122template <
typename Row>
123typename RowsMapper<Row>::Iterator RowsMapper<Row>::Iterator::operator++(
int) {
125 old.iterators_ = IteratorsHelperT::PostfixIncrement(iterators_);
126 old.current_value_ = std::move_if_noexcept(current_value_);
127 current_value_.reset();
132template <
typename Row>
133typename RowsMapper<Row>::Iterator& RowsMapper<Row>::Iterator::operator++() {
134 IteratorsHelperT::PrefixIncrement(iterators_);
135 current_value_.reset();
140template <
typename Row>
141typename RowsMapper<Row>::Iterator::reference RowsMapper<Row>::Iterator::operator*()
const {
142 return UpdateValue();
145template <
typename Row>
146typename RowsMapper<Row>::Iterator::pointer RowsMapper<Row>::Iterator::operator->()
const {
147 return &UpdateValue();
150template <
typename Row>
151Row& RowsMapper<Row>::Iterator::UpdateValue()
const {
152 if (!current_value_.has_value()) {
154 boost::pfr::for_each_field(result, FieldMapper{iterators_});
155 current_value_.emplace(std::move(result));
158 return *current_value_;
161template <
typename Row>
162bool RowsMapper<Row>::Iterator::operator==(
const Iterator& other)
const {
163 return iterators_ == other.iterators_;
166template <
typename Row>
167bool RowsMapper<Row>::Iterator::operator!=(
const Iterator& other)
const {
168 return !((*
this) == other);