semilattice_database/
lib.rs

1pub mod search;
2
3mod collection;
4mod relation;
5
6use async_recursion::async_recursion;
7pub use collection::{Collection, CollectionRow};
8pub use relation::{Depend, RelationIndex};
9pub use search::{Condition, Search, SearchJoin, SearchResult};
10use versatile_data::idx_binary::AvltrieeSearch;
11pub use versatile_data::{
12    create_uuid, idx_binary, uuid_string, Activity, CustomOrderKey, CustomSort, DataOption, Field,
13    FieldName, Fields, FileMmap, IdxFile, Order, OrderKey, RowSet, Term, Uuid,
14};
15
16use std::{collections::BTreeMap, num::NonZeroI32, path::PathBuf};
17
18use hashbrown::HashMap;
19
20pub struct Database {
21    collections_dir: PathBuf,
22    collections_map: HashMap<String, NonZeroI32>,
23    collections: BTreeMap<NonZeroI32, Collection>,
24    relation: RelationIndex,
25    collection_settings: std::collections::HashMap<String, DataOption>,
26}
27impl Database {
28    pub fn new(
29        dir: PathBuf,
30        collection_settings: Option<std::collections::HashMap<String, DataOption>>,
31        relation_allocation_lot: u32,
32    ) -> Self {
33        let mut collections_dir = dir.to_path_buf();
34        collections_dir.push("collection");
35
36        let mut db = Self {
37            collections_dir,
38            collections: BTreeMap::new(),
39            collections_map: HashMap::new(),
40            relation: RelationIndex::new(&dir, relation_allocation_lot),
41            collection_settings: collection_settings.unwrap_or(std::collections::HashMap::new()),
42        };
43        if db.collections_dir.exists() {
44            let dir = db.collections_dir.read_dir().unwrap();
45            for d in dir.into_iter() {
46                let d = d.unwrap();
47                if d.file_type().unwrap().is_dir() {
48                    if let Some(fname) = d.file_name().to_str() {
49                        if let Some(pos) = fname.find("_") {
50                            if let Ok(collection_id) = (&fname[..pos]).parse::<NonZeroI32>() {
51                                let name = &fname[(pos + 1)..];
52                                db.create_collection(collection_id, name, d.path());
53                            }
54                        }
55                    }
56                }
57            }
58        }
59        db
60    }
61
62    #[async_recursion(?Send)]
63    pub async fn delete(&mut self, target: &CollectionRow) {
64        let rows: Vec<_> = self.relation.index_depend().iter_by(target).collect();
65        for relation_row in rows.into_iter() {
66            if let Some(collection_row) = self.relation.index_pend().value(relation_row).cloned() {
67                self.delete(&collection_row).await;
68            }
69        }
70        for relation_row in self
71            .relation
72            .index_pend()
73            .iter_by(target)
74            .collect::<Vec<_>>()
75            .into_iter()
76        {
77            self.relation.delete(relation_row).await;
78        }
79        if let Some(collection) = self.collection_mut(target.collection_id()) {
80            collection.delete(target.row()).await;
81        }
82    }
83}