use serde::{Deserialize, Serialize};
use std::fmt;
use super::ExprDataType;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum Expr {
Column(String),
Literal(Literal),
BinaryOp {
left: Box<Expr>,
op: BinaryOperator,
right: Box<Expr>,
},
UnaryOp {
op: UnaryOperator,
expr: Box<Expr>,
},
Function {
name: String,
args: Vec<Expr>,
},
Case {
when_then: Vec<(Expr, Expr)>,
else_expr: Option<Box<Expr>>,
},
Cast {
expr: Box<Expr>,
data_type: ExprDataType,
},
Coalesce {
exprs: Vec<Expr>,
},
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum Literal {
Null,
Boolean(bool),
Integer(i64),
Float(f64),
String(String),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum BinaryOperator {
Add,
Subtract,
Multiply,
Divide,
Modulo,
Equal,
NotEqual,
LessThan,
LessThanOrEqual,
GreaterThan,
GreaterThanOrEqual,
And,
Or,
BitwiseAnd,
BitwiseOr,
BitwiseXor,
Like,
Concat,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum UnaryOperator {
Negate,
Not,
IsNull,
IsNotNull,
}
impl fmt::Display for Literal {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Null => write!(f, "NULL"),
Self::Boolean(b) => write!(f, "{}", if *b { "TRUE" } else { "FALSE" }),
Self::Integer(i) => write!(f, "{}", i),
Self::Float(fl) => write!(f, "{}", fl),
Self::String(s) => write!(f, "'{}'", s.replace('\'', "''")), }
}
}
impl fmt::Display for BinaryOperator {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Add => write!(f, "+"),
Self::Subtract => write!(f, "-"),
Self::Multiply => write!(f, "*"),
Self::Divide => write!(f, "/"),
Self::Modulo => write!(f, "%"),
Self::Equal => write!(f, "="),
Self::NotEqual => write!(f, "<>"),
Self::LessThan => write!(f, "<"),
Self::LessThanOrEqual => write!(f, "<="),
Self::GreaterThan => write!(f, ">"),
Self::GreaterThanOrEqual => write!(f, ">="),
Self::And => write!(f, "AND"),
Self::Or => write!(f, "OR"),
Self::BitwiseAnd => write!(f, "&"),
Self::BitwiseOr => write!(f, "|"),
Self::BitwiseXor => write!(f, "^"),
Self::Like => write!(f, "LIKE"),
Self::Concat => write!(f, "||"),
}
}
}
impl fmt::Display for UnaryOperator {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Negate => write!(f, "-"),
Self::Not => write!(f, "NOT "),
Self::IsNull => write!(f, "IS NULL"),
Self::IsNotNull => write!(f, "IS NOT NULL"),
}
}
}
impl fmt::Display for Expr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Column(name) => write!(f, "{}", name),
Self::Literal(value) => write!(f, "{}", value),
Self::BinaryOp { left, op, right } => {
write!(f, "({} {} {})", left, op, right)
}
Self::UnaryOp { op, expr } => match op {
UnaryOperator::IsNull | UnaryOperator::IsNotNull => {
write!(f, "({} {})", expr, op)
}
_ => write!(f, "{}({})", op, expr),
},
Self::Function { name, args } => {
write!(f, "{}(", name)?;
for (i, arg) in args.iter().enumerate() {
if i > 0 {
write!(f, ", ")?;
}
write!(f, "{}", arg)?;
}
write!(f, ")")
}
Self::Case {
when_then,
else_expr,
} => {
write!(f, "CASE")?;
for (when, then) in when_then {
write!(f, " WHEN {} THEN {}", when, then)?;
}
if let Some(else_expr) = else_expr {
write!(f, " ELSE {}", else_expr)?;
}
write!(f, " END")
}
Self::Cast { expr, data_type } => {
write!(f, "CAST({} AS {})", expr, data_type)
}
Self::Coalesce { exprs } => {
write!(f, "COALESCE(")?;
for (i, expr) in exprs.iter().enumerate() {
if i > 0 {
write!(f, ", ")?;
}
write!(f, "{}", expr)?;
}
write!(f, ")")
}
}
}
}
impl Expr {
pub fn col(name: impl Into<String>) -> Self {
Self::Column(name.into())
}
pub fn lit<T: Into<Literal>>(value: T) -> Self {
Self::Literal(value.into())
}
pub fn null() -> Self {
Self::Literal(Literal::Null)
}
pub fn call(name: impl Into<String>, args: Vec<Expr>) -> Self {
Self::Function {
name: name.into(),
args,
}
}
pub fn binary(left: Expr, op: BinaryOperator, right: Expr) -> Self {
Self::BinaryOp {
left: Box::new(left),
op,
right: Box::new(right),
}
}
pub fn unary(op: UnaryOperator, expr: Expr) -> Self {
Self::UnaryOp {
op,
expr: Box::new(expr),
}
}
pub fn case(when_then: Vec<(Expr, Expr)>, else_expr: Option<Expr>) -> Self {
Self::Case {
when_then,
else_expr: else_expr.map(Box::new),
}
}
pub fn cast(expr: Expr, data_type: ExprDataType) -> Self {
Self::Cast {
expr: Box::new(expr),
data_type,
}
}
pub fn coalesce(exprs: Vec<Expr>) -> Self {
Self::Coalesce { exprs }
}
pub fn add(self, other: Expr) -> Self {
Self::binary(self, BinaryOperator::Add, other)
}
pub fn sub(self, other: Expr) -> Self {
Self::binary(self, BinaryOperator::Subtract, other)
}
pub fn mul(self, other: Expr) -> Self {
Self::binary(self, BinaryOperator::Multiply, other)
}
pub fn div(self, other: Expr) -> Self {
Self::binary(self, BinaryOperator::Divide, other)
}
pub fn modulo(self, other: Expr) -> Self {
Self::binary(self, BinaryOperator::Modulo, other)
}
pub fn eq(self, other: Expr) -> Self {
Self::binary(self, BinaryOperator::Equal, other)
}
pub fn neq(self, other: Expr) -> Self {
Self::binary(self, BinaryOperator::NotEqual, other)
}
pub fn lt(self, other: Expr) -> Self {
Self::binary(self, BinaryOperator::LessThan, other)
}
pub fn lte(self, other: Expr) -> Self {
Self::binary(self, BinaryOperator::LessThanOrEqual, other)
}
pub fn gt(self, other: Expr) -> Self {
Self::binary(self, BinaryOperator::GreaterThan, other)
}
pub fn gte(self, other: Expr) -> Self {
Self::binary(self, BinaryOperator::GreaterThanOrEqual, other)
}
pub fn and(self, other: Expr) -> Self {
Self::binary(self, BinaryOperator::And, other)
}
pub fn or(self, other: Expr) -> Self {
Self::binary(self, BinaryOperator::Or, other)
}
pub fn like(self, pattern: impl Into<String>) -> Self {
Self::binary(self, BinaryOperator::Like, Self::lit(pattern.into()))
}
pub fn concat(self, other: Expr) -> Self {
Self::binary(self, BinaryOperator::Concat, other)
}
pub fn negate(self) -> Self {
Self::unary(UnaryOperator::Negate, self)
}
pub fn not(self) -> Self {
Self::unary(UnaryOperator::Not, self)
}
pub fn is_null(self) -> Self {
Self::unary(UnaryOperator::IsNull, self)
}
pub fn is_not_null(self) -> Self {
Self::unary(UnaryOperator::IsNotNull, self)
}
pub fn to_boolean(self) -> Self {
Self::cast(self, ExprDataType::Boolean)
}
pub fn to_integer(self) -> Self {
Self::cast(self, ExprDataType::Integer)
}
pub fn to_float(self) -> Self {
Self::cast(self, ExprDataType::Float)
}
pub fn to_string(self) -> Self {
Self::cast(self, ExprDataType::String)
}
pub fn to_date(self) -> Self {
Self::cast(self, ExprDataType::Date)
}
pub fn to_timestamp(self) -> Self {
Self::cast(self, ExprDataType::Timestamp)
}
}
impl From<bool> for Literal {
fn from(value: bool) -> Self {
Self::Boolean(value)
}
}
impl From<i64> for Literal {
fn from(value: i64) -> Self {
Self::Integer(value)
}
}
impl From<i32> for Literal {
fn from(value: i32) -> Self {
Self::Integer(value as i64)
}
}
impl From<f64> for Literal {
fn from(value: f64) -> Self {
Self::Float(value)
}
}
impl From<f32> for Literal {
fn from(value: f32) -> Self {
Self::Float(value as f64)
}
}
impl From<String> for Literal {
fn from(value: String) -> Self {
Self::String(value)
}
}
impl From<&str> for Literal {
fn from(value: &str) -> Self {
Self::String(value.to_string())
}
}