1use core::any::Any;
2use core::ops::Deref;
3use alloc::sync::{Arc, Weak};
4use alloc::vec;
5
6use serde::de::DeserializeOwned;
7use serde::Serialize;
8use sled::{Db, Tree};
9
10use crate::encoding::{decode, encode};
11use crate::record::Record;
12use crate::result::DbResult;
13use crate::subscriber::{self, Subscriber};
14use crate::table::{TableInner, TableType};
15
16use self::private::AnyIndexInternal;
17
18#[allow(unused_imports)]
19use alloc::{boxed::Box, format, vec::Vec, string::{String, ToString}};
20
21pub trait IndexType: Serialize + DeserializeOwned {}
22impl<T: Serialize + DeserializeOwned> IndexType for T {}
23
24pub struct Index<T: TableType + 'static, I: IndexType>(pub(crate) Arc<IndexInner<T, I>>);
26
27impl<T: TableType, I: IndexType> Clone for Index<T, I> {
28 fn clone(&self) -> Self {
29 Self(self.0.clone())
30 }
31}
32
33impl<T: TableType, I: IndexType> Deref for Index<T, I> {
34 type Target = Arc<IndexInner<T, I>>;
35
36 fn deref(&self) -> &Self::Target {
37 &self.0
38 }
39}
40
41pub struct IndexInner<T: TableType + 'static, I: IndexType> {
43 table: Weak<TableInner<T>>,
44 key_func: Box<dyn Fn(&T) -> I + Send + Sync>,
46 indexed_data: Tree,
48 subscriber: Subscriber<T>,
50}
51
52impl<T: TableType, I: IndexType> IndexInner<T, I> {
53 pub(crate) fn new(
70 idx_name: &str,
71 engine: &Db,
72 table: Weak<TableInner<T>>,
73 key_func: impl Fn(&T) -> I + Send + Sync + 'static,
74 subscriber: Subscriber<T>,
75 ) -> DbResult<Self> {
76 let new_index = Self {
77 table,
78 key_func: Box::new(key_func),
79 indexed_data: engine.open_tree(idx_name)?,
80 subscriber,
81 };
82
83 new_index.sync()?;
84
85 Ok(new_index)
86 }
87
88 pub fn sync(&self) -> DbResult<()> {
90 self.indexed_data.clear()?;
91
92 let table = self.table.upgrade().unwrap();
93 let root = table.root.write();
94 for key in root.iter().keys() {
95 if let Some(data) = root.get(&key.clone()?)? {
97 self.insert(&Record {
98 id: decode(&key?)?,
99 data: decode(&data)?,
100 })?;
101 }
102 }
103
104 Ok(())
105 }
106
107 fn commit_log(&self) -> DbResult<()> {
109 while let Ok(event) = self.subscriber.rx.try_recv() {
111 match event {
112 subscriber::Event::Remove(record) => self.remove(&record)?,
113 subscriber::Event::Insert(record) => self.insert(&record)?,
114 subscriber::Event::Update {
115 id,
116 old_data,
117 new_data,
118 } => {
119 self.remove(&Record { id, data: old_data })?;
120 self.insert(&Record { id, data: new_data })?;
121 }
122 subscriber::Event::Default => {}
123 }
124 }
125
126 Ok(())
127 }
128
129 fn insert(&self, record: &Record<T>) -> DbResult<()> {
135 let key = encode(&(self.key_func)(&record.data))?;
136
137 match self.indexed_data.get(&key)? { Some(data) => {
138 let mut vec: Vec<u64> = decode(&data)?;
139 vec.push(record.id);
140 self.indexed_data.insert(key, encode(&vec)?)?;
141 } _ => {
142 self.indexed_data.insert(key, encode(&vec![record.id])?)?;
143 }}
144
145 Ok(())
146 }
147
148 fn remove(&self, record: &Record<T>) -> DbResult<()> {
155 let key = encode(&(self.key_func)(&record.data))?;
156
157 if let Some(data) = self.indexed_data.get(&key)? {
158 let mut index_values: Vec<u64> = decode(&data)?;
159
160 if index_values.len() < 2 {
162 self.indexed_data.remove(&key)?;
163 } else {
164 if let Some(pos) = index_values.iter().position(|id| *id == record.id) {
166 index_values.remove(pos);
167 self.indexed_data.insert(&key, encode(&index_values)?)?;
169 }
170 }
171 }
172
173 Ok(())
174 }
175
176 pub fn delete(&self, query: &I) -> DbResult<Vec<Record<T>>> {
186 let records = self.select(query)?;
187
188 let table = self.table.upgrade().unwrap();
189
190 for record in &records {
191 table.delete(record.id)?;
192 }
193
194 Ok(records)
195 }
196
197 pub fn select(&self, query: &I) -> DbResult<Vec<Record<T>>> {
207 self.commit_log()?;
208
209 let table = self.table.upgrade().unwrap();
210
211 Ok(
212 match self.indexed_data.get(encode(&query)?) { Ok(Some(bytes)) => {
213 let ids: Vec<u64> = decode(&bytes)?;
214
215 let mut results = vec![];
216 for id in ids {
217 if let Some(record) = table.select(id)? {
218 results.push(record);
219 }
220 }
221
222 results
223 } _ => {
224 Vec::new()
225 }},
226 )
227 }
228
229 fn tree_select(&self, tree: &Tree, query: &I) -> DbResult<Vec<Record<T>>> {
231 self.commit_log()?;
232
233 let table = self.table.upgrade().unwrap();
234
235 Ok(
236 match self.indexed_data.get(encode(&query)?) { Ok(Some(bytes)) => {
237 let ids: Vec<u64> = decode(&bytes)?;
238
239 let mut results = vec![];
240 for id in ids {
241 if let Some(record) = table.tree_select(tree, id)? {
242 results.push(record);
243 }
244 }
245
246 results
247 } _ => {
248 Vec::new()
249 }},
250 )
251 }
252
253 pub fn update(&self, query: &I, updater: fn(T) -> T) -> DbResult<Vec<Record<T>>> {
264 self.commit_log()?;
265
266 let table = self.table.upgrade().unwrap();
267
268 match self.indexed_data.get(encode(&query)?) { Ok(Some(bytes)) => {
269 let ids: Vec<u64> = decode(&bytes)?;
270 table.update(&ids, updater)
271 } _ => {
272 Ok(vec![])
273 }}
274 }
275
276 pub fn index_name(&self) -> String {
277 alloc::str::from_utf8(&self.indexed_data.name())
278 .unwrap()
279 .to_string()
280 }
281
282 pub fn generate_key(&self, data: &T) -> DbResult<Vec<u8>> {
283 encode(&(self.key_func)(&data))
284 }
285}
286
287pub(crate) mod private {
288 use super::*;
289
290 pub trait AnyIndexInternal<T: TableType> {
292 fn tree_exists(&self, tree: &Tree, record: &Record<T>) -> DbResult<Vec<u64>>;
293 }
294}
295
296impl<T, I> private::AnyIndexInternal<T> for Index<T, I>
297where
298 T: TableType,
299 I: IndexType + 'static,
300{
301 fn tree_exists(&self, tree: &Tree, record: &Record<T>) -> DbResult<Vec<u64>> {
302 let i = (self.key_func)(&record.data);
303
304 Ok(self
305 .tree_select(tree, &i)?
306 .iter()
307 .map(|record: &Record<T>| record.id)
308 .collect())
309 }
310}
311
312pub trait AnyIndex<T: TableType>: private::AnyIndexInternal<T> {
314 fn exists(&self, record: &Record<T>) -> DbResult<Vec<u64>>;
320 fn search(&self, value: Box<dyn Any>) -> DbResult<Vec<Record<T>>>;
322 fn idx_name(&self) -> String;
324 fn gen_key(&self, data: &T) -> DbResult<Vec<u8>>;
326}
327
328impl<T, I> AnyIndex<T> for Index<T, I>
329where
330 T: TableType,
331 I: IndexType + 'static,
332{
333 fn search(&self, value: Box<dyn Any>) -> DbResult<Vec<Record<T>>> {
334 let i = *value.downcast::<I>().unwrap();
335 self.select(&i)
336 }
337
338 fn idx_name(&self) -> String {
339 self.index_name()
340 }
341
342 fn exists(&self, record: &Record<T>) -> DbResult<Vec<u64>> {
343 self.tree_exists(&self.table.upgrade().unwrap().root.read(), record)
344 }
345
346 fn gen_key(&self, data: &T) -> DbResult<Vec<u8>> {
347 self.generate_key(data)
348 }
349}
350
351#[cfg(test)]
352mod tests {
353 use alloc::borrow::ToOwned;
354
355 use super::*;
356 use crate::{Table, TinyBase};
357
358 #[test]
359 fn index_sync() {
360 let db = TinyBase::new(None, true);
361 let table: Table<String> = db.open_table("test_table").unwrap();
362
363 let id = table.insert("value1".to_string()).unwrap();
365 let id2 = table.insert("value2".to_string()).unwrap();
366
367 let index = table.create_index("length", |value| value.len()).unwrap();
369
370 assert!(index.sync().is_ok());
371
372 let results = index.select(&6).unwrap();
373
374 assert_eq!(results.len(), 2);
375 assert_eq!(results[0].id, id);
376 assert_eq!(results[1].id, id2);
377 }
378
379 #[test]
380 fn index_select() {
381 let db = TinyBase::new(None, true);
382 let table: Table<String> = db.open_table("test_table").unwrap();
383
384 table.insert("value1".to_string()).unwrap();
386 table.insert("value2".to_string()).unwrap();
387
388 let index = table
390 .create_index("name", |value| value.to_owned())
391 .unwrap();
392
393 let record: Vec<Record<String>> =
394 index.select(&"value1".to_string()).expect("Select failed");
395
396 assert_eq!(record.len(), 1);
397 assert_eq!(record[0].data, "value1");
398
399 let record_2 = index
400 .select(&"non_existent_value".to_string())
401 .expect("Select failed");
402
403 assert_eq!(record_2.len(), 0);
404 }
405
406 #[test]
407 fn index_update() {
408 let db = TinyBase::new(None, true);
409 let table: Table<String> = db.open_table("test_table").unwrap();
410
411 let index: Index<String, String> = table
413 .create_index("index_name", |value| value.to_owned())
414 .unwrap();
415
416 let id1 = table.insert("initial_value_1".to_string()).unwrap();
418 table.insert("initial_value_2".to_string()).unwrap();
419
420 let updated_records = index
422 .update(&"initial_value_1".to_string(), |_| {
423 "updated_value".to_string()
424 })
425 .expect("Update failed");
426
427 assert_eq!(updated_records.len(), 1);
428 assert_eq!(updated_records[0].id, id1);
429 assert_eq!(updated_records[0].data, "updated_value");
430 }
431
432 #[test]
433 fn index_exists() {
434 let db = TinyBase::new(None, true);
435 let table: Table<String> = db.open_table("test_table").unwrap();
436
437 let index = table
439 .create_index("index_name", |value| value.to_owned())
440 .unwrap();
441
442 let id = table.insert("value1".to_string()).unwrap();
444
445 let record = Record {
446 id,
447 data: "value1".to_string(),
448 };
449
450 assert!(!index
451 .exists(&record)
452 .expect("Exists check failed")
453 .is_empty());
454
455 let record_not_exist = Record {
456 id: 999,
457 data: "non_existent_value".to_string(),
458 };
459
460 assert!(index
461 .exists(&record_not_exist)
462 .expect("Exists check failed")
463 .is_empty());
464 }
465}