use std::fmt;
#[derive(Debug, Clone, PartialEq)]
pub enum BooleanExpr {
Or(Box<BooleanExpr>, Box<BooleanExpr>),
And(Box<BooleanExpr>, Box<BooleanExpr>),
Not(Box<BooleanExpr>),
Literal(bool),
Variable(String),
Relational(RelationalExpr),
}
#[derive(Debug, Clone, PartialEq)]
pub enum RelationalExpr {
Equality {
left: ValueExpr,
op: EqualityOp,
right: ValueExpr,
},
Comparison {
left: ValueExpr,
op: ComparisonOp,
right: ValueExpr,
},
Like {
expr: ValueExpr,
pattern: String,
escape: Option<String>,
negated: bool,
},
Between {
expr: ValueExpr,
lower: ValueExpr,
upper: ValueExpr,
negated: bool,
},
In {
expr: ValueExpr,
values: Vec<ValueLiteral>,
negated: bool,
},
IsNull {
expr: ValueExpr,
negated: bool,
},
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum EqualityOp {
Equal, NotEqual, }
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ComparisonOp {
GreaterThan, GreaterOrEqual, LessThan, LessOrEqual, }
#[derive(Debug, Clone, PartialEq)]
pub enum ValueExpr {
Add(Box<ValueExpr>, Box<ValueExpr>),
Subtract(Box<ValueExpr>, Box<ValueExpr>),
Multiply(Box<ValueExpr>, Box<ValueExpr>),
Divide(Box<ValueExpr>, Box<ValueExpr>),
Modulo(Box<ValueExpr>, Box<ValueExpr>),
UnaryPlus(Box<ValueExpr>),
UnaryMinus(Box<ValueExpr>),
Literal(ValueLiteral),
Variable(String),
}
#[derive(Debug, Clone, PartialEq)]
pub enum ValueLiteral {
Integer(i64),
Float(f64),
String(String),
Null,
Boolean(bool),
}
impl fmt::Display for BooleanExpr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
BooleanExpr::Or(left, right) => write!(f, "({} OR {})", left, right),
BooleanExpr::And(left, right) => write!(f, "({} AND {})", left, right),
BooleanExpr::Not(expr) => write!(f, "NOT {}", expr),
BooleanExpr::Literal(b) => write!(f, "{}", if *b { "TRUE" } else { "FALSE" }),
BooleanExpr::Variable(name) => write!(f, "{}", name),
BooleanExpr::Relational(rel) => write!(f, "{}", rel),
}
}
}
impl fmt::Display for RelationalExpr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
RelationalExpr::Equality { left, op, right } => {
write!(f, "{} {} {}", left, op, right)
}
RelationalExpr::Comparison { left, op, right } => {
write!(f, "{} {} {}", left, op, right)
}
RelationalExpr::Like { expr, pattern, escape, negated } => {
if *negated {
write!(f, "{} NOT LIKE '{}'", expr, pattern)?;
} else {
write!(f, "{} LIKE '{}'", expr, pattern)?;
}
if let Some(esc) = escape {
write!(f, " ESCAPE '{}'", esc)?;
}
Ok(())
}
RelationalExpr::Between { expr, lower, upper, negated } => {
if *negated {
write!(f, "{} NOT BETWEEN {} AND {}", expr, lower, upper)
} else {
write!(f, "{} BETWEEN {} AND {}", expr, lower, upper)
}
}
RelationalExpr::In { expr, values, negated } => {
if *negated {
write!(f, "{} NOT IN (", expr)?;
} else {
write!(f, "{} IN (", expr)?;
}
for (i, val) in values.iter().enumerate() {
if i > 0 {
write!(f, ", ")?;
}
write!(f, "{}", val)?;
}
write!(f, ")")
}
RelationalExpr::IsNull { expr, negated } => {
if *negated {
write!(f, "{} IS NOT NULL", expr)
} else {
write!(f, "{} IS NULL", expr)
}
}
}
}
}
impl fmt::Display for EqualityOp {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
EqualityOp::Equal => write!(f, "="),
EqualityOp::NotEqual => write!(f, "<>"),
}
}
}
impl fmt::Display for ComparisonOp {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ComparisonOp::GreaterThan => write!(f, ">"),
ComparisonOp::GreaterOrEqual => write!(f, ">="),
ComparisonOp::LessThan => write!(f, "<"),
ComparisonOp::LessOrEqual => write!(f, "<="),
}
}
}
impl fmt::Display for ValueExpr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ValueExpr::Add(left, right) => write!(f, "({} + {})", left, right),
ValueExpr::Subtract(left, right) => write!(f, "({} - {})", left, right),
ValueExpr::Multiply(left, right) => write!(f, "({} * {})", left, right),
ValueExpr::Divide(left, right) => write!(f, "({} / {})", left, right),
ValueExpr::Modulo(left, right) => write!(f, "({} % {})", left, right),
ValueExpr::UnaryPlus(expr) => write!(f, "+{}", expr),
ValueExpr::UnaryMinus(expr) => write!(f, "-{}", expr),
ValueExpr::Literal(lit) => write!(f, "{}", lit),
ValueExpr::Variable(name) => write!(f, "{}", name),
}
}
}
impl fmt::Display for ValueLiteral {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ValueLiteral::Integer(n) => write!(f, "{}", n),
ValueLiteral::Float(n) => write!(f, "{}", n),
ValueLiteral::String(s) => write!(f, "'{}'", s),
ValueLiteral::Null => write!(f, "NULL"),
ValueLiteral::Boolean(b) => write!(f, "{}", if *b { "TRUE" } else { "FALSE" }),
}
}
}