Cppgres
Build Postgres extensions in C++
Loading...
Searching...
No Matches
xact.hpp
Go to the documentation of this file.
1
4#pragma once
5
6#include <exception>
7#include <string>
8#include <string_view>
9
10extern "C" {
11#include <access/xact.h>
12}
13
14#include "guard.hpp"
15
16namespace cppgres {
17
18using command_id = ::CommandId;
19
21
22 transaction_id() : id_(InvalidTransactionId) {}
23 transaction_id(::TransactionId id) : id_(id) {}
24 transaction_id(const transaction_id &id) : id_(id.id_) {}
25
26 static transaction_id current(bool acquire = true) {
27 return transaction_id(
28 ffi_guard{acquire ? ::GetCurrentTransactionId : ::GetCurrentTransactionIdIfAny}());
29 }
30
31 bool is_valid() const { return TransactionIdIsValid(id_); }
32
33 bool operator==(const transaction_id &other) const { return TransactionIdEquals(id_, other.id_); }
34 bool operator>(const transaction_id &other) const { return TransactionIdFollows(id_, other.id_); }
35 bool operator>=(const transaction_id &other) const {
36 return TransactionIdFollowsOrEquals(id_, other.id_);
37 }
38 bool operator<(const transaction_id &other) const {
39 return TransactionIdPrecedes(id_, other.id_);
40 }
41 bool operator<=(const transaction_id &other) const {
42 return TransactionIdPrecedesOrEquals(id_, other.id_);
43 }
44
45 bool did_abort() const { return is_valid() && TransactionIdDidAbort(id_); }
46 bool did_commit() const { return is_valid() && TransactionIdDidCommit(id_); }
47
48private:
49 ::TransactionId id_;
50};
51
52static_assert(sizeof(transaction_id) == sizeof(::TransactionId));
53
70 : ctx(::CurrentMemoryContext), owner(::CurrentResourceOwner), should_commit(commit),
71 uncaught(std::uncaught_exceptions()), finished(false), name("") {
72 ffi_guard{::BeginInternalSubTransaction}(nullptr);
73 ::CurrentMemoryContext = ctx;
74 }
75
76 internal_subtransaction(std::string_view name, bool commit = true)
77 : ctx(::CurrentMemoryContext), owner(::CurrentResourceOwner), should_commit(commit),
78 uncaught(std::uncaught_exceptions()), finished(false), name(name) {
79 ffi_guard{::BeginInternalSubTransaction}(this->name.c_str());
80 ::CurrentMemoryContext = ctx;
81 }
82
84 internal_subtransaction &operator=(const internal_subtransaction &) = delete;
87
91 void commit() {
92 ffi_guard{::ReleaseCurrentSubTransaction}();
93 restore();
94 finished = true;
95 }
96
100 void rollback() {
101 ffi_guard{::RollbackAndReleaseCurrentSubTransaction}();
102 restore();
103 finished = true;
104 }
105
106 ~internal_subtransaction() noexcept {
107 if (finished) {
108 return;
109 }
110 ffi_guard_noexcept(
111 [this] {
112 if (std::uncaught_exceptions() > uncaught || !should_commit) {
113 ::RollbackAndReleaseCurrentSubTransaction();
114 } else {
115 ::ReleaseCurrentSubTransaction();
116 }
117 },
118 "cppgres: finishing internal subtransaction failed");
119 restore();
120 }
121
122private:
123 void restore() noexcept {
124 ::CurrentMemoryContext = ctx;
125 ::CurrentResourceOwner = owner;
126 }
127
128 ::MemoryContext ctx;
129 ::ResourceOwner owner;
130 bool should_commit;
131 int uncaught;
132 bool finished;
133 std::string name;
134};
135
137 transaction(bool commit = true) : should_commit(commit), released(false) {
138 ffi_guard([]() {
139 if (!::IsTransactionState()) {
140 ::SetCurrentStatementStartTimestamp();
141 ::StartTransactionCommand();
142 ::PushActiveSnapshot(::GetTransactionSnapshot());
143 }
144 })();
145 }
146
147 ~transaction() {
148 if (!released) {
149 ffi_guard([this]() {
150 ::PopActiveSnapshot();
151 if (should_commit) {
152 ::CommitTransactionCommand();
153 } else {
154 ::AbortCurrentTransaction();
155 }
156 })();
157 }
158 }
159
160 void commit() {
161 ffi_guard([]() {
162 ::PopActiveSnapshot();
163 ::CommitTransactionCommand();
164 })();
165 released = true;
166 }
167
168 void rollback() {
169 ffi_guard([]() {
170 ::PopActiveSnapshot();
171 ::AbortCurrentTransaction();
172 })();
173 released = true;
174 }
175
176private:
177 bool should_commit;
178 bool released;
179};
180
181} // namespace cppgres
Definition: guard.hpp:20
Internal subtransaction guard.
Definition: xact.hpp:68
void rollback()
Roll the subtransaction back now.
Definition: xact.hpp:100
void commit()
Commit the subtransaction now.
Definition: xact.hpp:91
Definition: name.hpp:7
Definition: xact.hpp:20
Definition: xact.hpp:136