1#include "duckdb/transaction/transaction_context.hpp"
2
3#include "duckdb/common/exception.hpp"
4#include "duckdb/transaction/meta_transaction.hpp"
5#include "duckdb/transaction/transaction_manager.hpp"
6#include "duckdb/main/config.hpp"
7#include "duckdb/main/database_manager.hpp"
8
9namespace duckdb {
10
11TransactionContext::TransactionContext(ClientContext &context)
12 : context(context), auto_commit(true), current_transaction(nullptr) {
13}
14
15TransactionContext::~TransactionContext() {
16 if (current_transaction) {
17 try {
18 Rollback();
19 } catch (...) {
20 }
21 }
22}
23
24void TransactionContext::BeginTransaction() {
25 if (current_transaction) {
26 throw TransactionException("cannot start a transaction within a transaction");
27 }
28 auto start_timestamp = Timestamp::GetCurrentTimestamp();
29 auto catalog_version = Catalog::GetSystemCatalog(context).GetCatalogVersion();
30 current_transaction = make_uniq<MetaTransaction>(args&: context, args&: start_timestamp, args&: catalog_version);
31
32 auto &config = DBConfig::GetConfig(context);
33 if (config.options.immediate_transaction_mode) {
34 // if immediate transaction mode is enabled then start all transactions immediately
35 auto databases = DatabaseManager::Get(db&: context).GetDatabases(context);
36 for (auto db : databases) {
37 current_transaction->GetTransaction(db&: db.get());
38 }
39 }
40}
41
42void TransactionContext::Commit() {
43 if (!current_transaction) {
44 throw TransactionException("failed to commit: no transaction active");
45 }
46 auto transaction = std::move(current_transaction);
47 ClearTransaction();
48 string error = transaction->Commit();
49 if (!error.empty()) {
50 throw TransactionException("Failed to commit: %s", error);
51 }
52}
53
54void TransactionContext::SetAutoCommit(bool value) {
55 auto_commit = value;
56 if (!auto_commit && !current_transaction) {
57 BeginTransaction();
58 }
59}
60
61void TransactionContext::Rollback() {
62 if (!current_transaction) {
63 throw TransactionException("failed to rollback: no transaction active");
64 }
65 auto transaction = std::move(current_transaction);
66 ClearTransaction();
67 transaction->Rollback();
68}
69
70void TransactionContext::ClearTransaction() {
71 SetAutoCommit(true);
72 current_transaction = nullptr;
73}
74
75idx_t TransactionContext::GetActiveQuery() {
76 if (!current_transaction) {
77 throw InternalException("GetActiveQuery called without active transaction");
78 }
79 return current_transaction->GetActiveQuery();
80}
81
82void TransactionContext::ResetActiveQuery() {
83 if (current_transaction) {
84 SetActiveQuery(MAXIMUM_QUERY_ID);
85 }
86}
87
88void TransactionContext::SetActiveQuery(transaction_t query_number) {
89 if (!current_transaction) {
90 throw InternalException("SetActiveQuery called without active transaction");
91 }
92 current_transaction->SetActiveQuery(query_number);
93}
94
95} // namespace duckdb
96