linkrs_query/executor/streaming/operators/spec/recursive.rs
1//! Immutable configuration for recursive fragment operators.
2
3use std::sync::Arc;
4
5use linkrs_core::{EdgeDirection, Value};
6
7use crate::executor::streaming::plan::types::PhysicalPlan;
8
9/// Immutable config for recursive fragment operators.
10///
11/// Variable-length path traversal, BFS, shortest-path, and multi-round
12/// graph algorithms use this explicit recursive fragment spec.
13///
14/// Frontier, visited-set, path-predecessor, and result-queue allocations
15/// are all accounted against the query memory pool. Each round and
16/// batch-expansion checks the cancellation token.
17#[derive(Debug, Clone)]
18pub enum RecursiveFragmentSpec {
19 /// Bidirectional BFS shortest path between start and target vertices.
20 ///
21 /// When `weight` is set the search runs Dijkstra on that edge property
22 /// instead of hop-count BFS (see `algorithms::weighted_shortest_path`).
23 ShortestPath {
24 edge_types: Vec<String>,
25 direction: EdgeDirection,
26 max_depth: usize,
27 start_vertices: Vec<Value>,
28 target_vertices: Vec<Value>,
29 /// Single vertex label used to materialize path vertices.
30 vertex_tag: String,
31 /// Edge property used as the traversal weight (None = hop-count BFS).
32 weight: Option<String>,
33 },
34 /// Multi-source multi-target shortest path via bidirectional BFS.
35 MultiShortestPath {
36 edge_types: Vec<String>,
37 direction: EdgeDirection,
38 max_depth: usize,
39 left_vertex_column: String,
40 right_vertex_column: String,
41 single_shortest: bool,
42 /// Single vertex label used to materialize path vertices.
43 vertex_tag: String,
44 },
45 /// BFS traversal with configurable depth and cycle policies.
46 BFSShortest {
47 edge_types: Vec<String>,
48 direction: EdgeDirection,
49 max_depth: usize,
50 allow_loops: bool,
51 /// Single vertex label used to materialize path vertices.
52 vertex_tag: String,
53 },
54 /// Enumerate all paths between start and target vertices.
55 AllPaths {
56 edge_types: Vec<String>,
57 direction: EdgeDirection,
58 min_depth: usize,
59 max_depth: usize,
60 path_uniqueness:
61 crate::planning::plan::core::nodes::traversal::path_algorithms::PathUniqueness,
62 limit: Option<usize>,
63 offset: usize,
64 start_vertices: Vec<Value>,
65 target_vertices: Vec<Value>,
66 /// Single vertex label used to materialize path vertices.
67 vertex_tag: String,
68 },
69 /// Recursive-CTE fixpoint (`WITH [RECURSIVE] name AS (anchor [UNION ALL step])`).
70 ///
71 /// The anchor sub-plan runs once; the step sub-plan re-runs with the
72 /// previous delta published as the CTE working table (read through
73 /// [`CteScan`](super::source::SourceSpec::CteScan) sources keyed by the
74 /// mangled `cte_name`) until no new rows appear or `max_iterations` is
75 /// reached. `step` is `None` for a non-recursive CTE (inline view).
76 Fixpoint {
77 /// Mangled CTE tag (`crate::cte::mangle_cte_name`).
78 cte_name: String,
79 /// Anchor sub-plan (runs once, seeds the working table).
80 anchor: Arc<PhysicalPlan>,
81 /// Step sub-plan (re-runs per iteration over the delta).
82 step: Option<Arc<PhysicalPlan>>,
83 /// Fixpoint iteration cap (errors when exceeded).
84 max_iterations: u64,
85 /// Output column names (single column in V1).
86 col_names: Vec<String>,
87 },
88}