userver: userver/storages/sqlite/client.hpp Source File
Loading...
Searching...
No Matches
client.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/storages/sqlite/client.hpp
4/// @brief @copybrief storages::sqlite::Client
5
6#include <exception>
7
8#include <userver/engine/task/task_processor_fwd.hpp>
9#include <userver/utils/statistics/writer.hpp>
10
11#include <userver/storages/sqlite/cursor_result_set.hpp>
12#include <userver/storages/sqlite/impl/binder_help.hpp>
13#include <userver/storages/sqlite/infra/connection_ptr.hpp>
14#include <userver/storages/sqlite/operation_types.hpp>
15#include <userver/storages/sqlite/options.hpp>
16#include <userver/storages/sqlite/query.hpp>
17#include <userver/storages/sqlite/result_set.hpp>
18#include <userver/storages/sqlite/savepoint.hpp>
19#include <userver/storages/sqlite/sqlite_fwd.hpp>
20#include <userver/storages/sqlite/transaction.hpp>
21
22USERVER_NAMESPACE_BEGIN
23
24namespace storages::sqlite {
25
26/// @ingroup userver_clients
27///
28/// @brief Interface for executing queries on SQLite connection.
29/// Usually retrieved from components::SQLite
30class Client final {
31public:
32 /// @brief Client constructor
33 Client(const settings::SQLiteSettings& settings, engine::TaskProcessor& blocking_task_processor);
34
35 /// @brief Client destructor
37
38 /// @brief Executes a statement with provided operation type.
39 ///
40 /// Fills placeholders of the statement with args..., `Args` are expected to
41 /// be of supported types.
42 /// See @ref scripts/docs/en/userver/sqlite/supported_types.md for better understanding of `Args`
43 /// requirements.
44 ///
45 /// @tparam Args Types of parameters to bind
46 /// @param operation_type Type of the operation (e.g., Read, Write)
47 /// @param query SQL query to execute
48 /// @param args Parameters to bind to the query
49 /// @return ResultSet containing the results of the query
50 template <typename... Args>
51 ResultSet Execute(OperationType operation_type, const Query& query, const Args&... args) const;
52
53 /// @brief Executes a statement with provided operation type, decomposing the row.
54 ///
55 /// Decomposes the fields of the row and binds them as parameters to the query.
56 /// See @ref scripts/docs/en/userver/sqlite/supported_types.md for better understanding of `T` requirements.
57 ///
58 /// @tparam T Type of the row to decompose
59 /// @param operation_type Type of the operation (e.g., Read, Write)
60 /// @param query SQL query to execute
61 /// @param row Row object to decompose and bind
62 /// @return ResultSet containing the results of the query
63 template <typename T>
64 ResultSet ExecuteDecompose(OperationType operation_type, const Query& query, const T& row) const;
65
66 /// @brief Executes a statement multiple times with provided operation type.
67 ///
68 /// Iterates over the container and executes the query for each element.
69 /// Container is expected to be a std::Container, Container::value_type is
70 /// expected to be an aggregate of supported types.
71 /// See @ref scripts/docs/en/userver/mysql/supported_types.md for better understanding of
72 /// `Container::value_type` requirements.
73 ///
74 /// @tparam Container Type of the container holding rows
75 /// @param operation_type Type of the operation (e.g., Read, Write)
76 /// @param query SQL query to execute
77 /// @param params Container of rows to bind and execute
78 template <typename Container>
79 void ExecuteMany(OperationType operation_type, const Query& query, const Container& params) const;
80
81 /// @brief Begins a transaction with specified operation type and options.
82 ///
83 /// @param operation_type Type of the operation (e.g., Read, Write)
84 /// @param options Transaction options
85 /// @return Transaction object representing the started transaction
86 Transaction Begin(OperationType operation_type, const settings::TransactionOptions& options) const;
87
88 /// @brief Creates a savepoint with specified operation type and name.
89 ///
90 /// @param operation_type Type of the operation (e.g., Read, Write)
91 /// @param name Name of the savepoint
92 /// @return Savepoint object representing the created savepoint
93 Savepoint Save(OperationType operation_type, std::string name) const;
94
95 /// @brief Executes a statement and returns a lazy cursor for batched result retrieval.
96 ///
97 /// This cursor combines execution and iteration: it fetches up to `batch_size` rows
98 /// on each step, loading data on demand rather than all at once. Placeholders in the
99 /// statement are filled with `args...`, which must be of supported types.
100 /// See @ref scripts/docs/en/userver/sqlite/supported_types.md for detailed mapping of `Args`.
101 ///
102 /// @tparam T Type of each result row
103 /// @tparam Args Parameter types to bind
104 /// @param operation_type Hint for selecting the connection pool (e.g., ReadOnly, ReadWrite)
105 /// @param batch_size Number of rows to fetch per iteration
106 /// @param query SQL query to execute
107 /// @param args Parameters to bind to the query
108 /// @return CursorResultSet<T> lazily delivering rows in batches
109 template <typename T, typename... Args>
110 CursorResultSet<T> GetCursor(
111 OperationType operation_type,
112 std::size_t batch_size,
113 const Query& query,
114 const Args&... args
115 ) const;
116
117 /// @brief Writes client statistics to the provided writer.
118 ///
119 /// @param writer Statistics writer to output the statistics
120 void WriteStatistics(utils::statistics::Writer& writer) const;
121
122private:
123 ResultSet DoExecute(impl::io::ParamsBinderBase& params, std::shared_ptr<infra::ConnectionPtr> connection) const;
124
125 std::shared_ptr<infra::ConnectionPtr> GetConnection(OperationType operation_type) const;
126
127 void AccountQueryExecute(std::shared_ptr<infra::ConnectionPtr> connection) const noexcept;
128 void AccountQueryFailed(std::shared_ptr<infra::ConnectionPtr> connection) const noexcept;
129
130 impl::ClientImplPtr pimpl_;
131};
132
133template <typename... Args>
134ResultSet Client::Execute(OperationType operation_type, const Query& query, const Args&... args) const {
135 auto connection = GetConnection(operation_type);
136 AccountQueryExecute(connection);
137 try {
138 auto params_binder = impl::BindHelper::UpdateParamsBindings(query, *connection, args...);
139 return DoExecute(params_binder, connection);
140 } catch (const std::exception& err) {
141 AccountQueryFailed(connection);
142 throw;
143 }
144}
145
146template <typename T>
147ResultSet Client::ExecuteDecompose(OperationType operation_type, const Query& query, const T& row) const {
148 auto connection = GetConnection(operation_type);
149 AccountQueryExecute(connection);
150 try {
151 auto params_binder = impl::BindHelper::UpdateRowAsParamsBindings(query, *connection, row);
152 return DoExecute(params_binder, connection);
153 } catch (const std::exception& err) {
154 AccountQueryFailed(connection);
155 throw;
156 }
157}
158
159template <typename Container>
160void Client::ExecuteMany(OperationType operation_type, const Query& query, const Container& params) const {
161 auto connection = GetConnection(operation_type);
162 for (const auto& row : params) {
163 AccountQueryExecute(connection);
164 try {
165 auto params_binder = impl::BindHelper::UpdateRowAsParamsBindings(query, *connection, row);
166 DoExecute(params_binder, connection);
167 } catch (const std::exception& err) {
168 AccountQueryFailed(connection);
169 throw;
170 }
171 }
172}
173
174template <typename T, typename... Args>
175CursorResultSet<T> Client::GetCursor(
176 OperationType operation_type,
177 std::size_t batch_size,
178 const Query& query,
179 const Args&... args
180) const {
181 auto connection = GetConnection(operation_type);
182 AccountQueryExecute(connection);
183 try {
184 auto params_binder = impl::BindHelper::UpdateParamsBindings(query, *connection, args...);
185 return CursorResultSet<T>{DoExecute(params_binder, connection), batch_size};
186 } catch (const std::exception& err) {
187 AccountQueryFailed(connection);
188 throw;
189 }
190}
191
192} // namespace storages::sqlite
193
194USERVER_NAMESPACE_END