1use entity::{
2 Database, DatabaseError, DatabaseResult, EdgeDeletionPolicy, Ent, Filter, Id, IdAllocator,
3 Predicate, Primitive, Query, Value, EPHEMERAL_ID,
4};
5use std::{
6 collections::{HashMap, HashSet},
7 sync::Mutex,
8};
9
10type EntIdSet = HashSet<Id>;
11
12#[cfg_attr(feature = "serde-1", derive(serde::Serialize, serde::Deserialize))]
16pub struct InmemoryDatabase {
17 ents: Mutex<HashMap<Id, Box<dyn Ent>>>,
19
20 ents_of_type: Mutex<HashMap<String, EntIdSet>>,
22
23 alloc: Mutex<IdAllocator>,
25}
26
27impl InmemoryDatabase {
28 pub fn new() -> Self {
30 Self::default()
31 }
32}
33
34impl Default for InmemoryDatabase {
35 fn default() -> Self {
37 Self {
38 ents: Mutex::new(HashMap::new()),
39 ents_of_type: Mutex::new(HashMap::new()),
40 alloc: Mutex::new(IdAllocator::new()),
41 }
42 }
43}
44
45impl Database for InmemoryDatabase {
46 fn get_all(&self, ids: Vec<Id>) -> DatabaseResult<Vec<Box<dyn Ent>>> {
47 ids.into_iter()
48 .filter_map(|id| self.get(id).transpose())
49 .collect()
50 }
51
52 fn find_all(&self, query: Query) -> DatabaseResult<Vec<Box<dyn Ent>>> {
53 let mut pipeline: Option<EntIdSet> = None;
54
55 for filter in query {
56 let mut_pipeline = pipeline.get_or_insert_with(|| prefill_ids(self, &filter));
57
58 match filter {
62 Filter::IntoEdge(name) => {
63 pipeline = Some(
64 mut_pipeline
65 .iter()
66 .flat_map(|id| {
67 self.get(*id)
68 .map(|maybe_ent| {
69 maybe_ent
70 .and_then(|ent| {
71 ent.edge(&name).map(|edge| edge.to_ids())
72 })
73 .unwrap_or_default()
74 })
75 .unwrap_or_default()
76 })
77 .collect(),
78 )
79 }
80 f => {
83 mut_pipeline.retain(|id| filter_id(self, id, &f));
84 }
85 }
86 }
87
88 pipeline
89 .unwrap_or_default()
90 .into_iter()
91 .filter_map(|id| self.get(id).transpose())
92 .collect()
93 }
94
95 fn get(&self, id: Id) -> DatabaseResult<Option<Box<dyn Ent>>> {
96 let maybe_ent = self
97 .ents
98 .lock()
99 .unwrap()
100 .get(&id)
101 .map(|ent| dyn_clone::clone_box(ent.as_ref()));
102
103 Ok(if let Some(mut ent) = maybe_ent {
106 if !ent.is_connected() {
107 ent.connect(entity::global::db());
108 }
109 Some(ent)
110 } else {
111 None
112 })
113 }
114
115 fn remove(&self, id: Id) -> DatabaseResult<bool> {
116 if let Some(ent) = self.ents.lock().unwrap().remove(&id) {
119 for edge in ent.edges() {
120 match edge.deletion_policy() {
121 EdgeDeletionPolicy::ShallowDelete => {
124 for edge_id in edge.to_ids() {
125 if let Some(ent) = self.ents.lock().unwrap().get_mut(&edge_id) {
126 for mut edge in ent.edges() {
127 let _ = edge.value_mut().remove_ids(Some(edge_id));
128 let name = edge.name().to_string();
129 let _ = ent.update_edge(&name, edge.into_value());
130 }
131 }
132 }
133 }
134 EdgeDeletionPolicy::DeepDelete => {
137 for id in edge.to_ids() {
138 let _ = self.remove(id);
139 }
140 }
141 EdgeDeletionPolicy::Nothing => {}
143 }
144 }
145
146 self.ents_of_type
148 .lock()
149 .unwrap()
150 .entry(ent.r#type().to_string())
151 .and_modify(|e| {
152 e.remove(&id);
153 });
154
155 self.alloc.lock().unwrap().extend(vec![id]);
157
158 Ok(true)
159 } else {
160 Ok(false)
161 }
162 }
163
164 fn insert(&self, mut ent: Box<dyn Ent>) -> DatabaseResult<Id> {
165 let id = ent.id();
167 let id = if id == EPHEMERAL_ID {
168 if let Some(id) = self.alloc.lock().unwrap().next() {
169 id
170 } else {
171 return Err(DatabaseError::EntCapacityReached);
172 }
173 } else {
174 self.alloc.lock().unwrap().mark_external_id(id);
175 id
176 };
177
178 ent.set_id(id);
180
181 ent.clear_cache();
183
184 ent.mark_updated().map_err(|e| DatabaseError::Other {
186 source: Box::from(e),
187 })?;
188
189 self.ents_of_type
191 .lock()
192 .unwrap()
193 .entry(ent.r#type().to_string())
194 .or_insert_with(HashSet::new)
195 .insert(id);
196
197 self.ents.lock().unwrap().insert(id, ent);
199
200 Ok(id)
201 }
202}
203
204impl InmemoryDatabase {
205 pub fn ids(&self) -> EntIdSet {
207 self.ents.lock().unwrap().keys().copied().collect()
208 }
209
210 pub fn has_id(&self, id: Id) -> bool {
212 self.ents.lock().unwrap().contains_key(&id)
213 }
214
215 pub fn ids_for_type(&self, r#type: &str) -> EntIdSet {
217 self.ents_of_type
218 .lock()
219 .unwrap()
220 .get(r#type)
221 .cloned()
222 .unwrap_or_default()
223 }
224}
225
226fn prefill_ids(db: &InmemoryDatabase, filter: &Filter) -> EntIdSet {
236 fn from_id_predicate(
237 db: &InmemoryDatabase,
238 p: &Predicate,
239 mut ids: EntIdSet,
240 ) -> Option<EntIdSet> {
241 match p {
242 Predicate::Equals(Value::Primitive(Primitive::Number(id))) => Some({
243 ids.insert(id.to_usize());
244 ids
245 }),
246 Predicate::Or(list) => list.iter().fold(Some(ids), |ids, p| match ids {
247 Some(ids) => from_id_predicate(db, p, ids),
248 None => None,
249 }),
250 _ => None,
251 }
252 }
253
254 fn from_type_predicate(
255 db: &InmemoryDatabase,
256 p: &Predicate,
257 mut ids: EntIdSet,
258 ) -> Option<EntIdSet> {
259 match p {
260 Predicate::Equals(Value::Text(t)) => Some({
261 ids.extend(db.ids_for_type(t));
262 ids
263 }),
264 Predicate::Or(list) => list.iter().fold(Some(ids), |ids, p| match ids {
265 Some(ids) => from_type_predicate(db, p, ids),
266 None => None,
267 }),
268 _ => None,
269 }
270 }
271
272 match filter {
273 Filter::Id(p) => {
276 from_id_predicate(db, p.as_untyped(), EntIdSet::new()).unwrap_or_else(|| db.ids())
277 }
278
279 Filter::Type(p) => {
282 from_type_predicate(db, p.as_untyped(), EntIdSet::new()).unwrap_or_else(|| db.ids())
283 }
284
285 _ => db.ids(),
289 }
290}
291
292fn filter_id(db: &InmemoryDatabase, id: &Id, filter: &Filter) -> bool {
293 match filter {
294 Filter::Id(p) => p.check(*id),
295 Filter::Type(p) => with_ent(db, id, |ent| p.check(ent.r#type().to_string())),
296 Filter::Created(p) => with_ent(db, id, |ent| p.check(ent.created())),
297 Filter::LastUpdated(p) => with_ent(db, id, |ent| p.check(ent.last_updated())),
298 Filter::Field(name, p) => with_ent(db, id, |ent| match ent.field(name) {
299 Some(value) => p.check(&value),
300 None => false,
301 }),
302 Filter::Edge(name, f) => with_ent(db, id, |ent| match ent.edge(name) {
303 Some(edge) => edge.to_ids().iter().any(|id| filter_id(db, id, f)),
304 None => false,
305 }),
306
307 Filter::IntoEdge(_) => unreachable!("Bug: Transformation in filter"),
310 }
311}
312
313fn with_ent<F: Fn(Box<dyn Ent>) -> bool>(db: &InmemoryDatabase, id: &Id, f: F) -> bool {
314 db.get(*id)
315 .map(|maybe_ent| maybe_ent.map(f).unwrap_or_default())
316 .unwrap_or_default()
317}
318
319#[cfg(test)]
320mod tests {
321 use super::*;
322 use entity::{Predicate as P, TypedPredicate as TP, *};
323
324 fn new_test_database() -> InmemoryDatabase {
331 let db = InmemoryDatabase::default();
332
333 let _ = db
335 .insert(Box::from(UntypedEnt::from_collections(1, vec![], vec![])))
336 .unwrap();
337 let _ = db
338 .insert(Box::from(UntypedEnt::from_collections(2, vec![], vec![])))
339 .unwrap();
340 let _ = db
341 .insert(Box::from(UntypedEnt::from_collections(3, vec![], vec![])))
342 .unwrap();
343
344 let _ = db
346 .insert(Box::from(UntypedEnt::from_collections(
347 4,
348 vec![Field::new("a", 1), Field::new("b", 2)],
349 vec![],
350 )))
351 .unwrap();
352 let _ = db
353 .insert(Box::from(UntypedEnt::from_collections(
354 5,
355 vec![Field::new("a", 3), Field::new("b", 4)],
356 vec![],
357 )))
358 .unwrap();
359 let _ = db
360 .insert(Box::from(UntypedEnt::from_collections(
361 6,
362 vec![Field::new("a", 5), Field::new("b", 6)],
363 vec![],
364 )))
365 .unwrap();
366
367 let _ = db
369 .insert(Box::from(UntypedEnt::from_collections(
370 7,
371 vec![Field::new(
372 "f",
373 Value::from(
374 vec![(String::from("a"), 3), (String::from("b"), 5)]
375 .into_iter()
376 .collect::<HashMap<String, u8>>(),
377 ),
378 )],
379 vec![],
380 )))
381 .unwrap();
382 let _ = db
383 .insert(Box::from(UntypedEnt::from_collections(
384 8,
385 vec![Field::new("f", vec![1, 2])],
386 vec![],
387 )))
388 .unwrap();
389 let _ = db
390 .insert(Box::from(UntypedEnt::from_collections(
391 9,
392 vec![Field::new(
393 "f",
394 Value::from(
395 vec![
396 (String::from("a"), Value::from(vec![1, 2])),
397 (String::from("b"), Value::from(vec![3, 4])),
398 ]
399 .into_iter()
400 .collect::<HashMap<String, Value>>(),
401 ),
402 )],
403 vec![],
404 )))
405 .unwrap();
406
407 let _ = db
409 .insert(Box::from(UntypedEnt::from_collections(
410 10,
411 vec![],
412 vec![
413 Edge::new("a", 1),
414 Edge::new("b", vec![3, 4, 5]),
415 Edge::new("c", None),
416 ],
417 )))
418 .unwrap();
419 let _ = db
420 .insert(Box::from(UntypedEnt::from_collections(
421 11,
422 vec![],
423 vec![Edge::new("a", 2), Edge::new("b", vec![1, 2, 3, 4, 5, 6])],
424 )))
425 .unwrap();
426 let _ = db
427 .insert(Box::from(UntypedEnt::from_collections(
428 12,
429 vec![],
430 vec![
431 Edge::new("a", 3),
432 Edge::new("b", vec![]),
433 Edge::new("c", Some(8)),
434 ],
435 )))
436 .unwrap();
437
438 db
439 }
440
441 fn query_and_assert<Q: Into<Query>>(db: &InmemoryDatabase, query: Q, expected: &[Id]) {
442 let query = query.into();
443 let results = db
444 .find_all(query.clone())
445 .expect("Failed to retrieve ents")
446 .iter()
447 .map(|ent| ent.id())
448 .collect::<HashSet<Id>>();
449 assert_eq!(
450 results,
451 expected.into_iter().copied().collect(),
452 "{:?}\nExpected: {:?}, Actual: {:?}",
453 query,
454 expected,
455 results
456 );
457 }
458
459 #[test]
460 fn insert_should_replace_ephemeral_id_with_allocator_id() {
461 let db = InmemoryDatabase::default();
462
463 let ent = UntypedEnt::empty_with_id(EPHEMERAL_ID);
464 let id = db.insert(Box::from(ent)).expect("Failed to insert ent");
465 assert_ne!(id, EPHEMERAL_ID);
466
467 let ent = db.get(id).expect("Failed to get ent").expect("Ent missing");
468 assert_eq!(ent.id(), id);
469 }
470
471 #[test]
472 fn insert_should_update_the_last_updated_time_with_the_current_time() {
473 let db = InmemoryDatabase::default();
474
475 let ent = UntypedEnt::empty_with_id(EPHEMERAL_ID);
476 let last_updated = ent.last_updated();
477 std::thread::sleep(std::time::Duration::from_millis(10));
478
479 let id = db.insert(Box::from(ent)).expect("Failed to insert ent");
480 let ent = db.get(id).expect("Failed to get ent").expect("Ent missing");
481 assert!(ent.last_updated() > last_updated);
482 }
483
484 #[test]
485 fn insert_should_add_a_new_ent_using_its_id() {
486 let db = InmemoryDatabase::default();
487
488 let ent = UntypedEnt::empty_with_id(999);
489 let id = db.insert(Box::from(ent)).expect("Failed to insert ent");
490 assert_eq!(id, 999);
491
492 let ent = db
493 .get(999)
494 .expect("Failed to get ent")
495 .expect("Ent missing");
496 assert_eq!(ent.id(), 999);
497 assert_eq!(db.alloc.lock().unwrap().next(), Some(1000));
498 }
499
500 #[test]
501 fn insert_should_overwrite_an_existing_ent_with_the_same_id() {
502 let db = InmemoryDatabase::default();
503
504 let ent = UntypedEnt::from_collections(999, vec![Field::new("field1", 3)], vec![]);
505 let _ = db.insert(Box::from(ent)).expect("Failed to insert ent");
506
507 let ent = db
508 .get(999)
509 .expect("Failed to get ent")
510 .expect("Ent missing");
511 assert_eq!(ent.field("field1").expect("Field missing"), Value::from(3));
512 }
513
514 #[test]
515 fn insert_should_reset_all_computed_field_caches_to_none() {
516 let db = InmemoryDatabase::default();
517
518 let ent = UntypedEnt::from_collections(
520 999,
521 vec![Field::new_with_attributes(
522 "field1",
523 Some(3),
524 vec![FieldAttribute::Computed],
525 )],
526 vec![],
527 );
528 let _ = db.insert(Box::from(ent)).expect("Failed to insert ent");
529
530 let ent = db
531 .get(999)
532 .expect("Failed to get ent")
533 .expect("Ent missing");
534 assert_eq!(
535 ent.field("field1").expect("Field missing"),
536 Value::Optional(None)
537 );
538 }
539
540 #[test]
541 fn get_should_return_an_ent_by_id() {
542 use entity::DatabaseRc;
543 let db = InmemoryDatabase::default();
544
545 let result = db.get(999).expect("Failed to get ent");
546 assert!(result.is_none(), "Unexpectedly acquired ent");
547
548 let _ = db
549 .insert(Box::from(UntypedEnt::empty_with_id(999)))
550 .unwrap();
551
552 let result = db.get(999).expect("Failed to get ent");
553 assert!(result.is_some(), "Unexpectedly missing ent");
554 assert!(
555 !result.unwrap().is_connected(),
556 "Ent unexpectedly connected to database"
557 );
558
559 let db = DatabaseRc::new(Box::new(db));
561 entity::global::with_db_from_rc(DatabaseRc::clone(&db), || {
562 let result = db.get(999).expect("Failed to get ent");
563 assert!(result.is_some(), "Unexpectedly missing ent");
564 assert!(
565 result.unwrap().is_connected(),
566 "Ent unexpectedly not connected to database"
567 );
568 });
569 }
570
571 #[test]
572 fn remove_should_remove_an_ent_by_id() {
573 let db = InmemoryDatabase::default();
574
575 let _ = db.remove(999).expect("Failed to remove ent");
576
577 let _ = db
578 .insert(Box::from(UntypedEnt::empty_with_id(999)))
579 .unwrap();
580 assert!(db.get(999).unwrap().is_some(), "Failed to set up ent");
581
582 let _ = db.remove(999).expect("Failed to remove ent");
583 assert!(db.get(999).unwrap().is_none(), "Did not remove ent");
584
585 assert_eq!(db.alloc.lock().unwrap().freed(), &[999]);
587 }
588
589 #[test]
590 fn get_all_should_return_all_ents_with_associated_ids() {
591 let db = InmemoryDatabase::default();
592
593 let _ = db.insert(Box::from(UntypedEnt::empty_with_id(1))).unwrap();
594 let _ = db.insert(Box::from(UntypedEnt::empty_with_id(2))).unwrap();
595 let _ = db.insert(Box::from(UntypedEnt::empty_with_id(3))).unwrap();
596
597 let results = db
598 .get_all(vec![1, 2, 3])
599 .expect("Failed to retrieve ents")
600 .iter()
601 .map(|ent| ent.id())
602 .collect::<HashSet<Id>>();
603 assert_eq!(results, [1, 2, 3].iter().copied().collect());
604
605 let results = db
606 .get_all(vec![1, 3])
607 .expect("Failed to retrieve ents")
608 .iter()
609 .map(|ent| ent.id())
610 .collect::<HashSet<Id>>();
611 assert_eq!(results, [1, 3].iter().copied().collect());
612
613 let results = db
614 .get_all(vec![2, 3, 4, 5, 6, 7, 8])
615 .expect("Failed to retrieve ents")
616 .iter()
617 .map(|ent| ent.id())
618 .collect::<HashSet<Id>>();
619 assert_eq!(results, [2, 3].iter().copied().collect());
620 }
621
622 #[test]
623 fn find_all_should_return_no_ents_by_default() {
624 let db = new_test_database();
625
626 let q = Query::default();
627 query_and_assert(&db, q, &[]);
628 }
629
630 #[test]
631 fn find_all_should_support_filtering_by_id() {
632 let db = new_test_database();
633
634 let q = Query::default().where_id(TP::equals(1));
636 query_and_assert(&db, q, &[1]);
637
638 let q = Query::default().where_id(TP::equals(1) | TP::equals(2));
640 query_and_assert(&db, q, &[1, 2]);
641
642 let q = Query::default().where_id(TP::equals(999));
644 query_and_assert(&db, q, &[]);
645
646 let q = Query::default()
648 .where_id(TP::equals(1) | TP::equals(2))
649 .where_id(TP::equals(1) | TP::equals(3));
650 query_and_assert(&db, q, &[1]);
651 }
652
653 #[test]
654 fn find_all_should_support_filtering_by_type() {
655 let db = new_test_database();
656 let _ = db.insert(Box::from(TestEnt::new(20))).unwrap();
657 let _ = db.insert(Box::from(TestEnt::new(21))).unwrap();
658 let _ = db.insert(Box::from(TestEnt::new(22))).unwrap();
659
660 let ts = <UntypedEnt as EntType>::type_str();
662 let q = Query::default().where_type(TP::equals(ts.to_string()));
663 query_and_assert(&db, q, &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]);
664
665 let q = Query::default().where_type(TP::or(vec![
667 TP::equals(<UntypedEnt as EntType>::type_str().to_string()),
668 TP::equals(<TestEnt as EntType>::type_str().to_string()),
669 ]));
670 query_and_assert(&db, q, &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 20, 21, 22]);
671
672 let q = Query::default().where_type(TP::equals(String::from("unknown")));
674 query_and_assert(&db, q, &[]);
675
676 let q = Query::default()
678 .where_id(TP::equals(1) | TP::equals(2) | TP::equals(4))
679 .where_type(TP::equals(ts.to_string()));
680 query_and_assert(&db, q, &[1, 2, 4]);
681 }
682
683 #[test]
684 fn find_all_should_support_filtering_by_created_timestamp() {
685 let db = new_test_database();
686
687 for i in 1..=12 {
690 let ent = UntypedEnt::empty_with_id(i);
691 db.insert(Box::from(ent))
692 .expect(&format!("Failed to replace ent {}", i));
693 std::thread::sleep(std::time::Duration::from_millis(1));
694 }
695
696 let time = db.get(3).unwrap().expect("Missing ent 3").created();
698 let q = Query::default().where_created(TP::greater_than(time));
699 query_and_assert(&db, q, &[4, 5, 6, 7, 8, 9, 10, 11, 12]);
700
701 let time = db.get(3).unwrap().expect("Missing ent 3").created();
703 let q = Query::default()
704 .where_id(TP::less_than(8))
705 .where_created(TP::greater_than(time));
706 query_and_assert(&db, q, &[4, 5, 6, 7]);
707 }
708
709 #[test]
710 fn find_all_should_support_filtering_by_last_updated_timestamp() {
711 let db = new_test_database();
712
713 for i in (1..=12).rev() {
716 use entity::DatabaseExt;
717 let mut ent = db
718 .get_typed::<UntypedEnt>(i)
719 .unwrap()
720 .expect(&format!("Missing ent {}", i));
721 ent.mark_updated().unwrap();
722 db.insert(Box::from(ent))
723 .expect(&format!("Failed to update ent {}", i));
724 std::thread::sleep(std::time::Duration::from_millis(1));
725 }
726
727 let time = db.get(3).unwrap().expect("Missing ent 3").last_updated();
729 let q = Query::default().where_last_updated(TP::greater_than(time));
730 query_and_assert(&db, q, &[1, 2]);
731
732 let time = db.get(3).unwrap().expect("Missing ent 3").created();
734 let q = Query::default()
735 .where_id(TP::equals(2))
736 .where_last_updated(TP::greater_than(time));
737 query_and_assert(&db, q, &[2]);
738 }
739
740 #[test]
741 fn find_all_should_support_filtering_by_field() {
742 let db = new_test_database();
743
744 let q = Query::default().where_field("a", P::equals(3));
746 query_and_assert(&db, q, &[5]);
747
748 let q = Query::default()
750 .where_id(TP::equals(4) | TP::equals(6))
751 .where_field("a", P::greater_than(1));
752 query_and_assert(&db, q, &[6]);
753 }
754
755 #[test]
756 fn find_all_should_support_filtering_by_edge() {
757 let db = new_test_database();
758
759 let q = Query::default().where_edge("a", Filter::Id(TP::equals(3)));
761 query_and_assert(&db, q, &[12]);
762
763 let q = Query::default()
765 .where_id(TP::equals(10) | TP::equals(12))
766 .where_edge("a", Filter::Id(TP::always()));
767 query_and_assert(&db, q, &[10, 12]);
768 }
769
770 #[test]
771 fn find_all_should_support_transforming_into_edge() {
772 let db = new_test_database();
773
774 let q = Query::default().where_into_edge("b");
778 query_and_assert(&db, q, &[1, 2, 3, 4, 5, 6]);
779
780 let q = Query::default()
784 .where_id(TP::equals(10) | TP::equals(12))
785 .where_into_edge("b");
786 query_and_assert(&db, q, &[3, 4, 5]);
787 }
788
789 #[derive(Clone, Debug, PartialEq, Eq)]
790 #[cfg_attr(feature = "serde-1", derive(serde::Serialize, serde::Deserialize))]
791 struct TestEnt(Id);
792
793 impl TestEnt {
794 pub fn new(id: Id) -> Self {
795 Self(id)
796 }
797 }
798
799 impl EntType for TestEnt {
800 fn type_data() -> EntTypeData {
801 EntTypeData::Concrete {
802 ty: concat!(module_path!(), "::TestEnt"),
803 }
804 }
805 }
806
807 #[cfg_attr(feature = "serde-1", typetag::serde)]
808 impl Ent for TestEnt {
809 fn id(&self) -> Id {
810 self.0
811 }
812
813 fn set_id(&mut self, id: Id) {
814 self.0 = id;
815 }
816
817 fn r#type(&self) -> &str {
818 Self::type_str()
819 }
820
821 fn created(&self) -> u64 {
822 0
823 }
824
825 fn last_updated(&self) -> u64 {
826 0
827 }
828
829 fn mark_updated(&mut self) -> Result<(), EntMutationError> {
830 Ok(())
831 }
832
833 fn field_definitions(&self) -> Vec<FieldDefinition> {
834 Vec::new()
835 }
836
837 fn field_names(&self) -> Vec<String> {
838 Vec::new()
839 }
840
841 fn field(&self, _name: &str) -> Option<Value> {
842 None
843 }
844
845 fn update_field(&mut self, name: &str, _value: Value) -> Result<Value, EntMutationError> {
846 Err(EntMutationError::NoField {
847 name: name.to_string(),
848 })
849 }
850
851 fn edge_definitions(&self) -> Vec<EdgeDefinition> {
852 Vec::new()
853 }
854
855 fn edge_names(&self) -> Vec<String> {
856 Vec::new()
857 }
858
859 fn edge(&self, _name: &str) -> Option<EdgeValue> {
860 None
861 }
862
863 fn update_edge(
864 &mut self,
865 name: &str,
866 _value: EdgeValue,
867 ) -> Result<EdgeValue, EntMutationError> {
868 Err(EntMutationError::NoEdge {
869 name: name.to_string(),
870 })
871 }
872
873 fn connect(&mut self, _database: WeakDatabaseRc) {}
874
875 fn disconnect(&mut self) {}
876
877 fn is_connected(&self) -> bool {
878 false
879 }
880
881 fn load_edge(&self, _name: &str) -> DatabaseResult<Vec<Box<dyn Ent>>> {
882 Err(DatabaseError::Disconnected)
883 }
884
885 fn clear_cache(&mut self) {}
886
887 fn refresh(&mut self) -> DatabaseResult<()> {
888 Err(DatabaseError::Disconnected)
889 }
890
891 fn commit(&mut self) -> DatabaseResult<()> {
892 Err(DatabaseError::Disconnected)
893 }
894
895 fn remove(&self) -> DatabaseResult<bool> {
896 Err(DatabaseError::Disconnected)
897 }
898 }
899}