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 {
30public:
31 explicit Transaction(infra::ConnectionPtr&& connection, engine::Deadline deadline);
32 ~Transaction();
33 Transaction(const Transaction& other) = delete;
34 Transaction(Transaction&& other) noexcept;
35
36 /// @brief Executes a statement with default deadline.
37 /// Fills placeholders of the statement with args..., `Args` are expected to
38 /// be of supported types.
39 /// See @ref userver_mysql_types for better understanding of `Args`
40 /// requirements.
41 ///
42 /// UINVARIANTs on params count mismatch doesn't validate types.
43 template <typename... Args>
44 StatementResultSet Execute(const Query& query, const Args&... args) const;
45
46 /// @brief Executes a statement with default deadline.
47 ///
48 /// Basically an alias for Execute(host_type, query, AsArgs<T>(row)),
49 /// where AsArgs is an imaginary function which passes fields of T as
50 /// variadic params. Handy for one-liner inserts.
51 /// See @ref userver_mysql_types for better understanding of `T` requirements.
52 ///
53 /// UINVARIANTs on params count mismatch, doesn't validate types.
54 template <typename T>
55 StatementResultSet ExecuteDecompose(const Query& query, const T& row) const;
56
57 /// @brief Executes a statement with default deadline.
58 /// Fills placeholders of the statements with Container::value_type in a
59 /// bulk-manner.
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 userver_mysql_types for better understanding of
63 /// `Container::value_type` requirements.
64 ///
65 /// @note Requires MariaDB 10.2.6+ as a server
66 ///
67 /// UINVARIANTs on params count mismatch, doesn't validate types.
68 /// UINVARIANTs on empty params container.
69 template <typename Container>
70 StatementResultSet ExecuteBulk(const Query& query, const Container& params) const;
71
72 // TODO : don't require Container to be const, so Convert can move
73 // clang-format off
74 /// @brief Executes a statement with default deadline,
75 /// on the flight remapping from `Container::value_type` to `MapTo`.
76 /// `Container` is expected to be a std::Container of whatever type pleases
77 /// you, `MapTo` is expected to be an aggregate of supported types.
78 /// See @ref userver_mysql_types for better understanding of `MapTo` requirements.
79 /// You are expected to provide a converter function
80 /// `MapTo Convert(const Container::value_type&, storages::mysql::convert::To<MapTo>)`
81 /// in namespace of `MapTo` or storages::mysql::convert.
82 ///
83 /// @note Requires MariaDB 10.2.6+ as a server
84 ///
85 /// UINVARIANTs on params count mismatch, doesn't validate types.
86 /// UINVARIANTs on empty params container.
87 template <typename MapTo, typename Container>
88 StatementResultSet ExecuteBulkMapped(const Query& query,
89 const Container& params) const;
90 // clang-format on
91
92 /// @brief Commit the transaction
93 void Commit();
94
95 /// @brief Rollback the transaction
96 void Rollback();
97
98private:
99 StatementResultSet DoExecute(const Query& query, impl::io::ParamsBinderBase& params) const;
100
101 void AssertValid() const;
102
103 utils::FastPimpl<infra::ConnectionPtr, 24, 8> connection_;
104 engine::Deadline deadline_;
105 tracing::Span span_;
106};
107
108template <typename... Args>
109StatementResultSet Transaction::Execute(const Query& query, const Args&... args) const {
110 auto params_binder = impl::BindHelper::BindParams(args...);
111
112 return DoExecute(query.GetStatement(), params_binder);
113}
114
115template <typename T>
116StatementResultSet Transaction::ExecuteDecompose(const Query& query, const T& row) const {
117 auto params_binder = impl::BindHelper::BindRowAsParams(row);
118
119 return DoExecute(query, params_binder);
120}
121
122template <typename Container>
123StatementResultSet Transaction::ExecuteBulk(const Query& query, const Container& params) const {
124 UINVARIANT(!params.empty(), "Empty params in bulk execution");
125
126 auto params_binder = impl::BindHelper::BindContainerAsParams(params);
127
128 return DoExecute(query.GetStatement(), params_binder);
129}
130
131template <typename MapTo, typename Container>
132StatementResultSet Transaction::ExecuteBulkMapped(const Query& query, const Container& params) const {
133 UINVARIANT(!params.empty(), "Empty params in bulk execution");
134
135 auto params_binder = impl::BindHelper::BindContainerAsParamsMapped<MapTo>(params);
136
137 return DoExecute(query.GetStatement(), params_binder);
138}
139
140} // namespace storages::mysql
141
142USERVER_NAMESPACE_END