userver: userver/storages/clickhouse/execution_result.hpp Source File
Loading...
Searching...
No Matches
execution_result.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/storages/clickhouse/execution_result.hpp
4/// @brief Result accessor.
5
6#include <memory>
7#include <type_traits>
8
9#include <boost/pfr/core.hpp>
10
11#include <userver/storages/clickhouse/impl/block_wrapper_fwd.hpp>
12#include <userver/storages/clickhouse/io/impl/validate.hpp>
13
14#include <userver/storages/clickhouse/io/result_mapper.hpp>
15
16USERVER_NAMESPACE_BEGIN
17
18namespace storages::clickhouse {
19
20// clang-format off
21
22/// Thin wrapper over underlying block of data, returned by
23/// storages::clickhouse::Cluster Execute methods
24///
25/// ## Usage example:
26///
27/// @snippet storages/tests/execute_chtest.cpp Sample CppToClickhouse specialization
28///
29/// @snippet storages/tests/execute_chtest.cpp Sample ExecutionResult usage
30
31// clang-format on
32class ExecutionResult final {
33public:
34 explicit ExecutionResult(impl::BlockWrapperPtr);
35 ExecutionResult(ExecutionResult&&) noexcept;
36 ~ExecutionResult();
37
38 /// Returns number of columns in underlying block.
40
41 /// Returns number of rows in underlying block columns.
43
44 /// Converts underlying block to strongly-typed struct of vectors.
45 /// See @ref clickhouse_io for better understanding of `T`'s requirements.
46 template <typename T>
47 T As() &&;
48
49 /// Converts underlying block to iterable of strongly-typed struct.
50 /// See @ref clickhouse_io for better understanding of `T`'s requirements.
51 template <typename T>
52 auto AsRows() &&;
53
54 /// Converts underlying block to strongly-typed container.
55 /// See @ref clickhouse_io for better understanding
56 /// of `Container::value_type`'s requirements.
57 template <typename Container>
58 Container AsContainer() &&;
59
60private:
61 impl::BlockWrapperPtr block_;
62};
63
64template <typename T>
65T ExecutionResult::As() && {
66 UASSERT(block_);
67 T result{};
68 io::impl::ValidateColumnsMapping(result);
69 io::impl::ValidateColumnsCount<T>(GetColumnsCount());
70
71 using MappedType = typename io::CppToClickhouse<T>::mapped_type;
72 io::ColumnsMapper<MappedType> mapper{*block_};
73
74 boost::pfr::for_each_field(result, mapper);
75
76 return result;
77}
78
79template <typename T>
80auto ExecutionResult::AsRows() && {
81 UASSERT(block_);
82 io::impl::ValidateRowsMapping<T>();
83 io::impl::ValidateColumnsCount<T>(GetColumnsCount());
84
85 return io::RowsMapper<T>{std::move(block_)};
86}
87
88template <typename Container>
89Container ExecutionResult::AsContainer() && {
90 UASSERT(block_);
91 using Row = typename Container::value_type;
92
93 Container result;
94 if constexpr (io::traits::kIsReservable<Container>) {
95 result.reserve(GetRowsCount());
96 }
97
98 auto rows = std::move(*this).AsRows<Row>();
99 std::move(rows.begin(), rows.end(), io::traits::Inserter(result));
100 return result;
101}
102
103} // namespace storages::clickhouse
104
105USERVER_NAMESPACE_END