1use crate::store::{
18 AdjacencyReadMemory, GraphExecutionRead, GraphExecutionWrite, PrunedNodeScan,
19 PrunedRelationshipScan, ScanControl, SourceScanCandidateRow, SourceScanCandidateVisit,
20 SourceScanReadLimits,
21};
22use crate::QueryMemoryLease;
23use hawdb_core::error::Result;
24use hawdb_core::schema::Catalog;
25use hawdb_core::{LabelId, RelTypeId};
26use hawdb_plan_cypher::NodeProjectionAccess;
27use hawdb_storage::store::{GraphScanControl, GraphStore};
28use hawdb_storage::{
29 adjacency::{AdjacencyDirection, OrderedAdjacencyEntry},
30 mutation::{GraphMutation, MutationLimits, MutationSummary, NodeSetAssignment, PropertyFilter},
31 NodeId, NodeRecord, ProjectedNodeRecord, RelId, RelRecord,
32};
33use std::collections::BTreeSet;
34
35fn to_store_control(control: ScanControl) -> GraphScanControl {
36 match control {
37 ScanControl::Continue => GraphScanControl::Continue,
38 ScanControl::Stop => GraphScanControl::Stop,
39 }
40}
41
42fn to_execution_control(control: GraphScanControl) -> ScanControl {
43 match control {
44 GraphScanControl::Continue => ScanControl::Continue,
45 GraphScanControl::Stop => ScanControl::Stop,
46 }
47}
48
49fn adapt_node_consumer(
50 consumer: &mut dyn FnMut(NodeRecord) -> Result<ScanControl>,
51 visit: impl FnOnce(&mut dyn FnMut(NodeRecord) -> GraphScanControl) -> Result<GraphScanControl>,
52) -> Result<ScanControl> {
53 let mut consumer_error = None;
54 let control = visit(&mut |node| match consumer(node) {
55 Ok(control) => to_store_control(control),
56 Err(error) => {
57 consumer_error = Some(error);
58 GraphScanControl::Stop
59 }
60 })?;
61 match consumer_error {
62 Some(error) => Err(error),
63 None => Ok(to_execution_control(control)),
64 }
65}
66
67impl hawdb_storage::read_view::GraphReadAllocation for QueryMemoryLease {
68 fn bytes(&self) -> usize {
69 self.bytes()
70 }
71 fn grow(&mut self, bytes: usize) -> hawdb_core::Result<()> {
72 QueryMemoryLease::grow(self, bytes)
73 }
74}
75
76impl GraphExecutionRead for GraphStore {
77 fn file_descriptor_context(&self) -> Option<hawdb_storage::file_descriptors::FileOpenContext> {
78 GraphStore::file_descriptor_context(self)
79 }
80
81 fn is_out_of_core(&self) -> bool {
82 GraphStore::is_out_of_core(self)
83 }
84
85 fn projected_node_owned_admitted(
86 &self,
87 id: NodeId,
88 required_properties: &BTreeSet<String>,
89 admit: &mut dyn FnMut(usize) -> Result<()>,
90 ) -> Result<Option<ProjectedNodeRecord>> {
91 GraphStore::projected_node_owned_admitted(self, id, required_properties, admit)
92 }
93
94 fn node_owned(&self, id: NodeId) -> Result<Option<NodeRecord>> {
95 GraphStore::node_owned(self, id)
96 }
97
98 fn node_with_allocation(
99 &self,
100 id: NodeId,
101 label_ids: Option<&[LabelId]>,
102 admit: &mut hawdb_storage::read_view::ControlledGraphReadAllocator<'_>,
103 ) -> Result<hawdb_storage::read_view::AdmittedNodeRead> {
104 GraphStore::node_with_allocation(self, id, label_ids, admit)
105 }
106
107 fn relationship_property_endpoint_candidates(
108 &self,
109 rel_type: RelTypeId,
110 properties: &std::collections::BTreeMap<String, hawdb_core::Value>,
111 endpoints: hawdb_storage::store::RelationshipEndpoints,
112 max_relationships: usize,
113 admit: &mut dyn FnMut(
114 usize,
115 ) -> Result<
116 Option<Box<dyn hawdb_storage::read_view::GraphReadAllocation>>,
117 >,
118 ) -> Result<Option<hawdb_storage::store::EndpointCandidates>> {
119 GraphStore::relationship_property_endpoint_candidates(
120 self,
121 rel_type,
122 properties,
123 endpoints,
124 max_relationships,
125 admit,
126 )
127 }
128
129 fn relationship_with_allocation(
130 &self,
131 id: RelId,
132 admit: &mut hawdb_storage::read_view::ControlledGraphReadAllocator<'_>,
133 ) -> Result<hawdb_storage::read_view::AdmittedRelationshipRead> {
134 GraphStore::relationship_with_allocation(self, id, admit)
135 }
136
137 fn scan_nodes_borrowed<'a>(
138 &'a self,
139 label_id: Option<LabelId>,
140 ) -> Box<dyn Iterator<Item = &'a NodeRecord> + 'a> {
141 Box::new(GraphStore::scan_nodes(self, label_id))
142 }
143
144 fn scan_indexed_nodes_borrowed<'a>(
145 &'a self,
146 label_id: LabelId,
147 property: &str,
148 value: &hawdb_core::Value,
149 ) -> Option<Box<dyn Iterator<Item = &'a NodeRecord> + 'a>> {
150 Some(Box::new(GraphStore::seek_nodes_by_property(
151 self, label_id, property, value,
152 )))
153 }
154
155 fn node_count_for_label(&self, label_id: Option<LabelId>) -> usize {
156 GraphStore::node_count_for_label(self, label_id)
157 }
158
159 fn visit_indexed_projected_nodes_by_property_admitted(
160 &self,
161 label_id: LabelId,
162 property: &str,
163 values: &[hawdb_core::Value],
164 properties: &BTreeSet<String>,
165 admit: &mut hawdb_storage::read_view::GraphReadAllocator<'_>,
166 consumer: &mut dyn FnMut(ProjectedNodeRecord) -> Result<ScanControl>,
167 ) -> Result<Option<ScanControl>> {
168 GraphStore::visit_indexed_projected_nodes_by_property_admitted(
169 self,
170 label_id,
171 property,
172 values,
173 properties,
174 admit,
175 &mut |node| consumer(node).map(to_store_control),
176 )
177 .map(|control| control.map(to_execution_control))
178 }
179
180 fn relationship_count_for_type(&self, rel_type: Option<RelTypeId>) -> usize {
181 GraphStore::relationship_count_for_type(self, rel_type)
182 }
183
184 fn visit_nodes_owned(
185 &self,
186 label_id: Option<LabelId>,
187 consumer: &mut dyn FnMut(NodeRecord) -> Result<ScanControl>,
188 ) -> Result<ScanControl> {
189 GraphStore::try_visit_nodes_owned(self, label_id, |node| {
190 consumer(node).map(to_store_control)
191 })
192 .map(to_execution_control)
193 }
194
195 fn visit_relationships_with_allocation(
196 &self,
197 rel_type: Option<RelTypeId>,
198 admit: &mut hawdb_storage::read_view::ControlledGraphReadAllocator<'_>,
199 consumer: &mut dyn FnMut(
200 hawdb_storage::read_view::AdmittedRelationshipRecord,
201 ) -> Result<ScanControl>,
202 ) -> Result<ScanControl> {
203 GraphStore::visit_relationships_with_allocation(self, rel_type, admit, &mut |record| {
204 consumer(record).map(to_store_control)
205 })
206 .map(to_execution_control)
207 }
208
209 fn visit_nodes_with_allocation(
210 &self,
211 label_id: Option<LabelId>,
212 admit: &mut hawdb_storage::read_view::ControlledGraphReadAllocator<'_>,
213 consumer: &mut dyn FnMut(
214 hawdb_storage::read_view::AdmittedNodeRecord,
215 ) -> Result<ScanControl>,
216 ) -> Result<ScanControl> {
217 GraphStore::visit_nodes_with_allocation(self, label_id, admit, &mut |node| {
218 consumer(node).map(to_store_control)
219 })
220 .map(to_execution_control)
221 }
222
223 fn visit_nodes_by_access_with_allocation(
224 &self,
225 label_id: LabelId,
226 access: &NodeProjectionAccess,
227 admit: &mut hawdb_storage::read_view::ControlledGraphReadAllocator<'_>,
228 consumer: &mut dyn FnMut(
229 hawdb_storage::read_view::AdmittedNodeRecord,
230 ) -> Result<ScanControl>,
231 ) -> Result<ScanControl> {
232 GraphStore::visit_nodes_by_access_with_allocation(
233 self,
234 label_id,
235 access,
236 admit,
237 &mut |node| consumer(node).map(to_store_control),
238 )
239 .map(to_execution_control)
240 }
241
242 fn visit_projected_nodes_admitted(
243 &self,
244 label_id: Option<LabelId>,
245 properties: &BTreeSet<String>,
246 admit: &mut hawdb_storage::read_view::GraphReadAllocator<'_>,
247 consumer: &mut dyn FnMut(ProjectedNodeRecord) -> Result<ScanControl>,
248 ) -> Result<ScanControl> {
249 GraphStore::visit_projected_nodes_admitted(self, label_id, properties, admit, &mut |node| {
250 consumer(node).map(to_store_control)
251 })
252 .map(to_execution_control)
253 }
254
255 fn visit_projected_nodes_with_allocation(
256 &self,
257 label_id: Option<LabelId>,
258 properties: &BTreeSet<String>,
259 admit: &mut hawdb_storage::read_view::ControlledGraphReadAllocator<'_>,
260 consumer: &mut dyn FnMut(
261 hawdb_storage::read_view::AdmittedProjectedNode,
262 ) -> Result<ScanControl>,
263 ) -> Result<ScanControl> {
264 GraphStore::visit_projected_nodes_with_allocation(
265 self,
266 label_id,
267 properties,
268 admit,
269 &mut |node| consumer(node).map(to_store_control),
270 )
271 .map(to_execution_control)
272 }
273
274 fn visit_projected_nodes_by_access_admitted(
275 &self,
276 label_id: LabelId,
277 access: &NodeProjectionAccess,
278 properties: &BTreeSet<String>,
279 admit: &mut hawdb_storage::read_view::GraphReadAllocator<'_>,
280 consumer: &mut dyn FnMut(ProjectedNodeRecord) -> Result<ScanControl>,
281 ) -> Result<ScanControl> {
282 GraphStore::visit_projected_nodes_by_access_admitted(
283 self,
284 label_id,
285 access,
286 properties,
287 admit,
288 &mut |node| consumer(node).map(to_store_control),
289 )
290 .map(to_execution_control)
291 }
292
293 fn visit_projected_nodes_by_property_admitted(
294 &self,
295 label_id: LabelId,
296 property: &str,
297 values: &[hawdb_core::Value],
298 properties: &BTreeSet<String>,
299 admit: &mut hawdb_storage::read_view::GraphReadAllocator<'_>,
300 consumer: &mut dyn FnMut(ProjectedNodeRecord) -> Result<ScanControl>,
301 ) -> Result<ScanControl> {
302 GraphStore::visit_projected_nodes_by_property_admitted(
303 self,
304 label_id,
305 property,
306 values,
307 properties,
308 admit,
309 &mut |node| consumer(node).map(to_store_control),
310 )
311 .map(to_execution_control)
312 }
313
314 fn visit_projected_nodes_owned(
315 &self,
316 label_id: Option<LabelId>,
317 required_properties: &BTreeSet<String>,
318 consumer: &mut dyn FnMut(ProjectedNodeRecord) -> Result<ScanControl>,
319 ) -> Result<ScanControl> {
320 let mut consumer_error = None;
321 let control =
322 GraphStore::visit_projected_nodes_owned(self, label_id, required_properties, |node| {
323 match consumer(node) {
324 Ok(control) => to_store_control(control),
325 Err(error) => {
326 consumer_error = Some(error);
327 GraphScanControl::Stop
328 }
329 }
330 })?;
331 match consumer_error {
332 Some(error) => Err(error),
333 None => Ok(to_execution_control(control)),
334 }
335 }
336
337 fn visit_projected_nodes_by_access_owned(
338 &self,
339 label_id: LabelId,
340 access: &NodeProjectionAccess,
341 required_properties: &BTreeSet<String>,
342 consumer: &mut dyn FnMut(ProjectedNodeRecord) -> Result<ScanControl>,
343 ) -> Result<ScanControl> {
344 let mut consumer_error = None;
345 let control = GraphStore::visit_projected_nodes_by_access_owned(
346 self,
347 label_id,
348 access,
349 required_properties,
350 |node| match consumer(node) {
351 Ok(control) => to_store_control(control),
352 Err(error) => {
353 consumer_error = Some(error);
354 GraphScanControl::Stop
355 }
356 },
357 )?;
358 match consumer_error {
359 Some(error) => Err(error),
360 None => Ok(to_execution_control(control)),
361 }
362 }
363
364 fn visit_projected_nodes_by_property_owned(
365 &self,
366 label_id: LabelId,
367 property: &str,
368 values: &[hawdb_core::Value],
369 required_properties: &BTreeSet<String>,
370 consumer: &mut dyn FnMut(ProjectedNodeRecord) -> Result<ScanControl>,
371 ) -> Result<ScanControl> {
372 let mut consumer_error = None;
373 let control = GraphStore::visit_projected_nodes_by_property_owned(
374 self,
375 label_id,
376 property,
377 values,
378 required_properties,
379 |node| match consumer(node) {
380 Ok(control) => to_store_control(control),
381 Err(error) => {
382 consumer_error = Some(error);
383 GraphScanControl::Stop
384 }
385 },
386 )?;
387 match consumer_error {
388 Some(error) => Err(error),
389 None => Ok(to_execution_control(control)),
390 }
391 }
392
393 fn visit_nodes_by_property_owned(
394 &self,
395 label_id: LabelId,
396 property: &str,
397 values: &[hawdb_core::Value],
398 consumer: &mut dyn FnMut(NodeRecord) -> Result<ScanControl>,
399 ) -> Result<ScanControl> {
400 let mut consumer_error = None;
401 let control =
402 GraphStore::visit_nodes_by_property_owned(self, label_id, property, values, |node| {
403 match consumer(node) {
404 Ok(control) => to_store_control(control),
405 Err(error) => {
406 consumer_error = Some(error);
407 GraphScanControl::Stop
408 }
409 }
410 })?;
411 match consumer_error {
412 Some(error) => Err(error),
413 None => Ok(to_execution_control(control)),
414 }
415 }
416
417 fn visit_nodes_by_composite_property_owned(
418 &self,
419 label_id: LabelId,
420 predicates: &[(String, hawdb_core::Value)],
421 consumer: &mut dyn FnMut(NodeRecord) -> Result<ScanControl>,
422 ) -> Result<ScanControl> {
423 adapt_node_consumer(consumer, |consumer| {
424 GraphStore::visit_nodes_by_composite_property_owned(
425 self, label_id, predicates, consumer,
426 )
427 })
428 }
429
430 fn visit_nodes_by_composite_range_owned(
431 &self,
432 label_id: LabelId,
433 seek: &hawdb_plan_cypher::CompositeRangeSeek,
434 consumer: &mut dyn FnMut(NodeRecord) -> Result<ScanControl>,
435 ) -> Result<ScanControl> {
436 adapt_node_consumer(consumer, |consumer| {
437 GraphStore::visit_nodes_by_composite_range_owned(self, label_id, seek, consumer)
438 })
439 }
440
441 fn visit_nodes_by_property_range_owned(
442 &self,
443 label_id: LabelId,
444 property: &str,
445 lower: Option<&(hawdb_core::Value, bool)>,
446 upper: Option<&(hawdb_core::Value, bool)>,
447 consumer: &mut dyn FnMut(NodeRecord) -> Result<ScanControl>,
448 ) -> Result<ScanControl> {
449 adapt_node_consumer(consumer, |consumer| {
450 GraphStore::visit_nodes_by_property_range_owned(
451 self, label_id, property, lower, upper, consumer,
452 )
453 })
454 }
455
456 fn visit_nodes_by_full_text_property_owned(
457 &self,
458 label_id: LabelId,
459 property: &str,
460 query: &str,
461 consumer: &mut dyn FnMut(NodeRecord) -> Result<ScanControl>,
462 ) -> Result<ScanControl> {
463 adapt_node_consumer(consumer, |consumer| {
464 GraphStore::visit_nodes_by_full_text_property_owned(
465 self, label_id, property, query, consumer,
466 )
467 })
468 }
469
470 fn projected_graph_definition(
471 &self,
472 name: &str,
473 ) -> Option<hawdb_storage::projection::ProjectedGraphDefinition> {
474 GraphStore::projected_graph_definition(self, name).cloned()
475 }
476
477 fn visit_source_scan_candidates(
478 &self,
479 predicate: &hawdb_storage::scan::ScanPredicate,
480 limits: SourceScanReadLimits,
481 task_context: Option<&hawdb_core::RuntimeTaskContext>,
482 consumer: &mut dyn FnMut(SourceScanCandidateRow) -> Result<ScanControl>,
483 ) -> Result<SourceScanCandidateVisit> {
484 let mut consumer_error = None;
485 let visit = GraphStore::visit_published_source_scan_candidates_bounded(
486 self,
487 predicate,
488 hawdb_storage::store::SourceScanCandidateLimits::bounded(
489 limits.io_depth,
490 limits.max_coalesced_bytes,
491 limits.max_wave_bytes,
492 limits.max_live_candidate_bytes,
493 ),
494 task_context,
495 &mut |row| match consumer(SourceScanCandidateRow {
496 node_id: row.node_id,
497 properties: row.properties,
498 }) {
499 Ok(control) => Ok(to_store_control(control)),
500 Err(error) => {
501 consumer_error = Some(error);
502 Ok(hawdb_storage::store::GraphScanControl::Stop)
503 }
504 },
505 )?;
506 if let Some(error) = consumer_error {
507 return Err(error);
508 }
509 Ok(match visit {
510 hawdb_storage::store::SourceScanCandidateVisit::Rows {
511 graph_epoch,
512 skipped_segment_count,
513 report,
514 candidate_count,
515 } => SourceScanCandidateVisit::Rows {
516 graph_epoch,
517 skipped_segment_count,
518 report,
519 candidate_count,
520 },
521 hawdb_storage::store::SourceScanCandidateVisit::Fallback(reason) => {
522 SourceScanCandidateVisit::Fallback(reason)
523 }
524 })
525 }
526
527 fn visit_adjacent_relationships_owned(
528 &self,
529 node_id: NodeId,
530 rel_type: Option<RelTypeId>,
531 direction: AdjacencyDirection,
532 consumer: &mut dyn FnMut(RelRecord) -> Result<ScanControl>,
533 ) -> Result<ScanControl> {
534 GraphStore::try_visit_adjacent_relationships_owned(
535 self,
536 node_id,
537 rel_type,
538 direction,
539 |relationship| consumer(relationship).map(to_store_control),
540 )
541 .map(to_execution_control)
542 }
543
544 fn visit_ordered_adjacent_relationships_owned(
545 &self,
546 node_id: NodeId,
547 rel_type: Option<RelTypeId>,
548 direction: AdjacencyDirection,
549 memory: AdjacencyReadMemory<'_>,
550 consumer: &mut dyn FnMut(RelRecord) -> Result<ScanControl>,
551 ) -> Result<ScanControl> {
552 GraphExecutionRead::visit_ordered_adjacent_relationships_with_allocation(
553 self,
554 node_id,
555 rel_type,
556 direction,
557 memory,
558 &mut hawdb_storage::read_view::ControlledGraphReadAllocator::new(
559 &mut |bytes| memory.admit_node(bytes, 0, None).map(Some),
560 None,
561 ),
562 &mut |relationship| {
563 let (relationship, _allocation) = relationship.into_parts();
564 consumer(relationship)
565 },
566 )
567 }
568
569 fn visit_ordered_adjacent_relationships_with_allocation(
570 &self,
571 node_id: NodeId,
572 rel_type: Option<RelTypeId>,
573 direction: AdjacencyDirection,
574 memory: AdjacencyReadMemory<'_>,
575 admit: &mut hawdb_storage::read_view::ControlledGraphReadAllocator<'_>,
576 consumer: &mut dyn FnMut(
577 hawdb_storage::read_view::AdmittedRelationshipRecord,
578 ) -> Result<ScanControl>,
579 ) -> Result<ScanControl> {
580 GraphStore::visit_ordered_adjacent_relationships_with_allocation(
581 self,
582 node_id,
583 rel_type,
584 direction,
585 memory.budget_bytes,
586 admit,
587 |relationship| consumer(relationship).map(to_store_control),
588 )
589 .map(to_execution_control)
590 }
591
592 fn visit_ordered_projected_relationships_with_allocation(
593 &self,
594 adjacency: (NodeId, Option<RelTypeId>, AdjacencyDirection),
595 required_properties: &BTreeSet<String>,
596 memory: AdjacencyReadMemory<'_>,
597 admit: &mut hawdb_storage::read_view::ControlledGraphReadAllocator<'_>,
598 consumer: &mut dyn FnMut(
599 hawdb_storage::read_view::AdmittedRelationshipRecord,
600 ) -> Result<ScanControl>,
601 ) -> Result<ScanControl> {
602 GraphStore::visit_ordered_projected_relationships_with_allocation(
603 self,
604 adjacency,
605 required_properties,
606 memory.budget_bytes,
607 admit,
608 |relationship| consumer(relationship).map(to_store_control),
609 )
610 .map(to_execution_control)
611 }
612
613 fn visit_ordered_adjacency_entries_with_allocation(
614 &self,
615 adjacency: (NodeId, Option<RelTypeId>, AdjacencyDirection),
616 memory: AdjacencyReadMemory<'_>,
617 admit: &mut hawdb_storage::read_view::ControlledGraphReadAllocator<'_>,
618 consumer: &mut dyn FnMut(OrderedAdjacencyEntry) -> Result<ScanControl>,
619 ) -> Result<ScanControl> {
620 GraphStore::visit_ordered_adjacency_entries_with_allocation(
621 self,
622 adjacency,
623 memory.budget_bytes,
624 admit,
625 |entry| consumer(entry).map(to_store_control),
626 )
627 .map(to_execution_control)
628 }
629
630 fn visit_filtered_ordered_relationships_with_allocation(
631 &self,
632 adjacency: (NodeId, Option<RelTypeId>, AdjacencyDirection),
633 filter: &PropertyFilter,
634 memory: AdjacencyReadMemory<'_>,
635 admit: &mut hawdb_storage::read_view::ControlledGraphReadAllocator<'_>,
636 consumer: &mut dyn FnMut(
637 hawdb_storage::read_view::AdmittedRelationshipRecord,
638 ) -> Result<ScanControl>,
639 ) -> Result<(ScanControl, Option<hawdb_storage::scan::ScanPruningReport>)> {
640 GraphStore::visit_filtered_ordered_relationships_with_allocation(
641 self,
642 adjacency,
643 filter,
644 memory.budget_bytes,
645 admit,
646 |row| consumer(row).map(to_store_control),
647 )
648 .map(|(control, report)| (to_execution_control(control), report))
649 }
650
651 fn visit_adjacent_relationships_with_filter_owned(
652 &self,
653 node_id: NodeId,
654 rel_type: Option<RelTypeId>,
655 direction: AdjacencyDirection,
656 filter: &PropertyFilter,
657 consumer: &mut dyn FnMut(RelRecord) -> Result<ScanControl>,
658 ) -> Result<(ScanControl, Option<hawdb_storage::scan::ScanPruningReport>)> {
659 let mut consumer_error = None;
660 let (control, report) = GraphStore::visit_adjacent_relationships_with_filter_owned(
661 self,
662 node_id,
663 rel_type,
664 direction,
665 filter,
666 |relationship| match consumer(relationship) {
667 Ok(control) => to_store_control(control),
668 Err(error) => {
669 consumer_error = Some(error);
670 GraphScanControl::Stop
671 }
672 },
673 )?;
674 match consumer_error {
675 Some(error) => Err(error),
676 None => Ok((to_execution_control(control), report)),
677 }
678 }
679
680 fn visit_ordered_adjacent_relationships_with_filter_owned(
681 &self,
682 node_id: NodeId,
683 rel_type: Option<RelTypeId>,
684 direction: AdjacencyDirection,
685 filter: &PropertyFilter,
686 memory: AdjacencyReadMemory<'_>,
687 consumer: &mut dyn FnMut(RelRecord) -> Result<ScanControl>,
688 ) -> Result<(ScanControl, Option<hawdb_storage::scan::ScanPruningReport>)> {
689 GraphStore::visit_filtered_ordered_relationships_with_allocation(
690 self,
691 (node_id, rel_type, direction),
692 filter,
693 memory.budget_bytes,
694 &mut hawdb_storage::read_view::ControlledGraphReadAllocator::new(
695 &mut |bytes| memory.admit_node(bytes, 0, None).map(Some),
696 None,
697 ),
698 |row| {
699 let (relationship, _allocation) = row.into_parts();
700 consumer(relationship).map(to_store_control)
701 },
702 )
703 .map(|(control, report)| (to_execution_control(control), report))
704 }
705
706 fn visit_relationships_owned(
707 &self,
708 rel_type: Option<RelTypeId>,
709 consumer: &mut dyn FnMut(RelRecord) -> Result<ScanControl>,
710 ) -> Result<ScanControl> {
711 GraphStore::try_visit_relationships_owned(self, rel_type, |relationship| {
712 consumer(relationship).map(to_store_control)
713 })
714 .map(to_execution_control)
715 }
716
717 fn scan_relationships_with_filter_pruning<'a>(
718 &'a self,
719 rel_type: Option<RelTypeId>,
720 filter: Option<&PropertyFilter>,
721 ) -> Result<PrunedRelationshipScan<'a>> {
722 let scan = GraphStore::scan_relationships_with_filter_pruning(self, rel_type, filter);
723 Ok(PrunedRelationshipScan {
724 relationships: Box::new(scan.relationships.into_iter().cloned()),
725 report: scan.report,
726 })
727 }
728
729 fn scan_nodes_with_filter_pruning<'a>(
730 &'a self,
731 catalog: &Catalog,
732 label_id: Option<LabelId>,
733 filter: Option<&PropertyFilter>,
734 ) -> Result<PrunedNodeScan<'a>> {
735 let scan = GraphStore::scan_nodes_with_filter_pruning(self, catalog, label_id, filter);
736 Ok(PrunedNodeScan {
737 nodes: Box::new(scan.nodes.into_iter().map(std::borrow::Cow::Borrowed)),
738 report: scan.report,
739 })
740 }
741
742 fn scan_nodes_with_filter_pruning_admitted<'a>(
743 &'a self,
744 catalog: &Catalog,
745 label_id: Option<LabelId>,
746 filter: Option<&PropertyFilter>,
747 admit: &mut dyn FnMut(
748 usize,
749 )
750 -> Result<Box<dyn hawdb_storage::read_view::GraphReadAllocation>>,
751 ) -> Result<PrunedNodeScan<'a>> {
752 let (scan, allocation) = GraphStore::scan_nodes_with_filter_pruning_admitted(
753 self, catalog, label_id, filter, admit,
754 )?;
755 Ok(PrunedNodeScan {
756 nodes: Box::new(scan.nodes.into_iter().map(move |node| {
757 let _retained_allocation = &allocation;
758 std::borrow::Cow::Borrowed(node)
759 })),
760 report: scan.report,
761 })
762 }
763}
764
765impl GraphExecutionWrite for GraphStore {
766 fn commit_mutation_with_limits(
767 &mut self,
768 catalog: &mut Catalog,
769 mutation: GraphMutation,
770 limits: MutationLimits,
771 ) -> Result<MutationSummary> {
772 GraphStore::commit_mutation_with_limits(self, catalog, mutation, limits)
773 }
774
775 fn commit_mutations_with_limits(
776 &mut self,
777 catalog: &mut Catalog,
778 mutations: Vec<GraphMutation>,
779 limits: MutationLimits,
780 ) -> Result<MutationSummary> {
781 GraphStore::commit_mutations_with_limits(self, catalog, mutations, limits)
782 }
783
784 fn set_node_properties_by_ids_with_limits(
785 &mut self,
786 catalog: &mut Catalog,
787 ids: &[NodeId],
788 assignments: &[NodeSetAssignment],
789 limits: MutationLimits,
790 ) -> Result<Vec<NodeId>> {
791 GraphStore::set_node_properties_by_ids_with_limits(self, catalog, ids, assignments, limits)
792 }
793
794 fn delete_node_ids_with_limits(
795 &mut self,
796 catalog: &mut Catalog,
797 ids: &[NodeId],
798 detach: bool,
799 limits: MutationLimits,
800 ) -> Result<Vec<NodeId>> {
801 GraphStore::delete_node_ids_with_limits(self, catalog, ids, detach, limits)
802 }
803}