use serde::{Deserialize, Serialize};
use serde_json::Value as JsonValue;
use std::collections::HashMap;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CypherQuery {
pub clauses: Vec<Clause>,
}
impl CypherQuery {
pub fn new() -> Self {
Self {
clauses: Vec::new(),
}
}
pub fn with_clause(mut self, clause: Clause) -> Self {
self.clauses.push(clause);
self
}
}
impl Default for CypherQuery {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum Clause {
Match(MatchClause),
Create(CreateClause),
Return(ReturnClause),
Where(WhereClause),
Set(SetClause),
Delete(DeleteClause),
With(WithClause),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MatchClause {
pub patterns: Vec<Pattern>,
pub optional: bool,
}
impl MatchClause {
pub fn new(patterns: Vec<Pattern>) -> Self {
Self {
patterns,
optional: false,
}
}
pub fn optional(mut self) -> Self {
self.optional = true;
self
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CreateClause {
pub patterns: Vec<Pattern>,
}
impl CreateClause {
pub fn new(patterns: Vec<Pattern>) -> Self {
Self { patterns }
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ReturnClause {
pub items: Vec<ReturnItem>,
pub distinct: bool,
pub limit: Option<usize>,
pub skip: Option<usize>,
}
impl ReturnClause {
pub fn new(items: Vec<ReturnItem>) -> Self {
Self {
items,
distinct: false,
limit: None,
skip: None,
}
}
pub fn distinct(mut self) -> Self {
self.distinct = true;
self
}
pub fn limit(mut self, limit: usize) -> Self {
self.limit = Some(limit);
self
}
pub fn skip(mut self, skip: usize) -> Self {
self.skip = Some(skip);
self
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ReturnItem {
pub expression: Expression,
pub alias: Option<String>,
}
impl ReturnItem {
pub fn new(expression: Expression) -> Self {
Self {
expression,
alias: None,
}
}
pub fn with_alias(mut self, alias: impl Into<String>) -> Self {
self.alias = Some(alias.into());
self
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WhereClause {
pub condition: Expression,
}
impl WhereClause {
pub fn new(condition: Expression) -> Self {
Self { condition }
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SetClause {
pub items: Vec<SetItem>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SetItem {
pub variable: String,
pub property: String,
pub value: Expression,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeleteClause {
pub items: Vec<String>,
pub detach: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WithClause {
pub items: Vec<ReturnItem>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Pattern {
pub elements: Vec<PatternElement>,
}
impl Pattern {
pub fn new() -> Self {
Self {
elements: Vec::new(),
}
}
pub fn with_element(mut self, element: PatternElement) -> Self {
self.elements.push(element);
self
}
}
impl Default for Pattern {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum PatternElement {
Node(NodePattern),
Relationship(RelationshipPattern),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NodePattern {
pub variable: Option<String>,
pub labels: Vec<String>,
pub properties: HashMap<String, Expression>,
}
impl NodePattern {
pub fn new() -> Self {
Self {
variable: None,
labels: Vec::new(),
properties: HashMap::new(),
}
}
pub fn with_variable(mut self, variable: impl Into<String>) -> Self {
self.variable = Some(variable.into());
self
}
pub fn with_label(mut self, label: impl Into<String>) -> Self {
self.labels.push(label.into());
self
}
pub fn with_property(mut self, key: impl Into<String>, value: Expression) -> Self {
self.properties.insert(key.into(), value);
self
}
}
impl Default for NodePattern {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RelationshipPattern {
pub variable: Option<String>,
pub rel_type: Option<String>,
pub properties: HashMap<String, Expression>,
pub direction: Direction,
pub min_hops: Option<usize>,
pub max_hops: Option<usize>,
}
impl RelationshipPattern {
pub fn new(direction: Direction) -> Self {
Self {
variable: None,
rel_type: None,
properties: HashMap::new(),
direction,
min_hops: None,
max_hops: None,
}
}
pub fn with_variable(mut self, variable: impl Into<String>) -> Self {
self.variable = Some(variable.into());
self
}
pub fn with_type(mut self, rel_type: impl Into<String>) -> Self {
self.rel_type = Some(rel_type.into());
self
}
pub fn with_property(mut self, key: impl Into<String>, value: Expression) -> Self {
self.properties.insert(key.into(), value);
self
}
pub fn with_hops(mut self, min: usize, max: usize) -> Self {
self.min_hops = Some(min);
self.max_hops = Some(max);
self
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum Direction {
Outgoing, Incoming, Both, }
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum Expression {
Literal(JsonValue),
Variable(String),
Property(String, String), Parameter(String), FunctionCall(String, Vec<Expression>),
BinaryOp(Box<Expression>, BinaryOperator, Box<Expression>),
UnaryOp(UnaryOperator, Box<Expression>),
}
impl Expression {
pub fn literal(value: impl Into<JsonValue>) -> Self {
Self::Literal(value.into())
}
pub fn variable(name: impl Into<String>) -> Self {
Self::Variable(name.into())
}
pub fn property(var: impl Into<String>, prop: impl Into<String>) -> Self {
Self::Property(var.into(), prop.into())
}
pub fn parameter(name: impl Into<String>) -> Self {
Self::Parameter(name.into())
}
pub fn function(name: impl Into<String>, args: Vec<Expression>) -> Self {
Self::FunctionCall(name.into(), args)
}
pub fn binary(left: Expression, op: BinaryOperator, right: Expression) -> Self {
Self::BinaryOp(Box::new(left), op, Box::new(right))
}
pub fn unary(op: UnaryOperator, expr: Expression) -> Self {
Self::UnaryOp(op, Box::new(expr))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum BinaryOperator {
Eq, Neq, Lt, Lte, Gt, Gte, And, Or, Add, Sub, Mul, Div, Mod, In, Contains, StartsWith, EndsWith, }
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum UnaryOperator {
Not, Minus, }