1use reifydb_codec::{
5 key::encoded::{EncodedKey, EncodedKeyRange},
6 row::bytes::EncodedBytes,
7};
8use reifydb_value::{Result, util::cowvec::CowVec};
9
10use crate::{
11 common::CommitVersion,
12 delta::Delta,
13 interface::catalog::{object::ObjectId, storage::StorageId},
14 key::{EncodableKeyRange, Key, partitioned_row::PartitionedRowKeyRange, row::RowKeyRange},
15};
16
17#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
18pub enum Tier {
19 Buffer,
20 Persistent,
21}
22
23#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
24pub enum EntryKind {
25 Multi,
26
27 Source(StorageId),
28
29 PartitionedSource(ObjectId),
30}
31
32pub fn classify_key(key: &EncodedKey) -> EntryKind {
33 match Key::decode(key) {
34 Some(Key::Row(row_key)) => EntryKind::Source(row_key.storage),
35 Some(Key::PartitionedRow(partitioned_key)) => EntryKind::PartitionedSource(partitioned_key.object),
36 _ => EntryKind::Multi,
37 }
38}
39
40pub fn classify_range(range: &EncodedKeyRange) -> Option<EntryKind> {
41 if let (Some(start), Some(_end)) = RowKeyRange::decode(range) {
42 return Some(EntryKind::Source(start.storage));
43 }
44
45 if let (Some(start), Some(_end)) = PartitionedRowKeyRange::decode(range) {
46 return Some(EntryKind::PartitionedSource(start.object));
47 }
48
49 None
50}
51
52#[derive(Debug, Clone)]
53pub struct MultiVersionRow {
54 pub key: EncodedKey,
55 pub bytes: EncodedBytes,
56 pub version: CommitVersion,
57}
58
59#[derive(Debug, Clone)]
60pub struct SingleVersionRow {
61 pub key: EncodedKey,
62 pub bytes: EncodedBytes,
63}
64
65#[derive(Debug, Clone)]
66pub struct MultiVersionBatch {
67 pub items: Vec<MultiVersionRow>,
68
69 pub has_more: bool,
70}
71
72impl MultiVersionBatch {
73 pub fn empty() -> Self {
74 Self {
75 items: Vec::new(),
76 has_more: false,
77 }
78 }
79
80 pub fn is_empty(&self) -> bool {
81 self.items.is_empty()
82 }
83}
84
85pub trait MultiVersionCommit: Send + Sync {
86 fn commit(&self, deltas: CowVec<Delta>, version: CommitVersion) -> Result<()>;
87}
88
89pub trait MultiVersionGet: Send + Sync {
90 fn get(&self, key: &EncodedKey, version: CommitVersion) -> Result<Option<MultiVersionRow>>;
91}
92
93pub trait MultiVersionContains: Send + Sync {
94 fn contains(&self, key: &EncodedKey, version: CommitVersion) -> Result<bool>;
95}
96
97pub trait MultiVersionGetPrevious: Send + Sync {
98 fn get_previous_version(
99 &self,
100 key: &EncodedKey,
101 before_version: CommitVersion,
102 ) -> Result<Option<MultiVersionRow>>;
103}
104
105pub trait MultiVersionStore:
106 Send + Sync + Clone + MultiVersionCommit + MultiVersionGet + MultiVersionGetPrevious + MultiVersionContains + 'static
107{
108}
109
110#[derive(Debug, Clone)]
111pub struct SingleVersionBatch {
112 pub items: Vec<SingleVersionRow>,
113
114 pub has_more: bool,
115}
116
117impl SingleVersionBatch {
118 pub fn empty() -> Self {
119 Self {
120 items: Vec::new(),
121 has_more: false,
122 }
123 }
124
125 pub fn is_empty(&self) -> bool {
126 self.items.is_empty()
127 }
128}
129
130pub trait SingleVersionCommit: Send + Sync {
131 fn commit(&mut self, deltas: CowVec<Delta>) -> Result<()>;
132}
133
134pub trait SingleVersionGet: Send + Sync {
135 fn get(&self, key: &EncodedKey) -> Result<Option<SingleVersionRow>>;
136}
137
138pub trait SingleVersionContains: Send + Sync {
139 fn contains(&self, key: &EncodedKey) -> Result<bool>;
140}
141
142pub trait SingleVersionSet: SingleVersionCommit {
143 fn set(&mut self, key: &EncodedKey, bytes: EncodedBytes) -> Result<()> {
144 Self::commit(
145 self,
146 CowVec::new(vec![Delta::Set {
147 key: key.clone(),
148 bytes: bytes.clone(),
149 }]),
150 )
151 }
152}
153
154pub trait SingleVersionRemove: SingleVersionCommit {
155 fn remove(&mut self, key: &EncodedKey) -> Result<()> {
156 Self::commit(self, CowVec::new(vec![Delta::remove_silent(key.clone())]))
157 }
158}
159
160pub trait SingleVersionRange: Send + Sync {
161 fn range_batch(&self, range: EncodedKeyRange, batch_size: u64) -> Result<SingleVersionBatch>;
162
163 fn range(&self, range: EncodedKeyRange) -> Result<SingleVersionBatch> {
164 self.range_batch(range, 1024)
165 }
166
167 fn prefix(&self, prefix: &EncodedKey) -> Result<SingleVersionBatch> {
168 self.range(EncodedKeyRange::prefix(prefix))
169 }
170}
171
172pub trait SingleVersionRangeRev: Send + Sync {
173 fn range_rev_batch(&self, range: EncodedKeyRange, batch_size: u64) -> Result<SingleVersionBatch>;
174
175 fn range_rev(&self, range: EncodedKeyRange) -> Result<SingleVersionBatch> {
176 self.range_rev_batch(range, 1024)
177 }
178
179 fn prefix_rev(&self, prefix: &EncodedKey) -> Result<SingleVersionBatch> {
180 self.range_rev(EncodedKeyRange::prefix(prefix))
181 }
182}
183
184pub trait SingleVersionStore:
185 Send
186 + Sync
187 + Clone
188 + SingleVersionCommit
189 + SingleVersionGet
190 + SingleVersionContains
191 + SingleVersionSet
192 + SingleVersionRemove
193 + SingleVersionRange
194 + SingleVersionRangeRev
195 + 'static
196{
197}
198
199#[cfg(test)]
200mod tests {
201 use reifydb_value::value::{Value, partition::Partition, row_number::RowNumber};
202
203 use super::{EntryKind, classify_key, classify_range};
204 use crate::{
205 interface::catalog::{id::TableId, object::ObjectId, storage::StorageId},
206 key::{
207 partitioned_row::{PartitionedRowKey, RowLocator},
208 row::RowKey,
209 },
210 };
211
212 fn part(v: &str) -> Partition {
213 Partition::of(&[Value::Utf8(v.to_string())])
214 }
215
216 #[test]
217 fn classify_key_partitioned_row_is_partitioned_source() {
218 let object = ObjectId::Table(TableId(7));
219 let key = PartitionedRowKey::encoded(object, part("us"), RowLocator::Row(RowNumber(1)));
220 assert_eq!(classify_key(&key), EntryKind::PartitionedSource(object));
221 }
222
223 #[test]
224 fn classify_key_row_is_still_source() {
225 let storage = StorageId::Table(TableId(7));
226 let key = RowKey::encoded(storage, RowNumber(1));
227 assert_eq!(classify_key(&key), EntryKind::Source(storage));
228 }
229
230 #[test]
231 fn classify_range_all_partition_forms_are_partitioned_source() {
232 let object = ObjectId::Table(TableId(9));
233 let p = part("us");
234 let last = PartitionedRowKey::encoded(object, p, RowLocator::Row(RowNumber(5)));
235 assert_eq!(
236 classify_range(&PartitionedRowKey::partition_range(object, p)),
237 Some(EntryKind::PartitionedSource(object))
238 );
239 assert_eq!(
240 classify_range(&PartitionedRowKey::partition_scan_range(object, p, Some(&last))),
241 Some(EntryKind::PartitionedSource(object))
242 );
243 assert_eq!(
244 classify_range(&PartitionedRowKey::scan_range(object, None)),
245 Some(EntryKind::PartitionedSource(object))
246 );
247 assert_eq!(
248 classify_range(&PartitionedRowKey::full_scan(object)),
249 Some(EntryKind::PartitionedSource(object))
250 );
251 }
252
253 #[test]
254 fn classify_range_row_range_is_still_source() {
255 let storage = StorageId::Table(TableId(9));
256 assert_eq!(classify_range(&RowKey::full_scan(storage)), Some(EntryKind::Source(storage)));
257 }
258}