grafbase_sql_ast/ast/
conditions.rs

1use crate::ast::{Expression, ExpressionKind, Select};
2
3use super::Table;
4
5/// Tree structures and leaves for condition building.
6#[derive(Debug, PartialEq, Clone, Default)]
7pub enum ConditionTree<'a> {
8    /// `(left_expression AND right_expression)`
9    And(Vec<Expression<'a>>),
10    /// `(left_expression OR right_expression)`
11    Or(Vec<Expression<'a>>),
12    /// `(NOT expression)`
13    Not(Box<Expression<'a>>),
14    /// A single expression leaf
15    Single(Box<Expression<'a>>),
16    /// A leaf that does nothing to the condition, `1=1`
17    #[default]
18    NoCondition,
19    /// A leaf that cancels the condition, `1=0`
20    NegativeCondition,
21    /// Exists condition
22    Exists(Box<Table<'a>>),
23}
24
25impl<'a> ConditionTree<'a> {
26    /// An `AND` statement, is true when both sides are true.
27    pub fn and<E>(mut self, other: E) -> ConditionTree<'a>
28    where
29        E: Into<Expression<'a>>,
30    {
31        match self {
32            Self::And(ref mut conditions) => {
33                conditions.push(other.into());
34                self
35            }
36            Self::Single(expr) => Self::And(vec![*expr, other.into()]),
37            _ => Self::And(vec![Expression::from(self), other.into()]),
38        }
39    }
40
41    /// An `OR` statement, is true when one side is true.
42    pub fn or<E>(mut self, other: E) -> ConditionTree<'a>
43    where
44        E: Into<Expression<'a>>,
45    {
46        match self {
47            Self::Or(ref mut conditions) => {
48                conditions.push(other.into());
49                self
50            }
51            Self::Single(expr) => Self::Or(vec![*expr, other.into()]),
52            _ => Self::Or(vec![Expression::from(self), other.into()]),
53        }
54    }
55
56    /// A `NOT` statement, is true when the expression is false.
57    pub fn not<E>(left: E) -> ConditionTree<'a>
58    where
59        E: Into<Expression<'a>>,
60    {
61        ConditionTree::Not(Box::new(left.into()))
62    }
63
64    /// A single leaf, is true when the expression is true.
65    pub fn single<E>(left: E) -> ConditionTree<'a>
66    where
67        E: Into<Expression<'a>>,
68    {
69        ConditionTree::Single(Box::new(left.into()))
70    }
71
72    /// True if a nested table has any values.
73    pub fn exists<E>(select: E) -> ConditionTree<'a>
74    where
75        E: Into<Table<'a>>,
76    {
77        ConditionTree::Exists(Box::new(select.into()))
78    }
79
80    /// Inverts the entire condition tree if condition is met.
81    pub fn invert_if(self, invert: bool) -> ConditionTree<'a> {
82        if invert {
83            Self::not(self)
84        } else {
85            self
86        }
87    }
88}
89
90impl<'a> From<ConditionTree<'a>> for Expression<'a> {
91    fn from(ct: ConditionTree<'a>) -> Self {
92        Expression {
93            kind: ExpressionKind::ConditionTree(ct),
94            alias: None,
95        }
96    }
97}
98
99impl<'a> From<Select<'a>> for ConditionTree<'a> {
100    fn from(sel: Select<'a>) -> Self {
101        let exp = Expression {
102            kind: ExpressionKind::Value(Box::new(sel.into())),
103            alias: None,
104        };
105
106        ConditionTree::single(exp)
107    }
108}