semilattice_database/relation/
index.rs

1use std::{
2    num::{NonZeroI32, NonZeroU32},
3    path::Path,
4    sync::Arc,
5};
6
7use versatile_data::{
8    idx_binary::{AvltrieeSearch, AvltrieeUpdate},
9    IdxBinary, IdxFile, RowFragment,
10};
11
12use crate::{CollectionRow, Depend};
13
14struct RelationIndexRows {
15    key: IdxFile<u32>,
16    depend: IdxFile<CollectionRow>,
17    pend: IdxFile<CollectionRow>,
18}
19pub struct RelationIndex {
20    fragment: RowFragment,
21    key_names: IdxBinary,
22    rows: RelationIndexRows,
23}
24impl RelationIndex {
25    pub fn new(root_dir: &Path, allocation_lot: u32) -> Self {
26        let mut dir = root_dir.to_path_buf();
27        dir.push("relation");
28        if !dir.exists() {
29            std::fs::create_dir_all(&dir).unwrap();
30        }
31        Self {
32            key_names: IdxBinary::new_ext(
33                {
34                    let mut path = dir.clone();
35                    path.push("key_name");
36                    path
37                },
38                1,
39            ),
40            fragment: RowFragment::new({
41                let mut path = dir.clone();
42                path.push("fragment.f");
43                path
44            }),
45            rows: RelationIndexRows {
46                key: IdxFile::new(
47                    {
48                        let mut path = dir.clone();
49                        path.push("key.i");
50                        path
51                    },
52                    allocation_lot,
53                ),
54                depend: IdxFile::new(
55                    {
56                        let mut path = dir.clone();
57                        path.push("depend.i");
58                        path
59                    },
60                    allocation_lot,
61                ),
62                pend: IdxFile::new(
63                    {
64                        let mut path = dir.clone();
65                        path.push("pend.i");
66                        path
67                    },
68                    allocation_lot,
69                ),
70            },
71        }
72    }
73
74    pub async fn insert(
75        &mut self,
76        relation_key: &str,
77        depend: &CollectionRow,
78        pend: &CollectionRow,
79    ) {
80        let key_id = self.key_names.row_or_insert(relation_key.as_bytes()).get();
81        if let Some(row) = self.fragment.pop() {
82            futures::join!(
83                async { self.rows.key.update(row, &key_id) },
84                async { self.rows.depend.update(row, depend) },
85                async { self.rows.pend.update(row, pend) }
86            );
87        } else {
88            futures::join!(
89                async { self.rows.key.insert(&key_id) },
90                async { self.rows.depend.insert(depend) },
91                async { self.rows.pend.insert(pend) }
92            );
93        }
94    }
95
96    pub async fn delete(&mut self, row: NonZeroU32) {
97        futures::join!(
98            async {
99                self.rows.key.delete(row);
100            },
101            async {
102                self.rows.depend.delete(row);
103            },
104            async {
105                self.rows.pend.delete(row);
106            },
107            async {
108                self.fragment.insert_blank(row);
109            },
110        );
111    }
112
113    pub async fn delete_pends_by_collection_row(&mut self, collection_row: &CollectionRow) {
114        for row in self
115            .rows
116            .pend
117            .iter_by(collection_row)
118            .collect::<Vec<_>>()
119            .into_iter()
120        {
121            self.delete(row).await;
122        }
123    }
124
125    pub fn pends(
126        &self,
127        key: Option<Arc<String>>,
128        depend: &CollectionRow,
129        pend_collection_id: Option<NonZeroI32>,
130    ) -> Vec<&CollectionRow> {
131        if let Some(pend_collection_id) = pend_collection_id {
132            key.as_ref().map_or_else(
133                || {
134                    self.rows
135                        .depend
136                        .iter_by(depend)
137                        .filter_map(|row| {
138                            if let Some(v) = self.rows.pend.value(row) {
139                                if v.collection_id() == pend_collection_id {
140                                    return Some(v);
141                                }
142                            }
143                            None
144                        })
145                        .collect()
146                },
147                |key| {
148                    self.key_names.row(key.as_bytes()).map_or(vec![], |key| {
149                        self.rows
150                            .depend
151                            .iter_by(depend)
152                            .filter_map(|row| {
153                                if let (Some(key_row), Some(collection_row)) =
154                                    (self.rows.key.value(row), self.rows.pend.value(row))
155                                {
156                                    if *key_row == key.get() {
157                                        if collection_row.collection_id() == pend_collection_id {
158                                            return Some(collection_row);
159                                        }
160                                    }
161                                }
162                                None
163                            })
164                            .collect()
165                    })
166                },
167            )
168        } else {
169            key.as_ref().map_or_else(
170                || {
171                    self.rows
172                        .depend
173                        .iter_by(depend)
174                        .filter_map(|row| self.rows.pend.value(row))
175                        .collect()
176                },
177                |key| {
178                    self.key_names.row(key.as_bytes()).map_or(vec![], |key| {
179                        self.rows
180                            .depend
181                            .iter_by(depend)
182                            .filter_map(|row| {
183                                if let (Some(key_row), Some(collection_row)) =
184                                    (self.rows.key.value(row), self.rows.pend.value(row))
185                                {
186                                    (*key_row == key.get()).then_some(collection_row)
187                                } else {
188                                    None
189                                }
190                            })
191                            .collect()
192                    })
193                },
194            )
195        }
196    }
197
198    pub fn depends(&self, key: Option<Arc<String>>, pend: &CollectionRow) -> Vec<Depend> {
199        key.map_or_else(
200            || {
201                self.rows
202                    .pend
203                    .iter_by(pend)
204                    .filter_map(|row| {
205                        if let (Some(key), Some(collection_row)) =
206                            (self.rows.key.value(row), self.rows.depend.value(row))
207                        {
208                            Some(Depend::new(
209                                Arc::new(
210                                    unsafe {
211                                        std::str::from_utf8_unchecked(
212                                            self.key_names
213                                                .value(NonZeroU32::new(*key).unwrap())
214                                                .unwrap(),
215                                        )
216                                    }
217                                    .into(),
218                                ),
219                                collection_row.clone(),
220                            ))
221                        } else {
222                            None
223                        }
224                    })
225                    .collect()
226            },
227            |key_name| {
228                self.key_names
229                    .row(key_name.as_bytes())
230                    .map_or(vec![], |key| {
231                        self.rows
232                            .pend
233                            .iter_by(pend)
234                            .filter_map(|row| {
235                                if let (Some(key_row), Some(collection_row)) =
236                                    (self.rows.key.value(row), self.rows.depend.value(row))
237                                {
238                                    (*key_row == key.get()).then_some(Depend::new(
239                                        Arc::clone(&key_name),
240                                        collection_row.clone(),
241                                    ))
242                                } else {
243                                    None
244                                }
245                            })
246                            .collect()
247                    })
248            },
249        )
250    }
251
252    pub fn index_depend(&self) -> &IdxFile<CollectionRow> {
253        &self.rows.depend
254    }
255
256    pub fn index_pend(&self) -> &IdxFile<CollectionRow> {
257        &self.rows.pend
258    }
259
260    pub fn depend(&self, row: NonZeroU32) -> Option<&CollectionRow> {
261        self.rows.depend.value(row)
262    }
263
264    pub fn key(&self, row: NonZeroU32) -> &str {
265        self.rows.key.value(row).map_or("", |key_row| unsafe {
266            std::str::from_utf8_unchecked(
267                self.key_names
268                    .value(NonZeroU32::new(*key_row).unwrap())
269                    .unwrap(),
270            )
271        })
272    }
273}