Skip to main content

lora_compiler/
physical.rs

1use lora_analyzer::symbols::VarId;
2use lora_analyzer::{
3    ResolvedClause, ResolvedExpr, ResolvedMergeAction, ResolvedPattern, ResolvedPatternPart,
4    ResolvedProjection, ResolvedRemoveItem, ResolvedSetItem, ResolvedSortItem,
5};
6use lora_ast::{Direction, RangeLiteral};
7
8pub type PhysicalNodeId = usize;
9
10#[derive(Debug, Clone)]
11pub struct PhysicalPlan {
12    pub root: PhysicalNodeId,
13    pub nodes: Vec<PhysicalOp>,
14}
15
16#[derive(Debug, Clone)]
17pub enum PhysicalOp {
18    Argument(ArgumentExec),
19    NodeScan(NodeScanExec),
20    NodeByLabelScan(NodeByLabelScanExec),
21    NodeByPropertyScan(NodeByPropertyScanExec),
22    NodeByPropertyRangeScan(NodeByPropertyRangeScanExec),
23    NodeByTextScan(NodeByTextScanExec),
24    NodeByPointScan(NodeByPointScanExec),
25    RelByPropertyRangeScan(RelByPropertyRangeScanExec),
26    RelByTextScan(RelByTextScanExec),
27    RelByPointScan(RelByPointScanExec),
28    Expand(ExpandExec),
29    Filter(FilterExec),
30    Projection(ProjectionExec),
31    Unwind(UnwindExec),
32    HashAggregation(HashAggregationExec),
33    Sort(SortExec),
34    Limit(LimitExec),
35    Create(CreateExec),
36    Merge(MergeExec),
37    Delete(DeleteExec),
38    Set(SetExec),
39    Remove(RemoveExec),
40    Foreach(ForeachExec),
41    OptionalMatch(OptionalMatchExec),
42    PathBuild(PathBuildExec),
43    CallSubquery(CallSubqueryExec),
44}
45
46/// See [`crate::logical::Foreach`].
47#[derive(Debug, Clone)]
48pub struct ForeachExec {
49    pub input: PhysicalNodeId,
50    pub variable: VarId,
51    pub list: ResolvedExpr,
52    pub body: Vec<ResolvedClause>,
53}
54
55/// `CALL { ... }` subquery executor node. See [`crate::logical::CallSubquery`].
56#[derive(Debug, Clone)]
57pub struct CallSubqueryExec {
58    pub input: PhysicalNodeId,
59    pub inner: PhysicalNodeId,
60    pub new_vars: Vec<VarId>,
61}
62
63#[derive(Debug, Clone)]
64pub struct PathBuildExec {
65    pub input: PhysicalNodeId,
66    pub output: VarId,
67    pub node_vars: Vec<VarId>,
68    pub rel_vars: Vec<VarId>,
69    pub shortest_path_all: Option<bool>,
70}
71
72/// Left-outer-join: for each input row, runs inner sub-plan.
73/// If inner produces nothing, emits one row with nulls for new_vars.
74#[derive(Debug, Clone)]
75pub struct OptionalMatchExec {
76    pub input: PhysicalNodeId,
77    pub inner: PhysicalNodeId,
78    pub new_vars: Vec<VarId>,
79}
80
81#[derive(Debug, Clone)]
82pub struct ArgumentExec;
83
84#[derive(Debug, Clone)]
85pub struct NodeScanExec {
86    pub input: Option<PhysicalNodeId>,
87    pub var: VarId,
88}
89
90#[derive(Debug, Clone)]
91pub struct NodeByLabelScanExec {
92    pub input: Option<PhysicalNodeId>,
93    pub var: VarId,
94    /// Each inner Vec is a disjunctive group (OR). Outer Vec is conjunctive (AND).
95    pub labels: Vec<Vec<String>>,
96}
97
98#[derive(Debug, Clone)]
99pub struct NodeByPropertyScanExec {
100    pub input: Option<PhysicalNodeId>,
101    pub var: VarId,
102    /// Each inner Vec is a disjunctive group (OR). Outer Vec is conjunctive (AND).
103    pub labels: Vec<Vec<String>>,
104    pub key: String,
105    pub value: ResolvedExpr,
106}
107
108#[derive(Debug, Clone)]
109pub struct NodeByPropertyRangeScanExec {
110    pub input: Option<PhysicalNodeId>,
111    pub var: VarId,
112    pub labels: Vec<Vec<String>>,
113    pub key: String,
114    pub lo: Option<ResolvedExpr>,
115    pub lo_inclusive: bool,
116    pub hi: Option<ResolvedExpr>,
117    pub hi_inclusive: bool,
118}
119
120#[derive(Debug, Clone)]
121pub struct NodeByTextScanExec {
122    pub input: Option<PhysicalNodeId>,
123    pub var: VarId,
124    pub labels: Vec<Vec<String>>,
125    pub key: String,
126    pub predicate: crate::logical::TextPredicate,
127    pub query: ResolvedExpr,
128}
129
130#[derive(Debug, Clone)]
131pub struct NodeByPointScanExec {
132    pub input: Option<PhysicalNodeId>,
133    pub var: VarId,
134    pub labels: Vec<Vec<String>>,
135    pub key: String,
136    pub predicate: crate::logical::PointPredicate,
137}
138
139#[derive(Debug, Clone)]
140pub struct RelByPropertyRangeScanExec {
141    pub input: Option<PhysicalNodeId>,
142    pub src: VarId,
143    pub rel: VarId,
144    pub dst: VarId,
145    pub types: Vec<String>,
146    pub direction: Direction,
147    pub key: String,
148    pub lo: Option<ResolvedExpr>,
149    pub lo_inclusive: bool,
150    pub hi: Option<ResolvedExpr>,
151    pub hi_inclusive: bool,
152}
153
154#[derive(Debug, Clone)]
155pub struct RelByTextScanExec {
156    pub input: Option<PhysicalNodeId>,
157    pub src: VarId,
158    pub rel: VarId,
159    pub dst: VarId,
160    pub types: Vec<String>,
161    pub direction: Direction,
162    pub key: String,
163    pub predicate: crate::logical::TextPredicate,
164    pub query: ResolvedExpr,
165}
166
167#[derive(Debug, Clone)]
168pub struct RelByPointScanExec {
169    pub input: Option<PhysicalNodeId>,
170    pub src: VarId,
171    pub rel: VarId,
172    pub dst: VarId,
173    pub types: Vec<String>,
174    pub direction: Direction,
175    pub key: String,
176    pub predicate: crate::logical::PointPredicate,
177}
178
179#[derive(Debug, Clone)]
180pub struct ExpandExec {
181    pub input: PhysicalNodeId,
182    pub src: VarId,
183    pub rel: Option<VarId>,
184    pub dst: VarId,
185    pub types: Vec<String>,
186    pub direction: Direction,
187    pub rel_properties: Option<ResolvedExpr>,
188    pub range: Option<RangeLiteral>,
189}
190
191#[derive(Debug, Clone)]
192pub struct FilterExec {
193    pub input: PhysicalNodeId,
194    pub predicate: ResolvedExpr,
195}
196
197#[derive(Debug, Clone)]
198pub struct ProjectionExec {
199    pub input: PhysicalNodeId,
200    pub distinct: bool,
201    pub items: Vec<ResolvedProjection>,
202    pub include_existing: bool,
203}
204
205#[derive(Debug, Clone)]
206pub struct UnwindExec {
207    pub input: PhysicalNodeId,
208    pub expr: ResolvedExpr,
209    pub alias: VarId,
210}
211
212#[derive(Debug, Clone)]
213pub struct HashAggregationExec {
214    pub input: PhysicalNodeId,
215    pub group_by: Vec<ResolvedProjection>,
216    pub aggregates: Vec<ResolvedProjection>,
217}
218
219#[derive(Debug, Clone)]
220pub struct SortExec {
221    pub input: PhysicalNodeId,
222    pub items: Vec<ResolvedSortItem>,
223    /// Optional upper bound for rows Sort must retain before a parent LIMIT.
224    pub top_k: Option<usize>,
225}
226
227#[derive(Debug, Clone)]
228pub struct LimitExec {
229    pub input: PhysicalNodeId,
230    pub skip: Option<ResolvedExpr>,
231    pub limit: Option<ResolvedExpr>,
232}
233
234#[derive(Debug, Clone)]
235pub struct CreateExec {
236    pub input: PhysicalNodeId,
237    pub pattern: ResolvedPattern,
238}
239
240#[derive(Debug, Clone)]
241pub struct MergeExec {
242    pub input: PhysicalNodeId,
243    pub pattern_part: ResolvedPatternPart,
244    pub actions: Vec<ResolvedMergeAction>,
245}
246
247#[derive(Debug, Clone)]
248pub struct DeleteExec {
249    pub input: PhysicalNodeId,
250    pub detach: bool,
251    pub expressions: Vec<ResolvedExpr>,
252}
253
254#[derive(Debug, Clone)]
255pub struct SetExec {
256    pub input: PhysicalNodeId,
257    pub items: Vec<ResolvedSetItem>,
258}
259
260#[derive(Debug, Clone)]
261pub struct RemoveExec {
262    pub input: PhysicalNodeId,
263    pub items: Vec<ResolvedRemoveItem>,
264}