1use std::collections::BTreeSet;
9
10use lora_ast::Direction;
11
12use crate::memory::{
13 ConstraintDefinition, ConstraintRequest, CreateConstraintError, CreateConstraintOutcome,
14 CreateIndexError, CreateIndexOutcome, DropConstraintError, DropConstraintOutcome,
15 DropIndexError, DropIndexOutcome, GraphStats, IndexDefinition, IndexRequest,
16};
17use crate::types::{
18 ExpandedRelationship, LoraVector, NodeId, NodeRecord, NodeRef, Properties, PropertyValue,
19 RelRef, RelationshipId, RelationshipRecord,
20};
21
22pub trait GraphStorage {
38 fn contains_node(&self, id: NodeId) -> bool;
42
43 fn node(&self, id: NodeId) -> Option<NodeRecord>;
47
48 fn all_node_ids(&self) -> Vec<NodeId>;
50
51 fn node_ids_by_label(&self, label: &str) -> Vec<NodeId>;
54
55 fn scan_node_ids(
67 &self,
68 label: Option<&str>,
69 cursor: &mut u64,
70 max: usize,
71 out: &mut Vec<NodeId>,
72 ) -> bool {
73 let _ = max;
74 if *cursor == 0 {
75 *cursor = u64::MAX;
76 out.extend(match label {
77 Some(label) => self.node_ids_by_label(label),
78 None => self.all_node_ids(),
79 });
80 }
81 false
82 }
83
84 fn contains_relationship(&self, id: RelationshipId) -> bool;
87
88 fn relationship(&self, id: RelationshipId) -> Option<RelationshipRecord>;
89
90 fn all_rel_ids(&self) -> Vec<RelationshipId>;
91
92 fn rel_ids_by_type(&self, rel_type: &str) -> Vec<RelationshipId>;
93
94 fn relationship_endpoints(&self, id: RelationshipId) -> Option<(NodeId, NodeId)>;
98
99 fn expand_ids(
105 &self,
106 node_id: NodeId,
107 direction: Direction,
108 types: &[String],
109 ) -> Vec<(RelationshipId, NodeId)>;
110
111 fn try_for_each_expand_id<F, E>(
115 &self,
116 node_id: NodeId,
117 direction: Direction,
118 types: &[String],
119 mut visit: F,
120 ) -> Result<(), E>
121 where
122 F: FnMut(RelationshipId, NodeId) -> Result<(), E>,
123 Self: Sized,
124 {
125 for (rel_id, other_id) in self.expand_ids(node_id, direction, types) {
126 visit(rel_id, other_id)?;
127 }
128 Ok(())
129 }
130
131 fn all_labels(&self) -> Vec<String>;
134 fn all_relationship_types(&self) -> Vec<String>;
135
136 fn with_node<F, R>(&self, id: NodeId, f: F) -> Option<R>
144 where
145 F: FnOnce(NodeRef<'_>) -> R,
146 Self: Sized,
147 {
148 self.node(id).as_ref().map(|node| f(NodeRef::from(node)))
149 }
150
151 fn with_relationship<F, R>(&self, id: RelationshipId, f: F) -> Option<R>
152 where
153 F: FnOnce(RelRef<'_>) -> R,
154 Self: Sized,
155 {
156 self.relationship(id)
157 .as_ref()
158 .map(|rel| f(RelRef::from(rel)))
159 }
160
161 fn has_node(&self, id: NodeId) -> bool {
164 self.contains_node(id)
165 }
166
167 fn has_relationship(&self, id: RelationshipId) -> bool {
168 self.contains_relationship(id)
169 }
170
171 fn node_count(&self) -> usize {
172 self.all_node_ids().len()
173 }
174
175 fn relationship_count(&self) -> usize {
176 self.all_rel_ids().len()
177 }
178
179 fn node_count_by_label(&self, label: &str) -> usize {
183 self.node_ids_by_label(label).len()
184 }
185
186 fn all_nodes(&self) -> Vec<NodeRecord> {
194 self.all_node_ids()
195 .into_iter()
196 .filter_map(|id| self.node(id))
197 .collect()
198 }
199
200 fn nodes_by_label(&self, label: &str) -> Vec<NodeRecord> {
201 self.node_ids_by_label(label)
202 .into_iter()
203 .filter_map(|id| self.node(id))
204 .collect()
205 }
206
207 fn all_relationships(&self) -> Vec<RelationshipRecord> {
208 self.all_rel_ids()
209 .into_iter()
210 .filter_map(|id| self.relationship(id))
211 .collect()
212 }
213
214 fn relationships_by_type(&self, rel_type: &str) -> Vec<RelationshipRecord> {
215 self.rel_ids_by_type(rel_type)
216 .into_iter()
217 .filter_map(|id| self.relationship(id))
218 .collect()
219 }
220
221 fn relationship_ids_of(&self, node_id: NodeId, direction: Direction) -> Vec<RelationshipId> {
224 self.expand_ids(node_id, direction, &[])
225 .into_iter()
226 .map(|(rel_id, _)| rel_id)
227 .collect()
228 }
229
230 fn outgoing_relationships(&self, node_id: NodeId) -> Vec<RelationshipRecord> {
231 self.relationship_ids_of(node_id, Direction::Right)
232 .into_iter()
233 .filter_map(|id| self.relationship(id))
234 .collect()
235 }
236
237 fn incoming_relationships(&self, node_id: NodeId) -> Vec<RelationshipRecord> {
238 self.relationship_ids_of(node_id, Direction::Left)
239 .into_iter()
240 .filter_map(|id| self.relationship(id))
241 .collect()
242 }
243
244 fn relationships_of(&self, node_id: NodeId, direction: Direction) -> Vec<RelationshipRecord> {
245 self.relationship_ids_of(node_id, direction)
246 .into_iter()
247 .filter_map(|id| self.relationship(id))
248 .collect()
249 }
250
251 fn degree(&self, node_id: NodeId, direction: Direction) -> usize {
252 self.expand_ids(node_id, direction, &[]).len()
253 }
254
255 fn is_isolated(&self, node_id: NodeId) -> bool {
256 self.degree(node_id, Direction::Undirected) == 0
257 }
258
259 fn expand(
260 &self,
261 node_id: NodeId,
262 direction: Direction,
263 types: &[String],
264 ) -> Vec<(RelationshipRecord, NodeRecord)> {
265 self.expand_ids(node_id, direction, types)
266 .into_iter()
267 .filter_map(|(rid, nid)| {
268 let rel = self.relationship(rid)?;
269 let node = self.node(nid)?;
270 Some((rel, node))
271 })
272 .collect()
273 }
274
275 fn expand_detailed(
276 &self,
277 node_id: NodeId,
278 direction: Direction,
279 types: &[String],
280 ) -> Vec<ExpandedRelationship> {
281 self.expand(node_id, direction, types)
282 .into_iter()
283 .map(|(relationship, other_node)| ExpandedRelationship {
284 relationship,
285 other_node,
286 })
287 .collect()
288 }
289
290 fn neighbors(
291 &self,
292 node_id: NodeId,
293 direction: Direction,
294 types: &[String],
295 ) -> Vec<NodeRecord> {
296 self.expand_ids(node_id, direction, types)
297 .into_iter()
298 .filter_map(|(_, nid)| self.node(nid))
299 .collect()
300 }
301
302 fn node_has_label(&self, node_id: NodeId, label: &str) -> bool
305 where
306 Self: Sized,
307 {
308 self.with_node(node_id, |n| n.has_label(label))
309 .unwrap_or(false)
310 }
311
312 fn node_labels(&self, node_id: NodeId) -> Option<Vec<String>>
313 where
314 Self: Sized,
315 {
316 self.with_node(node_id, |n| n.labels().to_strings())
317 }
318
319 fn node_properties(&self, node_id: NodeId) -> Option<Properties>
320 where
321 Self: Sized,
322 {
323 self.with_node(node_id, |n| n.properties().to_owned())
324 }
325
326 fn node_property(&self, node_id: NodeId, key: &str) -> Option<PropertyValue>
327 where
328 Self: Sized,
329 {
330 self.with_node(node_id, |n| n.properties().get(key).map(|v| v.to_owned()))
331 .flatten()
332 }
333
334 fn relationship_type(&self, rel_id: RelationshipId) -> Option<String>
337 where
338 Self: Sized,
339 {
340 self.with_relationship(rel_id, |r| r.rel_type().to_string())
341 }
342
343 fn relationship_properties(&self, rel_id: RelationshipId) -> Option<Properties>
344 where
345 Self: Sized,
346 {
347 self.with_relationship(rel_id, |r| r.properties().to_owned())
348 }
349
350 fn relationship_property(&self, rel_id: RelationshipId, key: &str) -> Option<PropertyValue>
351 where
352 Self: Sized,
353 {
354 self.with_relationship(rel_id, |r| r.properties().get(key).map(|v| v.to_owned()))
355 .flatten()
356 }
357
358 fn relationship_source(&self, rel_id: RelationshipId) -> Option<NodeId> {
359 self.relationship_endpoints(rel_id).map(|(s, _)| s)
360 }
361
362 fn relationship_target(&self, rel_id: RelationshipId) -> Option<NodeId> {
363 self.relationship_endpoints(rel_id).map(|(_, d)| d)
364 }
365
366 fn other_node(&self, rel_id: RelationshipId, node_id: NodeId) -> Option<NodeId> {
367 let (src, dst) = self.relationship_endpoints(rel_id)?;
368 if src == node_id {
369 Some(dst)
370 } else if dst == node_id {
371 Some(src)
372 } else {
373 None
374 }
375 }
376
377 fn has_label_name(&self, label: &str) -> bool {
380 self.all_labels().iter().any(|l| l == label)
381 }
382
383 fn has_relationship_type_name(&self, rel_type: &str) -> bool {
384 self.all_relationship_types().iter().any(|t| t == rel_type)
385 }
386
387 fn all_node_property_keys(&self) -> Vec<String>
388 where
389 Self: Sized,
390 {
391 let mut keys = BTreeSet::new();
392 for id in self.all_node_ids() {
393 self.with_node(id, |n| {
394 for key in n.properties().keys() {
395 keys.insert(key.to_string());
396 }
397 });
398 }
399 keys.into_iter().collect()
400 }
401
402 fn all_relationship_property_keys(&self) -> Vec<String>
403 where
404 Self: Sized,
405 {
406 let mut keys = BTreeSet::new();
407 for id in self.all_rel_ids() {
408 self.with_relationship(id, |r| {
409 for key in r.properties().keys() {
410 keys.insert(key.to_string());
411 }
412 });
413 }
414 keys.into_iter().collect()
415 }
416
417 fn all_property_keys(&self) -> Vec<String>
418 where
419 Self: Sized,
420 {
421 let mut keys = BTreeSet::new();
422 for key in self.all_node_property_keys() {
423 keys.insert(key);
424 }
425 for key in self.all_relationship_property_keys() {
426 keys.insert(key);
427 }
428 keys.into_iter().collect()
429 }
430
431 fn has_property_key(&self, key: &str) -> bool
432 where
433 Self: Sized,
434 {
435 self.all_node_property_keys().iter().any(|k| k == key)
436 || self
437 .all_relationship_property_keys()
438 .iter()
439 .any(|k| k == key)
440 }
441
442 fn label_property_keys(&self, label: &str) -> Vec<String>
443 where
444 Self: Sized,
445 {
446 let mut keys = BTreeSet::new();
447 for id in self.node_ids_by_label(label) {
448 self.with_node(id, |n| {
449 for key in n.properties().keys() {
450 keys.insert(key.to_string());
451 }
452 });
453 }
454 keys.into_iter().collect()
455 }
456
457 fn rel_type_property_keys(&self, rel_type: &str) -> Vec<String>
458 where
459 Self: Sized,
460 {
461 let mut keys = BTreeSet::new();
462 for id in self.rel_ids_by_type(rel_type) {
463 self.with_relationship(id, |r| {
464 for key in r.properties().keys() {
465 keys.insert(key.to_string());
466 }
467 });
468 }
469 keys.into_iter().collect()
470 }
471
472 fn label_has_property_key(&self, label: &str, key: &str) -> bool
473 where
474 Self: Sized,
475 {
476 self.node_ids_by_label(label).into_iter().any(|id| {
477 self.with_node(id, |n| n.properties().contains_key(key))
478 .unwrap_or(false)
479 })
480 }
481
482 fn rel_type_has_property_key(&self, rel_type: &str, key: &str) -> bool
483 where
484 Self: Sized,
485 {
486 self.rel_ids_by_type(rel_type).into_iter().any(|id| {
487 self.with_relationship(id, |r| r.properties().contains_key(key))
488 .unwrap_or(false)
489 })
490 }
491
492 fn find_nodes_by_property(
495 &self,
496 label: Option<&str>,
497 key: &str,
498 value: &PropertyValue,
499 ) -> Vec<NodeRecord>
500 where
501 Self: Sized,
502 {
503 let ids = match label {
504 Some(label) => self.node_ids_by_label(label),
505 None => self.all_node_ids(),
506 };
507
508 ids.into_iter()
509 .filter_map(|id| {
510 let matches = self
511 .with_node(id, |n| n.properties().get(key).is_some_and(|v| v == *value))
512 .unwrap_or(false);
513 if matches {
514 self.node(id)
515 } else {
516 None
517 }
518 })
519 .collect()
520 }
521
522 fn find_node_ids_by_property(
523 &self,
524 label: Option<&str>,
525 key: &str,
526 value: &PropertyValue,
527 ) -> Vec<NodeId>
528 where
529 Self: Sized,
530 {
531 self.find_nodes_by_property(label, key, value)
532 .into_iter()
533 .map(|n| n.id)
534 .collect()
535 }
536
537 fn find_relationships_by_property(
538 &self,
539 rel_type: Option<&str>,
540 key: &str,
541 value: &PropertyValue,
542 ) -> Vec<RelationshipRecord>
543 where
544 Self: Sized,
545 {
546 let ids = match rel_type {
547 Some(rel_type) => self.rel_ids_by_type(rel_type),
548 None => self.all_rel_ids(),
549 };
550
551 ids.into_iter()
552 .filter_map(|id| {
553 let matches = self
554 .with_relationship(id, |r| r.properties().get(key).is_some_and(|v| v == *value))
555 .unwrap_or(false);
556 if matches {
557 self.relationship(id)
558 } else {
559 None
560 }
561 })
562 .collect()
563 }
564
565 fn find_relationship_ids_by_property(
566 &self,
567 rel_type: Option<&str>,
568 key: &str,
569 value: &PropertyValue,
570 ) -> Vec<RelationshipId>
571 where
572 Self: Sized,
573 {
574 self.find_relationships_by_property(rel_type, key, value)
575 .into_iter()
576 .map(|r| r.id)
577 .collect()
578 }
579
580 fn node_exists_with_label_and_property(
581 &self,
582 label: &str,
583 key: &str,
584 value: &PropertyValue,
585 ) -> bool
586 where
587 Self: Sized,
588 {
589 self.node_ids_by_label(label).into_iter().any(|id| {
590 self.with_node(id, |n| n.properties().get(key).is_some_and(|v| v == *value))
591 .unwrap_or(false)
592 })
593 }
594
595 fn relationship_exists_with_type_and_property(
596 &self,
597 rel_type: &str,
598 key: &str,
599 value: &PropertyValue,
600 ) -> bool
601 where
602 Self: Sized,
603 {
604 self.rel_ids_by_type(rel_type).into_iter().any(|id| {
605 self.with_relationship(id, |r| r.properties().get(key).is_some_and(|v| v == *value))
606 .unwrap_or(false)
607 })
608 }
609
610 fn list_indexes(&self) -> Vec<IndexDefinition> {
617 Vec::new()
618 }
619
620 fn get_index(&self, _name: &str) -> Option<IndexDefinition> {
621 None
622 }
623
624 fn fulltext_search(&self, _name: &str, _query: &str) -> Vec<(u64, f64)> {
630 Vec::new()
631 }
632
633 fn vector_search(
649 &self,
650 _name: &str,
651 _query: &LoraVector,
652 _k: usize,
653 _restrict_to: Option<&std::collections::BTreeSet<u64>>,
654 ) -> Vec<(u64, f64)> {
655 Vec::new()
656 }
657
658 fn list_constraints(&self) -> Vec<ConstraintDefinition> {
661 Vec::new()
662 }
663
664 fn get_constraint(&self, _name: &str) -> Option<ConstraintDefinition> {
665 None
666 }
667
668 fn check_node_create_against_constraints(
674 &self,
675 _labels: &[String],
676 _properties: &Properties,
677 ) -> Result<(), String> {
678 Ok(())
679 }
680
681 fn check_relationship_create_against_constraints(
683 &self,
684 _rel_type: &str,
685 _properties: &Properties,
686 ) -> Result<(), String> {
687 Ok(())
688 }
689
690 fn check_node_create_deferring_existence(
695 &self,
696 labels: &[String],
697 properties: &Properties,
698 ) -> Result<(), String> {
699 self.check_node_create_against_constraints(labels, properties)
700 }
701
702 fn check_relationship_create_deferring_existence(
705 &self,
706 rel_type: &str,
707 properties: &Properties,
708 ) -> Result<(), String> {
709 self.check_relationship_create_against_constraints(rel_type, properties)
710 }
711
712 fn check_node_existence_constraints(&self, _node_id: NodeId) -> Result<(), String> {
715 Ok(())
716 }
717
718 fn check_relationship_existence_constraints(
720 &self,
721 _rel_id: RelationshipId,
722 ) -> Result<(), String> {
723 Ok(())
724 }
725
726 fn check_node_set_property_against_constraints(
729 &self,
730 _node_id: NodeId,
731 _key: &str,
732 _value: &PropertyValue,
733 ) -> Result<(), String> {
734 Ok(())
735 }
736
737 fn check_node_remove_property_against_constraints(
740 &self,
741 _node_id: NodeId,
742 _key: &str,
743 ) -> Result<(), String> {
744 Ok(())
745 }
746
747 fn check_node_replace_properties_against_constraints(
751 &self,
752 _node_id: NodeId,
753 _properties: &Properties,
754 ) -> Result<(), String> {
755 Ok(())
756 }
757
758 fn check_relationship_set_property_against_constraints(
761 &self,
762 _rel_id: RelationshipId,
763 _key: &str,
764 _value: &PropertyValue,
765 ) -> Result<(), String> {
766 Ok(())
767 }
768
769 fn check_relationship_remove_property_against_constraints(
770 &self,
771 _rel_id: RelationshipId,
772 _key: &str,
773 ) -> Result<(), String> {
774 Ok(())
775 }
776
777 fn check_relationship_replace_properties_against_constraints(
781 &self,
782 _rel_id: RelationshipId,
783 _properties: &Properties,
784 ) -> Result<(), String> {
785 Ok(())
786 }
787
788 fn check_node_add_label_against_constraints(
791 &self,
792 _node_id: NodeId,
793 _label: &str,
794 ) -> Result<(), String> {
795 Ok(())
796 }
797
798 fn check_node_replace_properties_deferring_existence(
803 &self,
804 node_id: NodeId,
805 properties: &Properties,
806 ) -> Result<(), String> {
807 self.check_node_replace_properties_against_constraints(node_id, properties)
808 }
809
810 fn check_relationship_replace_properties_deferring_existence(
813 &self,
814 rel_id: RelationshipId,
815 properties: &Properties,
816 ) -> Result<(), String> {
817 self.check_relationship_replace_properties_against_constraints(rel_id, properties)
818 }
819
820 fn check_node_add_label_deferring_existence(
826 &self,
827 node_id: NodeId,
828 label: &str,
829 ) -> Result<(), String> {
830 self.check_node_add_label_against_constraints(node_id, label)
831 }
832
833 fn graph_stats(&self) -> GraphStats {
837 GraphStats::default()
838 }
839
840 fn node_text_candidates(
849 &self,
850 _label: &str,
851 _property: &str,
852 _query: &str,
853 ) -> Option<Vec<NodeId>> {
854 None
855 }
856
857 fn node_range_candidates(
863 &self,
864 _label: &str,
865 _property: &str,
866 _lo: Option<&PropertyValue>,
867 _hi: Option<&PropertyValue>,
868 ) -> Option<Vec<NodeId>> {
869 None
870 }
871
872 fn node_range_other_temporal_kind_ids(
879 &self,
880 _label: &str,
881 _property: &str,
882 _like: &PropertyValue,
883 ) -> Option<Vec<NodeId>> {
884 None
885 }
886
887 #[allow(clippy::too_many_arguments)]
893 fn node_range_ordered_chunk(
894 &self,
895 _label: &str,
896 _property: &str,
897 _lo: Option<&PropertyValue>,
898 _hi: Option<&PropertyValue>,
899 _descending: bool,
900 _after: Option<(&PropertyValue, NodeId)>,
901 _max: usize,
902 ) -> Option<Vec<NodeId>> {
903 None
904 }
905
906 fn node_point_within_bbox(
911 &self,
912 _label: &str,
913 _property: &str,
914 _ll: (f64, f64),
915 _ur: (f64, f64),
916 ) -> Option<Vec<NodeId>> {
917 None
918 }
919
920 fn node_point_within_distance(
924 &self,
925 _label: &str,
926 _property: &str,
927 _center: (f64, f64),
928 _max_distance: f64,
929 ) -> Option<Vec<NodeId>> {
930 None
931 }
932
933 fn relationship_text_candidates(
937 &self,
938 _rel_type: &str,
939 _property: &str,
940 _query: &str,
941 ) -> Option<Vec<RelationshipId>> {
942 None
943 }
944
945 fn relationship_range_candidates(
948 &self,
949 _rel_type: &str,
950 _property: &str,
951 _lo: Option<&PropertyValue>,
952 _hi: Option<&PropertyValue>,
953 ) -> Option<Vec<RelationshipId>> {
954 None
955 }
956
957 fn relationship_range_other_temporal_kind_ids(
960 &self,
961 _rel_type: &str,
962 _property: &str,
963 _like: &PropertyValue,
964 ) -> Option<Vec<RelationshipId>> {
965 None
966 }
967
968 fn relationship_point_within_bbox(
972 &self,
973 _rel_type: &str,
974 _property: &str,
975 _ll: (f64, f64),
976 _ur: (f64, f64),
977 ) -> Option<Vec<RelationshipId>> {
978 None
979 }
980
981 fn relationship_point_within_distance(
985 &self,
986 _rel_type: &str,
987 _property: &str,
988 _center: (f64, f64),
989 _max_distance: f64,
990 ) -> Option<Vec<RelationshipId>> {
991 None
992 }
993}
994
995pub trait GraphCatalog {
1003 fn node_count(&self) -> usize;
1004 fn relationship_count(&self) -> usize;
1005 fn has_label_name(&self, label: &str) -> bool;
1006 fn has_relationship_type_name(&self, rel_type: &str) -> bool;
1007 fn has_property_key(&self, key: &str) -> bool;
1008}
1009
1010impl<T: GraphStorage> GraphCatalog for T {
1011 fn node_count(&self) -> usize {
1012 GraphStorage::node_count(self)
1013 }
1014 fn relationship_count(&self) -> usize {
1015 GraphStorage::relationship_count(self)
1016 }
1017 fn has_label_name(&self, label: &str) -> bool {
1018 GraphStorage::has_label_name(self, label)
1019 }
1020 fn has_relationship_type_name(&self, rel_type: &str) -> bool {
1021 GraphStorage::has_relationship_type_name(self, rel_type)
1022 }
1023 fn has_property_key(&self, key: &str) -> bool {
1024 GraphStorage::has_property_key(self, key)
1025 }
1026}
1027
1028pub trait GraphStorageMut: GraphStorage {
1038 fn try_create_node(
1041 &mut self,
1042 labels: Vec<String>,
1043 properties: Properties,
1044 ) -> Option<NodeRecord>;
1045
1046 fn create_node(&mut self, labels: Vec<String>, properties: Properties) -> NodeRecord
1051 where
1052 Self: Sized,
1053 {
1054 self.try_create_node(labels, properties)
1055 .unwrap_or_else(|| NodeRecord {
1056 id: NodeId::MAX,
1057 labels: Default::default(),
1058 properties: Properties::new(),
1059 })
1060 }
1061
1062 fn create_relationship(
1063 &mut self,
1064 src: NodeId,
1065 dst: NodeId,
1066 rel_type: &str,
1067 properties: Properties,
1068 ) -> Option<RelationshipRecord>;
1069
1070 fn set_node_property(&mut self, node_id: NodeId, key: String, value: PropertyValue) -> bool;
1073
1074 fn remove_node_property(&mut self, node_id: NodeId, key: &str) -> bool;
1075
1076 fn add_node_label(&mut self, node_id: NodeId, label: &str) -> bool;
1077 fn remove_node_label(&mut self, node_id: NodeId, label: &str) -> bool;
1078
1079 fn set_relationship_property(
1082 &mut self,
1083 rel_id: RelationshipId,
1084 key: String,
1085 value: PropertyValue,
1086 ) -> bool;
1087
1088 fn remove_relationship_property(&mut self, rel_id: RelationshipId, key: &str) -> bool;
1089
1090 fn delete_relationship(&mut self, rel_id: RelationshipId) -> bool;
1093
1094 fn delete_node(&mut self, node_id: NodeId) -> bool;
1096
1097 fn detach_delete_node(&mut self, node_id: NodeId) -> bool;
1099
1100 fn clear(&mut self);
1109
1110 #[allow(clippy::result_large_err)]
1117 fn create_index(
1118 &mut self,
1119 _request: IndexRequest,
1120 _if_not_exists: bool,
1121 ) -> Result<CreateIndexOutcome, CreateIndexError> {
1122 Err(CreateIndexError::Unsupported(
1123 "this backend does not maintain an index catalog",
1124 ))
1125 }
1126
1127 fn drop_index(
1132 &mut self,
1133 _name: &str,
1134 _if_exists: bool,
1135 ) -> Result<DropIndexOutcome, DropIndexError> {
1136 Err(DropIndexError::Unsupported(
1137 "this backend does not maintain an index catalog",
1138 ))
1139 }
1140
1141 fn create_constraint(
1146 &mut self,
1147 _request: ConstraintRequest,
1148 _if_not_exists: bool,
1149 ) -> Result<CreateConstraintOutcome, CreateConstraintError> {
1150 Err(CreateConstraintError::Unsupported(
1151 "this backend does not maintain a constraint catalog",
1152 ))
1153 }
1154
1155 fn drop_constraint(
1158 &mut self,
1159 _name: &str,
1160 _if_exists: bool,
1161 ) -> Result<DropConstraintOutcome, DropConstraintError> {
1162 Err(DropConstraintError::Unsupported(
1163 "this backend does not maintain a constraint catalog",
1164 ))
1165 }
1166
1167 fn replace_node_properties(&mut self, node_id: NodeId, properties: Properties) -> bool
1170 where
1171 Self: Sized,
1172 {
1173 if !self.contains_node(node_id) {
1174 return false;
1175 }
1176
1177 let existing_keys = match self.node_properties(node_id) {
1178 Some(props) => props.into_keys().collect::<Vec<_>>(),
1179 None => return false,
1180 };
1181
1182 for key in existing_keys {
1183 self.remove_node_property(node_id, &key);
1184 }
1185
1186 for (k, v) in properties {
1187 self.set_node_property(node_id, k.to_string(), v);
1188 }
1189
1190 true
1191 }
1192
1193 fn merge_node_properties(&mut self, node_id: NodeId, properties: Properties) -> bool {
1194 if !self.contains_node(node_id) {
1195 return false;
1196 }
1197
1198 for (k, v) in properties {
1199 self.set_node_property(node_id, k.to_string(), v);
1200 }
1201
1202 true
1203 }
1204
1205 fn set_node_labels(&mut self, node_id: NodeId, labels: Vec<String>) -> bool
1206 where
1207 Self: Sized,
1208 {
1209 if !self.contains_node(node_id) {
1210 return false;
1211 }
1212
1213 let current = match self.node_labels(node_id) {
1214 Some(labels) => labels,
1215 None => return false,
1216 };
1217
1218 for label in ¤t {
1219 self.remove_node_label(node_id, label);
1220 }
1221
1222 for label in &labels {
1223 self.add_node_label(node_id, label);
1224 }
1225
1226 true
1227 }
1228
1229 fn replace_relationship_properties(
1230 &mut self,
1231 rel_id: RelationshipId,
1232 properties: Properties,
1233 ) -> bool
1234 where
1235 Self: Sized,
1236 {
1237 if !self.contains_relationship(rel_id) {
1238 return false;
1239 }
1240
1241 let existing_keys = match self.relationship_properties(rel_id) {
1242 Some(props) => props.into_keys().collect::<Vec<_>>(),
1243 None => return false,
1244 };
1245
1246 for key in existing_keys {
1247 self.remove_relationship_property(rel_id, &key);
1248 }
1249
1250 for (k, v) in properties {
1251 self.set_relationship_property(rel_id, k.to_string(), v);
1252 }
1253
1254 true
1255 }
1256
1257 fn merge_relationship_properties(
1258 &mut self,
1259 rel_id: RelationshipId,
1260 properties: Properties,
1261 ) -> bool {
1262 if !self.contains_relationship(rel_id) {
1263 return false;
1264 }
1265
1266 for (k, v) in properties {
1267 self.set_relationship_property(rel_id, k.to_string(), v);
1268 }
1269
1270 true
1271 }
1272
1273 fn delete_relationships_of(&mut self, node_id: NodeId, direction: Direction) -> usize {
1274 let rel_ids = self.relationship_ids_of(node_id, direction);
1275
1276 let mut deleted = 0;
1277 for rel_id in rel_ids {
1278 if self.delete_relationship(rel_id) {
1279 deleted += 1;
1280 }
1281 }
1282 deleted
1283 }
1284
1285 fn get_or_create_node(
1286 &mut self,
1287 labels: Vec<String>,
1288 match_key: &str,
1289 match_value: &PropertyValue,
1290 init_properties: Properties,
1291 ) -> NodeRecord
1292 where
1293 Self: Sized,
1294 {
1295 for label in &labels {
1296 let matches = self.find_nodes_by_property(Some(label), match_key, match_value);
1297 if let Some(node) = matches.into_iter().next() {
1298 return node;
1299 }
1300 }
1301
1302 self.create_node(labels, init_properties)
1303 }
1304}