1#![allow(missing_docs)]
13
14use graphforge_core::Span;
15use serde::{Deserialize, Serialize};
16use std::collections::HashMap;
17
18#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
24pub enum DialectVersion {
25 #[default]
27 OpenCypher9,
28}
29
30#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
34pub struct AstQuery {
35 pub dialect: DialectVersion,
37 pub clauses: Vec<AstClause>,
39 pub span: Span,
41}
42
43impl AstQuery {
44 #[must_use]
46 pub fn has_mutation_clauses(&self) -> bool {
47 self.clauses.iter().any(|clause| {
48 matches!(
49 clause,
50 AstClause::Create(_)
51 | AstClause::Merge(_)
52 | AstClause::Set(_)
53 | AstClause::Remove(_)
54 | AstClause::Delete(_)
55 )
56 })
57 }
58}
59
60#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
66#[non_exhaustive]
67pub enum AstClause {
68 Match(MatchClause),
69 OptionalMatch(MatchClause),
70 Where(WhereClause),
71 With(WithClause),
72 Return(ReturnClause),
73 Create(CreateClause),
74 Merge(MergeClause),
75 Set(SetClause),
76 Remove(RemoveClause),
77 Delete(DeleteClause),
78 Unwind(UnwindClause),
79 Call(CallClause),
80 Union(UnionClause),
81}
82
83impl AstClause {
84 #[must_use]
86 pub fn span(&self) -> Span {
87 match self {
88 Self::Match(c) | Self::OptionalMatch(c) => c.span,
89 Self::Where(c) => c.span,
90 Self::With(c) => c.span,
91 Self::Return(c) => c.span,
92 Self::Create(c) => c.span,
93 Self::Merge(c) => c.span,
94 Self::Set(c) => c.span,
95 Self::Remove(c) => c.span,
96 Self::Delete(c) => c.span,
97 Self::Unwind(c) => c.span,
98 Self::Call(c) => c.span,
99 Self::Union(c) => c.span,
100 }
101 }
102}
103
104#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
110pub struct MatchClause {
111 pub patterns: Vec<PathPattern>,
113 pub where_clause: Option<WhereClause>,
115 pub span: Span,
116}
117
118#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
124pub struct WhereClause {
125 pub predicate: Expr,
126 pub span: Span,
127}
128
129#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
135pub struct WithClause {
136 pub distinct: bool,
137 pub items: Vec<ReturnItem>,
138 pub order_by: Option<OrderByClause>,
139 pub skip: Option<Expr>,
140 pub limit: Option<Expr>,
141 pub where_clause: Option<WhereClause>,
142 pub span: Span,
143}
144
145#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
151pub struct ReturnClause {
152 pub distinct: bool,
153 pub items: Vec<ReturnItem>,
154 pub order_by: Option<OrderByClause>,
155 pub skip: Option<Expr>,
156 pub limit: Option<Expr>,
157 pub span: Span,
158}
159
160#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
162pub struct ReturnItem {
163 pub expr: Expr,
164 pub alias: Option<String>,
166 #[serde(default)]
172 pub display: Option<String>,
173 pub span: Span,
174}
175
176#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
182pub struct OrderByClause {
183 pub items: Vec<SortItem>,
184 pub span: Span,
185}
186
187#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
189pub struct SortItem {
190 pub expr: Expr,
191 pub order: SortOrder,
192 pub span: Span,
193}
194
195#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
197pub enum SortOrder {
198 #[default]
199 Ascending,
200 Descending,
201}
202
203#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
209pub struct CreateClause {
210 pub patterns: Vec<PathPattern>,
211 pub span: Span,
212}
213
214#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
216pub struct MergeClause {
217 pub pattern: PathPattern,
218 pub on_create: Vec<SetItem>,
219 pub on_match: Vec<SetItem>,
220 pub span: Span,
221}
222
223#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
229pub struct SetClause {
230 pub items: Vec<SetItem>,
231 pub span: Span,
232}
233
234#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
236#[non_exhaustive]
237pub enum SetItem {
238 Property {
240 target: PropertyAccess,
241 value: Expr,
242 span: Span,
243 },
244 PropertyMerge { var: String, map: Expr, span: Span },
246 PropertyReplace { var: String, map: Expr, span: Span },
248 Label {
250 var: String,
251 labels: Vec<String>,
252 span: Span,
253 },
254}
255
256#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
258pub struct RemoveClause {
259 pub items: Vec<RemoveItem>,
260 pub span: Span,
261}
262
263#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
265#[non_exhaustive]
266pub enum RemoveItem {
267 Property(PropertyAccess, Span),
269 Label {
271 var: String,
272 labels: Vec<String>,
273 span: Span,
274 },
275}
276
277#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
279pub struct DeleteClause {
280 pub detach: bool,
281 pub exprs: Vec<Expr>,
282 pub span: Span,
283}
284
285#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
291pub struct UnwindClause {
292 pub expr: Expr,
293 pub alias: String,
294 pub span: Span,
295}
296
297#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
303pub struct CallClause {
304 pub procedure: Vec<String>,
305 pub args: Vec<Expr>,
306 #[serde(default)]
308 pub args_explicit: bool,
309 pub yield_items: Vec<ReturnItem>,
310 pub span: Span,
311}
312
313#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
319pub struct UnionClause {
320 pub all: bool,
321 pub span: Span,
322}
323
324#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
330pub struct PathPattern {
331 pub var: Option<String>,
333 pub elements: Vec<PathElement>,
336 pub span: Span,
337}
338
339#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
341pub enum PathElement {
342 Node(NodePattern),
343 Rel(RelPattern),
344}
345
346#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
348pub struct NodePattern {
349 pub var: Option<String>,
351 pub labels: Vec<String>,
353 pub properties: Option<Expr>,
355 pub span: Span,
356}
357
358#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
360pub struct RelPattern {
361 pub var: Option<String>,
362 pub types: Vec<String>,
364 pub direction: Direction,
365 pub min_hops: Option<u32>,
367 pub max_hops: Option<u32>,
369 pub properties: Option<Expr>,
370 pub span: Span,
371}
372
373#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
375pub enum Direction {
376 Out,
378 In,
380 Undirected,
382}
383
384#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
393#[non_exhaustive]
394pub enum Expr {
395 Literal(Literal),
397 Var(VarRef),
399 Property(PropertyAccess),
401 BinaryOp(BinaryOp),
403 UnaryOp(UnaryOp),
405 FunctionCall(FunctionCall),
407 List(ListLiteral),
409 Map(MapLiteral),
411 Param(ParamRef),
413 Case(CaseExpr),
415 ListComprehension(ListComprehension),
417 Quantifier(Quantifier),
419 PatternComprehension(PatternComprehension),
421 PatternPredicate(PatternPredicate),
423 ExistentialSubquery(ExistentialSubquery),
426 LabelPredicate(LabelPredicate),
428 IsNull {
430 expr: Box<Expr>,
431 negated: bool,
432 span: Span,
433 },
434 InList {
436 expr: Box<Expr>,
437 list: Box<Expr>,
438 negated: bool,
439 span: Span,
440 },
441 StringOp {
443 expr: Box<Expr>,
444 op: StringOpKind,
445 pattern: Box<Expr>,
446 span: Span,
447 },
448 RegexMatch {
450 expr: Box<Expr>,
451 pattern: Box<Expr>,
452 span: Span,
453 },
454 Parenthesized { inner: Box<Expr>, span: Span },
456}
457
458impl Expr {
459 #[must_use]
461 pub fn span(&self) -> Span {
462 match self {
463 Self::Literal(l) => l.span(),
464 Self::Var(v) => v.span,
465 Self::Property(p) => p.span,
466 Self::BinaryOp(b) => b.span,
467 Self::UnaryOp(u) => u.span,
468 Self::FunctionCall(f) => f.span,
469 Self::List(l) => l.span,
470 Self::Map(m) => m.span,
471 Self::Param(p) => p.span,
472 Self::Case(c) => c.span,
473 Self::ListComprehension(lc) => lc.span,
474 Self::Quantifier(q) => q.span,
475 Self::PatternComprehension(pc) => pc.span,
476 Self::PatternPredicate(pp) => pp.span,
477 Self::ExistentialSubquery(es) => es.span,
478 Self::LabelPredicate(lp) => lp.span,
479 Self::IsNull { span, .. }
480 | Self::InList { span, .. }
481 | Self::StringOp { span, .. }
482 | Self::RegexMatch { span, .. }
483 | Self::Parenthesized { span, .. } => *span,
484 }
485 }
486}
487
488#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
494pub enum Literal {
495 Int(i64, Span),
496 Float(f64, Span),
497 Str(String, Span),
498 Bool(bool, Span),
499 Null(Span),
500}
501
502impl Literal {
503 #[must_use]
504 pub fn span(&self) -> Span {
505 match self {
506 Self::Int(_, s)
507 | Self::Float(_, s)
508 | Self::Str(_, s)
509 | Self::Bool(_, s)
510 | Self::Null(s) => *s,
511 }
512 }
513}
514
515#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
521pub struct VarRef {
522 pub name: String,
523 pub span: Span,
524}
525
526#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
528pub struct PropertyAccess {
529 pub object: Box<Expr>,
530 pub key: String,
531 pub span: Span,
532}
533
534#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
536pub struct ParamRef {
537 pub name: String,
538 pub span: Span,
539}
540
541#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
543pub struct LabelPredicate {
544 pub var: String,
545 pub labels: Vec<String>,
546 pub span: Span,
547}
548
549#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
555pub struct BinaryOp {
556 pub op: BinaryOpKind,
557 pub left: Box<Expr>,
558 pub right: Box<Expr>,
559 pub span: Span,
560}
561
562#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
564pub enum BinaryOpKind {
565 Eq,
567 Neq,
568 Lt,
569 Lte,
570 Gt,
571 Gte,
572 And,
574 Or,
575 Xor,
576 Add,
578 Sub,
579 Mul,
580 Div,
581 Mod,
582 Pow,
583 Concat,
585}
586
587#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
589pub struct UnaryOp {
590 pub op: UnaryOpKind,
591 pub expr: Box<Expr>,
592 pub span: Span,
593}
594
595#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
597pub enum UnaryOpKind {
598 Not,
599 Neg,
600}
601
602#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
604pub struct FunctionCall {
605 pub name: Vec<String>,
607 pub distinct: bool,
608 pub star: bool,
610 pub args: Vec<Expr>,
611 pub span: Span,
612}
613
614#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
616pub struct ListLiteral {
617 pub elements: Vec<Expr>,
618 pub span: Span,
619}
620
621#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
623pub struct MapLiteral {
624 pub entries: HashMap<String, Expr>,
625 #[serde(default)]
628 pub key_spans: HashMap<String, Span>,
629 pub span: Span,
630}
631
632#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
638pub struct CaseExpr {
639 pub subject: Option<Box<Expr>>,
641 pub when_clauses: Vec<WhenClause>,
642 pub else_expr: Option<Box<Expr>>,
643 pub span: Span,
644}
645
646#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
648pub struct WhenClause {
649 pub condition: Expr,
650 pub result: Expr,
651 pub span: Span,
652}
653
654#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
660pub struct ListComprehension {
661 pub var: String,
662 pub list: Box<Expr>,
663 pub filter: Option<Box<Expr>>,
664 pub projection: Option<Box<Expr>>,
665 pub span: Span,
666}
667
668#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
670pub enum QuantifierKind {
671 All,
673 Any,
675 None,
677 Single,
679}
680
681#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
683pub struct Quantifier {
684 pub kind: QuantifierKind,
685 pub var: String,
686 pub list: Box<Expr>,
687 pub predicate: Box<Expr>,
688 pub span: Span,
689}
690
691#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
693pub struct PatternComprehension {
694 pub var: Option<String>,
695 pub pattern: PathPattern,
696 pub filter: Option<Box<Expr>>,
697 pub projection: Box<Expr>,
698 pub span: Span,
699}
700
701#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
703pub struct PatternPredicate {
704 pub pattern: PathPattern,
705 pub span: Span,
706}
707
708#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
710pub struct ExistentialSubquery {
711 pub body: ExistentialSubqueryBody,
712 pub span: Span,
713}
714
715#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
716pub enum ExistentialSubqueryBody {
717 Simple {
718 pattern: PathPattern,
719 filter: Option<Box<Expr>>,
720 },
721 Full(Box<AstQuery>),
722}
723
724#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
730pub enum StringOpKind {
731 StartsWith,
732 EndsWith,
733 Contains,
734}