userver: userver/storages/mysql/transaction.hpp Source File
Loading...
Searching...
No Matches
transaction.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/storages/mysql/transaction.hpp
4
5#include <userver/tracing/span.hpp>
6#include <userver/utils/fast_pimpl.hpp>
7
8#include <userver/storages/mysql/cluster_host_type.hpp>
9#include <userver/storages/mysql/command_result_set.hpp>
10#include <userver/storages/mysql/cursor_result_set.hpp>
11#include <userver/storages/mysql/impl/bind_helper.hpp>
12#include <userver/storages/mysql/options.hpp>
13#include <userver/storages/mysql/query.hpp>
14#include <userver/storages/mysql/statement_result_set.hpp>
15
16USERVER_NAMESPACE_BEGIN
17
18namespace storages::mysql {
19
20namespace infra {
21class ConnectionPtr;
22}
23
24/// @brief RAII transaction wrapper, auto-<b>ROLLBACK</b>s on destruction if no
25/// prior `Commit`/`Rollback` call was made.
26///
27/// This type can't be constructed in user code and is always retrieved from
28/// storages::mysql::Cluster
29class Transaction final {
30 public:
31 explicit Transaction(infra::ConnectionPtr&& connection,
32 engine::Deadline deadline);
33 ~Transaction();
34 Transaction(const Transaction& other) = delete;
35 Transaction(Transaction&& other) noexcept;
36
37 /// @brief Executes a statement with default deadline.
38 /// Fills placeholders of the statement with args..., `Args` are expected to
39 /// be of supported types.
40 /// See @ref userver_mysql_types for better understanding of `Args`
41 /// requirements.
42 ///
43 /// UINVARIANTs on params count mismatch doesn't validate types.
44 template <typename... Args>
45 StatementResultSet Execute(const Query& query, const Args&... args) const;
46
47 /// @brief Executes a statement with default deadline.
48 ///
49 /// Basically an alias for Execute(host_type, query, AsArgs<T>(row)),
50 /// where AsArgs is an imaginary function which passes fields of T as
51 /// variadic params. Handy for one-liner inserts.
52 /// See @ref userver_mysql_types for better understanding of `T` requirements.
53 ///
54 /// UINVARIANTs on params count mismatch, doesn't validate types.
55 template <typename T>
56 StatementResultSet ExecuteDecompose(const Query& query, const T& row) const;
57
58 /// @brief Executes a statement with default deadline.
59 /// Fills placeholders of the statements with Container::value_type in a
60 /// bulk-manner.
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 userver_mysql_types for better understanding of
64 /// `Container::value_type` requirements.
65 ///
66 /// @note Requires MariaDB 10.2.6+ as a server
67 ///
68 /// UINVARIANTs on params count mismatch, doesn't validate types.
69 /// UINVARIANTs on empty params container.
70 template <typename Container>
71 StatementResultSet ExecuteBulk(const Query& query,
72 const Container& params) const;
73
74 // TODO : don't require Container to be const, so Convert can move
75 // clang-format off
76 /// @brief Executes a statement with default deadline,
77 /// on the flight remapping from `Container::value_type` to `MapTo`.
78 /// `Container` is expected to be a std::Container of whatever type pleases
79 /// you, `MapTo` is expected to be an aggregate of supported types.
80 /// See @ref userver_mysql_types for better understanding of `MapTo` requirements.
81 /// You are expected to provide a converter function
82 /// `MapTo Convert(const Container::value_type&, storages::mysql::convert::To<MapTo>)`
83 /// in namespace of `MapTo` or storages::mysql::convert.
84 ///
85 /// @note Requires MariaDB 10.2.6+ as a server
86 ///
87 /// UINVARIANTs on params count mismatch, doesn't validate types.
88 /// UINVARIANTs on empty params container.
89 template <typename MapTo, typename Container>
90 StatementResultSet ExecuteBulkMapped(const Query& query,
91 const Container& params) const;
92 // clang-format on
93
94 /// @brief Commit the transaction
95 void Commit();
96
97 /// @brief Rollback the transaction
98 void Rollback();
99
100 private:
101 StatementResultSet DoExecute(const Query& query,
102 impl::io::ParamsBinderBase& params) const;
103
104 void AssertValid() const;
105
106 utils::FastPimpl<infra::ConnectionPtr, 24, 8> connection_;
107 engine::Deadline deadline_;
108 tracing::Span span_;
109};
110
111template <typename... Args>
112StatementResultSet Transaction::Execute(const Query& query,
113 const Args&... args) const {
114 auto params_binder = impl::BindHelper::BindParams(args...);
115
116 return DoExecute(query.GetStatement(), params_binder);
117}
118
119template <typename T>
120StatementResultSet Transaction::ExecuteDecompose(const Query& query,
121 const T& row) const {
122 auto params_binder = impl::BindHelper::BindRowAsParams(row);
123
124 return DoExecute(query, params_binder);
125}
126
127template <typename Container>
128StatementResultSet Transaction::ExecuteBulk(const Query& query,
129 const Container& params) const {
130 UINVARIANT(!params.empty(), "Empty params in bulk execution");
131
132 auto params_binder = impl::BindHelper::BindContainerAsParams(params);
133
134 return DoExecute(query.GetStatement(), params_binder);
135}
136
137template <typename MapTo, typename Container>
138StatementResultSet Transaction::ExecuteBulkMapped(
139 const Query& query, const Container& params) const {
140 UINVARIANT(!params.empty(), "Empty params in bulk execution");
141
142 auto params_binder =
143 impl::BindHelper::BindContainerAsParamsMapped<MapTo>(params);
144
145 return DoExecute(query.GetStatement(), params_binder);
146}
147
148} // namespace storages::mysql
149
150USERVER_NAMESPACE_END