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