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