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 <stack>
7
8extern "C" {
9#include <access/xact.h>
10}
11
12namespace cppgres {
13
14using command_id = ::CommandId;
15
17
18 transaction_id() : id_(InvalidTransactionId) {}
19 transaction_id(::TransactionId id) : id_(id) {}
20 transaction_id(const transaction_id &id) : id_(id.id_) {}
21
22 static transaction_id current(bool acquire = true) {
23 return transaction_id(
24 ffi_guard{acquire ? ::GetCurrentTransactionId : ::GetCurrentTransactionIdIfAny}());
25 }
26
27 bool is_valid() const { return TransactionIdIsValid(id_); }
28
29 bool operator==(const transaction_id &other) const { return TransactionIdEquals(id_, other.id_); }
30 bool operator>(const transaction_id &other) const { return TransactionIdFollows(id_, other.id_); }
31 bool operator>=(const transaction_id &other) const {
32 return TransactionIdFollowsOrEquals(id_, other.id_);
33 }
34 bool operator<(const transaction_id &other) const {
35 return TransactionIdPrecedes(id_, other.id_);
36 }
37 bool operator<=(const transaction_id &other) const {
38 return TransactionIdPrecedesOrEquals(id_, other.id_);
39 }
40
41 bool did_abort() const { return is_valid() && TransactionIdDidAbort(id_); }
42 bool did_commit() const { return is_valid() && TransactionIdDidCommit(id_); }
43
44private:
45 ::TransactionId id_;
46};
47
48static_assert(sizeof(transaction_id) == sizeof(::TransactionId));
49
51 internal_subtransaction(bool commit = true)
52 : owner(::CurrentResourceOwner), commit(commit), name("") {
53 if (txns.empty()) {
54 ffi_guard{::BeginInternalSubTransaction}(nullptr);
55 txns.push(this);
56 } else {
57 throw std::runtime_error("internal subtransaction already started");
58 }
59 }
60
61 internal_subtransaction(std::string_view name, bool commit = true)
62 : owner(::CurrentResourceOwner), commit(commit), name(name) {
63 if (txns.empty()) {
64 ffi_guard{::BeginInternalSubTransaction}(this->name.c_str());
65 txns.push(this);
66 } else {
67 throw std::runtime_error("internal subtransaction already started");
68 }
69 }
70
72 txns.pop();
73 if (commit) {
74 ffi_guard{::ReleaseCurrentSubTransaction}();
75 } else {
76 ffi_guard{::RollbackAndReleaseCurrentSubTransaction}();
77 }
78 ::CurrentResourceOwner = owner;
79 }
80
81private:
82 ::ResourceOwner owner;
83 bool commit;
84 std::string name;
85 static inline std::stack<internal_subtransaction *> txns;
86};
87
89 transaction(bool commit = true) : should_commit(commit), released(false) {
90 ffi_guard([]() {
91 if (!::IsTransactionState()) {
92 ::SetCurrentStatementStartTimestamp();
93 ::StartTransactionCommand();
94 ::PushActiveSnapshot(::GetTransactionSnapshot());
95 }
96 })();
97 }
98
99 ~transaction() {
100 if (!released) {
101 ffi_guard([this]() {
102 ::PopActiveSnapshot();
103 if (should_commit) {
104 ::CommitTransactionCommand();
105 } else {
106 ::AbortCurrentTransaction();
107 }
108 })();
109 }
110 }
111
112 void commit() {
113 ffi_guard([]() {
114 ::PopActiveSnapshot();
115 ::CommitTransactionCommand();
116 })();
117 released = true;
118 }
119
120 void rollback() {
121 ffi_guard([]() {
122 ::PopActiveSnapshot();
123 ::AbortCurrentTransaction();
124 })();
125 released = true;
126 }
127
128private:
129 bool should_commit;
130 bool released;
131};
132
133} // namespace cppgres
Definition: guard.hpp:19
Definition: xact.hpp:50
Definition: name.hpp:7
Definition: xact.hpp:16
Definition: xact.hpp:88