userver: userver/storages/mysql/transaction.hpp Source File
⚠️ This is the documentation for an old userver version. Click here to switch to the latest version.
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/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