Skip to main content

reifydb_transaction/multi/
types.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2025 ReifyDB
3
4// This file includes and modifies code from the skipdb project (https://github.com/al8n/skipdb),
5// originally licensed under the Apache License, Version 2.0.
6// Original copyright:
7//   Copyright (c) 2024 Al Liu
8//
9// The original Apache License can be found at:
10//   http://www.apache.org/licenses/LICENSE-2.0
11
12use std::{cmp, cmp::Reverse};
13
14use reifydb_core::{
15	common::CommitVersion,
16	delta::Delta,
17	encoded::{key::EncodedKey, row::EncodedRow},
18	interface::store::MultiVersionRow,
19};
20use reifydb_type::util::cowvec::CowVec;
21
22pub enum TransactionValue {
23	PendingIter {
24		version: CommitVersion,
25		key: EncodedKey,
26		row: EncodedRow,
27	},
28	Pending(DeltaEntry),
29	Committed(Committed),
30}
31
32impl From<MultiVersionRow> for TransactionValue {
33	fn from(value: MultiVersionRow) -> Self {
34		Self::Committed(Committed {
35			key: value.key,
36			row: value.row,
37			version: value.version,
38		})
39	}
40}
41
42impl core::fmt::Debug for TransactionValue {
43	fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
44		f.debug_struct("TransactionValue")
45			.field("key", self.key())
46			.field("version", &self.version())
47			.field("value", &self.row())
48			.finish()
49	}
50}
51
52impl Clone for TransactionValue {
53	fn clone(&self) -> Self {
54		match self {
55			Self::Committed(item) => Self::Committed(item.clone()),
56			Self::Pending(delta) => Self::Pending(delta.clone()),
57			Self::PendingIter {
58				version,
59				key,
60				row: value,
61			} => Self::PendingIter {
62				version: *version,
63				key: key.clone(),
64				row: value.clone(),
65			},
66		}
67	}
68}
69
70impl TransactionValue {
71	pub fn key(&self) -> &EncodedKey {
72		match self {
73			Self::PendingIter {
74				key,
75				..
76			} => key,
77			Self::Pending(item) => item.key(),
78			Self::Committed(item) => item.key(),
79		}
80	}
81
82	pub fn version(&self) -> CommitVersion {
83		match self {
84			Self::PendingIter {
85				version,
86				..
87			} => *version,
88			Self::Pending(item) => item.version(),
89			Self::Committed(item) => item.version(),
90		}
91	}
92
93	pub fn row(&self) -> &EncodedRow {
94		match self {
95			Self::PendingIter {
96				row,
97				..
98			} => row,
99			Self::Pending(item) => item.row().expect("encoded of pending cannot be `None`"),
100			Self::Committed(item) => &item.row,
101		}
102	}
103
104	pub fn is_committed(&self) -> bool {
105		matches!(self, Self::Committed(_))
106	}
107
108	pub fn into_multi_version_row(self) -> MultiVersionRow {
109		match self {
110			Self::PendingIter {
111				version,
112				key,
113				row,
114			} => MultiVersionRow {
115				key,
116				row,
117				version,
118			},
119			Self::Pending(item) => match item.delta {
120				Delta::Set {
121					key,
122					row,
123				} => MultiVersionRow {
124					key,
125					row,
126					version: item.version,
127				},
128				Delta::Unset {
129					key,
130					..
131				}
132				| Delta::Remove {
133					key,
134				}
135				| Delta::Drop {
136					key,
137				} => MultiVersionRow {
138					key,
139					row: EncodedRow(CowVec::default()),
140					version: item.version,
141				},
142			},
143			Self::Committed(item) => MultiVersionRow {
144				key: item.key,
145				row: item.row,
146				version: item.version,
147			},
148		}
149	}
150}
151
152impl From<(CommitVersion, EncodedKey, EncodedRow)> for TransactionValue {
153	fn from((version, k, b): (CommitVersion, EncodedKey, EncodedRow)) -> Self {
154		Self::PendingIter {
155			version,
156			key: k,
157			row: b,
158		}
159	}
160}
161
162impl From<(CommitVersion, &EncodedKey, &EncodedRow)> for TransactionValue {
163	fn from((version, k, b): (CommitVersion, &EncodedKey, &EncodedRow)) -> Self {
164		Self::PendingIter {
165			version,
166			key: k.clone(),
167			row: b.clone(),
168		}
169	}
170}
171
172impl From<DeltaEntry> for TransactionValue {
173	fn from(pending: DeltaEntry) -> Self {
174		Self::Pending(pending)
175	}
176}
177
178impl From<Committed> for TransactionValue {
179	fn from(item: Committed) -> Self {
180		Self::Committed(item)
181	}
182}
183
184#[derive(Clone, Debug)]
185pub struct Committed {
186	pub(crate) key: EncodedKey,
187	pub(crate) row: EncodedRow,
188	pub(crate) version: CommitVersion,
189}
190
191impl From<MultiVersionRow> for Committed {
192	fn from(value: MultiVersionRow) -> Self {
193		Self {
194			key: value.key,
195			row: value.row,
196			version: value.version,
197		}
198	}
199}
200
201impl Committed {
202	pub fn key(&self) -> &EncodedKey {
203		&self.key
204	}
205
206	pub fn row(&self) -> &EncodedRow {
207		&self.row
208	}
209
210	pub fn version(&self) -> CommitVersion {
211		self.version
212	}
213}
214
215#[derive(Debug, PartialEq, Eq)]
216pub struct DeltaEntry {
217	pub delta: Delta,
218	pub version: CommitVersion,
219}
220
221impl PartialOrd for DeltaEntry {
222	fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
223		Some(self.cmp(other))
224	}
225}
226
227impl Ord for DeltaEntry {
228	fn cmp(&self, other: &Self) -> cmp::Ordering {
229		self.delta.key().cmp(other.delta.key()).then_with(|| Reverse(self.version).cmp(&Reverse(other.version)))
230	}
231}
232
233impl Clone for DeltaEntry {
234	fn clone(&self) -> Self {
235		Self {
236			version: self.version,
237			delta: self.delta.clone(),
238		}
239	}
240}
241
242impl DeltaEntry {
243	pub fn delta(&self) -> &Delta {
244		&self.delta
245	}
246
247	pub fn version(&self) -> CommitVersion {
248		self.version
249	}
250
251	pub fn into_components(self) -> (CommitVersion, Delta) {
252		(self.version, self.delta)
253	}
254
255	pub fn key(&self) -> &EncodedKey {
256		self.delta.key()
257	}
258
259	pub fn row(&self) -> Option<&EncodedRow> {
260		self.delta.row()
261	}
262
263	pub fn was_removed(&self) -> bool {
264		matches!(self.delta, Delta::Unset { .. } | Delta::Remove { .. })
265	}
266}