Skip to content

Commit 9a66a0a

Browse files
committed
Transaction class
1 parent 8499283 commit 9a66a0a

4 files changed

Lines changed: 712 additions & 0 deletions

File tree

src/lib/Transaction.cpp

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
/*
2+
* MIT License
3+
*
4+
* Copyright (c) 2025 Adriano dos Santos Fernandes
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in all
14+
* copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
* SOFTWARE.
23+
*/
24+
25+
#include "Transaction.h"
26+
#include "Attachment.h"
27+
#include "Client.h"
28+
#include "Exception.h"
29+
#include <cassert>
30+
31+
using namespace fbcpp;
32+
using namespace fbcpp::impl;
33+
34+
35+
Transaction::Transaction(Attachment& attachment, const TransactionOptions& options)
36+
: client{attachment.getClient()}
37+
{
38+
assert(attachment.isValid());
39+
40+
const auto master = client.getMaster();
41+
42+
const auto status = client.newStatus();
43+
StatusWrapper statusWrapper{client, status.get()};
44+
45+
auto tpbBuilder = fbUnique(master->getUtilInterface()->getXpbBuilder(&statusWrapper, fb::IXpbBuilder::TPB,
46+
reinterpret_cast<const std::uint8_t*>(options.getTpb().data()),
47+
static_cast<unsigned>(options.getTpb().size())));
48+
49+
if (const auto accessMode = options.getAccessMode())
50+
{
51+
switch (accessMode.value())
52+
{
53+
case TransactionAccessMode::READ_ONLY:
54+
tpbBuilder->insertTag(&statusWrapper, isc_tpb_read);
55+
break;
56+
57+
case TransactionAccessMode::READ_WRITE:
58+
tpbBuilder->insertTag(&statusWrapper, isc_tpb_write);
59+
break;
60+
61+
default:
62+
assert(false);
63+
break;
64+
}
65+
}
66+
67+
if (const auto waitMode = options.getWaitMode())
68+
{
69+
switch (waitMode.value())
70+
{
71+
case TransactionWaitMode::NO_WAIT:
72+
tpbBuilder->insertTag(&statusWrapper, isc_tpb_nowait);
73+
break;
74+
75+
case TransactionWaitMode::WAIT:
76+
tpbBuilder->insertTag(&statusWrapper, isc_tpb_wait);
77+
break;
78+
79+
default:
80+
assert(false);
81+
break;
82+
}
83+
}
84+
85+
if (const auto isolationLevel = options.getIsolationLevel())
86+
{
87+
switch (isolationLevel.value())
88+
{
89+
case TransactionIsolationLevel::CONSISTENCY:
90+
tpbBuilder->insertTag(&statusWrapper, isc_tpb_consistency);
91+
break;
92+
93+
case TransactionIsolationLevel::SNAPSHOT:
94+
tpbBuilder->insertTag(&statusWrapper, isc_tpb_concurrency);
95+
break;
96+
97+
case TransactionIsolationLevel::READ_COMMITTED:
98+
tpbBuilder->insertTag(&statusWrapper, isc_tpb_read_committed);
99+
100+
if (const auto readCommittedMode = options.getReadCommittedMode())
101+
{
102+
switch (readCommittedMode.value())
103+
{
104+
case TransactionReadCommittedMode::NO_RECORD_VERSION:
105+
tpbBuilder->insertTag(&statusWrapper, isc_tpb_no_rec_version);
106+
break;
107+
108+
case TransactionReadCommittedMode::RECORD_VERSION:
109+
tpbBuilder->insertTag(&statusWrapper, isc_tpb_rec_version);
110+
break;
111+
112+
default:
113+
assert(false);
114+
break;
115+
}
116+
}
117+
118+
break;
119+
120+
default:
121+
assert(false);
122+
break;
123+
}
124+
}
125+
126+
if (options.getNoAutoUndo())
127+
tpbBuilder->insertTag(&statusWrapper, isc_tpb_no_auto_undo);
128+
129+
if (options.getIgnoreLimbo())
130+
tpbBuilder->insertTag(&statusWrapper, isc_tpb_ignore_limbo);
131+
132+
if (options.getRestartRequests())
133+
tpbBuilder->insertTag(&statusWrapper, isc_tpb_restart_requests);
134+
135+
if (options.getAutoCommit())
136+
tpbBuilder->insertTag(&statusWrapper, isc_tpb_autocommit);
137+
138+
const auto tpbBuffer = tpbBuilder->getBuffer(&statusWrapper);
139+
const auto tpbBufferLen = tpbBuilder->getBufferLength(&statusWrapper);
140+
141+
handle.reset(attachment.getHandle()->startTransaction(&statusWrapper, tpbBufferLen, tpbBuffer));
142+
}
143+
144+
Transaction::Transaction(Attachment& attachment, std::string_view setTransactionCmd)
145+
: client{attachment.getClient()}
146+
{
147+
assert(attachment.isValid());
148+
149+
const auto status = client.newStatus();
150+
StatusWrapper statusWrapper{client, status.get()};
151+
152+
handle.reset(
153+
attachment.getHandle()->execute(&statusWrapper, nullptr, static_cast<unsigned>(setTransactionCmd.length()),
154+
setTransactionCmd.data(), SQL_DIALECT_V6, nullptr, nullptr, nullptr, nullptr));
155+
}
156+
157+
void Transaction::rollback()
158+
{
159+
assert(isValid());
160+
161+
const auto status = client.newStatus();
162+
StatusWrapper statusWrapper{client, status.get()};
163+
164+
handle->rollback(&statusWrapper);
165+
handle.reset();
166+
}
167+
168+
169+
void Transaction::commit()
170+
{
171+
assert(isValid());
172+
173+
const auto status = client.newStatus();
174+
StatusWrapper statusWrapper{client, status.get()};
175+
176+
handle->commit(&statusWrapper);
177+
handle.reset();
178+
}
179+
180+
void Transaction::commitRetaining()
181+
{
182+
assert(isValid());
183+
184+
const auto status = client.newStatus();
185+
StatusWrapper statusWrapper{client, status.get()};
186+
187+
handle->commitRetaining(&statusWrapper);
188+
}
189+
190+
void Transaction::rollbackRetaining()
191+
{
192+
assert(isValid());
193+
194+
const auto status = client.newStatus();
195+
StatusWrapper statusWrapper{client, status.get()};
196+
197+
handle->rollbackRetaining(&statusWrapper);
198+
}

0 commit comments

Comments
 (0)