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