#![allow(missing_docs)]
use graphforge_core::Span;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
pub enum DialectVersion {
#[default]
OpenCypher9,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct AstQuery {
pub dialect: DialectVersion,
pub clauses: Vec<AstClause>,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[non_exhaustive]
pub enum AstClause {
Match(MatchClause),
OptionalMatch(MatchClause),
Where(WhereClause),
With(WithClause),
Return(ReturnClause),
Create(CreateClause),
Merge(MergeClause),
Set(SetClause),
Remove(RemoveClause),
Delete(DeleteClause),
Unwind(UnwindClause),
Call(CallClause),
Union(UnionClause),
}
impl AstClause {
#[must_use]
pub fn span(&self) -> Span {
match self {
Self::Match(c) | Self::OptionalMatch(c) => c.span,
Self::Where(c) => c.span,
Self::With(c) => c.span,
Self::Return(c) => c.span,
Self::Create(c) => c.span,
Self::Merge(c) => c.span,
Self::Set(c) => c.span,
Self::Remove(c) => c.span,
Self::Delete(c) => c.span,
Self::Unwind(c) => c.span,
Self::Call(c) => c.span,
Self::Union(c) => c.span,
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct MatchClause {
pub patterns: Vec<PathPattern>,
pub where_clause: Option<WhereClause>,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct WhereClause {
pub predicate: Expr,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct WithClause {
pub distinct: bool,
pub items: Vec<ReturnItem>,
pub order_by: Option<OrderByClause>,
pub skip: Option<Expr>,
pub limit: Option<Expr>,
pub where_clause: Option<WhereClause>,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ReturnClause {
pub distinct: bool,
pub items: Vec<ReturnItem>,
pub order_by: Option<OrderByClause>,
pub skip: Option<Expr>,
pub limit: Option<Expr>,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ReturnItem {
pub expr: Expr,
pub alias: Option<String>,
#[serde(default)]
pub display: Option<String>,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct OrderByClause {
pub items: Vec<SortItem>,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct SortItem {
pub expr: Expr,
pub order: SortOrder,
pub span: Span,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
pub enum SortOrder {
#[default]
Ascending,
Descending,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct CreateClause {
pub patterns: Vec<PathPattern>,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct MergeClause {
pub pattern: PathPattern,
pub on_create: Vec<SetItem>,
pub on_match: Vec<SetItem>,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct SetClause {
pub items: Vec<SetItem>,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[non_exhaustive]
pub enum SetItem {
Property {
target: PropertyAccess,
value: Expr,
span: Span,
},
PropertyMerge { var: String, map: Expr, span: Span },
PropertyReplace { var: String, map: Expr, span: Span },
Label {
var: String,
labels: Vec<String>,
span: Span,
},
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct RemoveClause {
pub items: Vec<RemoveItem>,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[non_exhaustive]
pub enum RemoveItem {
Property(PropertyAccess, Span),
Label {
var: String,
labels: Vec<String>,
span: Span,
},
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct DeleteClause {
pub detach: bool,
pub exprs: Vec<Expr>,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct UnwindClause {
pub expr: Expr,
pub alias: String,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct CallClause {
pub procedure: Vec<String>,
pub args: Vec<Expr>,
#[serde(default)]
pub args_explicit: bool,
pub yield_items: Vec<ReturnItem>,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct UnionClause {
pub all: bool,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PathPattern {
pub var: Option<String>,
pub elements: Vec<PathElement>,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum PathElement {
Node(NodePattern),
Rel(RelPattern),
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct NodePattern {
pub var: Option<String>,
pub labels: Vec<String>,
pub properties: Option<Expr>,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct RelPattern {
pub var: Option<String>,
pub types: Vec<String>,
pub direction: Direction,
pub min_hops: Option<u32>,
pub max_hops: Option<u32>,
pub properties: Option<Expr>,
pub span: Span,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum Direction {
Out,
In,
Undirected,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[non_exhaustive]
pub enum Expr {
Literal(Literal),
Var(VarRef),
Property(PropertyAccess),
BinaryOp(BinaryOp),
UnaryOp(UnaryOp),
FunctionCall(FunctionCall),
List(ListLiteral),
Map(MapLiteral),
Param(ParamRef),
Case(CaseExpr),
ListComprehension(ListComprehension),
Quantifier(Quantifier),
PatternComprehension(PatternComprehension),
PatternPredicate(PatternPredicate),
ExistentialSubquery(ExistentialSubquery),
LabelPredicate(LabelPredicate),
IsNull {
expr: Box<Expr>,
negated: bool,
span: Span,
},
InList {
expr: Box<Expr>,
list: Box<Expr>,
negated: bool,
span: Span,
},
StringOp {
expr: Box<Expr>,
op: StringOpKind,
pattern: Box<Expr>,
span: Span,
},
RegexMatch {
expr: Box<Expr>,
pattern: Box<Expr>,
span: Span,
},
Parenthesized { inner: Box<Expr>, span: Span },
}
impl Expr {
#[must_use]
pub fn span(&self) -> Span {
match self {
Self::Literal(l) => l.span(),
Self::Var(v) => v.span,
Self::Property(p) => p.span,
Self::BinaryOp(b) => b.span,
Self::UnaryOp(u) => u.span,
Self::FunctionCall(f) => f.span,
Self::List(l) => l.span,
Self::Map(m) => m.span,
Self::Param(p) => p.span,
Self::Case(c) => c.span,
Self::ListComprehension(lc) => lc.span,
Self::Quantifier(q) => q.span,
Self::PatternComprehension(pc) => pc.span,
Self::PatternPredicate(pp) => pp.span,
Self::ExistentialSubquery(es) => es.span,
Self::LabelPredicate(lp) => lp.span,
Self::IsNull { span, .. }
| Self::InList { span, .. }
| Self::StringOp { span, .. }
| Self::RegexMatch { span, .. }
| Self::Parenthesized { span, .. } => *span,
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Literal {
Int(i64, Span),
Float(f64, Span),
Str(String, Span),
Bool(bool, Span),
Null(Span),
}
impl Literal {
#[must_use]
pub fn span(&self) -> Span {
match self {
Self::Int(_, s)
| Self::Float(_, s)
| Self::Str(_, s)
| Self::Bool(_, s)
| Self::Null(s) => *s,
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct VarRef {
pub name: String,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PropertyAccess {
pub object: Box<Expr>,
pub key: String,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ParamRef {
pub name: String,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct LabelPredicate {
pub var: String,
pub labels: Vec<String>,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct BinaryOp {
pub op: BinaryOpKind,
pub left: Box<Expr>,
pub right: Box<Expr>,
pub span: Span,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum BinaryOpKind {
Eq,
Neq,
Lt,
Lte,
Gt,
Gte,
And,
Or,
Xor,
Add,
Sub,
Mul,
Div,
Mod,
Pow,
Concat,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct UnaryOp {
pub op: UnaryOpKind,
pub expr: Box<Expr>,
pub span: Span,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum UnaryOpKind {
Not,
Neg,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct FunctionCall {
pub name: Vec<String>,
pub distinct: bool,
pub star: bool,
pub args: Vec<Expr>,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ListLiteral {
pub elements: Vec<Expr>,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct MapLiteral {
pub entries: HashMap<String, Expr>,
#[serde(default)]
pub key_spans: HashMap<String, Span>,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct CaseExpr {
pub subject: Option<Box<Expr>>,
pub when_clauses: Vec<WhenClause>,
pub else_expr: Option<Box<Expr>>,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct WhenClause {
pub condition: Expr,
pub result: Expr,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ListComprehension {
pub var: String,
pub list: Box<Expr>,
pub filter: Option<Box<Expr>>,
pub projection: Option<Box<Expr>>,
pub span: Span,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum QuantifierKind {
All,
Any,
None,
Single,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Quantifier {
pub kind: QuantifierKind,
pub var: String,
pub list: Box<Expr>,
pub predicate: Box<Expr>,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PatternComprehension {
pub var: Option<String>,
pub pattern: PathPattern,
pub filter: Option<Box<Expr>>,
pub projection: Box<Expr>,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PatternPredicate {
pub pattern: PathPattern,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ExistentialSubquery {
pub body: ExistentialSubqueryBody,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum ExistentialSubqueryBody {
Simple {
pattern: PathPattern,
filter: Option<Box<Expr>>,
},
Full(Box<AstQuery>),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum StringOpKind {
StartsWith,
EndsWith,
Contains,
}