use std::fmt::{Display, Formatter};
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Operator {
Minus,
Plus,
Asterisk,
Slash,
Percent,
Concat,
Eq, Neq, Lt, Lte, Gt, Gte,
Not,
And,
Or,
In,
NotIn,
Is,
IsNot,
Like,
}
impl Operator {
pub fn of(name: &str) -> anyhow::Result<Self> {
match name {
"-" => Ok(Self::Minus),
"+" => Ok(Self::Plus),
"*" => Ok(Self::Asterisk),
"/" => Ok(Self::Slash),
"%" => Ok(Self::Percent),
"||" => Ok(Self::Concat),
"=" => Ok(Self::Eq),
"<>" => Ok(Self::Neq),
"<" => Ok(Self::Lt),
"<=" => Ok(Self::Lte),
">" => Ok(Self::Gt),
">=" => Ok(Self::Gte),
"NOT" => Ok(Self::Not),
"AND" => Ok(Self::And),
"OR" => Ok(Self::Or),
"IN" => Ok(Self::In),
"NOT IN" => Ok(Self::NotIn),
"IS" => Ok(Self::Is),
"IS NOT" => Ok(Self::IsNot),
"LIKE" => Ok(Self::Like),
_ => anyhow::bail!("Unknown SQL operator: {}", name),
}
}
}
impl Display for Operator {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let s = match self {
Self::Minus => "-",
Self::Plus => "+",
Self::Asterisk => "*",
Self::Slash => "/",
Self::Percent => "%",
Self::Concat => "||",
Self::Eq => "=",
Self::Neq => "<>",
Self::Lt => "<",
Self::Lte => "<=",
Self::Gt => ">",
Self::Gte => ">=",
Self::Not => "NOT",
Self::And => "AND",
Self::Or => "OR",
Self::In => "IN",
Self::NotIn => "NOT IN",
Self::Is => "IS",
Self::IsNot => "IS NOT",
Self::Like => "LIKE",
};
write!(f, "{}", s)
}
}
impl TryFrom<crate::operator::Operator> for Operator {
type Error = ConversionError;
fn try_from(op: crate::operator::Operator) -> Result<Self, Self::Error> {
use crate::operator::Operator;
match op {
Operator::Minus => Ok(Self::Minus),
Operator::Plus => Ok(Self::Plus),
Operator::Asterisk => Ok(Self::Asterisk),
Operator::Slash => Ok(Self::Slash),
Operator::Percent => Ok(Self::Percent),
Operator::Concat => Ok(Self::Concat),
Operator::Eq => Ok(Self::Eq),
Operator::Neq => Ok(Self::Neq),
Operator::Lt => Ok(Self::Lt),
Operator::Lte => Ok(Self::Lte),
Operator::Gt => Ok(Self::Gt),
Operator::Gte => Ok(Self::Gte),
Operator::Not => Ok(Self::Not),
Operator::And => Ok(Self::And),
Operator::Or => Ok(Self::Or),
Operator::In => Ok(Self::In),
Operator::NotIn => Ok(Self::NotIn),
Operator::Is => Ok(Self::Is),
Operator::IsNot => Ok(Self::IsNot),
Operator::Like => Ok(Self::Like),
Operator::Range => Err(ConversionError::NoSqlEquivalent("Range (..)".to_string())),
Operator::RangeInclusive => {
Err(ConversionError::NoSqlEquivalent("Range (..=)".to_string()))
}
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ConversionError {
NoSqlEquivalent(String),
}
impl Display for ConversionError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Self::NoSqlEquivalent(op) => write!(f, "Operator {} has no SQL equivalent", op),
}
}
}
impl std::error::Error for ConversionError {}