semilattice_database/relation/
index.rs1use 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}