1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
pub mod search;

mod collection;
mod relation;

pub use binary_set::BinarySet;
pub use collection::{Collection, CollectionRow};
pub use relation::{Depend, RelationIndex};
pub use search::{Condition, Join, JoinCondition, Search};
pub use versatile_data::{
    create_uuid, idx_binary, uuid_string, Activity, CustomSort, DataOption, Field, FileMmap,
    IdxBinary, IdxFile, KeyValue, Operation, Order, OrderKey, Record, RowSet, Term, Uuid,
};

use std::{
    collections::{BTreeMap, HashMap},
    path::PathBuf,
    sync::{Arc, RwLock},
};

pub struct Database {
    collections_dir: PathBuf,
    collections_map: HashMap<String, i32>,
    collections: BTreeMap<i32, Collection>,
    relation: Arc<RwLock<RelationIndex>>,
    collection_settings: HashMap<String, DataOption>,
}
impl Database {
    pub fn new(dir: PathBuf, collection_settings: Option<HashMap<String, DataOption>>) -> Self {
        let mut collections_dir = dir.to_path_buf();
        collections_dir.push("collection");

        let mut db = Self {
            collections_dir,
            collections: BTreeMap::new(),
            collections_map: HashMap::new(),
            relation: Arc::new(RwLock::new(RelationIndex::new(&dir))),
            collection_settings: collection_settings.unwrap_or(HashMap::new()),
        };
        if db.collections_dir.exists() {
            let dir = db.collections_dir.read_dir().unwrap();
            for d in dir.into_iter() {
                let d = d.unwrap();
                if d.file_type().unwrap().is_dir() {
                    if let Some(fname) = d.file_name().to_str() {
                        if let Some(pos) = fname.find("_") {
                            if let Ok(collection_id) = (&fname[..pos]).parse::<i32>() {
                                let name = &fname[(pos + 1)..];
                                db.create_collection(collection_id, name, d.path());
                            }
                        }
                    }
                }
            }
        }
        db
    }

    pub fn delete_recursive(&mut self, target: &CollectionRow) {
        let rows = self
            .relation
            .read()
            .unwrap()
            .index_depend()
            .iter_by(|v| v.cmp(target))
            .collect::<Vec<u32>>();
        for relation_row in rows {
            let collection_row = self
                .relation
                .read()
                .unwrap()
                .index_pend()
                .value(relation_row)
                .cloned();
            if let Some(collection_row) = collection_row {
                self.delete_recursive(&collection_row);
            }
        }
        let rows = self
            .relation
            .read()
            .unwrap()
            .index_pend()
            .iter_by(|v| v.cmp(target))
            .collect::<Vec<u32>>();
        for relation_row in rows {
            self.relation.write().unwrap().delete(relation_row);
        }
        if let Some(collection) = self.collection_mut(target.collection_id()) {
            collection.update(&Operation::Delete { row: target.row() });
        }
    }
}