1#include "duckdb/execution/operator/helper/physical_transaction.hpp"
2#include "duckdb/main/client_context.hpp"
3#include "duckdb/main/valid_checker.hpp"
4
5namespace duckdb {
6
7SourceResultType PhysicalTransaction::GetData(ExecutionContext &context, DataChunk &chunk,
8 OperatorSourceInput &input) const {
9 auto &client = context.client;
10
11 auto type = info->type;
12 if (type == TransactionType::COMMIT && ValidChecker::IsInvalidated(o&: client.ActiveTransaction())) {
13 // transaction is invalidated - turn COMMIT into ROLLBACK
14 type = TransactionType::ROLLBACK;
15 }
16 switch (type) {
17 case TransactionType::BEGIN_TRANSACTION: {
18 if (client.transaction.IsAutoCommit()) {
19 // start the active transaction
20 // if autocommit is active, we have already called
21 // BeginTransaction by setting autocommit to false we
22 // prevent it from being closed after this query, hence
23 // preserving the transaction context for the next query
24 client.transaction.SetAutoCommit(false);
25 } else {
26 throw TransactionException("cannot start a transaction within a transaction");
27 }
28 break;
29 }
30 case TransactionType::COMMIT: {
31 if (client.transaction.IsAutoCommit()) {
32 throw TransactionException("cannot commit - no transaction is active");
33 } else {
34 // explicitly commit the current transaction
35 client.transaction.Commit();
36 }
37 break;
38 }
39 case TransactionType::ROLLBACK: {
40 if (client.transaction.IsAutoCommit()) {
41 throw TransactionException("cannot rollback - no transaction is active");
42 } else {
43 // explicitly rollback the current transaction
44 client.transaction.Rollback();
45 }
46 break;
47 }
48 default:
49 throw NotImplementedException("Unrecognized transaction type!");
50 }
51
52 return SourceResultType::FINISHED;
53}
54
55} // namespace duckdb
56