sqlint/ast/
compare.rs

1use super::ExpressionKind;
2use crate::ast::{Column, ConditionTree, Expression};
3use std::borrow::Cow;
4
5/// For modeling comparison expressions.
6#[derive(Debug, Clone, PartialEq)]
7pub enum Compare<'a> {
8    /// `left = right`
9    Equals(Box<Expression<'a>>, Box<Expression<'a>>),
10    /// `left <> right`
11    NotEquals(Box<Expression<'a>>, Box<Expression<'a>>),
12    /// `left < right`
13    LessThan(Box<Expression<'a>>, Box<Expression<'a>>),
14    /// `left <= right`
15    LessThanOrEquals(Box<Expression<'a>>, Box<Expression<'a>>),
16    /// `left > right`
17    GreaterThan(Box<Expression<'a>>, Box<Expression<'a>>),
18    /// `left >= right`
19    GreaterThanOrEquals(Box<Expression<'a>>, Box<Expression<'a>>),
20    /// `left IN (..)`
21    In(Box<Expression<'a>>, Box<Expression<'a>>),
22    /// `left NOT IN (..)`
23    NotIn(Box<Expression<'a>>, Box<Expression<'a>>),
24    /// `left LIKE %..%`
25    Like(Box<Expression<'a>>, Box<Expression<'a>>),
26    /// `left NOT LIKE %..%`
27    NotLike(Box<Expression<'a>>, Box<Expression<'a>>),
28    /// `value IS NULL`
29    Null(Box<Expression<'a>>),
30    /// `value IS NOT NULL`
31    NotNull(Box<Expression<'a>>),
32    /// `value` BETWEEN `left` AND `right`
33    Between(Box<Expression<'a>>, Box<Expression<'a>>, Box<Expression<'a>>),
34    /// `value` NOT BETWEEN `left` AND `right`
35    NotBetween(Box<Expression<'a>>, Box<Expression<'a>>, Box<Expression<'a>>),
36    /// Raw comparator, allows to use an operator `left <raw> right` as is,
37    /// without visitor transformation in between.
38    Raw(Box<Expression<'a>>, Cow<'a, str>, Box<Expression<'a>>),
39    /// All json related comparators
40    #[cfg(all(feature = "json", any(feature = "postgresql", feature = "mysql")))]
41    JsonCompare(JsonCompare<'a>),
42    /// `left` @@ to_tsquery(`value`)
43    #[cfg(feature = "postgresql")]
44    Matches(Box<Expression<'a>>, Cow<'a, str>),
45    /// (NOT `left` @@ to_tsquery(`value`))
46    #[cfg(feature = "postgresql")]
47    NotMatches(Box<Expression<'a>>, Cow<'a, str>),
48    /// ANY (`left`)
49    #[cfg(feature = "postgresql")]
50    Any(Box<Expression<'a>>),
51    /// ALL (`left`)
52    #[cfg(feature = "postgresql")]
53    All(Box<Expression<'a>>),
54}
55
56#[derive(Debug, Clone, PartialEq)]
57pub enum JsonCompare<'a> {
58    ArrayContains(Box<Expression<'a>>, Box<Expression<'a>>),
59    ArrayNotContains(Box<Expression<'a>>, Box<Expression<'a>>),
60    TypeEquals(Box<Expression<'a>>, JsonType<'a>),
61    TypeNotEquals(Box<Expression<'a>>, JsonType<'a>),
62}
63
64#[derive(Debug, Clone, PartialEq)]
65pub enum JsonType<'a> {
66    Array,
67    Object,
68    String,
69    Number,
70    Boolean,
71    Null,
72    ColumnRef(Box<Column<'a>>),
73}
74
75impl<'a> From<Column<'a>> for JsonType<'a> {
76    fn from(col: Column<'a>) -> Self {
77        JsonType::ColumnRef(Box::new(col))
78    }
79}
80
81impl<'a> Compare<'a> {
82    /// Finds a possible `(a,y) IN (SELECT x,z FROM B)`, takes the select out and
83    /// converts the comparison into `a IN (SELECT x FROM cte_n where z = y)`.
84    ///
85    /// Left side means a match and the CTE should be handled, right side is a
86    /// no-op.
87    #[cfg(feature = "mssql")]
88    pub(crate) fn convert_tuple_select_to_cte(
89        self,
90        level: &mut usize,
91    ) -> either::Either<Self, (Self, Vec<super::CommonTableExpression<'a>>)> {
92        use super::IntoCommonTableExpression;
93
94        fn convert<'a>(
95            row: super::Row<'a>,
96            select: super::SelectQuery<'a>,
97            mut selected_columns: Vec<String>,
98            level: &mut usize,
99        ) -> (super::Column<'a>, super::Select<'a>, Vec<super::CommonTableExpression<'a>>) {
100            // Get the columns out from the row.
101            let mut cols = row.into_columns();
102
103            // The name of the CTE in the query
104            let ident = format!("cte_{level}");
105
106            let (select, ctes) = select.convert_tuple_selects_to_ctes(level);
107
108            let mut combined_ctes = Vec::with_capacity(ctes.len() + 1);
109            combined_ctes.push(select.into_cte(ident.clone()));
110            combined_ctes.extend(ctes);
111
112            // The left side column of the comparison, `*this* IN (...)`. We can
113            // support a single value comparisons in all databases, so we try to
114            // find the first value of the tuple, converting the select to hold
115            // the rest of the values in its comparison.
116            let comp_col = cols.remove(0);
117
118            // The right side `SELECT` of the comparison, replacing the original
119            // `SELECT`.  At this point we just select the first column from the
120            // original select, changing the `SELECT` into
121            // `(SELECT first_col FROM cte_n)`.
122            let base_select = super::Select::from_table(ident).column(selected_columns.remove(0));
123
124            // We know we have the same amount of columns on both sides,
125            let column_pairs = cols.into_iter().zip(selected_columns.into_iter());
126
127            // Adding to the new select a condition to filter out the rest of
128            // the tuple, so if our tuple is `(a, b) IN (SELECT x, y ..)`, this
129            // will then turn into `a IN (SELECT x WHERE b = y)`.
130            let inner_select =
131                column_pairs.fold(base_select, |acc, (left_col, right_col)| acc.and_where(right_col.equals(left_col)));
132
133            // Now we added one cte, so we must increment the count for the
134            // possible other expressions.
135            *level += 1;
136
137            // Return the comparison data to the caller.
138            (comp_col, inner_select, combined_ctes)
139        }
140
141        match self {
142            Self::In(left, right) if left.is_row() && right.is_selection() => {
143                let row = left.into_row().unwrap();
144                let select = right.into_selection().unwrap();
145                let selection = select.named_selection();
146
147                if row.len() != selection.len() {
148                    let left = Expression::row(row);
149                    let right = Expression::selection(select);
150
151                    return either::Either::Left(left.in_selection(right));
152                }
153
154                if row.is_only_columns() && row.len() > 1 {
155                    let (comp_col, inner_select, ctes) = convert(row, select, selection, level);
156                    let cond = comp_col.in_selection(inner_select);
157
158                    either::Either::Right((cond, ctes))
159                } else if row.len() == 1 {
160                    let left = Expression::row(row);
161                    let (select, ctes) = select.convert_tuple_selects_to_ctes(level);
162
163                    let select = Expression::selection(select);
164                    let cond = Self::In(Box::new(left), Box::new(select));
165
166                    either::Either::Right((cond, ctes))
167                } else {
168                    let left = Expression::row(row);
169                    let select = Expression::selection(select);
170                    let cond = Self::In(Box::new(left), Box::new(select));
171
172                    either::Either::Left(cond)
173                }
174            }
175            Self::In(left, right) if right.is_selection() => {
176                let (selection, ctes) = right.into_selection().unwrap().convert_tuple_selects_to_ctes(level);
177                let cond = Self::In(left, Box::new(Expression::selection(selection)));
178
179                either::Either::Right((cond, ctes))
180            }
181            Self::NotIn(left, right) if left.is_row() && right.is_selection() => {
182                let row = left.into_row().unwrap();
183                let select = right.into_selection().unwrap();
184                let selection = select.named_selection();
185
186                if row.len() != selection.len() {
187                    let left = Expression::row(row);
188                    let right = Expression::selection(select);
189
190                    return either::Either::Left(left.not_in_selection(right));
191                }
192
193                if row.is_only_columns() && row.len() > 1 {
194                    let (comp_col, inner_select, ctes) = convert(row, select, selection, level);
195                    let cond = comp_col.not_in_selection(inner_select);
196
197                    either::Either::Right((cond, ctes))
198                } else if row.len() == 1 {
199                    let left = Expression::row(row);
200                    let (select, ctes) = select.convert_tuple_selects_to_ctes(level);
201
202                    let select = Expression::selection(select);
203                    let cond = Self::NotIn(Box::new(left), Box::new(select));
204
205                    either::Either::Right((cond, ctes))
206                } else {
207                    let left = Expression::row(row);
208                    let select = Expression::selection(select);
209                    let cond = Self::NotIn(Box::new(left), Box::new(select));
210
211                    either::Either::Left(cond)
212                }
213            }
214            Self::NotIn(left, right) if right.is_selection() => {
215                let (selection, ctes) = right.into_selection().unwrap().convert_tuple_selects_to_ctes(level);
216                let cond = Self::NotIn(left, Box::new(Expression::selection(selection)));
217
218                either::Either::Right((cond, ctes))
219            }
220            _ => either::Either::Left(self),
221        }
222    }
223}
224
225impl<'a> From<Compare<'a>> for ConditionTree<'a> {
226    fn from(cmp: Compare<'a>) -> Self {
227        ConditionTree::single(Expression::from(cmp))
228    }
229}
230
231impl<'a> From<Compare<'a>> for Expression<'a> {
232    fn from(cmp: Compare<'a>) -> Self {
233        Expression { kind: ExpressionKind::Compare(cmp), alias: None }
234    }
235}
236
237/// An item that can be compared against other values in the database.
238pub trait Comparable<'a> {
239    /// Tests if both sides are the same value.
240    ///
241    /// ```rust
242    /// # use sqlint::{ast::*, visitor::{Visitor, Sqlite}};
243    /// # fn main() -> Result<(), sqlint::error::Error> {
244    /// let query = Select::from_table("users").so_that("foo".equals("bar"));
245    /// let (sql, params) = Sqlite::build(query)?;
246    ///
247    /// assert_eq!("SELECT `users`.* FROM `users` WHERE `foo` = ?", sql);
248    ///
249    /// assert_eq!(
250    ///     vec![
251    ///         Value::from("bar"),
252    ///     ],
253    ///     params
254    /// );
255    /// # Ok(())
256    /// # }
257    /// ```
258    fn equals<T>(self, comparison: T) -> Compare<'a>
259    where
260        T: Into<Expression<'a>>;
261
262    /// Tests if both sides are not the same value.
263    ///
264    /// ```rust
265    /// # use sqlint::{ast::*, visitor::{Visitor, Sqlite}};
266    /// # fn main() -> Result<(), sqlint::error::Error> {
267    /// let query = Select::from_table("users").so_that("foo".not_equals("bar"));
268    /// let (sql, params) = Sqlite::build(query)?;
269    ///
270    /// assert_eq!("SELECT `users`.* FROM `users` WHERE `foo` <> ?", sql);
271    ///
272    /// assert_eq!(
273    ///     vec![
274    ///         Value::from("bar"),
275    ///     ],
276    ///     params
277    /// );
278    /// # Ok(())
279    /// # }
280    /// ```
281    fn not_equals<T>(self, comparison: T) -> Compare<'a>
282    where
283        T: Into<Expression<'a>>;
284
285    /// Tests if the left side is smaller than the right side.
286    ///
287    /// ```rust
288    /// # fn main() -> Result<(), sqlint::error::Error> {
289    /// # use sqlint::{ast::*, visitor::{Visitor, Sqlite}};
290    /// let query = Select::from_table("users").so_that("foo".less_than(10));
291    /// let (sql, params) = Sqlite::build(query)?;
292    ///
293    /// assert_eq!("SELECT `users`.* FROM `users` WHERE `foo` < ?", sql);
294    ///
295    /// assert_eq!(
296    ///     vec![
297    ///         Value::from(10),
298    ///     ],
299    ///     params
300    /// );
301    /// # Ok(())
302    /// # }
303    /// ```
304    fn less_than<T>(self, comparison: T) -> Compare<'a>
305    where
306        T: Into<Expression<'a>>;
307
308    /// Tests if the left side is smaller than the right side or the same.
309    ///
310    /// ```rust
311    /// # use sqlint::{ast::*, visitor::{Visitor, Sqlite}};
312    /// # fn main() -> Result<(), sqlint::error::Error> {
313    /// let query = Select::from_table("users").so_that("foo".less_than_or_equals(10));
314    /// let (sql, params) = Sqlite::build(query)?;
315    ///
316    /// assert_eq!("SELECT `users`.* FROM `users` WHERE `foo` <= ?", sql);
317    ///
318    /// assert_eq!(
319    ///     vec![
320    ///         Value::from(10),
321    ///     ],
322    ///     params
323    /// );
324    /// # Ok(())
325    /// # }
326    /// ```
327    fn less_than_or_equals<T>(self, comparison: T) -> Compare<'a>
328    where
329        T: Into<Expression<'a>>;
330
331    /// Tests if the left side is bigger than the right side.
332    ///
333    /// ```rust
334    /// # use sqlint::{ast::*, visitor::{Visitor, Sqlite}};
335    /// # fn main() -> Result<(), sqlint::error::Error> {
336    /// let query = Select::from_table("users").so_that("foo".greater_than(10));
337    /// let (sql, params) = Sqlite::build(query)?;
338    ///
339    /// assert_eq!("SELECT `users`.* FROM `users` WHERE `foo` > ?", sql);
340    ///
341    /// assert_eq!(
342    ///     vec![
343    ///         Value::from(10),
344    ///     ],
345    ///     params
346    /// );
347    /// # Ok(())
348    /// # }
349    /// ```
350    fn greater_than<T>(self, comparison: T) -> Compare<'a>
351    where
352        T: Into<Expression<'a>>;
353
354    /// Tests if the left side is bigger than the right side or the same.
355    ///
356    /// ```rust
357    /// # use sqlint::{ast::*, visitor::{Visitor, Sqlite}};
358    /// # fn main() -> Result<(), sqlint::error::Error> {
359    /// let query = Select::from_table("users").so_that("foo".greater_than_or_equals(10));
360    /// let (sql, params) = Sqlite::build(query)?;
361    ///
362    /// assert_eq!("SELECT `users`.* FROM `users` WHERE `foo` >= ?", sql);
363    ///
364    /// assert_eq!(
365    ///     vec![
366    ///         Value::from(10),
367    ///     ],
368    ///     params
369    /// );
370    /// # Ok(())
371    /// # }
372    /// ```
373    fn greater_than_or_equals<T>(self, comparison: T) -> Compare<'a>
374    where
375        T: Into<Expression<'a>>;
376
377    /// Tests if the left side is included in the right side collection.
378    ///
379    /// ```rust
380    /// # use sqlint::{ast::*, visitor::{Visitor, Sqlite}};
381    /// # fn main() -> Result<(), sqlint::error::Error> {
382    /// let query = Select::from_table("users").so_that("foo".in_selection(vec![1, 2]));
383    /// let (sql, params) = Sqlite::build(query)?;
384    ///
385    /// assert_eq!("SELECT `users`.* FROM `users` WHERE `foo` IN (?,?)", sql);
386    /// assert_eq!(vec![
387    ///     Value::from(1),
388    ///     Value::from(2),
389    /// ], params);
390    /// # Ok(())
391    /// # }
392    /// ```
393    fn in_selection<T>(self, selection: T) -> Compare<'a>
394    where
395        T: Into<Expression<'a>>;
396
397    /// Tests if the left side is not included in the right side collection.
398    ///
399    /// ```rust
400    /// # use sqlint::{ast::*, visitor::{Visitor, Sqlite}};
401    /// # fn main() -> Result<(), sqlint::error::Error> {
402    /// let query = Select::from_table("users").so_that("foo".not_in_selection(vec![1, 2]));
403    /// let (sql, params) = Sqlite::build(query)?;
404    ///
405    /// assert_eq!("SELECT `users`.* FROM `users` WHERE `foo` NOT IN (?,?)", sql);
406    ///
407    /// assert_eq!(vec![
408    ///     Value::from(1),
409    ///     Value::from(2),
410    /// ], params);
411    /// # Ok(())
412    /// # }
413    /// ```
414    fn not_in_selection<T>(self, selection: T) -> Compare<'a>
415    where
416        T: Into<Expression<'a>>;
417
418    /// Tests if the left side includes the right side string.
419    ///
420    /// ```rust
421    /// # use sqlint::{ast::*, visitor::{Visitor, Sqlite}};
422    /// # fn main() -> Result<(), sqlint::error::Error> {
423    /// let query = Select::from_table("users").so_that("foo".like("%bar%"));
424    /// let (sql, params) = Sqlite::build(query)?;
425    ///
426    /// assert_eq!("SELECT `users`.* FROM `users` WHERE `foo` LIKE ?", sql);
427    ///
428    /// assert_eq!(
429    ///     vec![
430    ///         Value::from("%bar%"),
431    ///     ],
432    ///     params
433    /// );
434    /// # Ok(())
435    /// # }
436    /// ```
437    fn like<T>(self, pattern: T) -> Compare<'a>
438    where
439        T: Into<Expression<'a>>;
440
441    /// Tests if the left side does not include the right side string.
442    ///
443    /// ```rust
444    /// # use sqlint::{ast::*, visitor::{Visitor, Sqlite}};
445    /// # fn main() -> Result<(), sqlint::error::Error> {
446    /// let query = Select::from_table("users").so_that("foo".not_like("%bar%"));
447    /// let (sql, params) = Sqlite::build(query)?;
448    ///
449    /// assert_eq!("SELECT `users`.* FROM `users` WHERE `foo` NOT LIKE ?", sql);
450    ///
451    /// assert_eq!(
452    ///     vec![
453    ///         Value::from("%bar%"),
454    ///     ],
455    ///     params
456    /// );
457    /// # Ok(())
458    /// # }
459    /// ```
460    fn not_like<T>(self, pattern: T) -> Compare<'a>
461    where
462        T: Into<Expression<'a>>;
463
464    /// Tests if the left side is `NULL`.
465    ///
466    /// ```rust
467    /// # use sqlint::{ast::*, visitor::{Visitor, Sqlite}};
468    /// # fn main() -> Result<(), sqlint::error::Error> {
469    /// let query = Select::from_table("users").so_that("foo".is_null());
470    /// let (sql, _) = Sqlite::build(query)?;
471    ///
472    /// assert_eq!("SELECT `users`.* FROM `users` WHERE `foo` IS NULL", sql);
473    /// # Ok(())
474    /// # }
475    /// ```
476    #[allow(clippy::wrong_self_convention)]
477    fn is_null(self) -> Compare<'a>;
478
479    /// Tests if the left side is not `NULL`.
480    ///
481    /// ```rust
482    /// # use sqlint::{ast::*, visitor::{Visitor, Sqlite}};
483    /// # fn main() -> Result<(), sqlint::error::Error> {
484    /// let query = Select::from_table("users").so_that("foo".is_not_null());
485    /// let (sql, _) = Sqlite::build(query)?;
486    ///
487    /// assert_eq!("SELECT `users`.* FROM `users` WHERE `foo` IS NOT NULL", sql);
488    /// # Ok(())
489    /// # }
490    /// ```
491    #[allow(clippy::wrong_self_convention)]
492    fn is_not_null(self) -> Compare<'a>;
493
494    /// Tests if the value is between two given values.
495    ///
496    /// ```rust
497    /// # use sqlint::{ast::*, visitor::{Visitor, Sqlite}};
498    /// # fn main() -> Result<(), sqlint::error::Error> {
499    /// let query = Select::from_table("users").so_that("foo".between(420, 666));
500    /// let (sql, params) = Sqlite::build(query)?;
501    ///
502    /// assert_eq!("SELECT `users`.* FROM `users` WHERE `foo` BETWEEN ? AND ?", sql);
503    ///
504    /// assert_eq!(vec![
505    ///     Value::from(420),
506    ///     Value::from(666),
507    /// ], params);
508    /// # Ok(())
509    /// # }
510    /// ```
511    fn between<T, V>(self, left: T, right: V) -> Compare<'a>
512    where
513        T: Into<Expression<'a>>,
514        V: Into<Expression<'a>>;
515
516    /// Tests if the value is not between two given values.
517    ///
518    /// ```rust
519    /// # use sqlint::{ast::*, visitor::{Visitor, Sqlite}};
520    /// # fn main() -> Result<(), sqlint::error::Error> {
521    /// let query = Select::from_table("users").so_that("foo".not_between(420, 666));
522    /// let (sql, params) = Sqlite::build(query)?;
523    ///
524    /// assert_eq!("SELECT `users`.* FROM `users` WHERE `foo` NOT BETWEEN ? AND ?", sql);
525    ///
526    /// assert_eq!(vec![
527    ///     Value::from(420),
528    ///     Value::from(666),
529    /// ], params);
530    /// # Ok(())
531    /// # }
532    /// ```
533    fn not_between<T, V>(self, left: T, right: V) -> Compare<'a>
534    where
535        T: Into<Expression<'a>>,
536        V: Into<Expression<'a>>;
537
538    /// Tests if the JSON array contains a value.
539    ///
540    /// ```rust
541    /// # use sqlint::{ast::*, visitor::{Visitor, Mysql}};
542    /// # fn main() -> Result<(), sqlint::error::Error> {
543    /// let query = Select::from_table("users")
544    ///     .so_that("json".json_array_contains(serde_json::json!(1)));
545    /// let (sql, params) = Mysql::build(query)?;
546    ///
547    /// assert_eq!("SELECT `users`.* FROM `users` WHERE JSON_CONTAINS(`json`, ?)", sql);
548    ///
549    /// assert_eq!(vec![Value::from(serde_json::json!(1))], params);
550    /// # Ok(())
551    /// # }
552    /// ```
553    #[cfg(all(feature = "json", any(feature = "postgresql", feature = "mysql")))]
554    fn json_array_contains<T>(self, item: T) -> Compare<'a>
555    where
556        T: Into<Expression<'a>>;
557
558    /// Tests if the JSON array does not contain a value.
559    ///
560    /// ```rust
561    /// # use sqlint::{ast::*, visitor::{Visitor, Mysql}};
562    /// # fn main() -> Result<(), sqlint::error::Error> {
563    /// let query = Select::from_table("users")
564    ///     .so_that("json".json_array_not_contains(serde_json::json!(1)));
565    /// let (sql, params) = Mysql::build(query)?;
566    ///
567    /// assert_eq!("SELECT `users`.* FROM `users` WHERE JSON_CONTAINS(`json`, ?) = FALSE", sql);
568    /// assert_eq!(vec![Value::from(serde_json::json!(1))], params);
569    ///
570    /// # Ok(())
571    /// # }
572    /// ```
573    #[cfg(all(feature = "json", any(feature = "postgresql", feature = "mysql")))]
574    fn json_array_not_contains<T>(self, item: T) -> Compare<'a>
575    where
576        T: Into<Expression<'a>>;
577
578    /// Tests if the JSON array starts with a value.
579    ///
580    /// ```rust
581    /// # use sqlint::{ast::*, visitor::{Visitor, Mysql}};
582    /// # fn main() -> Result<(), sqlint::error::Error> {
583    /// let query = Select::from_table("users")
584    ///     .so_that("json".json_array_begins_with(serde_json::json!(1)));
585    /// let (sql, params) = Mysql::build(query)?;
586    ///
587    /// assert_eq!(
588    ///   "SELECT `users`.* FROM `users` WHERE \
589    ///      (JSON_CONTAINS(JSON_EXTRACT(`json`, ?), ?) AND \
590    ///      JSON_CONTAINS(?, JSON_EXTRACT(`json`, ?)))",
591    ///   sql
592    /// );
593    /// assert_eq!(vec![
594    ///     Value::from("$[0]"),
595    ///     Value::from(serde_json::json!(1)),
596    ///     Value::from(serde_json::json!(1)),
597    ///     Value::from("$[0]"),
598    /// ], params);
599    ///
600    /// # Ok(())
601    /// # }
602    /// ```
603    #[cfg(all(feature = "json", any(feature = "postgresql", feature = "mysql")))]
604    fn json_array_begins_with<T>(self, item: T) -> Compare<'a>
605    where
606        T: Into<Expression<'a>>;
607
608    /// Tests if the JSON array does not start with a value.
609    ///
610    /// ```rust
611    /// # use sqlint::{ast::*, visitor::{Visitor, Mysql}};
612    /// # fn main() -> Result<(), sqlint::error::Error> {
613    /// let query = Select::from_table("users")
614    ///   .so_that("json".json_array_not_begins_with(serde_json::json!(1)));
615    /// let (sql, params) = Mysql::build(query)?;
616    ///
617    /// assert_eq!(
618    ///   "SELECT `users`.* FROM `users` WHERE \
619    ///      (NOT JSON_CONTAINS(JSON_EXTRACT(`json`, ?), ?) OR \
620    ///      NOT JSON_CONTAINS(?, JSON_EXTRACT(`json`, ?)))",
621    ///   sql
622    /// );
623    /// assert_eq!(vec![
624    ///     Value::from("$[0]"),
625    ///     Value::from(serde_json::json!(1)),
626    ///     Value::from(serde_json::json!(1)),
627    ///     Value::from("$[0]"),
628    /// ], params);
629    ///
630    /// # Ok(())
631    /// # }
632    /// ```
633    #[cfg(all(feature = "json", any(feature = "postgresql", feature = "mysql")))]
634    fn json_array_not_begins_with<T>(self, item: T) -> Compare<'a>
635    where
636        T: Into<Expression<'a>>;
637
638    /// Tests if the JSON array ends with a value.
639    ///
640    /// ```rust
641    /// # use sqlint::{ast::*, visitor::{Visitor, Mysql}};
642    /// # fn main() -> Result<(), sqlint::error::Error> {
643    /// let query = Select::from_table("users")
644    ///     .so_that("json".json_array_ends_into(serde_json::json!(1)));
645    /// let (sql, params) = Mysql::build(query)?;
646    ///
647    /// assert_eq!(
648    ///   "SELECT `users`.* FROM `users` WHERE \
649    ///      (JSON_CONTAINS(JSON_EXTRACT(`json`, CONCAT('$[', JSON_LENGTH(`json`) - 1, ']')), ?) AND \
650    ///      JSON_CONTAINS(?, JSON_EXTRACT(`json`, CONCAT('$[', JSON_LENGTH(`json`) - 1, ']'))))",
651    ///   sql
652    /// );
653    /// assert_eq!(vec![
654    ///    Value::from(serde_json::json!(1)),
655    ///    Value::from(serde_json::json!(1)),
656    /// ], params);
657    ///
658    /// # Ok(())
659    /// # }
660    /// ```
661    #[cfg(all(feature = "json", any(feature = "postgresql", feature = "mysql")))]
662    fn json_array_ends_into<T>(self, item: T) -> Compare<'a>
663    where
664        T: Into<Expression<'a>>;
665
666    /// Tests if the JSON array does not end with a value.
667    ///
668    /// ```rust
669    /// # use sqlint::{ast::*, visitor::{Visitor, Mysql}};
670    /// # fn main() -> Result<(), sqlint::error::Error> {
671    /// let query = Select::from_table("users").so_that("json".json_array_not_ends_into(serde_json::json!(1)));
672    /// let (sql, params) = Mysql::build(query)?;
673    ///
674    /// assert_eq!(
675    ///   "SELECT `users`.* FROM `users` WHERE \
676    ///      (NOT JSON_CONTAINS(JSON_EXTRACT(`json`, CONCAT('$[', JSON_LENGTH(`json`) - 1, ']')), ?) OR \
677    ///      NOT JSON_CONTAINS(?, JSON_EXTRACT(`json`, CONCAT('$[', JSON_LENGTH(`json`) - 1, ']'))))",
678    ///   sql
679    /// );
680    ///
681    /// assert_eq!(vec![
682    ///    Value::from(serde_json::json!(1)),
683    ///    Value::from(serde_json::json!(1)),
684    /// ], params);
685    ///
686    /// # Ok(())
687    /// # }
688    /// ```
689    #[cfg(all(feature = "json", any(feature = "postgresql", feature = "mysql")))]
690    fn json_array_not_ends_into<T>(self, item: T) -> Compare<'a>
691    where
692        T: Into<Expression<'a>>;
693
694    /// Tests if the JSON value is of a certain type.
695    ///
696    /// ```rust
697    /// # use sqlint::{ast::*, visitor::{Visitor, Mysql}};
698    /// # fn main() -> Result<(), sqlint::error::Error> {
699    /// let query = Select::from_table("users").so_that("json".json_type_equals(JsonType::Array));
700    /// let (sql, params) = Mysql::build(query)?;
701    ///
702    /// assert_eq!("SELECT `users`.* FROM `users` WHERE (JSON_TYPE(`json`) = ?)", sql);
703    ///
704    /// assert_eq!(vec![Value::from("ARRAY")], params);
705    /// # Ok(())
706    /// # }
707    /// ```
708    #[cfg(all(feature = "json", any(feature = "postgresql", feature = "mysql")))]
709    fn json_type_equals<T>(self, json_type: T) -> Compare<'a>
710    where
711        T: Into<JsonType<'a>>;
712
713    /// Tests if the JSON value is not of a certain type.
714    ///
715    /// ```rust
716    /// # use sqlint::{ast::*, visitor::{Visitor, Mysql}};
717    /// # fn main() -> Result<(), sqlint::error::Error> {
718    /// let query = Select::from_table("users").so_that("json".json_type_not_equals(JsonType::Array));
719    /// let (sql, params) = Mysql::build(query)?;
720    ///
721    /// assert_eq!("SELECT `users`.* FROM `users` WHERE (JSON_TYPE(`json`) != ?)", sql);
722    ///
723    /// assert_eq!(vec![Value::from("ARRAY")], params);
724    /// # Ok(())
725    /// # }
726    /// ```
727    #[cfg(all(feature = "json", any(feature = "postgresql", feature = "mysql")))]
728    fn json_type_not_equals<T>(self, json_type: T) -> Compare<'a>
729    where
730        T: Into<JsonType<'a>>;
731
732    /// Tests if a full-text search matches a certain query. Use it in combination with the `text_search()` function
733    ///
734    /// ```rust
735    /// # use sqlint::{ast::*, visitor::{Visitor, Postgres}};
736    /// # fn main() -> Result<(), sqlint::error::Error> {
737    /// let search: Expression = text_search(&[Column::from("name"), Column::from("ingredients")]).into();
738    /// let query = Select::from_table("recipes").so_that(search.matches("chicken"));
739    /// let (sql, params) = Postgres::build(query)?;
740    ///
741    /// assert_eq!(
742    ///    "SELECT \"recipes\".* FROM \"recipes\" \
743    ///     WHERE to_tsvector(concat_ws(' ', \"name\",\"ingredients\")) @@ to_tsquery($1)", sql
744    /// );
745    ///
746    /// assert_eq!(params, vec![Value::from("chicken")]);
747    ///
748    /// # Ok(())    
749    /// # }
750    /// ```
751    #[cfg(feature = "postgresql")]
752    fn matches<T>(self, query: T) -> Compare<'a>
753    where
754        T: Into<Cow<'a, str>>;
755
756    /// Tests if a full-text search does not match a certain query. Use it in combination with the `text_search()` function
757    ///
758    /// ```rust
759    /// # use sqlint::{ast::*, visitor::{Visitor, Postgres}};
760    /// # fn main() -> Result<(), sqlint::error::Error> {
761    /// let search: Expression = text_search(&[Column::from("name"), Column::from("ingredients")]).into();
762    /// let query = Select::from_table("recipes").so_that(search.not_matches("chicken"));
763    /// let (sql, params) = Postgres::build(query)?;
764    ///
765    /// assert_eq!(
766    ///    "SELECT \"recipes\".* FROM \"recipes\" \
767    ///     WHERE (NOT to_tsvector(concat_ws(' ', \"name\",\"ingredients\")) @@ to_tsquery($1))", sql
768    /// );
769    ///
770    /// assert_eq!(params, vec![Value::from("chicken")]);
771    ///
772    /// # Ok(())    
773    /// # }
774    /// ```
775    #[cfg(feature = "postgresql")]
776    fn not_matches<T>(self, query: T) -> Compare<'a>
777    where
778        T: Into<Cow<'a, str>>;
779
780    /// Matches at least one elem of a list of values.
781    ///
782    /// ```rust
783    /// # use sqlint::{ast::*, col, visitor::{Visitor, Postgres}};
784    /// # fn main() -> Result<(), sqlint::error::Error> {
785    /// let query = Select::from_table("users").so_that(col!("name").equals(col!("list").any()));
786    /// let (sql, _) = Postgres::build(query)?;
787    /// assert_eq!(r#"SELECT "users".* FROM "users" WHERE "name" = ANY("list")"#, sql);
788    /// # Ok(())
789    /// # }
790    /// ```
791    #[cfg(feature = "postgresql")]
792    fn any(self) -> Compare<'a>;
793
794    /// Matches all elem of a list of values.
795    ///
796    /// ```rust
797    /// # use sqlint::{ast::*, col, visitor::{Visitor, Postgres}};
798    /// # fn main() -> Result<(), sqlint::error::Error> {
799    /// let query = Select::from_table("users").so_that(col!("name").equals(col!("list").all()));
800    /// let (sql, _) = Postgres::build(query)?;
801    /// assert_eq!(r#"SELECT "users".* FROM "users" WHERE "name" = ALL("list")"#, sql);
802    /// # Ok(())
803    /// # }
804    /// ```
805    #[cfg(feature = "postgresql")]
806    fn all(self) -> Compare<'a>;
807
808    /// Compares two expressions with a custom operator.
809    ///
810    /// ```rust
811    /// # use sqlint::{ast::*, visitor::{Visitor, Sqlite}};
812    /// # fn main() -> Result<(), sqlint::error::Error> {
813    /// let query = Select::from_table("users").so_that("foo".compare_raw("ILIKE", "%bar%"));
814    /// let (sql, params) = Sqlite::build(query)?;
815    ///
816    /// assert_eq!("SELECT `users`.* FROM `users` WHERE `foo` ILIKE ?", sql);
817    ///
818    /// assert_eq!(vec![
819    ///     Value::from("%bar%"),
820    /// ], params);
821    ///
822    /// # Ok(())
823    /// # }
824    /// ```
825    fn compare_raw<T, V>(self, raw_comparator: T, right: V) -> Compare<'a>
826    where
827        T: Into<Cow<'a, str>>,
828        V: Into<Expression<'a>>;
829}
830
831impl<'a, U> Comparable<'a> for U
832where
833    U: Into<Column<'a>>,
834{
835    fn equals<T>(self, comparison: T) -> Compare<'a>
836    where
837        T: Into<Expression<'a>>,
838    {
839        let col: Column<'a> = self.into();
840        let val: Expression<'a> = col.into();
841
842        val.equals(comparison)
843    }
844
845    fn not_equals<T>(self, comparison: T) -> Compare<'a>
846    where
847        T: Into<Expression<'a>>,
848    {
849        let col: Column<'a> = self.into();
850        let val: Expression<'a> = col.into();
851        val.not_equals(comparison)
852    }
853
854    fn less_than<T>(self, comparison: T) -> Compare<'a>
855    where
856        T: Into<Expression<'a>>,
857    {
858        let col: Column<'a> = self.into();
859        let val: Expression<'a> = col.into();
860        val.less_than(comparison)
861    }
862
863    fn less_than_or_equals<T>(self, comparison: T) -> Compare<'a>
864    where
865        T: Into<Expression<'a>>,
866    {
867        let col: Column<'a> = self.into();
868        let val: Expression<'a> = col.into();
869        val.less_than_or_equals(comparison)
870    }
871
872    fn greater_than<T>(self, comparison: T) -> Compare<'a>
873    where
874        T: Into<Expression<'a>>,
875    {
876        let col: Column<'a> = self.into();
877        let val: Expression<'a> = col.into();
878        val.greater_than(comparison)
879    }
880
881    fn greater_than_or_equals<T>(self, comparison: T) -> Compare<'a>
882    where
883        T: Into<Expression<'a>>,
884    {
885        let col: Column<'a> = self.into();
886        let val: Expression<'a> = col.into();
887        val.greater_than_or_equals(comparison)
888    }
889
890    fn in_selection<T>(self, selection: T) -> Compare<'a>
891    where
892        T: Into<Expression<'a>>,
893    {
894        let col: Column<'a> = self.into();
895        let val: Expression<'a> = col.into();
896        val.in_selection(selection)
897    }
898
899    fn not_in_selection<T>(self, selection: T) -> Compare<'a>
900    where
901        T: Into<Expression<'a>>,
902    {
903        let col: Column<'a> = self.into();
904        let val: Expression<'a> = col.into();
905        val.not_in_selection(selection)
906    }
907
908    fn like<T>(self, pattern: T) -> Compare<'a>
909    where
910        T: Into<Expression<'a>>,
911    {
912        let col: Column<'a> = self.into();
913        let val: Expression<'a> = col.into();
914        val.like(pattern)
915    }
916
917    fn not_like<T>(self, pattern: T) -> Compare<'a>
918    where
919        T: Into<Expression<'a>>,
920    {
921        let col: Column<'a> = self.into();
922        let val: Expression<'a> = col.into();
923        val.not_like(pattern)
924    }
925
926    #[allow(clippy::wrong_self_convention)]
927    fn is_null(self) -> Compare<'a> {
928        let col: Column<'a> = self.into();
929        let val: Expression<'a> = col.into();
930        val.is_null()
931    }
932
933    #[allow(clippy::wrong_self_convention)]
934    fn is_not_null(self) -> Compare<'a> {
935        let col: Column<'a> = self.into();
936        let val: Expression<'a> = col.into();
937        val.is_not_null()
938    }
939
940    fn between<T, V>(self, left: T, right: V) -> Compare<'a>
941    where
942        T: Into<Expression<'a>>,
943        V: Into<Expression<'a>>,
944    {
945        let col: Column<'a> = self.into();
946        let val: Expression<'a> = col.into();
947        val.between(left, right)
948    }
949
950    fn not_between<T, V>(self, left: T, right: V) -> Compare<'a>
951    where
952        T: Into<Expression<'a>>,
953        V: Into<Expression<'a>>,
954    {
955        let col: Column<'a> = self.into();
956        let val: Expression<'a> = col.into();
957        val.not_between(left, right)
958    }
959
960    fn compare_raw<T, V>(self, raw_comparator: T, right: V) -> Compare<'a>
961    where
962        T: Into<Cow<'a, str>>,
963        V: Into<Expression<'a>>,
964    {
965        let left: Column<'a> = self.into();
966        let left: Expression<'a> = left.into();
967        let right: Expression<'a> = right.into();
968
969        left.compare_raw(raw_comparator.into(), right)
970    }
971
972    #[cfg(all(feature = "json", any(feature = "postgresql", feature = "mysql")))]
973    fn json_array_contains<T>(self, item: T) -> Compare<'a>
974    where
975        T: Into<Expression<'a>>,
976    {
977        let col: Column<'a> = self.into();
978        let val: Expression<'a> = col.into();
979
980        val.json_array_contains(item)
981    }
982
983    #[cfg(all(feature = "json", any(feature = "postgresql", feature = "mysql")))]
984    fn json_array_not_contains<T>(self, item: T) -> Compare<'a>
985    where
986        T: Into<Expression<'a>>,
987    {
988        let col: Column<'a> = self.into();
989        let val: Expression<'a> = col.into();
990
991        val.json_array_not_contains(item)
992    }
993
994    #[cfg(all(feature = "json", any(feature = "postgresql", feature = "mysql")))]
995    fn json_array_begins_with<T>(self, item: T) -> Compare<'a>
996    where
997        T: Into<Expression<'a>>,
998    {
999        let col: Column<'a> = self.into();
1000        let val: Expression<'a> = col.into();
1001
1002        val.json_array_begins_with(item)
1003    }
1004
1005    #[cfg(all(feature = "json", any(feature = "postgresql", feature = "mysql")))]
1006    fn json_array_not_begins_with<T>(self, item: T) -> Compare<'a>
1007    where
1008        T: Into<Expression<'a>>,
1009    {
1010        let col: Column<'a> = self.into();
1011        let val: Expression<'a> = col.into();
1012
1013        val.json_array_not_begins_with(item)
1014    }
1015
1016    #[cfg(all(feature = "json", any(feature = "postgresql", feature = "mysql")))]
1017    fn json_array_ends_into<T>(self, item: T) -> Compare<'a>
1018    where
1019        T: Into<Expression<'a>>,
1020    {
1021        let col: Column<'a> = self.into();
1022        let val: Expression<'a> = col.into();
1023
1024        val.json_array_ends_into(item)
1025    }
1026
1027    #[cfg(all(feature = "json", any(feature = "postgresql", feature = "mysql")))]
1028    fn json_array_not_ends_into<T>(self, item: T) -> Compare<'a>
1029    where
1030        T: Into<Expression<'a>>,
1031    {
1032        let col: Column<'a> = self.into();
1033        let val: Expression<'a> = col.into();
1034
1035        val.json_array_not_ends_into(item)
1036    }
1037
1038    #[cfg(all(feature = "json", any(feature = "postgresql", feature = "mysql")))]
1039    fn json_type_equals<T>(self, json_type: T) -> Compare<'a>
1040    where
1041        T: Into<JsonType<'a>>,
1042    {
1043        let col: Column<'a> = self.into();
1044        let val: Expression<'a> = col.into();
1045
1046        val.json_type_equals(json_type)
1047    }
1048
1049    #[cfg(all(feature = "json", any(feature = "postgresql", feature = "mysql")))]
1050    fn json_type_not_equals<T>(self, json_type: T) -> Compare<'a>
1051    where
1052        T: Into<JsonType<'a>>,
1053    {
1054        let col: Column<'a> = self.into();
1055        let val: Expression<'a> = col.into();
1056
1057        val.json_type_not_equals(json_type)
1058    }
1059
1060    #[cfg(feature = "postgresql")]
1061    fn matches<T>(self, query: T) -> Compare<'a>
1062    where
1063        T: Into<Cow<'a, str>>,
1064    {
1065        let col: Column<'a> = self.into();
1066        let val: Expression<'a> = col.into();
1067
1068        val.matches(query)
1069    }
1070
1071    #[cfg(feature = "postgresql")]
1072    fn not_matches<T>(self, query: T) -> Compare<'a>
1073    where
1074        T: Into<Cow<'a, str>>,
1075    {
1076        let col: Column<'a> = self.into();
1077        let val: Expression<'a> = col.into();
1078
1079        val.not_matches(query)
1080    }
1081
1082    #[cfg(feature = "postgresql")]
1083    fn any(self) -> Compare<'a> {
1084        let col: Column<'a> = self.into();
1085        let val: Expression<'a> = col.into();
1086
1087        val.any()
1088    }
1089
1090    #[cfg(feature = "postgresql")]
1091    fn all(self) -> Compare<'a> {
1092        let col: Column<'a> = self.into();
1093        let val: Expression<'a> = col.into();
1094
1095        val.all()
1096    }
1097}