use crate::value::Value;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum Consumer {
Collect,
Exists,
None,
Count,
First,
Single,
}
impl Consumer {
pub fn as_str(self) -> &'static str {
match self {
Consumer::Collect => "collect",
Consumer::Exists => "exists",
Consumer::None => "none",
Consumer::Count => "count",
Consumer::First => "first",
Consumer::Single => "single",
}
}
pub fn from_word(word: &str) -> Option<Self> {
Some(match word {
"collect" => Consumer::Collect,
"exists" => Consumer::Exists,
"none" => Consumer::None,
"count" => Consumer::Count,
"first" => Consumer::First,
"single" => Consumer::Single,
_ => return Option::None,
})
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum RelOp {
Eq,
Ne,
Lt,
Le,
Gt,
Ge,
}
impl RelOp {
pub fn as_str(self) -> &'static str {
match self {
RelOp::Eq => "==",
RelOp::Ne => "!=",
RelOp::Lt => "<",
RelOp::Le => "<=",
RelOp::Gt => ">",
RelOp::Ge => ">=",
}
}
pub fn from_word(word: &str) -> Option<Self> {
Some(match word {
"==" => RelOp::Eq,
"!=" => RelOp::Ne,
"<" => RelOp::Lt,
"<=" => RelOp::Le,
">" => RelOp::Gt,
">=" => RelOp::Ge,
_ => return None,
})
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum BinaryOp {
Eq,
Ne,
Lt,
Le,
Gt,
Ge,
Add,
Sub,
Mul,
Div,
Mod,
}
impl BinaryOp {
pub fn as_str(self) -> &'static str {
match self {
BinaryOp::Eq => "==",
BinaryOp::Ne => "!=",
BinaryOp::Lt => "<",
BinaryOp::Le => "<=",
BinaryOp::Gt => ">",
BinaryOp::Ge => ">=",
BinaryOp::Add => "+",
BinaryOp::Sub => "-",
BinaryOp::Mul => "*",
BinaryOp::Div => "/",
BinaryOp::Mod => "%",
}
}
pub fn from_word(word: &str) -> Option<Self> {
Some(match word {
"==" => BinaryOp::Eq,
"!=" => BinaryOp::Ne,
"<" => BinaryOp::Lt,
"<=" => BinaryOp::Le,
">" => BinaryOp::Gt,
">=" => BinaryOp::Ge,
"+" => BinaryOp::Add,
"-" => BinaryOp::Sub,
"*" => BinaryOp::Mul,
"/" => BinaryOp::Div,
"%" => BinaryOp::Mod,
_ => return None,
})
}
pub fn is_comparison(self) -> bool {
matches!(
self,
BinaryOp::Eq | BinaryOp::Ne | BinaryOp::Lt | BinaryOp::Le | BinaryOp::Gt | BinaryOp::Ge
)
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum UnaryOp {
Not,
Neg,
}
impl UnaryOp {
pub fn as_str(self) -> &'static str {
match self {
UnaryOp::Not => "!",
UnaryOp::Neg => "-",
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum LogicalOp {
And,
Or,
}
impl LogicalOp {
pub fn as_str(self) -> &'static str {
match self {
LogicalOp::And => "&&",
LogicalOp::Or => "||",
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum Expr {
Lit(Value),
Ident {
name: String,
},
Outer {
levels: usize,
name: String,
},
Binding {
index: usize,
},
Member {
recv: Box<Expr>,
name: String,
},
Index {
recv: Box<Expr>,
index: Box<Expr>,
},
Call {
recv: Option<Box<Expr>>,
name: String,
args: Vec<Expr>,
},
Unary {
op: UnaryOp,
expr: Box<Expr>,
},
Binary {
op: BinaryOp,
left: Box<Expr>,
right: Box<Expr>,
},
Logical {
op: LogicalOp,
left: Box<Expr>,
right: Box<Expr>,
},
In {
left: Box<Expr>,
right: Box<Expr>,
},
Range {
lo: Option<Box<Expr>>,
hi: Option<Box<Expr>>,
exclusive_end: bool,
},
}
#[derive(Clone, Debug, PartialEq)]
pub struct OrderSpec {
pub expr: Expr,
pub desc: bool,
}
#[derive(Clone, Debug, PartialEq)]
pub enum SelectItem {
Field {
name: String,
expr: Expr,
lift: usize,
},
Collect {
name: String,
op: Box<OpNode>,
},
}
impl SelectItem {
pub fn name(&self) -> &str {
match self {
SelectItem::Field { name, .. } | SelectItem::Collect { name, .. } => name,
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct CountCmp {
pub op: RelOp,
pub value: f64,
}
#[derive(Clone, Debug, PartialEq)]
pub struct OpNode {
pub receiver: Expr,
pub op: Consumer,
pub sub: Subquery,
pub count_cmp: Option<CountCmp>,
pub distinct: bool,
}
#[derive(Clone, Debug, PartialEq)]
pub struct Follow {
pub receiver: Expr,
pub distinct: bool,
pub r#where: Option<Expr>,
pub frontier: Option<Expr>,
pub depth: Option<u32>,
pub by: Option<Expr>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct Subquery {
pub from: Vec<Expr>,
pub r#where: Option<Where>,
pub select: Vec<SelectItem>,
pub order_by: Option<Vec<OrderSpec>>,
pub follow: Option<Follow>,
pub values: bool,
pub limit: Option<Expr>,
pub offset: Option<Expr>,
}
#[derive(Clone, Debug, PartialEq)]
pub enum Where {
And { parts: Vec<Where> },
Or { parts: Vec<Where> },
Not { expr: Box<Where> },
Scalar { expr: Expr },
Op(Box<OpNode>),
}
#[derive(Clone, Debug, PartialEq)]
pub struct Query {
pub source: Expr,
pub from: Vec<Expr>,
pub r#where: Option<Where>,
pub select: Vec<SelectItem>,
pub order_by: Option<Vec<OrderSpec>>,
pub consumer: Consumer,
pub follow: Option<Follow>,
pub distinct: bool,
pub values: bool,
pub limit: Option<Expr>,
pub offset: Option<Expr>,
}