#![allow(clippy::module_name_repetitions)]
use crate::ast::{Expr, Ident, OrderByItem, Property};
#[derive(Clone, Debug, PartialEq)]
pub struct CypherMatchStmt {
pub optional: bool,
pub patterns: Vec<CypherPattern>,
pub where_clause: Option<Box<Expr>>,
pub return_clause: CypherReturn,
pub order_by: Vec<OrderByItem>,
pub skip: Option<Expr>,
pub limit: Option<Expr>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct CypherPattern {
pub variable: Option<Ident>,
pub elements: Vec<CypherElement>,
}
#[derive(Clone, Debug, PartialEq)]
pub enum CypherElement {
Node(CypherNode),
Rel(CypherRel),
}
#[derive(Clone, Debug, PartialEq)]
pub struct CypherNode {
pub variable: Option<Ident>,
pub labels: Vec<Ident>,
pub properties: Vec<Property>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct CypherRel {
pub variable: Option<Ident>,
pub rel_types: Vec<Ident>,
pub direction: CypherDirection,
pub var_length: Option<CypherVarLength>,
pub properties: Vec<Property>,
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub enum CypherDirection {
#[default]
Outgoing,
Incoming,
Undirected,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct CypherVarLength {
pub min: Option<u32>,
pub max: Option<u32>,
}
impl CypherVarLength {
#[must_use]
pub const fn exact(n: u32) -> Self {
Self {
min: Some(n),
max: Some(n),
}
}
#[must_use]
pub const fn range(min: Option<u32>, max: Option<u32>) -> Self {
Self { min, max }
}
#[must_use]
pub const fn unbounded() -> Self {
Self {
min: None,
max: None,
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct CypherReturn {
pub distinct: bool,
pub items: Vec<CypherReturnItem>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct CypherReturnItem {
pub expr: Expr,
pub alias: Option<Ident>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct CypherCreateStmt {
pub patterns: Vec<CypherPattern>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct CypherDeleteStmt {
pub detach: bool,
pub variables: Vec<Expr>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct CypherMergeStmt {
pub pattern: CypherPattern,
pub on_create: Vec<CypherSetItem>,
pub on_match: Vec<CypherSetItem>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct CypherSetItem {
pub property: Expr,
pub value: Expr,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_cypher_var_length_exact() {
let vl = CypherVarLength::exact(3);
assert_eq!(vl.min, Some(3));
assert_eq!(vl.max, Some(3));
}
#[test]
fn test_cypher_var_length_range() {
let vl = CypherVarLength::range(Some(1), Some(5));
assert_eq!(vl.min, Some(1));
assert_eq!(vl.max, Some(5));
}
#[test]
fn test_cypher_var_length_unbounded() {
let vl = CypherVarLength::unbounded();
assert_eq!(vl.min, None);
assert_eq!(vl.max, None);
}
#[test]
fn test_cypher_direction_default() {
let dir = CypherDirection::default();
assert_eq!(dir, CypherDirection::Outgoing);
}
#[test]
fn test_cypher_node_empty() {
let node = CypherNode {
variable: None,
labels: Vec::new(),
properties: Vec::new(),
};
assert!(node.variable.is_none());
assert!(node.labels.is_empty());
}
#[test]
fn test_cypher_pattern_empty() {
let pattern = CypherPattern {
variable: None,
elements: Vec::new(),
};
assert!(pattern.elements.is_empty());
}
}