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#include <userver/utils/trx_tracker.hpp>
8
9#include <userver/storages/mysql/cluster_host_type.hpp>
10#include <userver/storages/mysql/command_result_set.hpp>
11#include <userver/storages/mysql/cursor_result_set.hpp>
12#include <userver/storages/mysql/impl/bind_helper.hpp>
13#include <userver/storages/mysql/options.hpp>
14#include <userver/storages/mysql/query.hpp>
15#include <userver/storages/mysql/statement_result_set.hpp>
16
17USERVER_NAMESPACE_BEGIN
18
19namespace storages::mysql {
20
21namespace infra {
22class ConnectionPtr;
23}
24
25/// @brief RAII transaction wrapper, auto-<b>ROLLBACK</b>s on destruction if no
26/// prior `Commit`/`Rollback` call was made.
27///
28/// This type can't be constructed in user code and is always retrieved from
29/// storages::mysql::Cluster
30class Transaction final {
31public:
32 explicit Transaction(infra::ConnectionPtr&& connection, 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 scripts/docs/en/userver/mysql/supported_types.md 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 scripts/docs/en/userver/mysql/supported_types.md 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 scripts/docs/en/userver/mysql/supported_types.md 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, const Container& params) const;
72
73 // TODO : don't require Container to be const, so Convert can move
74 // clang-format off
75 /// @brief Executes a statement with default deadline,
76 /// on the flight remapping from `Container::value_type` to `MapTo`.
77 /// `Container` is expected to be a std::Container of whatever type pleases
78 /// you, `MapTo` is expected to be an aggregate of supported types.
79 /// See @ref scripts/docs/en/userver/mysql/supported_types.md for better understanding of `MapTo` requirements.
80 /// You are expected to provide a converter function
81 /// `MapTo Convert(const Container::value_type&, storages::mysql::convert::To<MapTo>)`
82 /// in namespace of `MapTo` or storages::mysql::convert.
83 ///
84 /// @note Requires MariaDB 10.2.6+ as a server
85 ///
86 /// UINVARIANTs on params count mismatch, doesn't validate types.
87 /// UINVARIANTs on empty params container.
88 template <typename MapTo, typename Container>
89 StatementResultSet ExecuteBulkMapped(const Query& query,
90 const Container& params) const;
91 // clang-format on
92
93 /// @brief Commit the transaction
94 void Commit();
95
96 /// @brief Rollback the transaction
97 void Rollback();
98
99private:
100 StatementResultSet DoExecute(const Query& query, impl::io::ParamsBinderBase& params) const;
101
102 void AssertValid() const;
103
104 utils::FastPimpl<infra::ConnectionPtr, 24, 8> connection_;
105 engine::Deadline deadline_;
106 tracing::Span span_;
107 utils::trx_tracker::TransactionLock trx_lock_;
108};
109
110template <typename... Args>
111StatementResultSet Transaction::Execute(const Query& query, const Args&... args) const {
112 auto params_binder = impl::BindHelper::BindParams(args...);
113
114 return DoExecute(query, params_binder);
115}
116
117template <typename T>
118StatementResultSet Transaction::ExecuteDecompose(const Query& query, const T& row) const {
119 auto params_binder = impl::BindHelper::BindRowAsParams(row);
120
121 return DoExecute(query, params_binder);
122}
123
124template <typename Container>
125StatementResultSet Transaction::ExecuteBulk(const Query& query, const Container& params) const {
126 UINVARIANT(!params.empty(), "Empty params in bulk execution");
127
128 auto params_binder = impl::BindHelper::BindContainerAsParams(params);
129
130 return DoExecute(query, params_binder);
131}
132
133template <typename MapTo, typename Container>
134StatementResultSet Transaction::ExecuteBulkMapped(const Query& query, const Container& params) const {
135 UINVARIANT(!params.empty(), "Empty params in bulk execution");
136
137 auto params_binder = impl::BindHelper::BindContainerAsParamsMapped<MapTo>(params);
138
139 return DoExecute(query, params_binder);
140}
141
142} // namespace storages::mysql
143
144USERVER_NAMESPACE_END