reifydb_engine/transaction/
mod.rs

1// Copyright (c) reifydb.com 2025
2// This file is licensed under the AGPL-3.0-or-later, see license.md file
3
4use reifydb_catalog::MaterializedCatalog;
5use reifydb_core::{
6	CommitVersion, EncodedKey, EncodedKeyRange, TransactionId,
7	interface::{
8		BoxedMultiVersionIter, MultiVersionQueryTransaction, MultiVersionValues, QueryTransaction,
9		SingleVersionTransaction,
10	},
11};
12use reifydb_transaction::single::TransactionSingleVersion;
13
14mod catalog;
15mod command;
16#[allow(dead_code)]
17pub(crate) mod operation;
18mod query;
19
20pub use command::StandardCommandTransaction;
21pub use query::StandardQueryTransaction;
22use reifydb_core::interface::CdcTransaction;
23use reifydb_transaction::cdc::TransactionCdc;
24
25/// An enum that can hold either a command or query transaction for flexible
26/// execution
27pub enum StandardTransaction<'a> {
28	Command(&'a mut StandardCommandTransaction),
29	Query(&'a mut StandardQueryTransaction),
30}
31
32impl<'a> QueryTransaction for StandardTransaction<'a> {
33	type SingleVersionQuery<'b>
34		= <TransactionSingleVersion as SingleVersionTransaction>::Query<'b>
35	where
36		Self: 'b;
37
38	type CdcQuery<'b>
39		= <TransactionCdc as CdcTransaction>::Query<'b>
40	where
41		Self: 'b;
42
43	fn begin_single_query(&self) -> crate::Result<Self::SingleVersionQuery<'_>> {
44		match self {
45			Self::Command(txn) => txn.begin_single_query(),
46			Self::Query(txn) => txn.begin_single_query(),
47		}
48	}
49
50	fn begin_cdc_query(&self) -> crate::Result<Self::CdcQuery<'_>> {
51		match self {
52			Self::Command(txn) => txn.begin_cdc_query(),
53			Self::Query(txn) => txn.begin_cdc_query(),
54		}
55	}
56}
57
58impl<'a> MultiVersionQueryTransaction for StandardTransaction<'a> {
59	fn version(&self) -> CommitVersion {
60		match self {
61			Self::Command(txn) => MultiVersionQueryTransaction::version(*txn),
62			Self::Query(txn) => MultiVersionQueryTransaction::version(*txn),
63		}
64	}
65
66	fn id(&self) -> TransactionId {
67		match self {
68			Self::Command(txn) => txn.id(),
69			Self::Query(txn) => txn.id(),
70		}
71	}
72
73	fn get(&mut self, key: &EncodedKey) -> crate::Result<Option<MultiVersionValues>> {
74		match self {
75			Self::Command(txn) => txn.get(key),
76			Self::Query(txn) => txn.get(key),
77		}
78	}
79
80	fn contains_key(&mut self, key: &EncodedKey) -> crate::Result<bool> {
81		match self {
82			Self::Command(txn) => txn.contains_key(key),
83			Self::Query(txn) => txn.contains_key(key),
84		}
85	}
86
87	fn range_batched(&mut self, range: EncodedKeyRange, batch_size: u64) -> crate::Result<BoxedMultiVersionIter> {
88		match self {
89			Self::Command(txn) => txn.range_batched(range, batch_size),
90			Self::Query(txn) => txn.range_batched(range, batch_size),
91		}
92	}
93
94	fn range_rev_batched(
95		&mut self,
96		range: EncodedKeyRange,
97		batch_size: u64,
98	) -> crate::Result<BoxedMultiVersionIter> {
99		match self {
100			Self::Command(txn) => txn.range_rev_batched(range, batch_size),
101			Self::Query(txn) => txn.range_rev_batched(range, batch_size),
102		}
103	}
104
105	fn prefix(&mut self, prefix: &EncodedKey) -> crate::Result<BoxedMultiVersionIter> {
106		match self {
107			Self::Command(txn) => txn.prefix(prefix),
108			Self::Query(txn) => txn.prefix(prefix),
109		}
110	}
111
112	fn prefix_rev(&mut self, prefix: &EncodedKey) -> crate::Result<BoxedMultiVersionIter> {
113		match self {
114			Self::Command(txn) => txn.prefix_rev(prefix),
115			Self::Query(txn) => txn.prefix_rev(prefix),
116		}
117	}
118
119	fn read_as_of_version_exclusive(&mut self, version: CommitVersion) -> reifydb_core::Result<()> {
120		match self {
121			StandardTransaction::Command(txn) => txn.read_as_of_version_inclusive(version),
122			StandardTransaction::Query(txn) => txn.read_as_of_version_exclusive(version),
123		}
124	}
125}
126
127impl<'a> From<&'a mut StandardCommandTransaction> for StandardTransaction<'a> {
128	fn from(txn: &'a mut StandardCommandTransaction) -> Self {
129		Self::Command(txn)
130	}
131}
132
133impl<'a> From<&'a mut StandardQueryTransaction> for StandardTransaction<'a> {
134	fn from(txn: &'a mut StandardQueryTransaction) -> Self {
135		Self::Query(txn)
136	}
137}
138
139impl<'a> StandardTransaction<'a> {
140	/// Extract the underlying StandardCommandTransaction, panics if this is
141	/// a Query transaction
142	pub fn command(self) -> &'a mut StandardCommandTransaction {
143		match self {
144			Self::Command(txn) => txn,
145			Self::Query(_) => panic!("Expected Command transaction but found Query transaction"),
146		}
147	}
148
149	/// Extract the underlying StandardQueryTransaction, panics if this is a
150	/// Command transaction
151	pub fn query(self) -> &'a mut StandardQueryTransaction {
152		match self {
153			Self::Query(txn) => txn,
154			Self::Command(_) => panic!("Expected Query transaction but found Command transaction"),
155		}
156	}
157
158	/// Get a mutable reference to the underlying
159	/// StandardCommandTransaction, panics if this is a Query transaction
160	pub fn command_mut(&mut self) -> &mut StandardCommandTransaction {
161		match self {
162			Self::Command(txn) => txn,
163			Self::Query(_) => panic!("Expected Command transaction but found Query transaction"),
164		}
165	}
166
167	/// Get a mutable reference to the underlying StandardQueryTransaction,
168	/// panics if this is a Command transaction
169	pub fn query_mut(&mut self) -> &mut StandardQueryTransaction {
170		match self {
171			Self::Query(txn) => txn,
172			Self::Command(_) => panic!("Expected Query transaction but found Command transaction"),
173		}
174	}
175
176	pub fn catalog(&self) -> &MaterializedCatalog {
177		match self {
178			StandardTransaction::Command(txn) => &txn.catalog,
179			StandardTransaction::Query(txn) => &txn.catalog,
180		}
181	}
182
183	pub fn version(&self) -> CommitVersion {
184		match self {
185			StandardTransaction::Command(txn) => MultiVersionQueryTransaction::version(*txn),
186			StandardTransaction::Query(txn) => MultiVersionQueryTransaction::version(*txn),
187		}
188	}
189}