1use std::collections::BTreeMap;
13
14use uqa_core::Value;
15
16#[derive(Debug, Clone, PartialEq)]
19pub struct PropertyAccess {
20 pub variable: String,
21 pub keys: Vec<String>,
22}
23
24#[derive(Debug, Clone, PartialEq)]
25pub struct Parameter {
26 pub name: String,
27}
28
29#[derive(Debug, Clone, PartialEq)]
30pub struct Literal {
31 pub value: Value,
32}
33
34#[derive(Debug, Clone, PartialEq)]
35pub struct Variable {
36 pub name: String,
37}
38
39#[derive(Debug, Clone, PartialEq)]
40pub struct FunctionCall {
41 pub name: String,
42 pub args: Vec<CypherExpr>,
43 pub distinct: bool,
44}
45
46#[derive(Debug, Clone, PartialEq)]
47pub struct BinaryOp {
48 pub op: String,
49 pub left: Box<CypherExpr>,
50 pub right: Box<CypherExpr>,
51}
52
53#[derive(Debug, Clone, PartialEq)]
54pub struct UnaryOp {
55 pub op: String,
56 pub operand: Box<CypherExpr>,
57}
58
59#[derive(Debug, Clone, PartialEq)]
60pub struct ListIndex {
61 pub expr: Box<CypherExpr>,
62 pub index: Box<CypherExpr>,
63}
64
65#[derive(Debug, Clone, PartialEq)]
68pub struct ListSlice {
69 pub expr: Box<CypherExpr>,
70 pub start: Option<Box<CypherExpr>>,
71 pub end: Option<Box<CypherExpr>>,
72}
73
74#[derive(Debug, Clone, PartialEq)]
76pub struct ListComprehension {
77 pub variable: String,
78 pub list_expr: Box<CypherExpr>,
79 pub filter: Option<Box<CypherExpr>>,
80 pub map_expr: Option<Box<CypherExpr>>,
81}
82
83#[derive(Debug, Clone, PartialEq)]
84pub struct InList {
85 pub expr: Box<CypherExpr>,
86 pub list_expr: Box<CypherExpr>,
87}
88
89#[derive(Debug, Clone, PartialEq)]
90pub struct IsNull {
91 pub expr: Box<CypherExpr>,
92}
93
94#[derive(Debug, Clone, PartialEq)]
95pub struct IsNotNull {
96 pub expr: Box<CypherExpr>,
97}
98
99#[derive(Debug, Clone, PartialEq)]
100pub struct CaseExpr {
101 pub operand: Option<Box<CypherExpr>>,
102 pub whens: Vec<(CypherExpr, CypherExpr)>,
103 pub else_expr: Option<Box<CypherExpr>>,
104}
105
106#[derive(Debug, Clone, PartialEq)]
107pub struct ListLiteral {
108 pub elements: Vec<CypherExpr>,
109}
110
111#[derive(Debug, Clone, PartialEq)]
112pub struct MapLiteral {
113 pub pairs: Vec<(String, CypherExpr)>,
114}
115
116#[derive(Debug, Clone, PartialEq)]
118pub enum CypherExpr {
119 PropertyAccess(PropertyAccess),
120 Parameter(Parameter),
121 Literal(Literal),
122 Variable(Variable),
123 FunctionCall(FunctionCall),
124 BinaryOp(BinaryOp),
125 UnaryOp(UnaryOp),
126 ListIndex(ListIndex),
127 ListSlice(ListSlice),
128 ListComprehension(ListComprehension),
129 InList(InList),
130 IsNull(IsNull),
131 IsNotNull(IsNotNull),
132 CaseExpr(CaseExpr),
133 ListLiteral(ListLiteral),
134 MapLiteral(MapLiteral),
135 ExistsPattern(PathPattern),
137}
138
139#[derive(Debug, Clone, PartialEq)]
142pub struct NodePattern {
143 pub variable: Option<String>,
144 pub labels: Vec<String>,
145 pub properties: Option<BTreeMap<String, CypherExpr>>,
146}
147
148#[derive(Debug, Clone, Copy, PartialEq, Eq)]
150pub enum RelDirection {
151 Right,
153 Left,
155 Both,
157}
158
159#[derive(Debug, Clone, PartialEq)]
160pub struct RelPattern {
161 pub variable: Option<String>,
162 pub types: Vec<String>,
163 pub properties: Option<BTreeMap<String, CypherExpr>>,
164 pub direction: RelDirection,
165 pub min_hops: Option<u32>,
168 pub max_hops: Option<u32>,
170}
171
172#[derive(Debug, Clone, PartialEq)]
174pub enum PathElement {
175 Node(NodePattern),
176 Rel(RelPattern),
177}
178
179#[derive(Debug, Clone, PartialEq)]
180pub struct PathPattern {
181 pub variable: Option<String>,
183 pub elements: Vec<PathElement>,
184}
185
186#[derive(Debug, Clone, PartialEq)]
189pub struct MatchClause {
190 pub patterns: Vec<PathPattern>,
191 pub r#where: Option<CypherExpr>,
192 pub optional: bool,
193}
194
195#[derive(Debug, Clone, PartialEq)]
196pub struct CreateClause {
197 pub patterns: Vec<PathPattern>,
198}
199
200#[derive(Debug, Clone, PartialEq)]
201pub struct MergeClause {
202 pub pattern: PathPattern,
203 pub on_create_set: Option<Vec<SetItem>>,
204 pub on_match_set: Option<Vec<SetItem>>,
205}
206
207#[derive(Debug, Clone, Copy, PartialEq, Eq)]
208pub enum SetOperator {
209 Assign,
211 Update,
213}
214
215#[derive(Debug, Clone, PartialEq)]
216pub struct SetItem {
217 pub target: CypherExpr,
218 pub value: CypherExpr,
219 pub operator: SetOperator,
220}
221
222#[derive(Debug, Clone, PartialEq)]
223pub struct SetClause {
224 pub items: Vec<SetItem>,
225}
226
227#[derive(Debug, Clone, PartialEq)]
228pub struct DeleteClause {
229 pub expressions: Vec<CypherExpr>,
230 pub detach: bool,
231}
232
233#[derive(Debug, Clone, PartialEq)]
234pub struct ReturnItem {
235 pub expr: CypherExpr,
236 pub alias: Option<String>,
237}
238
239#[derive(Debug, Clone, PartialEq)]
240pub struct OrderByItem {
241 pub expr: CypherExpr,
242 pub ascending: bool,
243}
244
245#[derive(Debug, Clone, PartialEq)]
246pub struct ReturnClause {
247 pub items: Vec<ReturnItem>,
248 pub distinct: bool,
249 pub order_by: Option<Vec<OrderByItem>>,
250 pub skip: Option<CypherExpr>,
251 pub limit: Option<CypherExpr>,
252}
253
254#[derive(Debug, Clone, PartialEq)]
255pub struct WithClause {
256 pub items: Vec<ReturnItem>,
257 pub distinct: bool,
258 pub order_by: Option<Vec<OrderByItem>>,
259 pub skip: Option<CypherExpr>,
260 pub limit: Option<CypherExpr>,
261 pub r#where: Option<CypherExpr>,
262}
263
264#[derive(Debug, Clone, PartialEq)]
265pub struct UnwindClause {
266 pub expr: CypherExpr,
267 pub variable: String,
268}
269
270#[derive(Debug, Clone, PartialEq)]
271pub enum CypherClause {
272 Match(MatchClause),
273 Create(CreateClause),
274 Merge(MergeClause),
275 Set(SetClause),
276 Delete(DeleteClause),
277 Return(ReturnClause),
278 With(WithClause),
279 Unwind(UnwindClause),
280}
281
282#[derive(Debug, Clone, PartialEq)]
283pub struct CypherQuery {
284 pub clauses: Vec<CypherClause>,
285}
286
287impl CypherQuery {
288 #[must_use]
290 pub fn mutates_graph(&self) -> bool {
291 self.clauses.iter().any(|clause| {
292 matches!(
293 clause,
294 CypherClause::Create(_)
295 | CypherClause::Merge(_)
296 | CypherClause::Set(_)
297 | CypherClause::Delete(_)
298 )
299 })
300 }
301}