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 | |
9 | namespace duckdb { |
10 | |
11 | TransactionContext::TransactionContext(ClientContext &context) |
12 | : context(context), auto_commit(true), current_transaction(nullptr) { |
13 | } |
14 | |
15 | TransactionContext::~TransactionContext() { |
16 | if (current_transaction) { |
17 | try { |
18 | Rollback(); |
19 | } catch (...) { |
20 | } |
21 | } |
22 | } |
23 | |
24 | void 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 | |
42 | void 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 | |
54 | void TransactionContext::SetAutoCommit(bool value) { |
55 | auto_commit = value; |
56 | if (!auto_commit && !current_transaction) { |
57 | BeginTransaction(); |
58 | } |
59 | } |
60 | |
61 | void 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 | |
70 | void TransactionContext::ClearTransaction() { |
71 | SetAutoCommit(true); |
72 | current_transaction = nullptr; |
73 | } |
74 | |
75 | idx_t TransactionContext::GetActiveQuery() { |
76 | if (!current_transaction) { |
77 | throw InternalException("GetActiveQuery called without active transaction"); |
78 | } |
79 | return current_transaction->GetActiveQuery(); |
80 | } |
81 | |
82 | void TransactionContext::ResetActiveQuery() { |
83 | if (current_transaction) { |
84 | SetActiveQuery(MAXIMUM_QUERY_ID); |
85 | } |
86 | } |
87 | |
88 | void 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 |