1use std::collections::HashMap;
4
5#[derive(Debug, Clone, PartialEq)]
7pub enum CypherValue {
8 String(String),
10 Integer(i64),
12 Float(f64),
14 Boolean(bool),
16 Null,
18 List(Vec<CypherValue>),
20 Map(HashMap<String, CypherValue>),
22}
23
24impl std::fmt::Display for CypherValue {
25 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
26 match self {
27 CypherValue::String(s) => write!(f, "\"{}\"", s),
28 CypherValue::Integer(i) => write!(f, "{}", i),
29 CypherValue::Float(v) => write!(f, "{}", v),
30 CypherValue::Boolean(b) => write!(f, "{}", b),
31 CypherValue::Null => write!(f, "null"),
32 CypherValue::List(items) => {
33 write!(f, "[")?;
34 for (i, item) in items.iter().enumerate() {
35 if i > 0 {
36 write!(f, ", ")?;
37 }
38 write!(f, "{}", item)?;
39 }
40 write!(f, "]")
41 }
42 CypherValue::Map(entries) => {
43 write!(f, "{{")?;
44 let mut keys: Vec<_> = entries.keys().collect();
45 keys.sort();
46 for (i, k) in keys.iter().enumerate() {
47 if i > 0 {
48 write!(f, ", ")?;
49 }
50 write!(f, "{}: {}", k, entries.get(*k).unwrap())?;
51 }
52 write!(f, "}}")
53 }
54 }
55 }
56}
57
58impl std::cmp::PartialOrd for CypherValue {
59 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
60 use std::cmp::Ordering;
61 match (self, other) {
62 (CypherValue::Null, CypherValue::Null) => Some(Ordering::Equal),
63 (CypherValue::Null, _) => Some(Ordering::Less),
64 (_, CypherValue::Null) => Some(Ordering::Greater),
65 (CypherValue::Boolean(a), CypherValue::Boolean(b)) => a.partial_cmp(b),
66 (CypherValue::Integer(a), CypherValue::Integer(b)) => a.partial_cmp(b),
67 (CypherValue::Integer(a), CypherValue::Float(b)) => (*a as f64).partial_cmp(b),
68 (CypherValue::Float(a), CypherValue::Integer(b)) => a.partial_cmp(&(*b as f64)),
69 (CypherValue::Float(a), CypherValue::Float(b)) => a.partial_cmp(b),
70 (CypherValue::String(a), CypherValue::String(b)) => a.partial_cmp(b),
71 (CypherValue::List(a), CypherValue::List(b)) => a.partial_cmp(b),
72 (CypherValue::Map(_), CypherValue::Map(_)) => None,
73 (CypherValue::Boolean(_), _) => Some(Ordering::Less),
75 (_, CypherValue::Boolean(_)) => Some(Ordering::Greater),
76 (CypherValue::Integer(_), _) => Some(Ordering::Less),
77 (_, CypherValue::Integer(_)) => Some(Ordering::Greater),
78 (CypherValue::Float(_), _) => Some(Ordering::Less),
79 (_, CypherValue::Float(_)) => Some(Ordering::Greater),
80 (CypherValue::String(_), _) => Some(Ordering::Less),
81 (_, CypherValue::String(_)) => Some(Ordering::Greater),
82 (CypherValue::List(_), _) => Some(Ordering::Less),
83 (_, CypherValue::List(_)) => Some(Ordering::Greater),
84 }
85 }
86}
87
88#[derive(Debug, Clone, PartialEq)]
90pub struct NodePattern {
91 pub variable: Option<String>,
93 pub labels: Vec<String>,
95 pub properties: HashMap<String, CypherValue>,
97}
98
99#[derive(Debug, Clone, Copy, PartialEq, Eq)]
101pub enum RelDirection {
102 Right,
104 Left,
106 Both,
108}
109
110#[derive(Debug, Clone, PartialEq)]
112pub struct RelPattern {
113 pub variable: Option<String>,
115 pub rel_type: Option<String>,
117 pub properties: HashMap<String, CypherValue>,
119 pub direction: RelDirection,
121 pub length: Option<RelationshipLength>,
123}
124
125#[derive(Debug, Clone, PartialEq, Eq)]
127pub struct RelationshipLength {
128 pub min: Option<usize>,
130 pub max: Option<usize>,
132}
133
134#[derive(Debug, Clone, PartialEq)]
139pub struct PathPattern {
140 pub start: NodePattern,
142 pub rels: Vec<(RelPattern, NodePattern)>,
144}
145
146#[derive(Debug, Clone, PartialEq)]
148pub struct ReturnItem {
149 pub expression: Expression,
151 pub alias: Option<String>,
153}
154
155#[derive(Debug, Clone, Copy, PartialEq, Eq)]
157pub enum UnaryOp {
158 Not,
160 Negate,
162 Plus,
164}
165
166#[derive(Debug, Clone, Copy, PartialEq, Eq)]
168pub enum BinaryOp {
169 Add,
171 Subtract,
173 Multiply,
175 Divide,
177 Modulo,
179 Power,
181 Eq,
183 Ne,
185 Lt,
187 Gt,
189 Le,
191 Ge,
193 And,
195 Or,
197 Xor,
199 StartsWith,
201 EndsWith,
203 Contains,
205 In,
207}
208
209#[derive(Debug, Clone, PartialEq)]
211pub enum Expression {
212 Variable(String),
214 Property(String, String),
216 All,
218 Literal(CypherValue),
220 Unary(UnaryOp, Box<Expression>),
222 Binary(BinaryOp, Box<Expression>, Box<Expression>),
224 List(Vec<Expression>),
226 FunctionCall {
228 name: String,
230 args: Vec<Expression>,
232 distinct: bool,
234 },
235 Parameter(String),
237 Case(CaseExpr),
239}
240
241#[derive(Debug, Clone, PartialEq)]
243pub struct CaseExpr {
244 pub scrutinee: Option<Box<Expression>>,
246 pub alternatives: Vec<(Expression, Expression)>,
248 pub default: Option<Box<Expression>>,
250}
251
252#[derive(Debug, Clone, PartialEq)]
254pub enum WhereExpr {
255 Eq(Expression, Expression),
257 NotEq(Expression, Expression),
259 Lt(Expression, Expression),
261 Gt(Expression, Expression),
263 Le(Expression, Expression),
265 Ge(Expression, Expression),
267 In(Expression, Vec<CypherValue>),
269 StartsWith(Expression, String),
271 EndsWith(Expression, String),
273 Contains(Expression, String),
275 IsNull(Expression),
277 IsNotNull(Expression),
279 Not(Box<WhereExpr>),
281 And(Box<WhereExpr>, Box<WhereExpr>),
283 Or(Box<WhereExpr>, Box<WhereExpr>),
285 Xor(Box<WhereExpr>, Box<WhereExpr>),
287}
288
289#[derive(Debug, Clone, Copy, PartialEq, Eq)]
291pub enum SortDirection {
292 Asc,
293 Desc,
294}
295
296#[derive(Debug, Clone, PartialEq)]
298pub struct SortItem {
299 pub expression: Expression,
301 pub direction: SortDirection,
303}
304
305#[derive(Debug, Clone, PartialEq)]
307pub enum SetItem {
308 SetProperty {
310 variable: String,
311 property: String,
312 value: Expression,
313 },
314 SetVariable {
316 variable: String,
317 properties: HashMap<String, CypherValue>,
318 },
319 SetLabels {
321 variable: String,
322 labels: Vec<String>,
323 },
324 MergeProperties {
326 variable: String,
327 properties: HashMap<String, CypherValue>,
328 },
329}
330
331#[derive(Debug, Clone, PartialEq)]
333pub enum RemoveItem {
334 RemoveProperty { variable: String, property: String },
336 RemoveLabels {
338 variable: String,
339 labels: Vec<String>,
340 },
341}
342
343#[derive(Debug, Clone, PartialEq)]
345pub enum Clause {
346 Match {
348 patterns: Vec<PathPattern>,
349 where_clause: Option<WhereExpr>,
350 },
351 OptionalMatch {
353 patterns: Vec<PathPattern>,
354 where_clause: Option<WhereExpr>,
355 },
356 Create { patterns: Vec<PathPattern> },
358 Merge {
360 pattern: PathPattern,
361 on_create: Vec<SetItem>,
362 on_match: Vec<SetItem>,
363 },
364 Return {
366 items: Vec<ReturnItem>,
367 distinct: bool,
368 },
369 With {
371 items: Vec<ReturnItem>,
372 where_clause: Option<WhereExpr>,
373 order_by: Option<Vec<SortItem>>,
374 skip: Option<usize>,
375 limit: Option<usize>,
376 distinct: bool,
377 },
378 Unwind {
380 expression: Expression,
381 variable: String,
382 },
383 Delete {
385 variables: Vec<String>,
386 detach: bool,
387 },
388 Set { items: Vec<SetItem> },
390 Remove { items: Vec<RemoveItem> },
392 OrderBy { items: Vec<SortItem> },
394 Skip { count: usize },
396 Limit { count: usize },
398}
399
400#[derive(Debug, Clone, PartialEq)]
402pub struct CypherQuery {
403 pub clauses: Vec<Clause>,
405}