1use std::{collections::HashMap, ops::Bound};
9
10use reifydb_codec::key::encoded::EncodedKey;
11use reifydb_core::{common::CommitVersion, interface::store::EntryKind};
12use reifydb_runtime::shutdown::Shutdown;
13#[cfg(all(feature = "sqlite", not(target_arch = "wasm32")))]
14use reifydb_sqlite::{SqliteConfig, SqliteTempPathGuard};
15use reifydb_value::{Result, util::cowvec::CowVec};
16
17use crate::{
18 MultiVersionScope,
19 tier::{
20 HistoricalCursor, RangeBatch, RangeCursor, RawEntry, TierBackend, TierBatch, TierStorage,
21 VersionedGetResult,
22 },
23};
24
25#[cfg(all(feature = "sqlite", not(target_arch = "wasm32")))]
26pub mod sqlite;
27
28#[cfg(all(feature = "sqlite", not(target_arch = "wasm32")))]
29use sqlite::storage::SqlitePersistentStorage;
30
31#[derive(Debug, Clone, Copy, PartialEq, Eq)]
32pub struct CheckpointOutcome {
33 pub log_frames: u32,
34 pub restarted: bool,
35}
36
37#[derive(Clone)]
38#[cfg_attr(all(feature = "sqlite", not(target_arch = "wasm32")), repr(u8))]
39pub enum MultiPersistentTier {
40 #[cfg(all(feature = "sqlite", not(target_arch = "wasm32")))]
41 Sqlite(SqlitePersistentStorage) = 0,
42}
43
44impl Shutdown for MultiPersistentTier {
45 fn shutdown(&self) {
46 match self {
47 #[cfg(all(feature = "sqlite", not(target_arch = "wasm32")))]
48 Self::Sqlite(s) => s.shutdown(),
49 #[cfg(not(all(feature = "sqlite", not(target_arch = "wasm32"))))]
50 _ => {}
51 }
52 }
53}
54
55#[cfg(all(feature = "sqlite", not(target_arch = "wasm32")))]
56impl MultiPersistentTier {
57 pub fn sqlite(config: SqliteConfig) -> Self {
58 Self::Sqlite(SqlitePersistentStorage::new(config))
59 }
60
61 pub fn sqlite_in_memory() -> (Self, SqliteTempPathGuard) {
62 let (storage, guard) = SqlitePersistentStorage::in_memory();
63 (Self::Sqlite(storage), guard)
64 }
65
66 pub fn maybe_checkpoint(&self) -> Result<CheckpointOutcome> {
67 match self {
68 Self::Sqlite(s) => s.maybe_checkpoint(),
69 }
70 }
71
72 pub fn reclaim(&self) -> Result<()> {
73 match self {
74 Self::Sqlite(s) => s.reclaim(),
75 }
76 }
77
78 pub fn delete_below_version(
79 &self,
80 table: EntryKind,
81 cutoff_version: CommitVersion,
82 prefix: Option<&[u8]>,
83 ) -> Result<Vec<EncodedKey>> {
84 match self {
85 Self::Sqlite(s) => s.delete_below_version(table, cutoff_version, prefix),
86 }
87 }
88
89 pub fn delete_keys(&self, table: EntryKind, keys: &[EncodedKey]) -> Result<u64> {
90 match self {
91 Self::Sqlite(s) => s.delete_keys(table, keys),
92 }
93 }
94
95 pub fn set_collecting_accepted(&self, version: CommitVersion, batches: TierBatch) -> Result<Vec<EncodedKey>> {
96 match self {
97 Self::Sqlite(s) => s.set_collecting_accepted(version, batches),
98 }
99 }
100
101 pub fn load_range_consistent(
102 &self,
103 table: EntryKind,
104 start: Bound<&[u8]>,
105 end: Bound<&[u8]>,
106 read: CommitVersion,
107 ) -> Result<Vec<RawEntry>> {
108 match self {
109 Self::Sqlite(s) => s.load_range_consistent(table, start, end, read),
110 }
111 }
112}
113
114#[cfg(not(all(feature = "sqlite", not(target_arch = "wasm32"))))]
115impl MultiPersistentTier {
116 pub fn maybe_checkpoint(&self) -> Result<CheckpointOutcome> {
117 match *self {}
118 }
119
120 pub fn reclaim(&self) -> Result<()> {
121 match *self {}
122 }
123
124 pub fn delete_below_version(
125 &self,
126 _table: EntryKind,
127 _cutoff_version: CommitVersion,
128 _prefix: Option<&[u8]>,
129 ) -> Result<Vec<EncodedKey>> {
130 match *self {}
131 }
132
133 pub fn delete_keys(&self, _table: EntryKind, _keys: &[EncodedKey]) -> Result<u64> {
134 match *self {}
135 }
136
137 pub fn load_range_consistent(
138 &self,
139 _table: EntryKind,
140 _start: Bound<&[u8]>,
141 _end: Bound<&[u8]>,
142 _read: CommitVersion,
143 ) -> Result<Vec<RawEntry>> {
144 match *self {}
145 }
146}
147
148#[cfg(all(feature = "sqlite", not(target_arch = "wasm32")))]
149impl TierStorage for MultiPersistentTier {
150 fn get(&self, table: EntryKind, key: &[u8], version: CommitVersion) -> Result<VersionedGetResult> {
151 match self {
152 Self::Sqlite(s) => s.get(table, key, version),
153 }
154 }
155
156 fn get_many(
157 &self,
158 table: EntryKind,
159 keys: &[&[u8]],
160 version: CommitVersion,
161 ) -> Result<Vec<VersionedGetResult>> {
162 match self {
163 Self::Sqlite(s) => s.get_many(table, keys, version),
164 }
165 }
166
167 fn set(&self, version: CommitVersion, batches: TierBatch) -> Result<()> {
168 match self {
169 Self::Sqlite(s) => s.set(version, batches),
170 }
171 }
172
173 fn range_next(
174 &self,
175 table: EntryKind,
176 cursor: &mut RangeCursor,
177 start: Bound<&[u8]>,
178 end: Bound<&[u8]>,
179 scope: MultiVersionScope,
180 batch_size: usize,
181 ) -> Result<RangeBatch> {
182 match self {
183 Self::Sqlite(s) => s.range_next(table, cursor, start, end, scope, batch_size),
184 }
185 }
186
187 fn range_rev_next(
188 &self,
189 table: EntryKind,
190 cursor: &mut RangeCursor,
191 start: Bound<&[u8]>,
192 end: Bound<&[u8]>,
193 scope: MultiVersionScope,
194 batch_size: usize,
195 ) -> Result<RangeBatch> {
196 match self {
197 Self::Sqlite(s) => s.range_rev_next(table, cursor, start, end, scope, batch_size),
198 }
199 }
200
201 fn ensure_table(&self, table: EntryKind) -> Result<()> {
202 match self {
203 Self::Sqlite(s) => s.ensure_table(table),
204 }
205 }
206
207 fn clear_table(&self, table: EntryKind) -> Result<()> {
208 match self {
209 Self::Sqlite(s) => s.clear_table(table),
210 }
211 }
212
213 fn drop(&self, batches: HashMap<EntryKind, Vec<(EncodedKey, CommitVersion)>>) -> Result<()> {
214 match self {
215 Self::Sqlite(s) => s.drop(batches),
216 }
217 }
218
219 fn get_all_versions(&self, table: EntryKind, key: &[u8]) -> Result<Vec<(CommitVersion, Option<CowVec<u8>>)>> {
220 match self {
221 Self::Sqlite(s) => s.get_all_versions(table, key),
222 }
223 }
224
225 fn scan_historical_below(
226 &self,
227 table: EntryKind,
228 cutoff: CommitVersion,
229 cursor: &mut HistoricalCursor,
230 batch_size: usize,
231 ) -> Result<Vec<(EncodedKey, CommitVersion)>> {
232 match self {
233 Self::Sqlite(s) => s.scan_historical_below(table, cutoff, cursor, batch_size),
234 }
235 }
236}
237
238#[cfg(not(all(feature = "sqlite", not(target_arch = "wasm32"))))]
239impl TierStorage for MultiPersistentTier {
240 fn get(&self, _table: EntryKind, _key: &[u8], _version: CommitVersion) -> Result<VersionedGetResult> {
241 match *self {}
242 }
243
244 fn set(&self, _version: CommitVersion, _batches: TierBatch) -> Result<()> {
245 match *self {}
246 }
247
248 fn range_next(
249 &self,
250 _table: EntryKind,
251 _cursor: &mut RangeCursor,
252 _start: Bound<&[u8]>,
253 _end: Bound<&[u8]>,
254 _scope: MultiVersionScope,
255 _batch_size: usize,
256 ) -> Result<RangeBatch> {
257 match *self {}
258 }
259
260 fn range_rev_next(
261 &self,
262 _table: EntryKind,
263 _cursor: &mut RangeCursor,
264 _start: Bound<&[u8]>,
265 _end: Bound<&[u8]>,
266 _scope: MultiVersionScope,
267 _batch_size: usize,
268 ) -> Result<RangeBatch> {
269 match *self {}
270 }
271
272 fn ensure_table(&self, _table: EntryKind) -> Result<()> {
273 match *self {}
274 }
275
276 fn clear_table(&self, _table: EntryKind) -> Result<()> {
277 match *self {}
278 }
279
280 fn drop(&self, _batches: HashMap<EntryKind, Vec<(EncodedKey, CommitVersion)>>) -> Result<()> {
281 match *self {}
282 }
283
284 fn get_all_versions(&self, _table: EntryKind, _key: &[u8]) -> Result<Vec<(CommitVersion, Option<CowVec<u8>>)>> {
285 match *self {}
286 }
287
288 fn scan_historical_below(
289 &self,
290 _table: EntryKind,
291 _cutoff: CommitVersion,
292 _cursor: &mut HistoricalCursor,
293 _batch_size: usize,
294 ) -> Result<Vec<(EncodedKey, CommitVersion)>> {
295 match *self {}
296 }
297}
298
299impl TierBackend for MultiPersistentTier {}