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/// Thin wrapper over underlying block of data, returned by
21/// storages::clickhouse::Cluster Execute methods
22///
23/// ## Usage example:
24///
25/// @snippet storages/tests/execute_chtest.cpp Sample CppToClickhouse specialization
26///
27/// @snippet storages/tests/execute_chtest.cpp Sample ExecutionResult usage
28class ExecutionResult final {
29public:
30 explicit ExecutionResult(impl::BlockWrapperPtr);
31 ExecutionResult(ExecutionResult&&) noexcept;
32 ~ExecutionResult();
33
34 /// Returns number of columns in underlying block.
35 size_t GetColumnsCount() const;
36
37 /// Returns number of rows in underlying block columns.
38 size_t GetRowsCount() const;
39
40 /// Converts underlying block to strongly-typed struct of vectors.
41 /// See @ref scripts/docs/en/userver/clickhouse/io.md for better understanding of `T`'s requirements.
42 template <typename T>
43 T As() &&;
44
45 /// Converts underlying block to iterable of strongly-typed struct.
46 /// See @ref scripts/docs/en/userver/clickhouse/io.md for better understanding of `T`'s requirements.
47 template <typename T>
48 auto AsRows() &&;
49
50 /// Converts underlying block to strongly-typed container.
51 /// See @ref scripts/docs/en/userver/clickhouse/io.md for better understanding
52 /// of `Container::value_type`'s requirements.
53 template <typename Container>
54 Container AsContainer() &&;
55
56private:
57 impl::BlockWrapperPtr block_;
58};
59
60template <typename T>
61T ExecutionResult::As() && {
62 UASSERT(block_);
63 T result{};
64 io::impl::ValidateColumnsMapping(result);
65 io::impl::ValidateColumnsCount<T>(GetColumnsCount());
66
67 using MappedType = typename io::CppToClickhouse<T>::mapped_type;
68 io::ColumnsMapper<MappedType> mapper{*block_};
69
70 boost::pfr::for_each_field(result, mapper);
71
72 return result;
73}
74
75template <typename T>
76auto ExecutionResult::AsRows() && {
77 UASSERT(block_);
78 io::impl::ValidateRowsMapping<T>();
79 io::impl::ValidateColumnsCount<T>(GetColumnsCount());
80
81 return io::RowsMapper<T>{std::move(block_)};
82}
83
84template <typename Container>
85Container ExecutionResult::AsContainer() && {
86 UASSERT(block_);
87 using Row = typename Container::value_type;
88
89 Container result;
90 if constexpr (io::traits::kIsReservable<Container>) {
91 result.reserve(GetRowsCount());
92 }
93
94 auto rows = std::move(*this).AsRows<Row>();
95 std::move(rows.begin(), rows.end(), io::traits::Inserter(result));
96 return result;
97}
98
99} // namespace storages::clickhouse
100
101USERVER_NAMESPACE_END