1use std::collections::BTreeSet;
5
6use lora_ast::Direction;
7
8use crate::encoded::PropEdit;
9use crate::{
10 ConstraintDefinition, ConstraintRequest, CreateConstraintError, CreateConstraintOutcome,
11 CreateIndexError, CreateIndexOutcome, DropConstraintError, DropConstraintOutcome,
12 DropIndexError, DropIndexOutcome, GraphStats, GraphStorage, GraphStorageMut, IndexDefinition,
13 IndexRequest, LoraVector, MutationEvent, NodeId, NodeRecord, NodeRef, Properties,
14 PropertyValue, RelRef, RelationshipId, RelationshipRecord, StoredIndexEntity,
15};
16
17use super::graph::PendingAdjRemovals;
18use super::property_index::PropertyIndexKey;
19use super::InMemoryGraph;
20
21impl GraphStorage for InMemoryGraph {
22 fn list_indexes(&self) -> Vec<IndexDefinition> {
25 self.index_catalog_read().list()
26 }
27
28 fn get_index(&self, name: &str) -> Option<IndexDefinition> {
29 self.index_catalog_read().get(name).cloned()
30 }
31
32 fn fulltext_search(&self, name: &str, query: &str, limit: Option<usize>) -> Vec<(u64, f64)> {
33 let node_hits = self
35 .fulltext_indexes_read(StoredIndexEntity::Node)
36 .get(name)
37 .map(|idx| idx.query(query, limit));
38 if let Some(hits) = node_hits {
39 if !hits.is_empty() {
40 return hits;
41 }
42 }
43 let rel_hits = self
44 .fulltext_indexes_read(StoredIndexEntity::Relationship)
45 .get(name)
46 .map(|idx| idx.query(query, limit));
47 rel_hits.unwrap_or_default()
48 }
49
50 fn vector_search(
51 &self,
52 name: &str,
53 query: &LoraVector,
54 k: usize,
55 restrict_to: Option<&std::collections::BTreeSet<u64>>,
56 ) -> Vec<(u64, f64)> {
57 self.lazy_populate_vector_index(name);
64
65 if let Some(hits) =
69 self.vector_indexes_read(StoredIndexEntity::Node)
70 .query(name, query, k, restrict_to)
71 {
72 if !hits.is_empty() {
73 return hits;
74 }
75 }
76 self.vector_indexes_read(StoredIndexEntity::Relationship)
77 .query(name, query, k, restrict_to)
78 .unwrap_or_default()
79 }
80
81 fn combines_property_writes(&self) -> bool {
82 !self.has_active_constraints()
83 || self
84 .constraint_catalog_read()
85 .list()
86 .iter()
87 .all(|c| c.properties.len() <= 1)
88 }
89
90 fn list_constraints(&self) -> Vec<ConstraintDefinition> {
91 self.constraint_catalog_read().list()
92 }
93
94 fn get_constraint(&self, name: &str) -> Option<ConstraintDefinition> {
95 self.constraint_catalog_read().get(name).cloned()
96 }
97
98 fn check_node_create_against_constraints(
99 &self,
100 labels: &[String],
101 properties: &Properties,
102 ) -> Result<(), String> {
103 if !self.has_active_constraints() {
104 return Ok(());
105 }
106 let catalog = self.constraint_catalog_read();
107 crate::memory::constraint_enforce::check_node_create(&catalog, self, labels, properties)
108 .map_err(|e| format!("[{}] {e}", e.gql_status()))
109 }
110
111 fn check_relationship_create_against_constraints(
112 &self,
113 rel_type: &str,
114 properties: &Properties,
115 ) -> Result<(), String> {
116 if !self.has_active_constraints() {
117 return Ok(());
118 }
119 let catalog = self.constraint_catalog_read();
120 crate::memory::constraint_enforce::check_relationship_create(
121 &catalog, self, rel_type, properties,
122 )
123 .map_err(|e| format!("[{}] {e}", e.gql_status()))
124 }
125
126 fn check_node_create_deferring_existence(
127 &self,
128 labels: &[String],
129 properties: &Properties,
130 ) -> Result<(), String> {
131 if !self.has_active_constraints() {
132 return Ok(());
133 }
134 let catalog = self.constraint_catalog_read();
135 crate::memory::constraint_enforce::check_node_create_deferred(
136 &catalog, self, labels, properties,
137 )
138 .map_err(|e| format!("[{}] {e}", e.gql_status()))
139 }
140
141 fn check_relationship_create_deferring_existence(
142 &self,
143 rel_type: &str,
144 properties: &Properties,
145 ) -> Result<(), String> {
146 if !self.has_active_constraints() {
147 return Ok(());
148 }
149 let catalog = self.constraint_catalog_read();
150 crate::memory::constraint_enforce::check_relationship_create_deferred(
151 &catalog, self, rel_type, properties,
152 )
153 .map_err(|e| format!("[{}] {e}", e.gql_status()))
154 }
155
156 fn check_node_existence_constraints(&self, node_id: NodeId) -> Result<(), String> {
157 if !self.has_active_constraints() {
158 return Ok(());
159 }
160 let catalog = self.constraint_catalog_read();
161 crate::memory::constraint_enforce::check_node_existence(&catalog, self, node_id)
162 .map_err(|e| format!("[{}] {e}", e.gql_status()))
163 }
164
165 fn check_relationship_existence_constraints(
166 &self,
167 rel_id: RelationshipId,
168 ) -> Result<(), String> {
169 if !self.has_active_constraints() {
170 return Ok(());
171 }
172 let catalog = self.constraint_catalog_read();
173 crate::memory::constraint_enforce::check_relationship_existence(&catalog, self, rel_id)
174 .map_err(|e| format!("[{}] {e}", e.gql_status()))
175 }
176
177 fn check_node_set_property_against_constraints(
178 &self,
179 node_id: NodeId,
180 key: &str,
181 value: &PropertyValue,
182 ) -> Result<(), String> {
183 if !self.has_active_constraints() {
184 return Ok(());
185 }
186 let catalog = self.constraint_catalog_read();
187 crate::memory::constraint_enforce::check_node_set_property(
188 &catalog, self, node_id, key, value,
189 )
190 .map_err(|e| format!("[{}] {e}", e.gql_status()))
191 }
192
193 fn check_node_remove_property_against_constraints(
194 &self,
195 node_id: NodeId,
196 key: &str,
197 ) -> Result<(), String> {
198 if !self.has_active_constraints() {
199 return Ok(());
200 }
201 let catalog = self.constraint_catalog_read();
202 crate::memory::constraint_enforce::check_node_remove_property(&catalog, self, node_id, key)
203 .map_err(|e| format!("[{}] {e}", e.gql_status()))
204 }
205
206 fn check_node_replace_properties_against_constraints(
207 &self,
208 node_id: NodeId,
209 properties: &Properties,
210 ) -> Result<(), String> {
211 if !self.has_active_constraints() {
212 return Ok(());
213 }
214 let catalog = self.constraint_catalog_read();
215 crate::memory::constraint_enforce::check_node_replace_properties(
216 &catalog, self, node_id, properties,
217 )
218 .map_err(|e| format!("[{}] {e}", e.gql_status()))
219 }
220
221 fn check_relationship_set_property_against_constraints(
222 &self,
223 rel_id: RelationshipId,
224 key: &str,
225 value: &PropertyValue,
226 ) -> Result<(), String> {
227 if !self.has_active_constraints() {
228 return Ok(());
229 }
230 let catalog = self.constraint_catalog_read();
231 crate::memory::constraint_enforce::check_relationship_set_property(
232 &catalog, self, rel_id, key, value,
233 )
234 .map_err(|e| format!("[{}] {e}", e.gql_status()))
235 }
236
237 fn check_relationship_remove_property_against_constraints(
238 &self,
239 rel_id: RelationshipId,
240 key: &str,
241 ) -> Result<(), String> {
242 if !self.has_active_constraints() {
243 return Ok(());
244 }
245 let catalog = self.constraint_catalog_read();
246 crate::memory::constraint_enforce::check_relationship_remove_property(
247 &catalog, self, rel_id, key,
248 )
249 .map_err(|e| format!("[{}] {e}", e.gql_status()))
250 }
251
252 fn check_relationship_replace_properties_against_constraints(
253 &self,
254 rel_id: RelationshipId,
255 properties: &Properties,
256 ) -> Result<(), String> {
257 if !self.has_active_constraints() {
258 return Ok(());
259 }
260 let catalog = self.constraint_catalog_read();
261 crate::memory::constraint_enforce::check_relationship_replace_properties(
262 &catalog, self, rel_id, properties,
263 )
264 .map_err(|e| format!("[{}] {e}", e.gql_status()))
265 }
266
267 fn check_node_add_label_against_constraints(
268 &self,
269 node_id: NodeId,
270 label: &str,
271 ) -> Result<(), String> {
272 if !self.has_active_constraints() {
273 return Ok(());
274 }
275 let catalog = self.constraint_catalog_read();
276 crate::memory::constraint_enforce::check_node_add_label(&catalog, self, node_id, label)
277 .map_err(|e| format!("[{}] {e}", e.gql_status()))
278 }
279
280 fn check_node_replace_properties_deferring_existence(
281 &self,
282 node_id: NodeId,
283 properties: &Properties,
284 ) -> Result<(), String> {
285 if !self.has_active_constraints() {
286 return Ok(());
287 }
288 let catalog = self.constraint_catalog_read();
289 crate::memory::constraint_enforce::check_node_replace_properties_deferred(
290 &catalog, self, node_id, properties,
291 )
292 .map_err(|e| format!("[{}] {e}", e.gql_status()))
293 }
294
295 fn check_relationship_replace_properties_deferring_existence(
296 &self,
297 rel_id: RelationshipId,
298 properties: &Properties,
299 ) -> Result<(), String> {
300 if !self.has_active_constraints() {
301 return Ok(());
302 }
303 let catalog = self.constraint_catalog_read();
304 crate::memory::constraint_enforce::check_relationship_replace_properties_deferred(
305 &catalog, self, rel_id, properties,
306 )
307 .map_err(|e| format!("[{}] {e}", e.gql_status()))
308 }
309
310 fn check_node_add_label_deferring_existence(
311 &self,
312 node_id: NodeId,
313 label: &str,
314 ) -> Result<(), String> {
315 if !self.has_active_constraints() {
316 return Ok(());
317 }
318 let catalog = self.constraint_catalog_read();
319 crate::memory::constraint_enforce::check_node_add_label_deferred(
320 &catalog, self, node_id, label,
321 )
322 .map_err(|e| format!("[{}] {e}", e.gql_status()))
323 }
324
325 fn graph_stats(&self) -> GraphStats {
326 InMemoryGraph::graph_stats(self)
327 }
328
329 fn plan_signature(&self) -> u64 {
330 InMemoryGraph::plan_signature(self)
331 }
332
333 fn node_text_candidates(
334 &self,
335 label: &str,
336 property: &str,
337 query: &str,
338 ) -> Option<Vec<NodeId>> {
339 let registry = self.text_indexes_read(crate::StoredIndexEntity::Node);
340 let candidates = registry.candidates(label, property, query)?;
341 Some(candidates.into_iter().collect())
342 }
343
344 fn node_range_candidates(
345 &self,
346 label: &str,
347 property: &str,
348 lo: Option<&PropertyValue>,
349 hi: Option<&PropertyValue>,
350 ) -> Option<Vec<NodeId>> {
351 let registry = self.sorted_indexes_read(crate::StoredIndexEntity::Node);
352 let candidates = registry.range_candidates(label, property, lo, hi)?;
356 Some(candidates.into_iter().collect())
357 }
358
359 fn node_range_other_temporal_kind_ids(
360 &self,
361 label: &str,
362 property: &str,
363 like: &PropertyValue,
364 ) -> Option<Vec<NodeId>> {
365 self.sorted_indexes_read(crate::StoredIndexEntity::Node)
366 .other_temporal_kind_ids(label, property, like)
367 }
368
369 fn node_range_ordered_chunk(
370 &self,
371 label: &str,
372 property: &str,
373 lo: Option<&PropertyValue>,
374 hi: Option<&PropertyValue>,
375 descending: bool,
376 after: Option<(&PropertyValue, NodeId)>,
377 max: usize,
378 ) -> Option<Vec<NodeId>> {
379 self.sorted_indexes_read(crate::StoredIndexEntity::Node)
380 .ordered_chunk(label, property, lo, hi, descending, after, max)
381 }
382
383 fn node_list_element_candidates(
384 &self,
385 label: &str,
386 property: &str,
387 element: &PropertyValue,
388 ) -> Option<Vec<NodeId>> {
389 self.sorted_indexes_read(crate::StoredIndexEntity::Node)
390 .element_candidates(label, property, element)
391 }
392
393 fn relationship_list_element_candidates(
394 &self,
395 rel_type: &str,
396 property: &str,
397 element: &PropertyValue,
398 ) -> Option<Vec<RelationshipId>> {
399 self.sorted_indexes_read(crate::StoredIndexEntity::Relationship)
400 .element_candidates(rel_type, property, element)
401 }
402
403 fn node_point_within_bbox(
404 &self,
405 label: &str,
406 property: &str,
407 ll: (f64, f64),
408 ur: (f64, f64),
409 ) -> Option<Vec<NodeId>> {
410 let registry = self.point_indexes_read(crate::StoredIndexEntity::Node);
411 let candidates = registry.within_bbox(label, property, ll, ur)?;
412 Some(candidates.into_iter().collect())
413 }
414
415 fn node_point_within_distance(
416 &self,
417 label: &str,
418 property: &str,
419 center: (f64, f64),
420 max_distance: f64,
421 ) -> Option<Vec<NodeId>> {
422 let registry = self.point_indexes_read(crate::StoredIndexEntity::Node);
423 let candidates = registry.within_distance(label, property, center, max_distance)?;
424 Some(candidates.into_iter().collect())
425 }
426
427 fn relationship_text_candidates(
428 &self,
429 rel_type: &str,
430 property: &str,
431 query: &str,
432 ) -> Option<Vec<RelationshipId>> {
433 let registry = self.text_indexes_read(crate::StoredIndexEntity::Relationship);
434 let candidates = registry.candidates(rel_type, property, query)?;
435 Some(candidates.into_iter().collect())
436 }
437
438 fn relationship_range_candidates(
439 &self,
440 rel_type: &str,
441 property: &str,
442 lo: Option<&PropertyValue>,
443 hi: Option<&PropertyValue>,
444 ) -> Option<Vec<RelationshipId>> {
445 let registry = self.sorted_indexes_read(crate::StoredIndexEntity::Relationship);
446 let candidates = registry.range_candidates(rel_type, property, lo, hi)?;
447 Some(candidates.into_iter().collect())
448 }
449
450 fn relationship_range_other_temporal_kind_ids(
451 &self,
452 rel_type: &str,
453 property: &str,
454 like: &PropertyValue,
455 ) -> Option<Vec<RelationshipId>> {
456 self.sorted_indexes_read(crate::StoredIndexEntity::Relationship)
457 .other_temporal_kind_ids(rel_type, property, like)
458 }
459
460 fn relationship_point_within_bbox(
461 &self,
462 rel_type: &str,
463 property: &str,
464 ll: (f64, f64),
465 ur: (f64, f64),
466 ) -> Option<Vec<RelationshipId>> {
467 let registry = self.point_indexes_read(crate::StoredIndexEntity::Relationship);
468 let candidates = registry.within_bbox(rel_type, property, ll, ur)?;
469 Some(candidates.into_iter().collect())
470 }
471
472 fn relationship_point_within_distance(
473 &self,
474 rel_type: &str,
475 property: &str,
476 center: (f64, f64),
477 max_distance: f64,
478 ) -> Option<Vec<RelationshipId>> {
479 let registry = self.point_indexes_read(crate::StoredIndexEntity::Relationship);
480 let candidates = registry.within_distance(rel_type, property, center, max_distance)?;
481 Some(candidates.into_iter().collect())
482 }
483
484 fn contains_node(&self, id: NodeId) -> bool {
485 self.has_node_at(id)
486 }
487
488 fn node(&self, id: NodeId) -> Option<NodeRecord> {
489 self.node_at(id).map(|r| r.to_record())
490 }
491
492 fn all_node_ids(&self) -> Vec<NodeId> {
493 self.iter_node_ids().collect()
494 }
495
496 fn node_ids_by_label(&self, label: &str) -> Vec<NodeId> {
497 match self.nodes_by_label.get(label) {
498 Some(ids) => ids.to_vec(),
499 None => Vec::new(),
500 }
501 }
502
503 fn scan_node_ids(
504 &self,
505 label: Option<&str>,
506 cursor: &mut u64,
507 max: usize,
508 out: &mut Vec<NodeId>,
509 ) -> bool {
510 let max = max.max(1);
511 match label {
512 Some(label) => {
513 let Some(ids) = self.nodes_by_label.get(label) else {
514 return false;
515 };
516 fill_page(ids.iter_from(*cursor), cursor, max, out)
518 }
519 None => {
520 let Ok(from) = usize::try_from(*cursor) else {
522 return false;
523 };
524 let slots = self.nodes.slots_from(from).map(|slot| slot as NodeId);
525 fill_page(slots, cursor, max, out)
526 }
527 }
528 }
529
530 fn contains_relationship(&self, id: RelationshipId) -> bool {
531 self.has_rel_at(id)
532 }
533
534 fn relationship(&self, id: RelationshipId) -> Option<RelationshipRecord> {
535 self.rel_at(id).map(|r| r.to_record())
536 }
537
538 fn all_rel_ids(&self) -> Vec<RelationshipId> {
539 self.iter_rel_ids().collect()
540 }
541
542 fn rel_ids_by_type(&self, rel_type: &str) -> Vec<RelationshipId> {
543 match self.relationships_by_type.get(rel_type) {
544 Some(ids) => ids.to_vec(),
545 None => Vec::new(),
546 }
547 }
548
549 fn relationship_endpoints(&self, id: RelationshipId) -> Option<(NodeId, NodeId)> {
550 self.rel_endpoints_at(id)
551 }
552
553 fn expand_ids(
554 &self,
555 node_id: NodeId,
556 direction: Direction,
557 types: &[String],
558 ) -> Vec<(RelationshipId, NodeId)> {
559 if !self.has_node_at(node_id) {
560 return Vec::new();
561 }
562
563 let mut out: Vec<(RelationshipId, NodeId)> = Vec::new();
564 let _ = self.try_for_each_adjacent_id_unchecked(
565 node_id,
566 direction,
567 types,
568 |rel_id, other_id| {
569 out.push((rel_id, other_id));
570 Ok::<(), ()>(())
571 },
572 );
573 out
574 }
575
576 fn try_for_each_expand_id<F, E>(
577 &self,
578 node_id: NodeId,
579 direction: Direction,
580 types: &[String],
581 visit: F,
582 ) -> Result<(), E>
583 where
584 F: FnMut(RelationshipId, NodeId) -> Result<(), E>,
585 Self: Sized,
586 {
587 self.try_for_each_adjacent_id(node_id, direction, types, visit)
588 }
589
590 fn all_labels(&self) -> Vec<String> {
591 self.nodes_by_label.keys().map(|k| k.to_string()).collect()
592 }
593
594 fn all_relationship_types(&self) -> Vec<String> {
595 self.relationships_by_type
596 .keys()
597 .map(|k| k.to_string())
598 .collect()
599 }
600
601 fn with_node<F, R>(&self, id: NodeId, f: F) -> Option<R>
604 where
605 F: FnOnce(NodeRef<'_>) -> R,
606 Self: Sized,
607 {
608 self.node_at(id).map(f)
609 }
610
611 fn with_relationship<F, R>(&self, id: RelationshipId, f: F) -> Option<R>
612 where
613 F: FnOnce(RelRef<'_>) -> R,
614 Self: Sized,
615 {
616 self.rel_at(id).map(f)
617 }
618
619 fn has_node(&self, id: NodeId) -> bool {
622 self.has_node_at(id)
623 }
624
625 fn has_relationship(&self, id: RelationshipId) -> bool {
626 self.has_rel_at(id)
627 }
628
629 fn node_count(&self) -> usize {
630 self.live_node_count
631 }
632
633 fn relationship_count(&self) -> usize {
634 self.live_rel_count
635 }
636
637 fn node_count_by_label(&self, label: &str) -> usize {
638 self.nodes_by_label.get(label).map_or(0, |ids| ids.len())
639 }
640
641 fn all_nodes(&self) -> Vec<NodeRecord> {
644 self.iter_node_refs().map(|r| r.to_record()).collect()
645 }
646
647 fn nodes_by_label(&self, label: &str) -> Vec<NodeRecord> {
648 self.nodes_by_label
649 .get(label)
650 .into_iter()
651 .flat_map(|ids| ids.iter())
652 .filter_map(|id| self.node_at(id).map(|r| r.to_record()))
653 .collect()
654 }
655
656 fn all_relationships(&self) -> Vec<RelationshipRecord> {
657 self.iter_rel_refs().map(|r| r.to_record()).collect()
658 }
659
660 fn relationships_by_type(&self, rel_type: &str) -> Vec<RelationshipRecord> {
661 self.relationships_by_type
662 .get(rel_type)
663 .into_iter()
664 .flat_map(|ids| ids.iter())
665 .filter_map(|id| self.rel_at(id).map(|r| r.to_record()))
666 .collect()
667 }
668
669 fn relationship_ids_of(&self, node_id: NodeId, direction: Direction) -> Vec<RelationshipId> {
670 self.relationship_ids_for_direction(node_id, direction)
671 }
672
673 fn outgoing_relationships(&self, node_id: NodeId) -> Vec<RelationshipRecord> {
674 self.outgoing_at(node_id)
675 .into_iter()
676 .flat_map(|adj| adj.iter())
677 .filter_map(|entry| self.rel_at(entry.rel).map(|r| r.to_record()))
678 .collect()
679 }
680
681 fn incoming_relationships(&self, node_id: NodeId) -> Vec<RelationshipRecord> {
682 self.incoming_at(node_id)
683 .into_iter()
684 .flat_map(|adj| adj.iter())
685 .filter_map(|entry| self.rel_at(entry.rel).map(|r| r.to_record()))
686 .collect()
687 }
688
689 fn relationships_of(&self, node_id: NodeId, direction: Direction) -> Vec<RelationshipRecord> {
690 let mut out = Vec::new();
691 let _ = self.try_for_each_expand_id(node_id, direction, &[], |rel_id, _| {
692 if let Some(rel) = self.rel_at(rel_id) {
693 out.push(rel.to_record());
694 }
695 Ok::<(), ()>(())
696 });
697 out
698 }
699
700 fn degree(&self, node_id: NodeId, direction: Direction) -> usize {
701 let out = || self.outgoing_at(node_id).map_or(0, |adj| adj.count());
703 match direction {
704 Direction::Right => out(),
705 Direction::Left => self.incoming_at(node_id).map_or(0, |adj| adj.count()),
706 Direction::Undirected => {
707 let incoming_non_self = self
708 .incoming_at(node_id)
709 .into_iter()
710 .flat_map(|adj| adj.iter())
711 .filter(|entry| entry.neighbour != node_id)
712 .count();
713 out() + incoming_non_self
714 }
715 }
716 }
717
718 fn expand(
719 &self,
720 node_id: NodeId,
721 direction: Direction,
722 types: &[String],
723 ) -> Vec<(RelationshipRecord, NodeRecord)> {
724 if !self.has_node_at(node_id) {
725 return Vec::new();
726 }
727
728 let mut out = Vec::new();
729 let _ = self.try_for_each_expand_id(node_id, direction, types, |rel_id, other_id| {
730 if let (Some(rel), Some(other)) = (self.rel_at(rel_id), self.node_at(other_id)) {
731 out.push((rel.to_record(), other.to_record()));
732 }
733 Ok::<(), ()>(())
734 });
735 out
736 }
737
738 fn neighbors(
739 &self,
740 node_id: NodeId,
741 direction: Direction,
742 types: &[String],
743 ) -> Vec<NodeRecord> {
744 let mut out = Vec::new();
745 let _ = self.try_for_each_expand_id(node_id, direction, types, |_, other_id| {
746 if let Some(node) = self.node_at(other_id) {
747 out.push(node.to_record());
748 }
749 Ok::<(), ()>(())
750 });
751 out
752 }
753
754 fn all_node_property_keys(&self) -> Vec<String> {
755 let mut keys = BTreeSet::new();
756 for node in self.iter_node_refs() {
757 for key in node.properties().keys() {
758 keys.insert(key.to_string());
759 }
760 }
761 keys.into_iter().collect()
762 }
763
764 fn all_relationship_property_keys(&self) -> Vec<String> {
767 let mut keys = BTreeSet::new();
768 for rel in self.iter_rel_refs() {
769 for key in rel.properties().keys() {
770 keys.insert(key.to_string());
771 }
772 }
773 keys.into_iter().collect()
774 }
775
776 fn label_property_keys(&self, label: &str) -> Vec<String> {
777 let mut keys = BTreeSet::new();
778
779 if let Some(ids) = self.nodes_by_label.get(label) {
780 for id in ids.iter() {
781 if let Some(node) = self.node_at(id) {
782 for key in node.properties().keys() {
783 keys.insert(key.to_string());
784 }
785 }
786 }
787 }
788
789 keys.into_iter().collect()
790 }
791
792 fn rel_type_property_keys(&self, rel_type: &str) -> Vec<String> {
793 let mut keys = BTreeSet::new();
794
795 if let Some(ids) = self.relationships_by_type.get(rel_type) {
796 for id in ids.iter() {
797 if let Some(rel) = self.rel_at(id) {
798 for key in rel.properties().keys() {
799 keys.insert(key.to_string());
800 }
801 }
802 }
803 }
804
805 keys.into_iter().collect()
806 }
807
808 fn find_nodes_by_property(
809 &self,
810 label: Option<&str>,
811 key: &str,
812 value: &PropertyValue,
813 ) -> Vec<NodeRecord>
814 where
815 Self: Sized,
816 {
817 if PropertyIndexKey::from_value(value).is_none() {
818 return self.scan_nodes_by_property(label, key, value);
819 }
820
821 if !self.try_ensure_node_property_index(key) {
822 return self.scan_nodes_by_property(label, key, value);
823 }
824 if label.is_none() {
825 self.ensure_any_scope_node_property_index(key);
826 }
827 let indexes = self.indexes_read();
828
829 match label {
830 Some(label) => {
831 let Some(ids) =
832 indexes
833 .node_properties
834 .scoped_ids_for(label, key, value, &self.node_values())
835 else {
836 return Vec::new();
837 };
838 ids.iter()
839 .filter_map(|id| self.node_at(id).map(|r| r.to_record()))
840 .collect()
841 }
842 None => indexes
843 .node_properties
844 .ids_for(key, value, &self.node_values())
845 .into_iter()
846 .flat_map(|ids| ids.iter())
847 .filter_map(|id| self.node_at(id).map(|r| r.to_record()))
848 .collect(),
849 }
850 }
851
852 fn find_node_ids_by_property(
853 &self,
854 label: Option<&str>,
855 key: &str,
856 value: &PropertyValue,
857 ) -> Vec<NodeId>
858 where
859 Self: Sized,
860 {
861 if PropertyIndexKey::from_value(value).is_none() {
862 return self.scan_node_ids_by_property(label, key, value);
863 }
864
865 if !self.try_ensure_node_property_index(key) {
866 return self.scan_node_ids_by_property(label, key, value);
867 }
868 if label.is_none() {
869 self.ensure_any_scope_node_property_index(key);
870 }
871 let indexes = self.indexes_read();
872
873 match label {
874 Some(label) => indexes
875 .node_properties
876 .scoped_ids_for(label, key, value, &self.node_values())
877 .map(|ids| ids.to_vec())
878 .unwrap_or_default(),
879 None => indexes
880 .node_properties
881 .ids_for(key, value, &self.node_values())
882 .map(|ids| ids.to_vec())
883 .unwrap_or_default(),
884 }
885 }
886 fn find_relationships_by_property(
889 &self,
890 rel_type: Option<&str>,
891 key: &str,
892 value: &PropertyValue,
893 ) -> Vec<RelationshipRecord>
894 where
895 Self: Sized,
896 {
897 if PropertyIndexKey::from_value(value).is_none() {
898 return self.scan_relationships_by_property(rel_type, key, value);
899 }
900
901 if !self.try_ensure_relationship_property_index(key) {
902 return self.scan_relationships_by_property(rel_type, key, value);
903 }
904 if rel_type.is_none() {
905 self.ensure_any_scope_relationship_property_index(key);
906 }
907 let indexes = self.indexes_read();
908
909 match rel_type {
910 Some(rel_type) => {
911 let Some(ids) = indexes.relationship_properties.scoped_ids_for(
912 rel_type,
913 key,
914 value,
915 &self.relationship_values(),
916 ) else {
917 return Vec::new();
918 };
919 ids.iter()
920 .filter_map(|id| self.rel_at(id).map(|r| r.to_record()))
921 .collect()
922 }
923 None => indexes
924 .relationship_properties
925 .ids_for(key, value, &self.relationship_values())
926 .into_iter()
927 .flat_map(|ids| ids.iter())
928 .filter_map(|id| self.rel_at(id).map(|r| r.to_record()))
929 .collect(),
930 }
931 }
932
933 fn find_relationship_ids_by_property(
934 &self,
935 rel_type: Option<&str>,
936 key: &str,
937 value: &PropertyValue,
938 ) -> Vec<RelationshipId>
939 where
940 Self: Sized,
941 {
942 if PropertyIndexKey::from_value(value).is_none() {
943 return self.scan_relationship_ids_by_property(rel_type, key, value);
944 }
945
946 if !self.try_ensure_relationship_property_index(key) {
947 return self.scan_relationship_ids_by_property(rel_type, key, value);
948 }
949 if rel_type.is_none() {
950 self.ensure_any_scope_relationship_property_index(key);
951 }
952 let indexes = self.indexes_read();
953
954 match rel_type {
955 Some(rel_type) => indexes
956 .relationship_properties
957 .scoped_ids_for(rel_type, key, value, &self.relationship_values())
958 .map(|ids| ids.to_vec())
959 .unwrap_or_default(),
960 None => indexes
961 .relationship_properties
962 .ids_for(key, value, &self.relationship_values())
963 .map(|ids| ids.to_vec())
964 .unwrap_or_default(),
965 }
966 }
967
968 fn node_exists_with_label_and_property(
969 &self,
970 label: &str,
971 key: &str,
972 value: &PropertyValue,
973 ) -> bool
974 where
975 Self: Sized,
976 {
977 if PropertyIndexKey::from_value(value).is_none() {
978 return self.any_node_by_property(label, key, value);
979 }
980
981 if !self.try_ensure_node_property_index(key) {
982 return self.any_node_by_property(label, key, value);
983 }
984 let indexes = self.indexes_read();
985 indexes
986 .node_properties
987 .scoped_ids_for(label, key, value, &self.node_values())
988 .map(|ids| !ids.is_empty())
989 .unwrap_or(false)
990 }
991
992 fn relationship_exists_with_type_and_property(
993 &self,
994 rel_type: &str,
995 key: &str,
996 value: &PropertyValue,
997 ) -> bool
998 where
999 Self: Sized,
1000 {
1001 if PropertyIndexKey::from_value(value).is_none() {
1002 return self.any_relationship_by_property(rel_type, key, value);
1003 }
1004
1005 if !self.try_ensure_relationship_property_index(key) {
1006 return self.any_relationship_by_property(rel_type, key, value);
1007 }
1008 let indexes = self.indexes_read();
1009 indexes
1010 .relationship_properties
1011 .scoped_ids_for(rel_type, key, value, &self.relationship_values())
1012 .map(|ids| !ids.is_empty())
1013 .unwrap_or(false)
1014 }
1015}
1016
1017impl InMemoryGraph {
1018 fn delete_relationship_deferring(
1022 &mut self,
1023 rel_id: RelationshipId,
1024 pending: Option<&mut PendingAdjRemovals>,
1025 ) -> bool {
1026 let applied = match self.take_rel(rel_id) {
1027 Some(rel) => {
1028 if let Some(sink) = &self.deleted_sink {
1029 sink.relationship_deleted(&rel);
1030 }
1031 self.on_relationship_deleted(&rel, pending);
1032 true
1033 }
1034 None => false,
1035 };
1036 if applied {
1037 self.emit(|| MutationEvent::DeleteRelationship { rel_id });
1038 }
1039 applied
1040 }
1041
1042 fn detach_delete_deferring(
1048 &mut self,
1049 node_id: NodeId,
1050 pending: &mut PendingAdjRemovals,
1051 ) -> bool {
1052 if !self.has_node_at(node_id) {
1053 return false;
1054 }
1055
1056 let rel_ids = self.incident_relationship_ids(node_id);
1057
1058 self.clear_adjacency(node_id);
1069 for rel_id in rel_ids {
1070 let _ = self.delete_relationship_deferring(rel_id, Some(pending));
1071 }
1072
1073 if self.delete_node(node_id) {
1074 self.emit(|| MutationEvent::DetachDeleteNode { node_id });
1075 true
1076 } else {
1077 false
1078 }
1079 }
1080}
1081
1082impl GraphStorageMut for InMemoryGraph {
1083 fn try_create_node(
1084 &mut self,
1085 labels: Vec<String>,
1086 properties: Properties,
1087 ) -> Option<NodeRecord> {
1088 let (id, idx) = self.try_reserve_next_node_slot()?;
1089 let labels = Self::normalize_labels(labels);
1090
1091 let node = NodeRecord {
1092 id,
1093 labels,
1094 properties,
1095 };
1096
1097 self.put_node_at_slot(idx, &node);
1098
1099 self.on_node_created(&node);
1100
1101 self.emit(|| MutationEvent::CreateNode {
1105 id,
1106 labels: node.labels.to_strings(),
1107 properties: node.properties.clone(),
1108 });
1109
1110 Some(node)
1111 }
1112
1113 fn create_relationship(
1114 &mut self,
1115 src: NodeId,
1116 dst: NodeId,
1117 rel_type: &str,
1118 properties: Properties,
1119 ) -> Option<RelationshipRecord> {
1120 if !self.has_node_at(src) || !self.has_node_at(dst) {
1121 return None;
1122 }
1123
1124 let trimmed = rel_type.trim();
1125 if trimmed.is_empty() {
1126 return None;
1127 }
1128
1129 let (id, idx) = self.try_reserve_next_rel_slot()?;
1130 let rel = RelationshipRecord {
1131 id,
1132 src,
1133 dst,
1134 rel_type: trimmed.into(),
1135 properties,
1136 };
1137
1138 self.put_rel_at_slot(idx, &rel);
1139 self.on_relationship_created(&rel);
1140
1141 self.emit(|| MutationEvent::CreateRelationship {
1142 id,
1143 src,
1144 dst,
1145 rel_type: rel.rel_type.to_string(),
1146 properties: rel.properties.clone(),
1147 });
1148
1149 Some(rel)
1150 }
1151
1152 fn set_node_property(&mut self, node_id: NodeId, key: String, value: PropertyValue) -> bool {
1153 let Some(old) = self.edit_node_property(node_id, &key, PropEdit::Set(&value)) else {
1154 return false;
1155 };
1156 self.on_node_property_set(node_id, &key, old.as_ref(), &value);
1157
1158 self.emit(|| MutationEvent::SetNodeProperty {
1159 node_id,
1160 key: key.clone(),
1161 value: value.clone(),
1162 });
1163
1164 true
1165 }
1166
1167 fn update_node_properties(
1168 &mut self,
1169 node_id: NodeId,
1170 edits: Vec<(String, Option<PropertyValue>)>,
1171 ) -> bool {
1172 let Some(olds) = self.edit_node_properties(node_id, &edits) else {
1173 return false;
1174 };
1175 let Some(labels) = self.node_at(node_id).map(|node| node.labels().to_owned()) else {
1176 return false;
1177 };
1178 for ((key, value), old) in edits.into_iter().zip(olds) {
1179 let Some(old) = old else { continue };
1181 match value {
1182 Some(value) => {
1183 self.on_labelled_node_property_set(
1184 &labels,
1185 node_id,
1186 &key,
1187 old.as_ref(),
1188 &value,
1189 );
1190 self.emit(|| MutationEvent::SetNodeProperty {
1191 node_id,
1192 key,
1193 value,
1194 });
1195 }
1196 None => {
1197 let old = old.expect("a remove that changed the record had a value");
1198 self.on_labelled_node_property_removed(&labels, node_id, &key, &old);
1199 self.emit(|| MutationEvent::RemoveNodeProperty { node_id, key });
1200 }
1201 }
1202 }
1203 true
1204 }
1205
1206 fn remove_node_property(&mut self, node_id: NodeId, key: &str) -> bool {
1207 let Some(removed) = self
1208 .edit_node_property(node_id, key, PropEdit::Remove)
1209 .flatten()
1210 else {
1211 return false;
1212 };
1213
1214 self.on_node_property_removed(node_id, key, &removed);
1215
1216 self.emit(|| MutationEvent::RemoveNodeProperty {
1217 node_id,
1218 key: key.to_string(),
1219 });
1220
1221 true
1222 }
1223
1224 fn add_node_label(&mut self, node_id: NodeId, label: &str) -> bool {
1225 let label = label.trim();
1226 if label.is_empty() {
1227 return false;
1228 }
1229
1230 let applied = match self.node_at(node_id) {
1231 Some(node) if node.has_label(label) => return false,
1232 Some(_) => self
1233 .update_node(node_id, |node| node.labels.push(label))
1234 .is_some(),
1235 None => false,
1236 };
1237 if applied {
1238 self.on_node_label_added(node_id, label);
1239 self.emit(|| MutationEvent::AddNodeLabel {
1240 node_id,
1241 label: label.to_string(),
1242 });
1243 }
1244 applied
1245 }
1246
1247 fn remove_node_label(&mut self, node_id: NodeId, label: &str) -> bool {
1248 let applied = self
1249 .node_at(node_id)
1250 .is_some_and(|node| node.has_label(label))
1251 && self
1252 .update_node(node_id, |node| node.labels.retain(|l| l != label))
1253 .is_some();
1254 if applied {
1255 self.on_node_label_removed(node_id, label);
1256 self.emit(|| MutationEvent::RemoveNodeLabel {
1257 node_id,
1258 label: label.to_string(),
1259 });
1260 }
1261 applied
1262 }
1263
1264 fn set_relationship_property(
1265 &mut self,
1266 rel_id: RelationshipId,
1267 key: String,
1268 value: PropertyValue,
1269 ) -> bool {
1270 let Some(old) = self.edit_rel_property(rel_id, &key, PropEdit::Set(&value)) else {
1271 return false;
1272 };
1273 self.on_relationship_property_set(rel_id, &key, old.as_ref(), &value);
1274
1275 self.emit(|| MutationEvent::SetRelationshipProperty {
1276 rel_id,
1277 key: key.clone(),
1278 value: value.clone(),
1279 });
1280
1281 true
1282 }
1283
1284 fn remove_relationship_property(&mut self, rel_id: RelationshipId, key: &str) -> bool {
1285 let Some(removed) = self
1286 .edit_rel_property(rel_id, key, PropEdit::Remove)
1287 .flatten()
1288 else {
1289 return false;
1290 };
1291
1292 self.on_relationship_property_removed(rel_id, key, &removed);
1293
1294 self.emit(|| MutationEvent::RemoveRelationshipProperty {
1295 rel_id,
1296 key: key.to_string(),
1297 });
1298
1299 true
1300 }
1301
1302 fn delete_relationship(&mut self, rel_id: RelationshipId) -> bool {
1303 self.delete_relationship_deferring(rel_id, None)
1304 }
1305
1306 fn delete_relationships(&mut self, rel_ids: &[RelationshipId]) -> usize {
1307 let mut pending = PendingAdjRemovals::new();
1308 let deleted = rel_ids
1309 .iter()
1310 .filter(|&&rel_id| self.delete_relationship_deferring(rel_id, Some(&mut pending)))
1311 .count();
1312 self.flush_adjacency_removals(&mut pending);
1313 deleted
1314 }
1315
1316 fn delete_node(&mut self, node_id: NodeId) -> bool {
1317 if !self.has_node_at(node_id) {
1318 return false;
1319 }
1320
1321 if self.has_incident_relationships(node_id) {
1322 return false;
1323 }
1324
1325 let node = match self.take_node(node_id) {
1326 Some(node) => node,
1327 None => return false,
1328 };
1329
1330 if let Some(sink) = &self.deleted_sink {
1331 sink.node_deleted(&node);
1332 }
1333 self.on_node_deleted(&node);
1334
1335 self.emit(|| MutationEvent::DeleteNode { node_id });
1338
1339 true
1340 }
1341
1342 fn detach_delete_node(&mut self, node_id: NodeId) -> bool {
1343 self.detach_delete_nodes(&[node_id]) == 1
1344 }
1345
1346 fn detach_delete_nodes(&mut self, node_ids: &[NodeId]) -> usize {
1347 let mut pending = PendingAdjRemovals::new();
1348 let deleted = node_ids
1349 .iter()
1350 .filter(|&&node_id| self.detach_delete_deferring(node_id, &mut pending))
1351 .count();
1352 self.flush_adjacency_removals(&mut pending);
1353 deleted
1354 }
1355
1356 fn clear(&mut self) {
1357 let recorder = self.recorder.take();
1361 let deleted_sink = self.deleted_sink.take();
1362 *self = Self::default();
1363 self.recorder = recorder;
1364 self.deleted_sink = deleted_sink;
1365 self.emit(|| MutationEvent::Clear);
1366 }
1367
1368 fn create_index(
1369 &mut self,
1370 request: IndexRequest,
1371 if_not_exists: bool,
1372 ) -> Result<CreateIndexOutcome, CreateIndexError> {
1373 self.register_index(request, if_not_exists)
1379 }
1380
1381 fn drop_index(
1382 &mut self,
1383 name: &str,
1384 if_exists: bool,
1385 ) -> Result<DropIndexOutcome, DropIndexError> {
1386 self.drop_named_index(name, if_exists)
1387 }
1388
1389 fn create_constraint(
1390 &mut self,
1391 request: ConstraintRequest,
1392 if_not_exists: bool,
1393 ) -> Result<CreateConstraintOutcome, CreateConstraintError> {
1394 self.register_constraint(request, if_not_exists)
1395 }
1396
1397 fn drop_constraint(
1398 &mut self,
1399 name: &str,
1400 if_exists: bool,
1401 ) -> Result<DropConstraintOutcome, DropConstraintError> {
1402 self.drop_named_constraint(name, if_exists)
1403 }
1404}
1405
1406#[inline]
1409fn fill_page(
1410 mut ids: impl Iterator<Item = NodeId>,
1411 cursor: &mut u64,
1412 max: usize,
1413 out: &mut Vec<NodeId>,
1414) -> bool {
1415 for id in ids.by_ref().take(max) {
1416 out.push(id);
1417 *cursor = id.saturating_add(1);
1418 }
1419 ids.next().is_some()
1420}