userver: userver/storages/sqlite/transaction.hpp Source File
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
transaction.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/storages/sqlite/transaction.hpp
4
5#include <userver/utils/fast_pimpl.hpp>
6
7#include <userver/storages/sqlite/cursor_result_set.hpp>
8#include <userver/storages/sqlite/impl/binder_help.hpp>
9#include <userver/storages/sqlite/options.hpp>
10#include <userver/storages/sqlite/query.hpp>
11#include <userver/storages/sqlite/result_set.hpp>
12#include <userver/storages/sqlite/savepoint.hpp>
13#include <userver/storages/sqlite/sqlite_fwd.hpp>
14
15USERVER_NAMESPACE_BEGIN
16
17namespace storages::sqlite {
18
19/// @brief RAII transaction wrapper, auto-<b>ROLLBACK</b>s on destruction if no
20/// prior `Commit`/`Rollback` call was made.
21///
22/// This type can't be constructed in user code and is always retrieved from
23/// storages::sqlite::Client
24class Transaction final {
25public:
26 Transaction(std::shared_ptr<infra::ConnectionPtr> connection, const settings::TransactionOptions& options);
27 ~Transaction();
28 Transaction(const Transaction& other) = delete;
29 Transaction(Transaction&& other) noexcept;
30 Transaction& operator=(Transaction&&) noexcept;
31
32 /// @brief Executes a statement.
33 ///
34 /// Fills placeholders of the statement with args..., `Args` are expected to
35 /// be of supported types.
36 /// See @ref scripts/docs/en/userver/sqlite/supported_types.md for better understanding of `Args`
37 /// requirements.
38 ///
39 /// @tparam Args Types of parameters to bind
40 /// @param query SQL query to execute
41 /// @param args Parameters to bind to the query
42 /// @return ResultSet containing the results of the query
43 template <typename... Args>
44 ResultSet Execute(const Query& query, const Args&... args) const;
45
46 /// @brief Executes a statement, decomposing the row.
47 ///
48 /// Decomposes the fields of the row and binds them as parameters to the query.
49 /// See @ref scripts/docs/en/userver/sqlite/supported_types.md for better understanding of `T` requirements.
50 ///
51 /// @tparam T Type of the row to decompose
52 /// @param query SQL query to execute
53 /// @param row Row object to decompose and bind
54 /// @return ResultSet containing the results of the query
55 template <typename T>
56 ResultSet ExecuteDecompose(const Query& query, const T& row) const;
57
58 /// @brief Executes a statement multiple times.
59 ///
60 /// Iterates over the container and executes the query for each element.
61 /// Container is expected to be a std::Container, Container::value_type is
62 /// expected to be an aggregate of supported types.
63 /// See @ref scripts/docs/en/userver/mysql/supported_types.md for better understanding of
64 /// `Container::value_type` requirements.
65 ///
66 /// @tparam Container Type of the container holding rows
67 /// @param query SQL query to execute
68 /// @param params Container of rows to bind and execute
69 template <typename Container>
70 void ExecuteMany(const Query& query, const Container& params) const;
71
72 /// @brief Executes a statement and returns a cursor for iterating over results.
73 ///
74 /// Fills placeholders of the statement with args..., `Args` are expected to
75 /// be of supported types.
76 /// See @ref scripts/docs/en/userver/sqlite/supported_types.md for better understanding of `Args`
77 /// requirements.
78 ///
79 /// @tparam T Type of the result rows
80 /// @tparam Args Types of parameters to bind
81 /// @param batch_size Number of rows to fetch per batch
82 /// @param query SQL query to execute
83 /// @param args Parameters to bind to the query
84 /// @return CursorResultSet for iterating over the results
85 template <typename T, typename... Args>
86 CursorResultSet<T> GetCursor(std::size_t batch_size, const Query& query, const Args&... args) const;
87
88 /// @brief Creates a savepoint with specified name.
89 ///
90 /// @param name Name of the savepoint
91 /// @return Savepoint object representing the created savepoint
92 Savepoint Save(std::string name) const;
93
94 /// @brief Commit the transaction
95 void Commit();
96
97 /// @brief Rollback the transaction
98 void Rollback();
99
100private:
101 ResultSet DoExecute(impl::io::ParamsBinderBase& params) const;
102 void AssertValid() const;
103
104 void AccountQueryExecute() const noexcept;
105 void AccountQueryFailed() const noexcept;
106
107 std::shared_ptr<infra::ConnectionPtr> connection_;
108};
109
110template <typename... Args>
111ResultSet Transaction::Execute(const Query& query, const Args&... args) const {
112 AssertValid();
113 AccountQueryExecute();
114 try {
115 auto params_binder = impl::BindHelper::UpdateParamsBindings(query.GetStatement(), *connection_, args...);
116 return DoExecute(params_binder);
117 } catch (const std::exception& err) {
118 AccountQueryFailed();
119 throw;
120 }
121}
122
123template <typename T>
124ResultSet Transaction::ExecuteDecompose(const Query& query, const T& row) const {
125 AssertValid();
126 AccountQueryExecute();
127 try {
128 auto params_binder = impl::BindHelper::UpdateRowAsParamsBindings(query.GetStatement(), *connection_, row);
129 return DoExecute(params_binder);
130 } catch (const std::exception& err) {
131 AccountQueryFailed();
132 throw;
133 }
134}
135
136template <typename Container>
137void Transaction::ExecuteMany(const Query& query, const Container& params) const {
138 AssertValid();
139 AccountQueryExecute();
140 for (const auto& row : params) {
141 try {
142 auto params_binder = impl::BindHelper::UpdateRowAsParamsBindings(query.GetStatement(), *connection_, row);
143 DoExecute(params_binder);
144 } catch (const std::exception& err) {
145 AccountQueryFailed();
146 throw;
147 }
148 }
149}
150
151template <typename T, typename... Args>
152CursorResultSet<T> Transaction::GetCursor(std::size_t batch_size, const Query& query, const Args&... args) const {
153 AssertValid();
154 AccountQueryExecute();
155 try {
156 auto params_binder = impl::BindHelper::UpdateParamsBindings(query.GetStatement(), *connection_, args...);
157 return CursorResultSet<T>{DoExecute(params_binder, connection_), batch_size};
158 } catch (const std::exception& err) {
159 AccountQueryFailed();
160 throw;
161 }
162}
163
164} // namespace storages::sqlite
165
166USERVER_NAMESPACE_END