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, _limit: Option<usize>) -> Vec<(u64, f64)> {
631 Vec::new()
632 }
633
634 fn vector_search(
650 &self,
651 _name: &str,
652 _query: &LoraVector,
653 _k: usize,
654 _restrict_to: Option<&std::collections::BTreeSet<u64>>,
655 ) -> Vec<(u64, f64)> {
656 Vec::new()
657 }
658
659 fn list_constraints(&self) -> Vec<ConstraintDefinition> {
662 Vec::new()
663 }
664
665 fn get_constraint(&self, _name: &str) -> Option<ConstraintDefinition> {
666 None
667 }
668
669 fn check_node_create_against_constraints(
675 &self,
676 _labels: &[String],
677 _properties: &Properties,
678 ) -> Result<(), String> {
679 Ok(())
680 }
681
682 fn check_relationship_create_against_constraints(
684 &self,
685 _rel_type: &str,
686 _properties: &Properties,
687 ) -> Result<(), String> {
688 Ok(())
689 }
690
691 fn check_node_create_deferring_existence(
696 &self,
697 labels: &[String],
698 properties: &Properties,
699 ) -> Result<(), String> {
700 self.check_node_create_against_constraints(labels, properties)
701 }
702
703 fn check_relationship_create_deferring_existence(
706 &self,
707 rel_type: &str,
708 properties: &Properties,
709 ) -> Result<(), String> {
710 self.check_relationship_create_against_constraints(rel_type, properties)
711 }
712
713 fn check_node_existence_constraints(&self, _node_id: NodeId) -> Result<(), String> {
716 Ok(())
717 }
718
719 fn check_relationship_existence_constraints(
721 &self,
722 _rel_id: RelationshipId,
723 ) -> Result<(), String> {
724 Ok(())
725 }
726
727 fn check_node_set_property_against_constraints(
730 &self,
731 _node_id: NodeId,
732 _key: &str,
733 _value: &PropertyValue,
734 ) -> Result<(), String> {
735 Ok(())
736 }
737
738 fn check_node_remove_property_against_constraints(
741 &self,
742 _node_id: NodeId,
743 _key: &str,
744 ) -> Result<(), String> {
745 Ok(())
746 }
747
748 fn check_node_replace_properties_against_constraints(
752 &self,
753 _node_id: NodeId,
754 _properties: &Properties,
755 ) -> Result<(), String> {
756 Ok(())
757 }
758
759 fn check_relationship_set_property_against_constraints(
762 &self,
763 _rel_id: RelationshipId,
764 _key: &str,
765 _value: &PropertyValue,
766 ) -> Result<(), String> {
767 Ok(())
768 }
769
770 fn check_relationship_remove_property_against_constraints(
771 &self,
772 _rel_id: RelationshipId,
773 _key: &str,
774 ) -> Result<(), String> {
775 Ok(())
776 }
777
778 fn check_relationship_replace_properties_against_constraints(
782 &self,
783 _rel_id: RelationshipId,
784 _properties: &Properties,
785 ) -> Result<(), String> {
786 Ok(())
787 }
788
789 fn check_node_add_label_against_constraints(
792 &self,
793 _node_id: NodeId,
794 _label: &str,
795 ) -> Result<(), String> {
796 Ok(())
797 }
798
799 fn check_node_replace_properties_deferring_existence(
804 &self,
805 node_id: NodeId,
806 properties: &Properties,
807 ) -> Result<(), String> {
808 self.check_node_replace_properties_against_constraints(node_id, properties)
809 }
810
811 fn check_relationship_replace_properties_deferring_existence(
814 &self,
815 rel_id: RelationshipId,
816 properties: &Properties,
817 ) -> Result<(), String> {
818 self.check_relationship_replace_properties_against_constraints(rel_id, properties)
819 }
820
821 fn check_node_add_label_deferring_existence(
827 &self,
828 node_id: NodeId,
829 label: &str,
830 ) -> Result<(), String> {
831 self.check_node_add_label_against_constraints(node_id, label)
832 }
833
834 fn graph_stats(&self) -> GraphStats {
838 GraphStats::default()
839 }
840
841 fn node_text_candidates(
850 &self,
851 _label: &str,
852 _property: &str,
853 _query: &str,
854 ) -> Option<Vec<NodeId>> {
855 None
856 }
857
858 fn node_range_candidates(
864 &self,
865 _label: &str,
866 _property: &str,
867 _lo: Option<&PropertyValue>,
868 _hi: Option<&PropertyValue>,
869 ) -> Option<Vec<NodeId>> {
870 None
871 }
872
873 fn node_range_other_temporal_kind_ids(
880 &self,
881 _label: &str,
882 _property: &str,
883 _like: &PropertyValue,
884 ) -> Option<Vec<NodeId>> {
885 None
886 }
887
888 #[allow(clippy::too_many_arguments)]
894 fn node_range_ordered_chunk(
895 &self,
896 _label: &str,
897 _property: &str,
898 _lo: Option<&PropertyValue>,
899 _hi: Option<&PropertyValue>,
900 _descending: bool,
901 _after: Option<(&PropertyValue, NodeId)>,
902 _max: usize,
903 ) -> Option<Vec<NodeId>> {
904 None
905 }
906
907 fn node_point_within_bbox(
912 &self,
913 _label: &str,
914 _property: &str,
915 _ll: (f64, f64),
916 _ur: (f64, f64),
917 ) -> Option<Vec<NodeId>> {
918 None
919 }
920
921 fn node_point_within_distance(
925 &self,
926 _label: &str,
927 _property: &str,
928 _center: (f64, f64),
929 _max_distance: f64,
930 ) -> Option<Vec<NodeId>> {
931 None
932 }
933
934 fn relationship_text_candidates(
938 &self,
939 _rel_type: &str,
940 _property: &str,
941 _query: &str,
942 ) -> Option<Vec<RelationshipId>> {
943 None
944 }
945
946 fn relationship_range_candidates(
949 &self,
950 _rel_type: &str,
951 _property: &str,
952 _lo: Option<&PropertyValue>,
953 _hi: Option<&PropertyValue>,
954 ) -> Option<Vec<RelationshipId>> {
955 None
956 }
957
958 fn relationship_range_other_temporal_kind_ids(
961 &self,
962 _rel_type: &str,
963 _property: &str,
964 _like: &PropertyValue,
965 ) -> Option<Vec<RelationshipId>> {
966 None
967 }
968
969 fn relationship_point_within_bbox(
973 &self,
974 _rel_type: &str,
975 _property: &str,
976 _ll: (f64, f64),
977 _ur: (f64, f64),
978 ) -> Option<Vec<RelationshipId>> {
979 None
980 }
981
982 fn relationship_point_within_distance(
986 &self,
987 _rel_type: &str,
988 _property: &str,
989 _center: (f64, f64),
990 _max_distance: f64,
991 ) -> Option<Vec<RelationshipId>> {
992 None
993 }
994}
995
996pub trait GraphCatalog {
1004 fn node_count(&self) -> usize;
1005 fn relationship_count(&self) -> usize;
1006 fn has_label_name(&self, label: &str) -> bool;
1007 fn has_relationship_type_name(&self, rel_type: &str) -> bool;
1008 fn has_property_key(&self, key: &str) -> bool;
1009}
1010
1011impl<T: GraphStorage> GraphCatalog for T {
1012 fn node_count(&self) -> usize {
1013 GraphStorage::node_count(self)
1014 }
1015 fn relationship_count(&self) -> usize {
1016 GraphStorage::relationship_count(self)
1017 }
1018 fn has_label_name(&self, label: &str) -> bool {
1019 GraphStorage::has_label_name(self, label)
1020 }
1021 fn has_relationship_type_name(&self, rel_type: &str) -> bool {
1022 GraphStorage::has_relationship_type_name(self, rel_type)
1023 }
1024 fn has_property_key(&self, key: &str) -> bool {
1025 GraphStorage::has_property_key(self, key)
1026 }
1027}
1028
1029pub trait GraphStorageMut: GraphStorage {
1039 fn try_create_node(
1042 &mut self,
1043 labels: Vec<String>,
1044 properties: Properties,
1045 ) -> Option<NodeRecord>;
1046
1047 fn create_node(&mut self, labels: Vec<String>, properties: Properties) -> NodeRecord
1052 where
1053 Self: Sized,
1054 {
1055 self.try_create_node(labels, properties)
1056 .unwrap_or_else(|| NodeRecord {
1057 id: NodeId::MAX,
1058 labels: Default::default(),
1059 properties: Properties::new(),
1060 })
1061 }
1062
1063 fn create_relationship(
1064 &mut self,
1065 src: NodeId,
1066 dst: NodeId,
1067 rel_type: &str,
1068 properties: Properties,
1069 ) -> Option<RelationshipRecord>;
1070
1071 fn set_node_property(&mut self, node_id: NodeId, key: String, value: PropertyValue) -> bool;
1074
1075 fn remove_node_property(&mut self, node_id: NodeId, key: &str) -> bool;
1076
1077 fn add_node_label(&mut self, node_id: NodeId, label: &str) -> bool;
1078 fn remove_node_label(&mut self, node_id: NodeId, label: &str) -> bool;
1079
1080 fn set_relationship_property(
1083 &mut self,
1084 rel_id: RelationshipId,
1085 key: String,
1086 value: PropertyValue,
1087 ) -> bool;
1088
1089 fn remove_relationship_property(&mut self, rel_id: RelationshipId, key: &str) -> bool;
1090
1091 fn delete_relationship(&mut self, rel_id: RelationshipId) -> bool;
1094
1095 fn delete_node(&mut self, node_id: NodeId) -> bool;
1097
1098 fn detach_delete_node(&mut self, node_id: NodeId) -> bool;
1100
1101 fn clear(&mut self);
1110
1111 #[allow(clippy::result_large_err)]
1118 fn create_index(
1119 &mut self,
1120 _request: IndexRequest,
1121 _if_not_exists: bool,
1122 ) -> Result<CreateIndexOutcome, CreateIndexError> {
1123 Err(CreateIndexError::Unsupported(
1124 "this backend does not maintain an index catalog",
1125 ))
1126 }
1127
1128 fn drop_index(
1133 &mut self,
1134 _name: &str,
1135 _if_exists: bool,
1136 ) -> Result<DropIndexOutcome, DropIndexError> {
1137 Err(DropIndexError::Unsupported(
1138 "this backend does not maintain an index catalog",
1139 ))
1140 }
1141
1142 fn create_constraint(
1147 &mut self,
1148 _request: ConstraintRequest,
1149 _if_not_exists: bool,
1150 ) -> Result<CreateConstraintOutcome, CreateConstraintError> {
1151 Err(CreateConstraintError::Unsupported(
1152 "this backend does not maintain a constraint catalog",
1153 ))
1154 }
1155
1156 fn drop_constraint(
1159 &mut self,
1160 _name: &str,
1161 _if_exists: bool,
1162 ) -> Result<DropConstraintOutcome, DropConstraintError> {
1163 Err(DropConstraintError::Unsupported(
1164 "this backend does not maintain a constraint catalog",
1165 ))
1166 }
1167
1168 fn replace_node_properties(&mut self, node_id: NodeId, properties: Properties) -> bool
1171 where
1172 Self: Sized,
1173 {
1174 if !self.contains_node(node_id) {
1175 return false;
1176 }
1177
1178 let existing_keys = match self.node_properties(node_id) {
1179 Some(props) => props.into_keys().collect::<Vec<_>>(),
1180 None => return false,
1181 };
1182
1183 for key in existing_keys {
1184 self.remove_node_property(node_id, &key);
1185 }
1186
1187 for (k, v) in properties {
1188 self.set_node_property(node_id, k.to_string(), v);
1189 }
1190
1191 true
1192 }
1193
1194 fn merge_node_properties(&mut self, node_id: NodeId, properties: Properties) -> bool {
1195 if !self.contains_node(node_id) {
1196 return false;
1197 }
1198
1199 for (k, v) in properties {
1200 self.set_node_property(node_id, k.to_string(), v);
1201 }
1202
1203 true
1204 }
1205
1206 fn set_node_labels(&mut self, node_id: NodeId, labels: Vec<String>) -> bool
1207 where
1208 Self: Sized,
1209 {
1210 if !self.contains_node(node_id) {
1211 return false;
1212 }
1213
1214 let current = match self.node_labels(node_id) {
1215 Some(labels) => labels,
1216 None => return false,
1217 };
1218
1219 for label in ¤t {
1220 self.remove_node_label(node_id, label);
1221 }
1222
1223 for label in &labels {
1224 self.add_node_label(node_id, label);
1225 }
1226
1227 true
1228 }
1229
1230 fn replace_relationship_properties(
1231 &mut self,
1232 rel_id: RelationshipId,
1233 properties: Properties,
1234 ) -> bool
1235 where
1236 Self: Sized,
1237 {
1238 if !self.contains_relationship(rel_id) {
1239 return false;
1240 }
1241
1242 let existing_keys = match self.relationship_properties(rel_id) {
1243 Some(props) => props.into_keys().collect::<Vec<_>>(),
1244 None => return false,
1245 };
1246
1247 for key in existing_keys {
1248 self.remove_relationship_property(rel_id, &key);
1249 }
1250
1251 for (k, v) in properties {
1252 self.set_relationship_property(rel_id, k.to_string(), v);
1253 }
1254
1255 true
1256 }
1257
1258 fn merge_relationship_properties(
1259 &mut self,
1260 rel_id: RelationshipId,
1261 properties: Properties,
1262 ) -> bool {
1263 if !self.contains_relationship(rel_id) {
1264 return false;
1265 }
1266
1267 for (k, v) in properties {
1268 self.set_relationship_property(rel_id, k.to_string(), v);
1269 }
1270
1271 true
1272 }
1273
1274 fn delete_relationships_of(&mut self, node_id: NodeId, direction: Direction) -> usize {
1275 let rel_ids = self.relationship_ids_of(node_id, direction);
1276
1277 let mut deleted = 0;
1278 for rel_id in rel_ids {
1279 if self.delete_relationship(rel_id) {
1280 deleted += 1;
1281 }
1282 }
1283 deleted
1284 }
1285
1286 fn get_or_create_node(
1287 &mut self,
1288 labels: Vec<String>,
1289 match_key: &str,
1290 match_value: &PropertyValue,
1291 init_properties: Properties,
1292 ) -> NodeRecord
1293 where
1294 Self: Sized,
1295 {
1296 for label in &labels {
1297 let matches = self.find_nodes_by_property(Some(label), match_key, match_value);
1298 if let Some(node) = matches.into_iter().next() {
1299 return node;
1300 }
1301 }
1302
1303 self.create_node(labels, init_properties)
1304 }
1305}