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