use crate::filter::CmpOp;
use core_storage::Value;
#[derive(Debug, Clone, PartialEq)]
pub enum LimitSkip {
Exact(u64),
Param(String),
}
#[derive(Debug, Clone, PartialEq)]
pub struct OptionalClause {
pub patterns: Vec<Pattern>,
pub where_expr: Option<Expr>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Query {
pub matches: Vec<Pattern>,
pub optional_clauses: Vec<OptionalClause>,
pub where_expr: Option<Expr>,
pub unwinds: Vec<UnwindClause>,
pub post_unwind_where: Option<Expr>,
pub stages: Vec<WithStage>,
pub returns: Vec<RetItem>,
pub distinct: bool,
pub order_by: Vec<OrderItem>,
pub skip: Option<LimitSkip>,
pub limit: Option<LimitSkip>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct UnwindClause {
pub list: UnwindExpr,
pub alias: String,
}
#[derive(Debug, Clone, PartialEq)]
pub enum UnwindExpr {
Lit(Vec<Value>),
Prop { var: String, field: String },
Var(String),
}
#[derive(Debug, Clone, PartialEq)]
pub struct WithStage {
pub items: Vec<RetItem>,
pub where_expr: Option<Expr>,
pub order_by: Vec<OrderItem>,
pub skip: Option<LimitSkip>,
pub limit: Option<LimitSkip>,
pub matches: Vec<Pattern>,
pub optional_clauses: Vec<OptionalClause>,
pub unwinds: Vec<UnwindClause>,
pub post_where: Option<Expr>,
}
#[derive(Debug, Clone, PartialEq)]
pub enum AggFunc {
Count,
Sum,
Avg,
Min,
Max,
Collect,
}
#[derive(Debug, Clone, PartialEq)]
pub enum AggArg {
Star,
Var(String),
Prop { var: String, field: String },
Distinct(Box<AggArg>),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct HopRange {
pub min: u8,
pub max: u8,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Pattern {
pub start: NodePat,
pub chain: Vec<(RelPat, NodePat)>,
pub shortest: bool,
}
#[derive(Debug, Clone, PartialEq)]
pub struct NodePat {
pub var: Option<String>,
pub label: Option<String>,
pub props: Vec<(String, Operand)>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RelDir {
Right,
Left,
Undirected,
}
#[derive(Debug, Clone, PartialEq)]
pub struct RelPat {
pub var: Option<String>,
pub etypes: Vec<String>,
pub dir: RelDir,
pub hops: Option<HopRange>,
}
#[derive(Debug, Clone, PartialEq)]
pub enum Expr {
And(Box<Expr>, Box<Expr>),
Or(Box<Expr>, Box<Expr>),
Not(Box<Expr>),
Cmp {
lhs: Operand,
op: CmpOp,
rhs: Operand,
},
Truthy(Operand),
IsNull(Operand),
IsNotNull(Operand),
In {
expr: Operand,
list: Vec<Operand>,
},
}
#[derive(Debug, Clone, PartialEq)]
pub enum Operand {
Prop {
var: String,
field: String,
},
Lit(Value),
Param(String),
Var(String),
FuncCall {
name: String,
args: Vec<Operand>,
},
BinArith {
op: ArithOp,
left: Box<Operand>,
right: Box<Operand>,
},
Index {
base: Box<Operand>,
index: Box<Operand>,
},
Case {
branches: Vec<(Expr, Operand)>,
default: Option<Box<Operand>>,
},
}
pub fn operand_label(op: &Operand) -> String {
match op {
Operand::Var(v) => v.clone(),
Operand::Prop { var, field } => format!("{var}.{field}"),
Operand::Lit(_) => "<lit>".to_string(),
Operand::Param(p) => format!("${p}"),
Operand::FuncCall { name, .. } => format!("{name}(...)"),
Operand::BinArith { .. } => "<arith>".to_string(),
Operand::Case { .. } => "<case>".to_string(),
Operand::Index { base, index } => {
format!("{}[{}]", operand_label(base), subscript_label(index))
}
}
}
fn subscript_label(op: &Operand) -> String {
match op {
Operand::Lit(Value::Int(n)) => n.to_string(),
other => operand_label(other),
}
}
pub fn ret_val_label(value: &RetVal) -> Option<String> {
match value {
RetVal::Var(v) => Some(v.clone()),
RetVal::Prop { var, field } => Some(format!("{var}.{field}")),
RetVal::FuncCall { name, args } => {
let arg_strs: Vec<String> = args.iter().map(operand_label).collect();
Some(format!("{name}({})", arg_strs.join(", ")))
}
RetVal::ScalarExpr(op @ Operand::Index { .. }) => Some(operand_label(op)),
RetVal::ScalarExpr(_) => Some("<expr>".to_string()),
RetVal::Agg { .. } => None,
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum ArithOp {
Add,
Sub,
Mul,
Div,
}
#[derive(Debug, Clone, PartialEq)]
pub enum RetVal {
Var(String),
Prop {
var: String,
field: String,
},
Agg {
func: AggFunc,
arg: AggArg,
},
FuncCall {
name: String,
args: Vec<Operand>,
},
ScalarExpr(Operand),
}
#[derive(Debug, Clone, PartialEq)]
pub struct RetItem {
pub value: RetVal,
pub alias: Option<String>,
}
#[derive(Debug, Clone, PartialEq)]
pub enum OrderTarget {
Alias(String),
Var(String),
Prop { var: String, field: String },
}
#[derive(Debug, Clone, PartialEq)]
pub struct OrderItem {
pub target: OrderTarget,
pub descending: bool,
}
#[derive(Debug, Clone, PartialEq)]
pub enum WriteStatement {
Create(CreateStmt),
MatchSet(MatchSetStmt),
MatchDelete(MatchDeleteStmt),
MatchDeleteNode(MatchDeleteNodeStmt),
Merge(MergeStmt),
}
#[derive(Debug, Clone, PartialEq)]
pub struct CreateStmt {
pub nodes: Vec<CreateNode>,
pub edges: Vec<CreateEdge>,
pub returns: Option<Vec<RetItem>>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct CreateNode {
pub var: Option<String>,
pub label: String,
pub props: Vec<(String, core_storage::Value)>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct CreateEdge {
pub src_var: String,
pub etype: String,
pub dst_var: String,
}
#[derive(Debug, Clone, PartialEq)]
pub struct MatchSetStmt {
pub matches: Vec<Pattern>,
pub where_expr: Option<Expr>,
pub sets: Vec<SetClause>,
pub returns: Option<Vec<RetItem>>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct SetClause {
pub var: String,
pub field: String,
pub value: Operand,
}
#[derive(Debug, Clone, PartialEq)]
pub struct MatchDeleteStmt {
pub matches: Vec<Pattern>,
pub where_expr: Option<Expr>,
pub deletes: Vec<EdgeDelete>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct EdgeDelete {
pub rel_var: String,
pub etype: String,
pub src_var: String,
pub dst_var: String,
}
#[derive(Debug, Clone, PartialEq)]
pub struct MatchDeleteNodeStmt {
pub matches: Vec<Pattern>,
pub where_expr: Option<Expr>,
pub node_vars: Vec<String>,
pub detach: bool,
}
#[derive(Debug, Clone, PartialEq)]
pub struct MergeStmt {
pub label: String,
pub key_field: String,
pub key_value: core_storage::Value,
pub ns: Option<core_storage::Value>,
pub var: Option<String>,
pub on_create: Vec<SetClause>,
pub on_match: Vec<SetClause>,
pub returns: Option<Vec<RetItem>>,
}