use std::collections::HashMap;
#[derive(Debug, Clone, PartialEq)]
pub enum CypherValue {
String(String),
Integer(i64),
Float(f64),
Boolean(bool),
Null,
List(Vec<CypherValue>),
Map(HashMap<String, CypherValue>),
}
impl std::fmt::Display for CypherValue {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
CypherValue::String(s) => write!(f, "\"{}\"", s),
CypherValue::Integer(i) => write!(f, "{}", i),
CypherValue::Float(v) => write!(f, "{}", v),
CypherValue::Boolean(b) => write!(f, "{}", b),
CypherValue::Null => write!(f, "null"),
CypherValue::List(items) => {
write!(f, "[")?;
for (i, item) in items.iter().enumerate() {
if i > 0 {
write!(f, ", ")?;
}
write!(f, "{}", item)?;
}
write!(f, "]")
}
CypherValue::Map(entries) => {
write!(f, "{{")?;
let mut keys: Vec<_> = entries.keys().collect();
keys.sort();
for (i, k) in keys.iter().enumerate() {
if i > 0 {
write!(f, ", ")?;
}
write!(f, "{}: {}", k, entries.get(*k).unwrap())?;
}
write!(f, "}}")
}
}
}
}
impl std::cmp::PartialOrd for CypherValue {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
use std::cmp::Ordering;
match (self, other) {
(CypherValue::Null, CypherValue::Null) => Some(Ordering::Equal),
(CypherValue::Null, _) => Some(Ordering::Less),
(_, CypherValue::Null) => Some(Ordering::Greater),
(CypherValue::Boolean(a), CypherValue::Boolean(b)) => a.partial_cmp(b),
(CypherValue::Integer(a), CypherValue::Integer(b)) => a.partial_cmp(b),
(CypherValue::Integer(a), CypherValue::Float(b)) => (*a as f64).partial_cmp(b),
(CypherValue::Float(a), CypherValue::Integer(b)) => a.partial_cmp(&(*b as f64)),
(CypherValue::Float(a), CypherValue::Float(b)) => a.partial_cmp(b),
(CypherValue::String(a), CypherValue::String(b)) => a.partial_cmp(b),
(CypherValue::List(a), CypherValue::List(b)) => a.partial_cmp(b),
(CypherValue::Map(_), CypherValue::Map(_)) => None,
(CypherValue::Boolean(_), _) => Some(Ordering::Less),
(_, CypherValue::Boolean(_)) => Some(Ordering::Greater),
(CypherValue::Integer(_), _) => Some(Ordering::Less),
(_, CypherValue::Integer(_)) => Some(Ordering::Greater),
(CypherValue::Float(_), _) => Some(Ordering::Less),
(_, CypherValue::Float(_)) => Some(Ordering::Greater),
(CypherValue::String(_), _) => Some(Ordering::Less),
(_, CypherValue::String(_)) => Some(Ordering::Greater),
(CypherValue::List(_), _) => Some(Ordering::Less),
(_, CypherValue::List(_)) => Some(Ordering::Greater),
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct NodePattern {
pub variable: Option<String>,
pub labels: Vec<String>,
pub properties: HashMap<String, CypherValue>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RelDirection {
Right,
Left,
Both,
}
#[derive(Debug, Clone, PartialEq)]
pub struct RelPattern {
pub variable: Option<String>,
pub rel_type: Option<String>,
pub properties: HashMap<String, CypherValue>,
pub direction: RelDirection,
pub length: Option<RelationshipLength>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RelationshipLength {
pub min: Option<usize>,
pub max: Option<usize>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct PathPattern {
pub start: NodePattern,
pub rels: Vec<(RelPattern, NodePattern)>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct ReturnItem {
pub expression: Expression,
pub alias: Option<String>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum UnaryOp {
Not,
Negate,
Plus,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BinaryOp {
Add,
Subtract,
Multiply,
Divide,
Modulo,
Power,
Eq,
Ne,
Lt,
Gt,
Le,
Ge,
And,
Or,
Xor,
StartsWith,
EndsWith,
Contains,
In,
}
#[derive(Debug, Clone, PartialEq)]
pub enum Expression {
Variable(String),
Property(String, String),
All,
Literal(CypherValue),
Unary(UnaryOp, Box<Expression>),
Binary(BinaryOp, Box<Expression>, Box<Expression>),
List(Vec<Expression>),
FunctionCall {
name: String,
args: Vec<Expression>,
distinct: bool,
},
Parameter(String),
Case(CaseExpr),
}
#[derive(Debug, Clone, PartialEq)]
pub struct CaseExpr {
pub scrutinee: Option<Box<Expression>>,
pub alternatives: Vec<(Expression, Expression)>,
pub default: Option<Box<Expression>>,
}
#[derive(Debug, Clone, PartialEq)]
pub enum WhereExpr {
Eq(Expression, Expression),
NotEq(Expression, Expression),
Lt(Expression, Expression),
Gt(Expression, Expression),
Le(Expression, Expression),
Ge(Expression, Expression),
In(Expression, Vec<CypherValue>),
StartsWith(Expression, String),
EndsWith(Expression, String),
Contains(Expression, String),
IsNull(Expression),
IsNotNull(Expression),
Not(Box<WhereExpr>),
And(Box<WhereExpr>, Box<WhereExpr>),
Or(Box<WhereExpr>, Box<WhereExpr>),
Xor(Box<WhereExpr>, Box<WhereExpr>),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SortDirection {
Asc,
Desc,
}
#[derive(Debug, Clone, PartialEq)]
pub struct SortItem {
pub expression: Expression,
pub direction: SortDirection,
}
#[derive(Debug, Clone, PartialEq)]
pub enum SetItem {
SetProperty {
variable: String,
property: String,
value: Expression,
},
SetVariable {
variable: String,
properties: HashMap<String, CypherValue>,
},
SetLabels {
variable: String,
labels: Vec<String>,
},
MergeProperties {
variable: String,
properties: HashMap<String, CypherValue>,
},
}
#[derive(Debug, Clone, PartialEq)]
pub enum RemoveItem {
RemoveProperty { variable: String, property: String },
RemoveLabels {
variable: String,
labels: Vec<String>,
},
}
#[derive(Debug, Clone, PartialEq)]
pub enum Clause {
Match {
patterns: Vec<PathPattern>,
where_clause: Option<WhereExpr>,
},
OptionalMatch {
patterns: Vec<PathPattern>,
where_clause: Option<WhereExpr>,
},
Create { patterns: Vec<PathPattern> },
Merge {
pattern: PathPattern,
on_create: Vec<SetItem>,
on_match: Vec<SetItem>,
},
Return {
items: Vec<ReturnItem>,
distinct: bool,
},
With {
items: Vec<ReturnItem>,
where_clause: Option<WhereExpr>,
order_by: Option<Vec<SortItem>>,
skip: Option<usize>,
limit: Option<usize>,
distinct: bool,
},
Unwind {
expression: Expression,
variable: String,
},
Delete {
variables: Vec<String>,
detach: bool,
},
Set { items: Vec<SetItem> },
Remove { items: Vec<RemoveItem> },
OrderBy { items: Vec<SortItem> },
Skip { count: usize },
Limit { count: usize },
}
#[derive(Debug, Clone, PartialEq)]
pub struct CypherQuery {
pub clauses: Vec<Clause>,
}