lumus_sql_builder/sqlite/
condition.rs

1use super::{escape_value, BuildableStatement};
2use crate::errors::SqlBuilderError;
3
4/// Represents a WHERE clause builder for SQL queries.
5#[derive(Debug)]
6pub struct Where {
7    statement: String,
8}
9
10impl Where {
11    /// Creates a new `Where` instance with an empty statement.
12    /// # Example
13    /// ```
14    /// use lumus_sql_builder::sqlite::Where;
15    ///
16    /// let mut condition = Where::new();
17    /// condition.equal_to("name", "Dayvson Spacca");
18    ///
19    /// assert_eq!(condition.build(), "name = 'Dayvson Spacca'")
20    /// ```
21    pub fn new() -> Self {
22        Self {
23            statement: String::new(),
24        }
25    }
26
27    /// Creates a new `Where` instance with a specified initial statement.
28    /// # Example
29    /// ```
30    /// use lumus_sql_builder::sqlite::Where;
31    ///
32    /// let mut condition = Where::from("name = 'Dayvson Spacca'");
33    /// condition.and().greater_than("age", "21");
34    ///
35    /// assert_eq!(condition.build(), "name = 'Dayvson Spacca' AND age > '21'");
36    /// ```
37    pub fn from(statement: &str) -> Self {
38        Self {
39            statement: statement.to_string(),
40        }
41    }
42
43    /// Adds an equality condition (`field = value`) to the WHERE clause.
44    pub fn equal_to(&mut self, field: &str, value: &str) -> &mut Self {
45        self.add_predicate(field, "=", escape_value(value).as_str())
46            .unwrap();
47        self
48    }
49
50    /// Adds a not equal condition (`field != value`) to the WHERE clause.
51    pub fn not_equal_to(&mut self, field: &str, value: &str) -> &mut Self {
52        self.add_predicate(field, "!=", escape_value(value).as_str())
53            .unwrap();
54        self
55    }
56
57    /// Adds a greater than condition (`field > value`) to the WHERE clause.
58    pub fn greater_than(&mut self, field: &str, value: &str) -> &mut Self {
59        self.add_predicate(field, ">", escape_value(value).as_str())
60            .unwrap();
61        self
62    }
63
64    /// Adds a greater than or equal condition (`field >= value`) to the WHERE clause.
65    pub fn greater_than_equal(&mut self, field: &str, value: &str) -> &mut Self {
66        self.add_predicate(field, ">=", escape_value(value).as_str())
67            .unwrap();
68        self
69    }
70
71    /// Adds a less than condition (`field < value`) to the WHERE clause.
72    pub fn less_than(&mut self, field: &str, value: &str) -> &mut Self {
73        self.add_predicate(field, "<", escape_value(value).as_str())
74            .unwrap();
75        self
76    }
77
78    /// Adds a less than or equal condition (`field <= value`) to the WHERE clause.
79    pub fn less_than_equal(&mut self, field: &str, value: &str) -> &mut Self {
80        self.add_predicate(field, "<=", escape_value(value).as_str())
81            .unwrap();
82        self
83    }
84
85    /// Adds a `IS NULL` condition (`field IS NULL`) to the WHERE clause.
86    pub fn is_null(&mut self, field: &str) -> &mut Self {
87        self.add_predicate(field, "IS NULL", "").unwrap();
88        self
89    }
90
91    /// Adds a `IS NOT NULL` condition (`field IS NOT NULL`) to the WHERE clause.
92    pub fn is_not_null(&mut self, field: &str) -> &mut Self {
93        self.add_predicate(field, "IS NOT NULL", "").unwrap();
94        self
95    }
96
97    /// Adds an `IN` condition (`field IN (values)`) to the WHERE clause.
98    pub fn inside(&mut self, field: &str, values: Vec<&str>) -> &mut Self {
99        self.add_predicate(
100            field,
101            "IN",
102            &format!(
103                "({})",
104                values
105                    .iter()
106                    .map(|v| escape_value(v))
107                    .collect::<Vec<_>>()
108                    .join(", ")
109            ),
110        )
111        .unwrap();
112        self
113    }
114
115    /// Adds a `NOT IN` condition (`field NOT IN (values)`) to the WHERE clause.
116    pub fn not_inside(&mut self, field: &str, values: Vec<&str>) -> &mut Self {
117        self.add_predicate(
118            field,
119            "NOT IN",
120            &format!(
121                "({})",
122                values
123                    .iter()
124                    .map(|v| escape_value(v))
125                    .collect::<Vec<_>>()
126                    .join(", ")
127            ),
128        )
129        .unwrap();
130        self
131    }
132
133    /// Adds a `LIKE` condition (`field LIKE value`) to the WHERE clause.
134    pub fn like(&mut self, field: &str, value: &str) -> &mut Self {
135        self.add_predicate(field, "LIKE", escape_value(value).as_str())
136            .unwrap();
137        self
138    }
139
140    /// Adds a `NOT LIKE` condition (`field NOT LIKE value`) to the WHERE clause.
141    pub fn not_like(&mut self, field: &str, value: &str) -> &mut Self {
142        self.add_predicate(field, "NOT LIKE", escape_value(value).as_str())
143            .unwrap();
144        self
145    }
146
147    /// Appends `AND` to the current statement in the WHERE clause.
148    pub fn and(&mut self) -> &mut Self {
149        self.statement.push_str(" AND ");
150        self
151    }
152
153    /// Appends `OR` to the current statement in the WHERE clause.
154    pub fn or(&mut self) -> &mut Self {
155        self.statement.push_str(" OR ");
156        self
157    }
158
159    /// Appends a left parenthesis `(` to the current statement in the WHERE clause.
160    pub fn nest(&mut self) -> &mut Self {
161        self.statement.push('(');
162        self
163    }
164
165    /// Appends a right parenthesis `)` to the current statement in the WHERE clause.
166    pub fn unnest(&mut self) -> &mut Self {
167        self.statement.push(')');
168        self
169    }
170
171    /// Constructs and returns the final SQL statement represented by the WHERE clause.
172    pub fn build(&self) -> String {
173        self.statement.trim().to_string()
174    }
175
176    /// Internal method to add a predicate (`field predicate value`) to the WHERE clause.
177    fn add_predicate(
178        &mut self,
179        field: &str,
180        predicate: &str,
181        value: &str,
182    ) -> Result<&mut Self, SqlBuilderError> {
183        if field.is_empty() {
184            return Err(SqlBuilderError::EmptyColumnName);
185        }
186
187        if predicate == "IS NULL" || predicate == "IS NOT NULL" {
188            self.statement.push_str(&format!("{} {}", field, predicate));
189            return Ok(self);
190        }
191
192        if value.is_empty() {
193            return Err(SqlBuilderError::EmptyValue);
194        }
195
196        self.statement
197            .push_str(&format!("{} {} {}", field, predicate, value));
198        Ok(self)
199    }
200}
201
202/// Implementation of the `BuildableStatement` trait for `ColumnOption`, allowing it to be printed.
203impl BuildableStatement for Where {
204    fn build(&self) -> String {
205        self.build()
206    }
207}