use crate::ast::{Expression, ExpressionKind, Select};
use super::Table;
#[derive(Debug, PartialEq, Clone, Default)]
pub enum ConditionTree<'a> {
And(Vec<Expression<'a>>),
Or(Vec<Expression<'a>>),
Not(Box<Expression<'a>>),
Single(Box<Expression<'a>>),
#[default]
NoCondition,
NegativeCondition,
Exists(Box<Table<'a>>),
}
impl<'a> ConditionTree<'a> {
pub fn and<E>(mut self, other: E) -> ConditionTree<'a>
where
E: Into<Expression<'a>>,
{
match self {
Self::And(ref mut conditions) => {
conditions.push(other.into());
self
}
Self::Single(expr) => Self::And(vec![*expr, other.into()]),
_ => Self::And(vec![Expression::from(self), other.into()]),
}
}
pub fn or<E>(mut self, other: E) -> ConditionTree<'a>
where
E: Into<Expression<'a>>,
{
match self {
Self::Or(ref mut conditions) => {
conditions.push(other.into());
self
}
Self::Single(expr) => Self::Or(vec![*expr, other.into()]),
_ => Self::Or(vec![Expression::from(self), other.into()]),
}
}
pub fn not<E>(left: E) -> ConditionTree<'a>
where
E: Into<Expression<'a>>,
{
ConditionTree::Not(Box::new(left.into()))
}
pub fn single<E>(left: E) -> ConditionTree<'a>
where
E: Into<Expression<'a>>,
{
ConditionTree::Single(Box::new(left.into()))
}
pub fn exists<E>(select: E) -> ConditionTree<'a>
where
E: Into<Table<'a>>,
{
ConditionTree::Exists(Box::new(select.into()))
}
pub fn invert_if(self, invert: bool) -> ConditionTree<'a> {
if invert {
Self::not(self)
} else {
self
}
}
}
impl<'a> From<ConditionTree<'a>> for Expression<'a> {
fn from(ct: ConditionTree<'a>) -> Self {
Expression {
kind: ExpressionKind::ConditionTree(ct),
alias: None,
}
}
}
impl<'a> From<Select<'a>> for ConditionTree<'a> {
fn from(sel: Select<'a>) -> Self {
let exp = Expression {
kind: ExpressionKind::Value(Box::new(sel.into())),
alias: None,
};
ConditionTree::single(exp)
}
}