use std::collections::BTreeMap;
use uqa_core::Value;
#[derive(Debug, Clone, PartialEq)]
pub struct PropertyAccess {
pub variable: String,
pub keys: Vec<String>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Parameter {
pub name: String,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Literal {
pub value: Value,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Variable {
pub name: String,
}
#[derive(Debug, Clone, PartialEq)]
pub struct FunctionCall {
pub name: String,
pub args: Vec<CypherExpr>,
pub distinct: bool,
}
#[derive(Debug, Clone, PartialEq)]
pub struct BinaryOp {
pub op: String,
pub left: Box<CypherExpr>,
pub right: Box<CypherExpr>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct UnaryOp {
pub op: String,
pub operand: Box<CypherExpr>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct ListIndex {
pub expr: Box<CypherExpr>,
pub index: Box<CypherExpr>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct ListSlice {
pub expr: Box<CypherExpr>,
pub start: Option<Box<CypherExpr>>,
pub end: Option<Box<CypherExpr>>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct ListComprehension {
pub variable: String,
pub list_expr: Box<CypherExpr>,
pub filter: Option<Box<CypherExpr>>,
pub map_expr: Option<Box<CypherExpr>>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct InList {
pub expr: Box<CypherExpr>,
pub list_expr: Box<CypherExpr>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct IsNull {
pub expr: Box<CypherExpr>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct IsNotNull {
pub expr: Box<CypherExpr>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct CaseExpr {
pub operand: Option<Box<CypherExpr>>,
pub whens: Vec<(CypherExpr, CypherExpr)>,
pub else_expr: Option<Box<CypherExpr>>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct ListLiteral {
pub elements: Vec<CypherExpr>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct MapLiteral {
pub pairs: Vec<(String, CypherExpr)>,
}
#[derive(Debug, Clone, PartialEq)]
pub enum CypherExpr {
PropertyAccess(PropertyAccess),
Parameter(Parameter),
Literal(Literal),
Variable(Variable),
FunctionCall(FunctionCall),
BinaryOp(BinaryOp),
UnaryOp(UnaryOp),
ListIndex(ListIndex),
ListSlice(ListSlice),
ListComprehension(ListComprehension),
InList(InList),
IsNull(IsNull),
IsNotNull(IsNotNull),
CaseExpr(CaseExpr),
ListLiteral(ListLiteral),
MapLiteral(MapLiteral),
ExistsPattern(PathPattern),
}
#[derive(Debug, Clone, PartialEq)]
pub struct NodePattern {
pub variable: Option<String>,
pub labels: Vec<String>,
pub properties: Option<BTreeMap<String, CypherExpr>>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RelDirection {
Right,
Left,
Both,
}
#[derive(Debug, Clone, PartialEq)]
pub struct RelPattern {
pub variable: Option<String>,
pub types: Vec<String>,
pub properties: Option<BTreeMap<String, CypherExpr>>,
pub direction: RelDirection,
pub min_hops: Option<u32>,
pub max_hops: Option<u32>,
}
#[derive(Debug, Clone, PartialEq)]
pub enum PathElement {
Node(NodePattern),
Rel(RelPattern),
}
#[derive(Debug, Clone, PartialEq)]
pub struct PathPattern {
pub variable: Option<String>,
pub elements: Vec<PathElement>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct MatchClause {
pub patterns: Vec<PathPattern>,
pub r#where: Option<CypherExpr>,
pub optional: bool,
}
#[derive(Debug, Clone, PartialEq)]
pub struct CreateClause {
pub patterns: Vec<PathPattern>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct MergeClause {
pub pattern: PathPattern,
pub on_create_set: Option<Vec<SetItem>>,
pub on_match_set: Option<Vec<SetItem>>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SetOperator {
Assign,
Update,
}
#[derive(Debug, Clone, PartialEq)]
pub struct SetItem {
pub target: CypherExpr,
pub value: CypherExpr,
pub operator: SetOperator,
}
#[derive(Debug, Clone, PartialEq)]
pub struct SetClause {
pub items: Vec<SetItem>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct DeleteClause {
pub expressions: Vec<CypherExpr>,
pub detach: bool,
}
#[derive(Debug, Clone, PartialEq)]
pub struct ReturnItem {
pub expr: CypherExpr,
pub alias: Option<String>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct OrderByItem {
pub expr: CypherExpr,
pub ascending: bool,
}
#[derive(Debug, Clone, PartialEq)]
pub struct ReturnClause {
pub items: Vec<ReturnItem>,
pub distinct: bool,
pub order_by: Option<Vec<OrderByItem>>,
pub skip: Option<CypherExpr>,
pub limit: Option<CypherExpr>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct WithClause {
pub items: Vec<ReturnItem>,
pub distinct: bool,
pub order_by: Option<Vec<OrderByItem>>,
pub skip: Option<CypherExpr>,
pub limit: Option<CypherExpr>,
pub r#where: Option<CypherExpr>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct UnwindClause {
pub expr: CypherExpr,
pub variable: String,
}
#[derive(Debug, Clone, PartialEq)]
pub enum CypherClause {
Match(MatchClause),
Create(CreateClause),
Merge(MergeClause),
Set(SetClause),
Delete(DeleteClause),
Return(ReturnClause),
With(WithClause),
Unwind(UnwindClause),
}
#[derive(Debug, Clone, PartialEq)]
pub struct CypherQuery {
pub clauses: Vec<CypherClause>,
}
impl CypherQuery {
#[must_use]
pub fn mutates_graph(&self) -> bool {
self.clauses.iter().any(|clause| {
matches!(
clause,
CypherClause::Create(_)
| CypherClause::Merge(_)
| CypherClause::Set(_)
| CypherClause::Delete(_)
)
})
}
}