1use super::internal::*;
13use super::layer::*;
14use crate::storage::*;
15use std::collections::HashMap;
16use std::io;
17use std::pin::Pin;
18use std::sync::Arc;
19
20use futures::future::Future;
21
22use bitvec::prelude::*;
23
24pub trait LayerBuilder: Send + Sync {
29 fn name(&self) -> [u32; 5];
31 fn parent(&self) -> Option<Arc<dyn Layer>>;
33 fn add_value_triple(&mut self, triple: ValueTriple);
35 fn add_id_triple(&mut self, triple: IdTriple);
37 fn remove_value_triple(&mut self, triple: ValueTriple);
39 fn remove_id_triple(&mut self, triple: IdTriple);
41 fn commit(self) -> Pin<Box<dyn Future<Output = io::Result<()>> + Send>>;
43 fn commit_boxed(self: Box<Self>) -> Pin<Box<dyn Future<Output = io::Result<()>> + Send>>;
45}
46
47#[derive(Clone)]
52pub struct SimpleLayerBuilder<F: 'static + FileLoad + FileStore + Clone> {
53 name: [u32; 5],
54 parent: Option<Arc<dyn Layer>>,
55 files: LayerFiles<F>,
56 id_additions: Vec<IdTriple>,
57 id_removals: Vec<IdTriple>,
58
59 nodes_values_map: HashMap<ObjectType, u64>,
60 predicates_map: HashMap<String, u64>,
61 nodes_values_map_count: usize,
62 predicates_map_count: usize,
63 node_count: usize,
64 pred_count: usize,
65 val_count: usize,
66}
67
68impl<F: 'static + FileLoad + FileStore + Clone> SimpleLayerBuilder<F> {
69 pub fn new(name: [u32; 5], files: BaseLayerFiles<F>) -> Self {
71 Self {
72 name,
73 parent: None,
74 files: LayerFiles::Base(files),
75 id_additions: Vec::with_capacity(0),
76 id_removals: Vec::with_capacity(0),
77
78 nodes_values_map: HashMap::new(),
79 predicates_map: HashMap::new(),
80 nodes_values_map_count: 0,
81 predicates_map_count: 0,
82 node_count: 0,
83 pred_count: 0,
84 val_count: 0,
85 }
86 }
87
88 pub fn from_parent(name: [u32; 5], parent: Arc<dyn Layer>, files: ChildLayerFiles<F>) -> Self {
90 let nodes_values_map_count = parent.node_and_value_count();
91 let predicates_map_count = parent.predicate_count();
92 Self {
93 name,
94 parent: Some(parent),
95 files: LayerFiles::Child(files),
96 id_additions: Vec::new(),
97 id_removals: Vec::new(),
98
99 nodes_values_map: HashMap::new(),
100 predicates_map: HashMap::new(),
101 nodes_values_map_count,
102 predicates_map_count,
103 node_count: 0,
104 pred_count: 0,
105 val_count: 0,
106 }
107 }
108
109 fn calculate_triple(&mut self, triple: ValueTriple) -> IdTriple {
110 let subject = ObjectType::Node(triple.subject);
111 let predicate = triple.predicate;
112 let object = triple.object;
113 let subject_id = if let Some(n) = self.nodes_values_map.get(&subject) {
114 *n
115 } else {
116 let node_id = if let Some(node_id) = self
117 .parent
118 .as_ref()
119 .and_then(|p| p.subject_id(subject.node_ref().unwrap()))
120 {
121 node_id
122 } else {
123 self.nodes_values_map_count += 1;
124 self.node_count += 1;
125 self.nodes_values_map_count as u64
126 };
127 self.nodes_values_map.insert(subject, node_id);
128
129 node_id
130 };
131
132 let predicate_id = if let Some(p) = self.predicates_map.get(&predicate) {
133 *p
134 } else {
135 let predicate_id = if let Some(predicate_id) = self
136 .parent
137 .as_ref()
138 .and_then(|p| p.predicate_id(&predicate))
139 {
140 predicate_id
141 } else {
142 self.predicates_map_count += 1;
143 self.pred_count += 1;
144 self.predicates_map_count as u64
145 };
146 self.predicates_map.insert(predicate, predicate_id);
147
148 predicate_id
149 };
150 let object_id = if let Some(o) = self.nodes_values_map.get(&object) {
151 *o
152 } else {
153 match object {
154 ObjectType::Node(n) => {
155 let node_id = if let Some(node_id) = self
156 .parent
157 .as_ref()
158 .and_then(|p| p.object_node_id(n.as_str()))
159 {
160 node_id
161 } else {
162 self.nodes_values_map_count += 1;
163 self.node_count += 1;
164 self.nodes_values_map_count as u64
165 };
166 self.nodes_values_map.insert(ObjectType::Node(n), node_id);
167
168 node_id
169 }
170 ObjectType::Value(v) => {
171 let value_id = if let Some(value_id) =
172 self.parent.as_ref().and_then(|p| p.object_value_id(&v))
173 {
174 value_id
175 } else {
176 self.nodes_values_map_count += 1;
177 self.val_count += 1;
178 self.nodes_values_map_count as u64
179 };
180 self.nodes_values_map.insert(ObjectType::Value(v), value_id);
181
182 value_id
183 }
184 }
185 };
186
187 IdTriple::new(subject_id, predicate_id, object_id)
188 }
189}
190
191impl<F: 'static + FileLoad + FileStore + Clone> LayerBuilder for SimpleLayerBuilder<F> {
192 fn name(&self) -> [u32; 5] {
193 self.name
194 }
195
196 fn parent(&self) -> Option<Arc<dyn Layer>> {
197 self.parent.clone()
198 }
199
200 fn add_value_triple(&mut self, addition: ValueTriple) {
201 let triple = self.calculate_triple(addition);
202 self.id_additions.push(triple);
203 }
204
205 fn add_id_triple(&mut self, triple: IdTriple) {
206 self.id_additions.push(triple);
207 }
208
209 fn remove_value_triple(&mut self, removal: ValueTriple) {
210 let triple = self.calculate_triple(removal);
211 self.id_removals.push(triple);
212 }
213
214 fn remove_id_triple(&mut self, triple: IdTriple) {
215 self.id_removals.push(triple);
216 }
217
218 fn commit(self) -> Pin<Box<dyn Future<Output = io::Result<()>> + Send>> {
219 let SimpleLayerBuilder {
220 name: _,
221 parent,
222 files,
223 mut id_additions,
224 mut id_removals,
225
226 nodes_values_map,
227 predicates_map,
228 nodes_values_map_count: _,
229 predicates_map_count: _,
230 node_count,
231 pred_count,
232 val_count,
233 } = self;
234 let parent_node_value_offset = parent
235 .as_ref()
236 .map(|p| p.node_and_value_count())
237 .unwrap_or(0);
238 let parent_predicate_offset = parent.as_ref().map(|p| p.predicate_count()).unwrap_or(0);
239 id_additions.sort();
242 id_additions.dedup();
243 id_additions.shrink_to_fit();
244 id_removals.sort();
245 id_removals.dedup();
246 id_removals.shrink_to_fit();
247
248 let mut additions_it = id_additions.iter_mut().peekable();
250 let mut removals_it = id_removals.iter_mut().peekable();
251 loop {
252 let addition = additions_it.peek();
253 let removal = removals_it.peek();
254
255 if removal.is_none() {
257 break;
258 }
259 if addition.is_none() {
260 for removal in removals_it {
262 if removal.subject > parent_node_value_offset as u64
263 || removal.predicate > parent_predicate_offset as u64
264 || removal.object > parent_node_value_offset as u64
265 {
266 *removal = IdTriple::new(0, 0, 0);
267 }
268 }
269 break;
270 }
271
272 if addition < removal {
273 additions_it.next();
274 } else if addition > removal {
275 let removal = removals_it.next().unwrap();
276 if removal.subject > parent_node_value_offset as u64
278 || removal.predicate > parent_predicate_offset as u64
279 || removal.object > parent_node_value_offset as u64
280 {
281 *removal = IdTriple::new(0, 0, 0);
282 }
283 } else {
284 let addition = additions_it.next().unwrap();
286 let removal = removals_it.next().unwrap();
287 *addition = IdTriple::new(0, 0, 0);
288 *removal = IdTriple::new(0, 0, 0);
289 }
290 }
291
292 let mut node_value_existences = bitvec![0;node_count + val_count];
294 let mut predicate_existences = bitvec![0;pred_count];
295 for triple in id_additions.iter().chain(id_removals.iter()) {
296 if triple.subject > parent_node_value_offset as u64 {
297 node_value_existences
298 .set(triple.subject as usize - parent_node_value_offset - 1, true);
299 }
300 if triple.predicate > parent_predicate_offset as u64 {
301 predicate_existences.set(
302 triple.predicate as usize - parent_predicate_offset - 1,
303 true,
304 );
305 }
306 if triple.object > parent_node_value_offset as u64 {
307 node_value_existences
308 .set(triple.object as usize - parent_node_value_offset - 1, true);
309 }
310 }
311
312 let mut nodes = Vec::with_capacity(node_count);
314 let mut predicates = Vec::with_capacity(pred_count);
315 let mut values = Vec::with_capacity(val_count);
316
317 for (entry, id) in nodes_values_map.into_iter() {
318 if id <= parent_node_value_offset as u64 {
319 continue;
321 }
322 if !node_value_existences[id as usize - parent_node_value_offset - 1] {
323 continue;
325 }
326 match entry {
327 ObjectType::Node(n) => nodes.push((n, id)),
328 ObjectType::Value(v) => values.push((v, id)),
329 }
330 }
331 for (entry, id) in predicates_map.into_iter() {
332 if id <= parent_predicate_offset as u64 {
333 continue;
335 }
336 if !predicate_existences[id as usize - parent_predicate_offset - 1] {
337 continue;
339 }
340
341 predicates.push((entry, id));
342 }
343
344 nodes.sort();
345 predicates.sort();
346 values.sort();
347
348 let mut node_value_id_map = vec![0_u64; node_count + val_count];
350 let mut predicate_id_map = vec![0_u64; pred_count];
351 for (new_id, (_, old_id)) in nodes.iter().enumerate() {
352 let mapped_old_id = *old_id as usize - parent_node_value_offset - 1;
353 node_value_id_map[mapped_old_id] = (new_id + parent_node_value_offset + 1) as u64;
354 }
355 for (new_id, (_, old_id)) in values.iter().enumerate() {
356 let mapped_old_id = *old_id as usize - parent_node_value_offset - 1;
357 node_value_id_map[mapped_old_id] =
358 (new_id + parent_node_value_offset + nodes.len() + 1) as u64;
359 }
360 for (new_id, (_, old_id)) in predicates.iter().enumerate() {
361 let mapped_old_id = *old_id as usize - parent_predicate_offset - 1;
362 predicate_id_map[mapped_old_id] = (new_id + parent_predicate_offset + 1) as u64;
363 }
364
365 for triple in id_additions.iter_mut().chain(id_removals.iter_mut()) {
367 if triple.subject > parent_node_value_offset as u64 {
368 let mapped_id = triple.subject as usize - parent_node_value_offset - 1;
369 triple.subject = node_value_id_map[mapped_id];
370 }
371 if triple.predicate > parent_predicate_offset as u64 {
372 let mapped_id = triple.predicate as usize - parent_predicate_offset - 1;
373 triple.predicate = predicate_id_map[mapped_id];
374 }
375 if triple.object > parent_node_value_offset as u64 {
376 let mapped_id = triple.object as usize - parent_node_value_offset - 1;
377 triple.object = node_value_id_map[mapped_id];
378 }
379 }
380 id_additions.sort();
382 id_removals.sort();
383
384 Box::pin(async {
386 match parent {
387 Some(parent) => {
388 let files = files.into_child();
389 let mut builder =
390 ChildLayerFileBuilder::from_files(parent.clone(), &files).await?;
391
392 builder.add_nodes(nodes.into_iter().map(|x| x.0));
393 builder.add_predicates(predicates.into_iter().map(|x| x.0));
394 builder.add_values(values.into_iter().map(|x| x.0));
395
396 let mut builder = builder.into_phase2().await?;
397
398 builder.add_id_triples(id_additions).await?;
399 builder.remove_id_triples(id_removals).await?;
400
401 builder.finalize().await
402 }
403 None => {
404 let files = files.into_base();
406 let mut builder = BaseLayerFileBuilder::from_files(&files).await?;
407
408 builder.add_nodes(nodes.into_iter().map(|x| x.0));
409 builder.add_predicates(predicates.into_iter().map(|x| x.0));
410 builder.add_values(values.into_iter().map(|x| x.0));
411
412 let mut builder = builder.into_phase2().await?;
413
414 builder.add_id_triples(id_additions).await?;
415
416 builder.finalize().await
417 }
418 }
419 })
420 }
421
422 fn commit_boxed(self: Box<Self>) -> Pin<Box<dyn Future<Output = io::Result<()>> + Send>> {
423 let builder = *self;
424 builder.commit()
425 }
426}
427
428#[cfg(test)]
429mod tests {
430 use super::*;
431 use crate::storage::memory::*;
432 use tdb_succinct::TdbDataType;
433
434 fn new_base_files() -> BaseLayerFiles<MemoryBackedStore> {
435 base_layer_memory_files()
437 }
438
439 fn new_child_files() -> ChildLayerFiles<MemoryBackedStore> {
440 child_layer_memory_files()
442 }
443
444 async fn example_base_layer() -> Arc<InternalLayer> {
445 let name = [1, 2, 3, 4, 5];
446 let files = new_base_files();
447 let mut builder = SimpleLayerBuilder::new(name, files.clone());
448
449 builder.add_value_triple(ValueTriple::new_string_value("cow", "says", "moo"));
450 builder.add_value_triple(ValueTriple::new_string_value("pig", "says", "oink"));
451 builder.add_value_triple(ValueTriple::new_string_value("duck", "says", "quack"));
452
453 builder.commit().await.unwrap();
454
455 let layer = BaseLayer::load_from_files(name, &files).await.unwrap();
456 Arc::new(layer.into())
457 }
458
459 #[tokio::test]
460 async fn simple_base_layer_construction() {
461 let layer = example_base_layer().await;
462
463 assert!(layer.value_triple_exists(&ValueTriple::new_string_value("cow", "says", "moo")));
464 assert!(layer.value_triple_exists(&ValueTriple::new_string_value("pig", "says", "oink")));
465 assert!(layer.value_triple_exists(&ValueTriple::new_string_value("duck", "says", "quack")));
466 }
467
468 #[tokio::test]
469 async fn simple_child_layer_construction() {
470 let base_layer = example_base_layer().await;
471 let files = new_child_files();
472 let name = [0, 0, 0, 0, 0];
473 let mut builder = SimpleLayerBuilder::from_parent(name, base_layer.clone(), files.clone());
474
475 builder.add_value_triple(ValueTriple::new_string_value("horse", "says", "neigh"));
476 builder.add_value_triple(ValueTriple::new_node("horse", "likes", "cow"));
477 builder.remove_value_triple(ValueTriple::new_string_value("duck", "says", "quack"));
478
479 let child_layer = Arc::new(
480 async {
481 builder.commit().await?;
482
483 ChildLayer::load_from_files(name, base_layer, &files).await
484 }
485 .await
486 .unwrap(),
487 );
488
489 assert!(child_layer
490 .value_triple_exists(&ValueTriple::new_string_value("horse", "says", "neigh")));
491 assert!(child_layer.value_triple_exists(&ValueTriple::new_node("horse", "likes", "cow")));
492 assert!(
493 child_layer.value_triple_exists(&ValueTriple::new_string_value("cow", "says", "moo"))
494 );
495 assert!(
496 child_layer.value_triple_exists(&ValueTriple::new_string_value("pig", "says", "oink"))
497 );
498 assert!(!child_layer
499 .value_triple_exists(&ValueTriple::new_string_value("duck", "says", "quack")));
500 }
501
502 #[tokio::test]
503 async fn multi_level_layers() {
504 let base_layer = example_base_layer().await;
505 let name2 = [0, 0, 0, 0, 0];
506 let files2 = new_child_files();
507 let mut builder =
508 SimpleLayerBuilder::from_parent(name2, base_layer.clone(), files2.clone());
509
510 builder.add_value_triple(ValueTriple::new_string_value("horse", "says", "neigh"));
511 builder.add_value_triple(ValueTriple::new_node("horse", "likes", "cow"));
512 builder.remove_value_triple(ValueTriple::new_string_value("duck", "says", "quack"));
513
514 builder.commit().await.unwrap();
515 let layer2: Arc<InternalLayer> = Arc::new(
516 ChildLayer::load_from_files(name2, base_layer, &files2)
517 .await
518 .unwrap()
519 .into(),
520 );
521
522 let name3 = [0, 0, 0, 0, 1];
523 let files3 = new_child_files();
524 builder = SimpleLayerBuilder::from_parent(name3, layer2.clone(), files3.clone());
525 builder.remove_value_triple(ValueTriple::new_node("horse", "likes", "cow"));
526 builder.add_value_triple(ValueTriple::new_node("horse", "likes", "pig"));
527 builder.add_value_triple(ValueTriple::new_string_value("duck", "says", "quack"));
528
529 builder.commit().await.unwrap();
530 let layer3: Arc<InternalLayer> = Arc::new(
531 ChildLayer::load_from_files(name3, layer2, &files3)
532 .await
533 .unwrap()
534 .into(),
535 );
536
537 let name4 = [0, 0, 0, 0, 1];
538 let files4 = new_child_files();
539 builder = SimpleLayerBuilder::from_parent(name4, layer3.clone(), files4.clone());
540 builder.remove_value_triple(ValueTriple::new_string_value("pig", "says", "oink"));
541 builder.add_value_triple(ValueTriple::new_node("cow", "likes", "horse"));
542 builder.commit().await.unwrap();
543 let layer4: Arc<InternalLayer> = Arc::new(
544 ChildLayer::load_from_files(name4, layer3, &files4)
545 .await
546 .unwrap()
547 .into(),
548 );
549
550 assert!(layer4.value_triple_exists(&ValueTriple::new_string_value("cow", "says", "moo")));
551 assert!(layer4.value_triple_exists(&ValueTriple::new_string_value("duck", "says", "quack")));
552 assert!(
553 layer4.value_triple_exists(&ValueTriple::new_string_value("horse", "says", "neigh"))
554 );
555 assert!(layer4.value_triple_exists(&ValueTriple::new_node("horse", "likes", "pig")));
556 assert!(layer4.value_triple_exists(&ValueTriple::new_node("cow", "likes", "horse")));
557
558 assert!(!layer4.value_triple_exists(&ValueTriple::new_string_value("pig", "says", "oink")));
559 assert!(!layer4.value_triple_exists(&ValueTriple::new_node("horse", "likes", "cow")));
560 }
561
562 #[tokio::test]
563 async fn remove_and_add_same_triple_on_base_layer_is_noop() {
564 let files = new_base_files();
565 let name = [0, 0, 0, 0, 0];
566 let mut builder = SimpleLayerBuilder::new(name, files.clone());
567
568 builder.remove_value_triple(ValueTriple::new_string_value("crow", "says", "caw"));
569 builder.add_value_triple(ValueTriple::new_string_value("crow", "says", "caw"));
570
571 builder.commit().await.unwrap();
572 let base_layer: Arc<InternalLayer> = Arc::new(
573 BaseLayer::load_from_files(name, &files)
574 .await
575 .unwrap()
576 .into(),
577 );
578
579 assert!(
580 !base_layer.value_triple_exists(&ValueTriple::new_string_value("crow", "says", "caw"))
581 );
582 }
583
584 #[tokio::test]
585 async fn add_and_remove_same_triple_on_base_layer_is_noop() {
586 let files = new_base_files();
587 let name = [0, 0, 0, 0, 0];
588 let mut builder = SimpleLayerBuilder::new(name, files.clone());
589
590 builder.add_value_triple(ValueTriple::new_string_value("crow", "says", "caw"));
591 builder.remove_value_triple(ValueTriple::new_string_value("crow", "says", "caw"));
592
593 builder.commit().await.unwrap();
594 let base_layer: Arc<InternalLayer> = Arc::new(
595 BaseLayer::load_from_files(name, &files)
596 .await
597 .unwrap()
598 .into(),
599 );
600
601 assert!(
602 !base_layer.value_triple_exists(&ValueTriple::new_string_value("crow", "says", "caw"))
603 );
604 }
605
606 #[tokio::test]
607 async fn remove_and_add_same_existing_triple_on_child_layer_is_noop() {
608 let base_layer = example_base_layer().await;
609 let files = new_child_files();
610 let name = [0, 0, 0, 0, 0];
611 let mut builder = SimpleLayerBuilder::from_parent(name, base_layer.clone(), files.clone());
612
613 builder.remove_value_triple(ValueTriple::new_string_value("cow", "says", "moo"));
614 builder.add_value_triple(ValueTriple::new_string_value("cow", "says", "moo"));
615
616 builder.commit().await.unwrap();
617 let child_layer: Arc<InternalLayer> = Arc::new(
618 ChildLayer::load_from_files(name, base_layer, &files)
619 .await
620 .unwrap()
621 .into(),
622 );
623
624 assert!(
625 child_layer.value_triple_exists(&ValueTriple::new_string_value("cow", "says", "moo"))
626 );
627 }
628
629 #[tokio::test]
630 async fn add_and_remove_same_existing_triple_on_child_layer_is_noop() {
631 let base_layer = example_base_layer().await;
632 let files = new_child_files();
633 let name = [0, 0, 0, 0, 0];
634 let mut builder = SimpleLayerBuilder::from_parent(name, base_layer.clone(), files.clone());
635
636 builder.add_value_triple(ValueTriple::new_string_value("cow", "says", "moo"));
637 builder.remove_value_triple(ValueTriple::new_string_value("cow", "says", "moo"));
638
639 builder.commit().await.unwrap();
640 let child_layer: Arc<InternalLayer> = Arc::new(
641 ChildLayer::load_from_files(name, base_layer, &files)
642 .await
643 .unwrap()
644 .into(),
645 );
646
647 assert!(
648 child_layer.value_triple_exists(&ValueTriple::new_string_value("cow", "says", "moo"))
649 );
650 }
651
652 #[tokio::test]
653 async fn remove_and_add_same_nonexisting_triple_on_child_layer_is_noop() {
654 let base_layer = example_base_layer().await;
655 let files = new_child_files();
656 let name = [0, 0, 0, 0, 0];
657 let mut builder = SimpleLayerBuilder::from_parent(name, base_layer.clone(), files.clone());
658
659 builder.remove_value_triple(ValueTriple::new_string_value("crow", "says", "caw"));
660 builder.add_value_triple(ValueTriple::new_string_value("crow", "says", "caw"));
661
662 builder.commit().await.unwrap();
663 let child_layer: Arc<InternalLayer> = Arc::new(
664 ChildLayer::load_from_files(name, base_layer, &files)
665 .await
666 .unwrap()
667 .into(),
668 );
669
670 assert!(
671 !child_layer.value_triple_exists(&ValueTriple::new_string_value("crow", "says", "caw"))
672 );
673 }
674
675 #[tokio::test]
676 async fn add_and_remove_same_nonexisting_triple_on_child_layer_is_noop() {
677 let base_layer = example_base_layer().await;
678 let files = new_child_files();
679 let name = [0, 0, 0, 0, 0];
680 let mut builder = SimpleLayerBuilder::from_parent(name, base_layer.clone(), files.clone());
681
682 builder.add_value_triple(ValueTriple::new_string_value("crow", "says", "caw"));
683 builder.remove_value_triple(ValueTriple::new_string_value("crow", "says", "caw"));
684
685 builder.commit().await.unwrap();
686 let child_layer: Arc<InternalLayer> = Arc::new(
687 ChildLayer::load_from_files(name, base_layer, &files)
688 .await
689 .unwrap()
690 .into(),
691 );
692
693 assert!(
694 !child_layer.value_triple_exists(&ValueTriple::new_string_value("crow", "says", "caw"))
695 );
696 }
697
698 #[tokio::test]
699 async fn remove_and_add_same_triple_by_id_and_string_on_child_layer_is_noop() {
700 let base_layer = example_base_layer().await;
701 let files = new_child_files();
702 let name = [0, 0, 0, 0, 0];
703 let node_id = base_layer.subject_id("cow").unwrap();
704 let predicate_id = base_layer.predicate_id("says").unwrap();
705 let value_id = base_layer
706 .object_value_id(&String::make_entry(&"moo"))
707 .unwrap();
708 let mut builder = SimpleLayerBuilder::from_parent(name, base_layer.clone(), files.clone());
709
710 builder.remove_value_triple(ValueTriple::new_string_value("cow", "says", "moo"));
711 builder.add_id_triple(IdTriple::new(node_id, predicate_id, value_id));
712
713 builder.commit().await.unwrap();
714 let child_layer: Arc<InternalLayer> = Arc::new(
715 ChildLayer::load_from_files(name, base_layer, &files)
716 .await
717 .unwrap()
718 .into(),
719 );
720
721 assert!(
722 child_layer.value_triple_exists(&ValueTriple::new_string_value("cow", "says", "moo"))
723 );
724 }
725
726 #[tokio::test]
727 async fn remove_and_add_same_triple_by_string_and_id_on_child_layer_is_noop() {
728 let base_layer = example_base_layer().await;
729 let files = new_child_files();
730 let name = [0, 0, 0, 0, 0];
731 let node_id = base_layer.subject_id("cow").unwrap();
732 let predicate_id = base_layer.predicate_id("says").unwrap();
733 let value_id = base_layer
734 .object_value_id(&String::make_entry(&"moo"))
735 .unwrap();
736 let mut builder = SimpleLayerBuilder::from_parent(name, base_layer.clone(), files.clone());
737
738 builder.remove_id_triple(IdTriple::new(node_id, predicate_id, value_id));
739 builder.add_value_triple(ValueTriple::new_string_value("cow", "says", "moo"));
740
741 builder.commit().await.unwrap();
742 let child_layer: Arc<InternalLayer> = Arc::new(
743 ChildLayer::load_from_files(name, base_layer, &files)
744 .await
745 .unwrap()
746 .into(),
747 );
748
749 assert!(
750 child_layer.value_triple_exists(&ValueTriple::new_string_value("cow", "says", "moo"))
751 );
752 }
753
754 #[tokio::test]
755 async fn add_and_remove_same_triple_by_id_and_string_on_child_layer_is_noop() {
756 let base_layer = example_base_layer().await;
757 let files = new_child_files();
758 let name = [0, 0, 0, 0, 0];
759 let node_id = base_layer.subject_id("cow").unwrap();
760 let predicate_id = base_layer.predicate_id("says").unwrap();
761 let value_id = base_layer
762 .object_value_id(&String::make_entry(&"moo"))
763 .unwrap();
764 let mut builder = SimpleLayerBuilder::from_parent(name, base_layer.clone(), files.clone());
765
766 builder.add_value_triple(ValueTriple::new_string_value("cow", "says", "moo"));
767 builder.remove_id_triple(IdTriple::new(node_id, predicate_id, value_id));
768
769 builder.commit().await.unwrap();
770 let child_layer: Arc<InternalLayer> = Arc::new(
771 ChildLayer::load_from_files(name, base_layer, &files)
772 .await
773 .unwrap()
774 .into(),
775 );
776
777 assert!(
778 child_layer.value_triple_exists(&ValueTriple::new_string_value("cow", "says", "moo"))
779 );
780 }
781
782 #[tokio::test]
783 async fn add_and_remove_same_triple_by_string_and_id_on_child_layer_is_noop() {
784 let base_layer = example_base_layer().await;
785 let files = new_child_files();
786 let name = [0, 0, 0, 0, 0];
787 let node_id = base_layer.subject_id("cow").unwrap();
788 let predicate_id = base_layer.predicate_id("says").unwrap();
789 let value_id = base_layer
790 .object_value_id(&String::make_entry(&"moo"))
791 .unwrap();
792 let mut builder = SimpleLayerBuilder::from_parent(name, base_layer.clone(), files.clone());
793
794 builder.add_id_triple(IdTriple::new(node_id, predicate_id, value_id));
795 builder.remove_value_triple(ValueTriple::new_string_value("cow", "says", "moo"));
796
797 builder.commit().await.unwrap();
798 let child_layer: Arc<InternalLayer> = Arc::new(
799 ChildLayer::load_from_files(name, base_layer, &files)
800 .await
801 .unwrap()
802 .into(),
803 );
804
805 assert!(
806 child_layer.value_triple_exists(&ValueTriple::new_string_value("cow", "says", "moo"))
807 );
808 }
809}