userver: userver/storages/sqlite/client.hpp Source File
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
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>
111 GetCursor(OperationType operation_type, std::size_t batch_size, const Query& query, const Args&... args) const;
112
113 /// @brief Writes client statistics to the provided writer.
114 ///
115 /// @param writer Statistics writer to output the statistics
116 void WriteStatistics(utils::statistics::Writer& writer) const;
117
118private:
119 ResultSet DoExecute(impl::io::ParamsBinderBase& params, std::shared_ptr<infra::ConnectionPtr> connection) const;
120
121 std::shared_ptr<infra::ConnectionPtr> GetConnection(OperationType operation_type) const;
122
123 void AccountQueryExecute(std::shared_ptr<infra::ConnectionPtr> connection) const noexcept;
124 void AccountQueryFailed(std::shared_ptr<infra::ConnectionPtr> connection) const noexcept;
125
126 impl::ClientImplPtr pimpl_;
127};
128
129template <typename... Args>
130ResultSet Client::Execute(OperationType operation_type, const Query& query, const Args&... args) const {
131 auto connection = GetConnection(operation_type);
132 AccountQueryExecute(connection);
133 try {
134 auto params_binder = impl::BindHelper::UpdateParamsBindings(query.GetStatement(), *connection, args...);
135 return DoExecute(params_binder, connection);
136 } catch (const std::exception& err) {
137 AccountQueryFailed(connection);
138 throw;
139 }
140}
141
142template <typename T>
143ResultSet Client::ExecuteDecompose(OperationType operation_type, const Query& query, const T& row) const {
144 auto connection = GetConnection(operation_type);
145 AccountQueryExecute(connection);
146 try {
147 auto params_binder = impl::BindHelper::UpdateRowAsParamsBindings(query.GetStatement(), *connection, row);
148 return DoExecute(params_binder, connection);
149 } catch (const std::exception& err) {
150 AccountQueryFailed(connection);
151 throw;
152 }
153}
154
155template <typename Container>
156void Client::ExecuteMany(OperationType operation_type, const Query& query, const Container& params) const {
157 auto connection = GetConnection(operation_type);
158 for (const auto& row : params) {
159 AccountQueryExecute(connection);
160 try {
161 auto params_binder = impl::BindHelper::UpdateRowAsParamsBindings(query.GetStatement(), *connection, row);
162 DoExecute(params_binder, connection);
163 } catch (const std::exception& err) {
164 AccountQueryFailed(connection);
165 throw;
166 }
167 }
168}
169
170template <typename T, typename... Args>
171CursorResultSet<T>
172Client::GetCursor(OperationType operation_type, std::size_t batch_size, const Query& query, const Args&... args) const {
173 auto connection = GetConnection(operation_type);
174 AccountQueryExecute(connection);
175 try {
176 auto params_binder = impl::BindHelper::UpdateParamsBindings(query.GetStatement(), *connection, args...);
177 return CursorResultSet<T>{DoExecute(params_binder, connection), batch_size};
178 } catch (const std::exception& err) {
179 AccountQueryFailed(connection);
180 throw;
181 }
182}
183
184} // namespace storages::sqlite
185
186USERVER_NAMESPACE_END