sqlx_plus_builder/
where-builder.rs

1use crate::error::SqlBuilderError;
2use std::fmt;
3
4#[macro_export]
5macro_rules! and {
6    ( $f:expr, $( $l:expr ),* ) => {
7        {
8            let mut x = String::from("(");
9            x.push_str( & $f .to_string() );
10            $(
11                x.push_str(") AND (");
12                x.push_str( & $l .to_string() );
13            )*
14            x.push(')');
15            x
16        }
17    };
18}
19
20#[macro_export]
21macro_rules! or {
22    ( $f:expr, $( $l:expr ),* ) => {
23        {
24            let mut x = String::from( $f );
25            $(
26                x.push_str(" OR ");
27                x.push_str( & $l .to_string() );
28            )*
29            x
30        }
31    };
32}
33
34#[macro_export]
35macro_rules! not {
36    ( $f:expr ) => {{
37        let mut x = String::from("NOT ");
38        x.push_str(&$f.to_string());
39        x
40    }};
41}
42
43#[macro_export]
44macro_rules! brackets {
45    ( $el:expr ) => {
46        {
47            let mut x = String::from("(");
48            x.push_str( & $el .to_string() );
49            x.push(')');
50            x
51        }
52    };
53    ( $first:expr, $( $el:expr ),* ) => {
54        {
55            let mut x = String::from("(");
56            x.push_str( & $first .to_string() );
57            $(
58                x.push_str(", ");
59                x.push_str( & $el .to_string() );
60            )*
61            x.push(')');
62            x
63        }
64    };
65}
66
67/// Build WHERE for SQL.
68#[derive(Clone, Default)]
69pub struct Where {
70    text: String,
71    prefix: Option<String>,
72    error: Option<SqlBuilderError>,
73    was_and: bool,
74}
75
76impl fmt::Display for Where {
77    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
78        write!(f, "{}", self.text)
79    }
80}
81
82impl Where {
83    pub fn new<S>(smth: S) -> Self
84    where
85        S: ToString,
86    {
87        // Checks
88        let text = smth.to_string();
89        if text.is_empty() {
90            return Self {
91                error: Some(SqlBuilderError::NoWhereField),
92                ..Self::default()
93            };
94        }
95
96        // Create
97        Self {
98            text,
99            ..Self::default()
100        }
101    }
102
103    pub fn empty() -> Self {
104        Self::default()
105    }
106
107    pub fn in_brackets(&mut self) -> &mut Self {
108        // Checks
109        if self.text.is_empty() {
110            self.error = Some(SqlBuilderError::NoWhereField);
111            return self;
112        }
113
114        // Change
115        self.text.insert(0, '(');
116        self.text.push(')');
117        self
118    }
119
120    pub fn not(&mut self) -> &mut Self {
121        // Checks
122        if self.text.is_empty() {
123            self.error = Some(SqlBuilderError::NoWhereField);
124            return self;
125        }
126
127        // Change
128        self.text.insert_str(0, "NOT ");
129        self
130    }
131
132    pub fn and<S>(&mut self, smth: S) -> &mut Self
133    where
134        S: ToString,
135    {
136        // Checks
137        if self.text.is_empty() {
138            self.error = Some(SqlBuilderError::NoWhereField);
139            return self;
140        }
141        let smth = smth.to_string();
142        if smth.is_empty() {
143            self.error = Some(SqlBuilderError::NoWhereValue(self.text.clone()));
144            return self;
145        }
146
147        // Change
148        if !self.was_and {
149            self.text.insert(0, '(');
150            self.text.push(')');
151            self.was_and = true;
152        }
153        self.text.push_str(" AND (");
154        self.text.push_str(&smth);
155        self.text.push(')');
156        self
157    }
158
159    pub fn or<S>(&mut self, smth: S) -> &mut Self
160    where
161        S: ToString,
162    {
163        // Checks
164        if self.text.is_empty() {
165            self.error = Some(SqlBuilderError::NoWhereField);
166            return self;
167        }
168        let smth = smth.to_string();
169        if smth.is_empty() {
170            self.error = Some(SqlBuilderError::NoWhereValue(self.text.clone()));
171            return self;
172        }
173
174        // Change
175        self.text.push_str(" OR ");
176        self.text.push_str(&smth);
177        self
178    }
179
180    pub fn eq<S>(&mut self, smth: S) -> &mut Self
181    where
182        S: ToString,
183    {
184        // Checks
185        let smth = smth.to_string();
186        if smth.is_empty() {
187            self.error = Some(SqlBuilderError::NoWhereValue(self.text.clone()));
188            return self;
189        }
190
191        // Change
192        if let Some(prefix) = &self.prefix {
193            self.text.push(' ');
194            self.text.push_str(&prefix);
195            self.prefix = None;
196        }
197        self.text.push_str(" = ");
198        self.text.push_str(&smth);
199        self
200    }
201
202    pub fn ne<S>(&mut self, smth: S) -> &mut Self
203    where
204        S: ToString,
205    {
206        // Checks
207        let smth = smth.to_string();
208        if smth.is_empty() {
209            self.error = Some(SqlBuilderError::NoWhereValue(self.text.clone()));
210            return self;
211        }
212
213        // Change
214        if let Some(prefix) = &self.prefix {
215            self.text.push(' ');
216            self.text.push_str(&prefix);
217            self.prefix = None;
218        }
219        self.text.push_str(" <> ");
220        self.text.push_str(&smth);
221        self
222    }
223
224    pub fn build(&self) -> Result<String, SqlBuilderError> {
225        match &self.error {
226            Some(err) => Err(err.clone()),
227            None => Ok(self.text.to_string()),
228        }
229    }
230}
231
232#[cfg(test)]
233mod tests {
234    use super::*;
235
236    #[test]
237    fn test_macro_and() {
238        let sql = and!("10", "20", "30");
239        assert_eq!("(10) AND (20) AND (30)", sql);
240    }
241
242    #[test]
243    fn test_macro_or() {
244        let sql = or!("10", "20", "30");
245        assert_eq!("10 OR 20 OR 30", sql);
246    }
247
248    #[test]
249    fn test_macro_not() {
250        let sql = not!("10");
251        assert_eq!("NOT 10", sql);
252    }
253
254    #[test]
255    fn test_macro_brackets() {
256        let sql = brackets!("10", "20", "30");
257        assert_eq!("(10, 20, 30)", sql);
258
259        let sql = brackets!("10");
260        assert_eq!("(10)", sql);
261    }
262
263    #[test]
264    fn test_macro_and_or_not() {
265        let sql = and!("10", or!("20", not!("30"), "40"));
266        assert_eq!("(10) AND (20 OR NOT 30 OR 40)", &sql);
267    }
268
269    #[test]
270    fn test_new_where() {
271        let text = Where::new("abc").to_string();
272        assert_eq!("abc", &text);
273    }
274
275    #[test]
276    fn test_where_brackets() {
277        let text = Where::new("abc").eq(10).in_brackets().to_string();
278        assert_eq!("(abc = 10)", &text);
279    }
280
281    #[test]
282    fn test_where_build() {
283        let res = Where::new("abc").eq(10).build();
284        assert_eq!(Ok("abc = 10".to_string()), res);
285    }
286
287    #[test]
288    fn test_where_not() {
289        let text = Where::new("abc").eq(10).in_brackets().not().to_string();
290        assert_eq!("NOT (abc = 10)", &text);
291    }
292
293    #[test]
294    fn test_where_and() {
295        let text = Where::new("abc").eq(10).and(20).to_string();
296        assert_eq!("(abc = 10) AND (20)", &text);
297    }
298
299    #[test]
300    fn test_where_or() {
301        let text = Where::new("abc").eq(10).or(20).to_string();
302        assert_eq!("abc = 10 OR 20", &text);
303    }
304
305    #[test]
306    fn test_where_eq() {
307        let text = Where::new("abc").eq(10).to_string();
308        assert_eq!("abc = 10", &text);
309    }
310
311    #[test]
312    fn test_where_ne() {
313        let text = Where::new("abc").ne(10).to_string();
314        assert_eq!("abc <> 10", &text);
315    }
316}