Skip to main content

lora_analyzer/
resolved.rs

1use crate::{analyzer::FunctionId, symbols::*};
2use lora_ast::{
3    BinaryOp, Direction, ListPredicateKind, RangeLiteral, SortDirection, Span, UnaryOp,
4};
5
6#[derive(Debug, Clone)]
7pub struct ResolvedQuery {
8    pub clauses: Vec<ResolvedClause>,
9    /// Additional UNION branches. Each branch is a separate resolved query
10    /// that produces rows to be combined with the head query's results.
11    pub unions: Vec<ResolvedUnionPart>,
12}
13
14#[derive(Debug, Clone)]
15pub struct ResolvedUnionPart {
16    /// If true, this is UNION ALL (no deduplication). If false, plain UNION (deduplicate).
17    pub all: bool,
18    /// The resolved clauses for this branch.
19    pub clauses: Vec<ResolvedClause>,
20}
21
22#[derive(Debug, Clone)]
23pub enum ResolvedClause {
24    Match(ResolvedMatch),
25    Unwind(ResolvedUnwind),
26    Create(ResolvedCreate),
27    Merge(ResolvedMerge),
28    Delete(ResolvedDelete),
29    Set(ResolvedSet),
30    Remove(ResolvedRemove),
31    Return(ResolvedReturn),
32    With(ResolvedWith),
33    CallSubquery(ResolvedCallSubquery),
34}
35
36/// `CALL { ... }` subquery body. The inner clause list reads from
37/// the outer scope (variables visible at the call site are still
38/// visible inside the subquery), runs once per outer row, and
39/// projects the variables named in its final RETURN back into the
40/// outer scope.
41#[derive(Debug, Clone)]
42pub struct ResolvedCallSubquery {
43    pub clauses: Vec<ResolvedClause>,
44    /// VarIds produced by the inner final RETURN that become
45    /// available in the outer scope after the CALL.
46    pub return_vars: Vec<VarId>,
47}
48
49#[derive(Debug, Clone)]
50pub struct ResolvedMatch {
51    pub optional: bool,
52    pub pattern: ResolvedPattern,
53    pub where_: Option<ResolvedExpr>,
54}
55
56#[derive(Debug, Clone)]
57pub struct ResolvedUnwind {
58    pub expr: ResolvedExpr,
59    pub alias: VarId,
60}
61
62#[derive(Debug, Clone)]
63pub struct ResolvedCreate {
64    pub pattern: ResolvedPattern,
65}
66
67#[derive(Debug, Clone)]
68pub struct ResolvedMerge {
69    pub pattern_part: ResolvedPatternPart,
70    pub actions: Vec<ResolvedMergeAction>,
71}
72
73#[derive(Debug, Clone)]
74pub struct ResolvedMergeAction {
75    pub on_match: bool,
76    pub set: ResolvedSet,
77}
78
79#[derive(Debug, Clone)]
80pub struct ResolvedDelete {
81    pub detach: bool,
82    pub expressions: Vec<ResolvedExpr>,
83}
84
85#[derive(Debug, Clone)]
86pub struct ResolvedSet {
87    pub items: Vec<ResolvedSetItem>,
88}
89
90#[derive(Debug, Clone)]
91pub enum ResolvedSetItem {
92    SetProperty {
93        target: ResolvedExpr,
94        value: ResolvedExpr,
95    },
96    SetVariable {
97        variable: VarId,
98        value: ResolvedExpr,
99    },
100    MutateVariable {
101        variable: VarId,
102        value: ResolvedExpr,
103    },
104    SetLabels {
105        variable: VarId,
106        labels: Vec<String>,
107    },
108}
109
110#[derive(Debug, Clone)]
111pub struct ResolvedRemove {
112    pub items: Vec<ResolvedRemoveItem>,
113}
114
115#[derive(Debug, Clone)]
116pub enum ResolvedRemoveItem {
117    Labels {
118        variable: VarId,
119        labels: Vec<String>,
120    },
121    Property {
122        expr: ResolvedExpr,
123    },
124}
125
126#[derive(Debug, Clone)]
127pub struct ResolvedReturn {
128    pub distinct: bool,
129    pub items: Vec<ResolvedProjection>,
130    pub include_existing: bool,
131    pub order: Vec<ResolvedSortItem>,
132    pub skip: Option<ResolvedExpr>,
133    pub limit: Option<ResolvedExpr>,
134}
135
136#[derive(Debug, Clone)]
137pub struct ResolvedWith {
138    pub distinct: bool,
139    pub items: Vec<ResolvedProjection>,
140    pub include_existing: bool,
141    pub order: Vec<ResolvedSortItem>,
142    pub skip: Option<ResolvedExpr>,
143    pub limit: Option<ResolvedExpr>,
144    pub where_: Option<ResolvedExpr>,
145}
146
147#[derive(Debug, Clone)]
148pub struct ResolvedProjection {
149    pub expr: ResolvedExpr,
150    pub output: VarId,
151    pub name: String,
152    /// True when the name came from an explicit `AS` alias.
153    pub explicit_alias: bool,
154    pub span: Span,
155}
156
157#[derive(Debug, Clone)]
158pub struct ResolvedSortItem {
159    pub expr: ResolvedExpr,
160    pub direction: SortDirection,
161}
162
163#[derive(Debug, Clone)]
164pub struct ResolvedPattern {
165    pub parts: Vec<ResolvedPatternPart>,
166}
167
168#[derive(Debug, Clone)]
169pub struct ResolvedPatternPart {
170    pub binding: Option<VarId>,
171    pub element: ResolvedPatternElement,
172}
173
174#[derive(Debug, Clone)]
175pub enum ResolvedPatternElement {
176    Node {
177        var: Option<VarId>,
178        /// Each inner Vec is a disjunctive group (OR). Outer Vec is conjunctive (AND).
179        labels: Vec<Vec<String>>,
180        properties: Option<ResolvedExpr>,
181    },
182    NodeChain {
183        head: ResolvedNode,
184        chain: Vec<ResolvedChain>,
185    },
186    ShortestPath {
187        all: bool,
188        head: ResolvedNode,
189        chain: Vec<ResolvedChain>,
190    },
191}
192
193#[derive(Debug, Clone)]
194pub struct ResolvedNode {
195    pub var: Option<VarId>,
196    /// Each inner Vec is a disjunctive group (OR). Outer Vec is conjunctive (AND).
197    pub labels: Vec<Vec<String>>,
198    pub properties: Option<ResolvedExpr>,
199}
200
201#[derive(Debug, Clone)]
202pub struct ResolvedChain {
203    pub rel: ResolvedRel,
204    pub node: ResolvedNode,
205}
206
207#[derive(Debug, Clone)]
208pub struct ResolvedRel {
209    pub var: Option<VarId>,
210    pub types: Vec<String>,
211    pub direction: Direction,
212    pub range: Option<RangeLiteral>,
213    pub properties: Option<ResolvedExpr>,
214}
215
216#[derive(Debug, Clone)]
217pub enum ResolvedExpr {
218    Variable(VarId),
219    Literal(LiteralValue),
220    Property {
221        expr: Box<ResolvedExpr>,
222        property: String,
223    },
224    Binary {
225        lhs: Box<ResolvedExpr>,
226        op: BinaryOp,
227        rhs: Box<ResolvedExpr>,
228    },
229    Unary {
230        op: UnaryOp,
231        expr: Box<ResolvedExpr>,
232    },
233    Function {
234        function: FunctionId,
235        distinct: bool,
236        args: Vec<ResolvedExpr>,
237    },
238    List(Vec<ResolvedExpr>),
239    Map(Vec<(String, ResolvedExpr)>),
240    Case {
241        input: Option<Box<ResolvedExpr>>,
242        alternatives: Vec<(ResolvedExpr, ResolvedExpr)>,
243        else_expr: Option<Box<ResolvedExpr>>,
244    },
245    Parameter(String),
246    ListPredicate {
247        kind: ListPredicateKind,
248        variable: VarId,
249        list: Box<ResolvedExpr>,
250        predicate: Box<ResolvedExpr>,
251    },
252    ListComprehension {
253        variable: VarId,
254        list: Box<ResolvedExpr>,
255        filter: Option<Box<ResolvedExpr>>,
256        map_expr: Option<Box<ResolvedExpr>>,
257    },
258    Reduce {
259        accumulator: VarId,
260        init: Box<ResolvedExpr>,
261        variable: VarId,
262        list: Box<ResolvedExpr>,
263        expr: Box<ResolvedExpr>,
264    },
265    MapProjection {
266        base: Box<ResolvedExpr>,
267        selectors: Vec<ResolvedMapSelector>,
268    },
269    Index {
270        expr: Box<ResolvedExpr>,
271        index: Box<ResolvedExpr>,
272    },
273    Slice {
274        expr: Box<ResolvedExpr>,
275        from: Option<Box<ResolvedExpr>>,
276        to: Option<Box<ResolvedExpr>>,
277    },
278    ExistsSubquery {
279        pattern: ResolvedPattern,
280        where_: Option<Box<ResolvedExpr>>,
281    },
282    PatternComprehension {
283        pattern: ResolvedPattern,
284        where_: Option<Box<ResolvedExpr>>,
285        map_expr: Box<ResolvedExpr>,
286    },
287}
288
289#[derive(Debug, Clone)]
290pub enum ResolvedMapSelector {
291    Property(String),
292    AllProperties,
293    Literal(String, ResolvedExpr),
294}
295
296#[derive(Debug, Clone, PartialEq)]
297pub enum LiteralValue {
298    Integer(i64),
299    Float(f64),
300    String(String),
301    TypeName(String),
302    Bool(bool),
303    Null,
304}