reifydb_store_multi/store/
version.rs1use reifydb_core::common::CommitVersion;
5use reifydb_type::{Result, util::cowvec::CowVec};
6
7use crate::tier::{EntryKind, TierStorage};
8
9#[derive(Debug, Clone)]
11pub enum VersionedGetResult {
12 Value {
14 value: CowVec<u8>,
15 version: CommitVersion,
16 },
17 Tombstone,
19 NotFound,
21}
22
23pub fn get_at_version<S: TierStorage>(
25 storage: &S,
26 table: EntryKind,
27 key: &[u8],
28 version: CommitVersion,
29) -> Result<VersionedGetResult> {
30 match storage.get(table, key, version)? {
32 Some(value) => Ok(VersionedGetResult::Value {
33 value,
34 version,
35 }),
36 None => {
37 let all_versions = storage.get_all_versions(table, key)?;
40
41 for (v, value) in all_versions {
43 if v <= version {
44 return match value {
46 Some(val) => Ok(VersionedGetResult::Value {
47 value: val,
48 version: v,
49 }),
50 None => Ok(VersionedGetResult::Tombstone),
51 };
52 }
53 }
54
55 Ok(VersionedGetResult::NotFound)
57 }
58 }
59}
60
61#[cfg(test)]
62pub mod tests {
63 use std::collections::HashMap;
64
65 use super::*;
66 use crate::hot::{memory::storage::MemoryPrimitiveStorage, storage::HotStorage};
67
68 #[test]
69 fn test_get_at_version_basic() {
70 let storage = MemoryPrimitiveStorage::new();
71
72 let key = CowVec::new(b"test_key".to_vec());
73 let version = CommitVersion(42);
74
75 storage.set(
77 version,
78 HashMap::from([(EntryKind::Multi, vec![(key.clone(), Some(CowVec::new(b"value".to_vec())))])]),
79 )
80 .unwrap();
81
82 match get_at_version(&storage, EntryKind::Multi, &key, version).unwrap() {
84 VersionedGetResult::Value {
85 value,
86 ..
87 } => {
88 assert_eq!(value.as_slice(), b"value");
89 }
90 _ => panic!("Expected Value result"),
91 }
92
93 match get_at_version(&storage, EntryKind::Multi, &key, CommitVersion(100)).unwrap() {
95 VersionedGetResult::Value {
96 value,
97 ..
98 } => {
99 assert_eq!(value.as_slice(), b"value");
100 }
101 _ => panic!("Expected Value result"),
102 }
103 }
104
105 #[test]
106 fn test_get_at_version_not_found() {
107 let storage = MemoryPrimitiveStorage::new();
108
109 let result = get_at_version(&storage, EntryKind::Multi, b"nonexistent", CommitVersion(100)).unwrap();
110 assert!(matches!(result, VersionedGetResult::NotFound));
111 }
112
113 #[test]
114 fn test_get_at_version_tombstone() {
115 let storage = MemoryPrimitiveStorage::new();
116
117 let key = CowVec::new(b"test_key".to_vec());
118
119 storage.set(CommitVersion(1), HashMap::from([(EntryKind::Multi, vec![(key.clone(), None)])])).unwrap();
121
122 let result = get_at_version(&storage, EntryKind::Multi, &key, CommitVersion(1)).unwrap();
123 assert!(matches!(result, VersionedGetResult::Tombstone));
124 }
125
126 #[test]
127 fn test_get_at_version_multiple_versions() {
128 let storage = HotStorage::memory();
129
130 let key = CowVec::new(b"test_key".to_vec());
131
132 storage.set(
134 CommitVersion(1),
135 HashMap::from([(EntryKind::Multi, vec![(key.clone(), Some(CowVec::new(b"v1".to_vec())))])]),
136 )
137 .unwrap();
138 storage.set(
139 CommitVersion(5),
140 HashMap::from([(EntryKind::Multi, vec![(key.clone(), Some(CowVec::new(b"v5".to_vec())))])]),
141 )
142 .unwrap();
143 storage.set(
144 CommitVersion(10),
145 HashMap::from([(EntryKind::Multi, vec![(key.clone(), Some(CowVec::new(b"v10".to_vec())))])]),
146 )
147 .unwrap();
148
149 match get_at_version(&storage, EntryKind::Multi, &key, CommitVersion(3)).unwrap() {
151 VersionedGetResult::Value {
152 value,
153 ..
154 } => {
155 assert_eq!(value.as_slice(), b"v1");
156 }
157 _ => panic!("Expected Value result"),
158 }
159
160 match get_at_version(&storage, EntryKind::Multi, &key, CommitVersion(7)).unwrap() {
162 VersionedGetResult::Value {
163 value,
164 ..
165 } => {
166 assert_eq!(value.as_slice(), b"v5");
167 }
168 _ => panic!("Expected Value result"),
169 }
170
171 match get_at_version(&storage, EntryKind::Multi, &key, CommitVersion(15)).unwrap() {
173 VersionedGetResult::Value {
174 value,
175 ..
176 } => {
177 assert_eq!(value.as_slice(), b"v10");
178 }
179 _ => panic!("Expected Value result"),
180 }
181 }
182
183 #[test]
184 fn test_get_at_version_before_any_version() {
185 let storage = HotStorage::memory();
186
187 let key = CowVec::new(b"test_key".to_vec());
188
189 storage.set(
191 CommitVersion(10),
192 HashMap::from([(EntryKind::Multi, vec![(key.clone(), Some(CowVec::new(b"value".to_vec())))])]),
193 )
194 .unwrap();
195
196 let result = get_at_version(&storage, EntryKind::Multi, &key, CommitVersion(5)).unwrap();
198 assert!(matches!(result, VersionedGetResult::NotFound));
199 }
200}