Skip to main content

lora_compiler/
logical.rs

1use lora_analyzer::symbols::VarId;
2use lora_analyzer::{
3    ResolvedExpr, ResolvedMergeAction, ResolvedPattern, ResolvedPatternPart, ResolvedProjection,
4    ResolvedRemoveItem, ResolvedSetItem, ResolvedSortItem,
5};
6use lora_ast::{Direction, RangeLiteral};
7
8pub type PlanNodeId = usize;
9
10#[derive(Debug, Clone)]
11pub struct LogicalPlan {
12    pub root: PlanNodeId,
13    pub nodes: Vec<LogicalOp>,
14}
15
16#[derive(Debug, Clone)]
17pub enum LogicalOp {
18    Argument(Argument),
19    NodeScan(NodeScan),
20    NodeByPropertyScan(NodeByPropertyScan),
21    Expand(Expand),
22    Filter(Filter),
23    Projection(Projection),
24    Unwind(Unwind),
25    Aggregation(Aggregation),
26    Sort(Sort),
27    Limit(Limit),
28    Merge(Merge),
29    Delete(Delete),
30    Set(Set),
31    Remove(Remove),
32    Create(Create),
33    OptionalMatch(OptionalMatch),
34    PathBuild(PathBuild),
35}
36
37/// Assembles a path value from matched node and relationship VarIds.
38#[derive(Debug, Clone)]
39pub struct PathBuild {
40    pub input: PlanNodeId,
41    /// VarId to store the assembled path.
42    pub output: VarId,
43    /// Node VarIds in order: head, chain[0].node, chain[1].node, ...
44    pub node_vars: Vec<VarId>,
45    /// Relationship VarIds in order: chain[0].rel, chain[1].rel, ...
46    pub rel_vars: Vec<VarId>,
47    /// `None` = normal path, `Some(false)` = shortestPath, `Some(true)` = allShortestPaths
48    pub shortest_path_all: Option<bool>,
49}
50
51/// Left-outer-join style node: runs the inner sub-plan for each input row.
52/// If no rows are produced, emits one row with nulls for the new variables.
53#[derive(Debug, Clone)]
54pub struct OptionalMatch {
55    /// Upstream rows that feed the optional match.
56    pub input: PlanNodeId,
57    /// The root of the inner sub-plan that implements the pattern + filter.
58    pub inner: PlanNodeId,
59    /// Variables introduced by the optional match (need null-extension).
60    pub new_vars: Vec<VarId>,
61}
62
63#[derive(Debug, Clone)]
64pub struct Argument;
65
66#[derive(Debug, Clone)]
67pub struct NodeScan {
68    pub input: Option<PlanNodeId>,
69    pub var: VarId,
70    /// Each inner Vec is a disjunctive group (OR). Outer Vec is conjunctive (AND).
71    pub labels: Vec<Vec<String>>,
72}
73
74#[derive(Debug, Clone)]
75pub struct NodeByPropertyScan {
76    pub input: Option<PlanNodeId>,
77    pub var: VarId,
78    /// Each inner Vec is a disjunctive group (OR). Outer Vec is conjunctive (AND).
79    pub labels: Vec<Vec<String>>,
80    pub key: String,
81    pub value: ResolvedExpr,
82}
83
84#[derive(Debug, Clone)]
85pub struct Expand {
86    pub input: PlanNodeId,
87    pub src: VarId,
88    pub rel: Option<VarId>,
89    pub dst: VarId,
90    pub types: Vec<String>,
91    pub direction: Direction,
92    pub rel_properties: Option<ResolvedExpr>,
93    pub range: Option<RangeLiteral>,
94}
95
96#[derive(Debug, Clone)]
97pub struct Filter {
98    pub input: PlanNodeId,
99    pub predicate: ResolvedExpr,
100}
101
102#[derive(Debug, Clone)]
103pub struct Projection {
104    pub input: PlanNodeId,
105    pub distinct: bool,
106    pub items: Vec<ResolvedProjection>,
107    pub include_existing: bool,
108}
109
110#[derive(Debug, Clone)]
111pub struct Unwind {
112    pub input: PlanNodeId,
113    pub expr: ResolvedExpr,
114    pub alias: VarId,
115}
116
117#[derive(Debug, Clone)]
118pub struct Aggregation {
119    pub input: PlanNodeId,
120    pub group_by: Vec<ResolvedProjection>,
121    pub aggregates: Vec<ResolvedProjection>,
122}
123
124#[derive(Debug, Clone)]
125pub struct Sort {
126    pub input: PlanNodeId,
127    pub items: Vec<ResolvedSortItem>,
128}
129
130#[derive(Debug, Clone)]
131pub struct Limit {
132    pub input: PlanNodeId,
133    pub skip: Option<ResolvedExpr>,
134    pub limit: Option<ResolvedExpr>,
135}
136
137#[derive(Debug, Clone)]
138pub struct Create {
139    pub input: PlanNodeId,
140    pub pattern: ResolvedPattern,
141}
142
143#[derive(Debug, Clone)]
144pub struct Merge {
145    pub input: PlanNodeId,
146    pub pattern_part: ResolvedPatternPart,
147    pub actions: Vec<ResolvedMergeAction>,
148}
149
150#[derive(Debug, Clone)]
151pub struct Delete {
152    pub input: PlanNodeId,
153    pub detach: bool,
154    pub expressions: Vec<ResolvedExpr>,
155}
156
157#[derive(Debug, Clone)]
158pub struct Set {
159    pub input: PlanNodeId,
160    pub items: Vec<ResolvedSetItem>,
161}
162
163#[derive(Debug, Clone)]
164pub struct Remove {
165    pub input: PlanNodeId,
166    pub items: Vec<ResolvedRemoveItem>,
167}