diesel/expression_methods/global_expression_methods.rs
1use crate::dsl;
2use crate::expression::array_comparison::{AsInExpression, In, NotIn};
3use crate::expression::grouped::Grouped;
4use crate::expression::operators::*;
5use crate::expression::{AsExpression, Expression, assume_not_null, cast, nullable};
6use crate::sql_types::{SingleValue, SqlType, Untyped};
7
8/// Methods present on all expressions, except tuples
9pub trait ExpressionMethods: Expression + Sized {
10 /// Creates a SQL `=` expression.
11 ///
12 /// Note that this function follows SQL semantics around `None`/`null` values,
13 /// so `eq(None)` will never match. Use [`is_null`](ExpressionMethods::is_null()) instead.
14 ///
15 #[cfg_attr(
16 any(feature = "__sqlite-shared", feature = "postgres"),
17 doc = "To get behavior that is more like the Rust `=` operator you can also use the"
18 )]
19 #[cfg_attr(
20 feature = "__sqlite-shared",
21 doc = "sqlite-specific [`is`](crate::SqliteExpressionMethods::is())"
22 )]
23 #[cfg_attr(all(feature = "__sqlite-shared", feature = "postgres"), doc = "or the")]
24 #[cfg_attr(
25 feature = "postgres",
26 doc = "postgres-specific [`is_not_distinct_from`](crate::PgExpressionMethods::is_not_distinct_from())"
27 )]
28 #[cfg_attr(any(feature = "__sqlite-shared", feature = "postgres"), doc = ".")]
29 ///
30 /// # Example
31 ///
32 /// ```rust
33 /// # include!("../doctest_setup.rs");
34 /// #
35 /// # fn main() {
36 /// # use schema::users::dsl::*;
37 /// # let connection = &mut establish_connection();
38 /// let data = users.select(id).filter(name.eq("Sean"));
39 /// assert_eq!(Ok(1), data.first(connection));
40 /// # }
41 /// ```
42 ///
43 /// Matching against `None` follows SQL semantics:
44 /// ```rust
45 /// # include!("../doctest_setup.rs");
46 /// #
47 /// # fn main() {
48 /// # run_test().unwrap();
49 /// # }
50 /// #
51 /// # fn run_test() -> QueryResult<()> {
52 /// # use schema::animals::dsl::*;
53 /// # let connection = &mut establish_connection();
54 /// #
55 /// let data = animals
56 /// .select(species)
57 /// .filter(name.eq::<Option<String>>(None))
58 /// .first::<String>(connection);
59 /// assert_eq!(Err(diesel::NotFound), data);
60 ///
61 /// let data = animals
62 /// .select(species)
63 /// .filter(name.is_null())
64 /// .first::<String>(connection)?;
65 /// assert_eq!("spider", data);
66 /// # Ok(())
67 /// # }
68 /// ```
69 #[doc(alias = "=")]
70 fn eq<T>(self, other: T) -> dsl::Eq<Self, T>
71 where
72 Self::SqlType: SqlType,
73 T: AsExpression<Self::SqlType>,
74 {
75 Grouped(Eq::new(self, other.as_expression()))
76 }
77
78 /// Creates a SQL `!=` expression.
79 ///
80 /// # Example
81 ///
82 /// ```rust
83 /// # include!("../doctest_setup.rs");
84 /// #
85 /// # fn main() {
86 /// # use schema::users::dsl::*;
87 /// # let connection = &mut establish_connection();
88 /// let data = users.select(id).filter(name.ne("Sean"));
89 /// assert_eq!(Ok(2), data.first(connection));
90 /// # }
91 /// ```
92 #[doc(alias = "<>")]
93 fn ne<T>(self, other: T) -> dsl::NotEq<Self, T>
94 where
95 Self::SqlType: SqlType,
96 T: AsExpression<Self::SqlType>,
97 {
98 Grouped(NotEq::new(self, other.as_expression()))
99 }
100
101 /// Creates a SQL `IN` statement.
102 ///
103 /// Queries using this method will not typically be
104 /// placed in the prepared statement cache. However,
105 /// in cases when a subquery is passed to the method, that
106 /// query will use the cache (assuming the subquery
107 /// itself is safe to cache).
108 /// On PostgreSQL, this method automatically performs a `= ANY()`
109 /// query if this is possible. For cases where this is not possible
110 /// like for example if values is a vector of arrays we
111 /// generate an ordinary `IN` expression instead.
112 ///
113 /// # Example
114 ///
115 /// ```rust
116 /// # include!("../doctest_setup.rs");
117 /// #
118 /// # fn main() {
119 /// # use schema::users;
120 /// # use schema::posts;
121 /// # let connection = &mut establish_connection();
122 /// # diesel::sql_query("INSERT INTO users (name) VALUES
123 /// # ('Jim')").execute(connection).unwrap();
124 /// let data = users::table
125 /// .select(users::id)
126 /// .filter(users::name.eq_any(vec!["Sean", "Jim"]));
127 /// assert_eq!(Ok(vec![1, 3]), data.load(connection));
128 ///
129 /// // Calling `eq_any` with an empty array is the same as doing `WHERE 1=0`
130 /// let data = users::table
131 /// .select(users::id)
132 /// .filter(users::name.eq_any(Vec::<String>::new()));
133 /// assert_eq!(Ok(vec![]), data.load::<i32>(connection));
134 ///
135 /// // Calling `eq_any` with a subquery is the same as using
136 /// // `WHERE {column} IN {subquery}`.
137 ///
138 /// let subquery = users::table
139 /// .filter(users::name.eq("Sean"))
140 /// .select(users::id)
141 /// .into_boxed();
142 /// let data = posts::table
143 /// .select(posts::id)
144 /// .filter(posts::user_id.eq_any(subquery));
145 /// assert_eq!(Ok(vec![1, 2]), data.load::<i32>(connection));
146 ///
147 /// # }
148 /// ```
149 #[doc(alias = "in")]
150 fn eq_any<T>(self, values: T) -> dsl::EqAny<Self, T>
151 where
152 Self::SqlType: SqlType,
153 T: AsInExpression<Self::SqlType>,
154 {
155 Grouped(In::new(self, values.as_in_expression()))
156 }
157
158 /// Creates a SQL `NOT IN` statement.
159 ///
160 /// Queries using this method will not be
161 /// placed in the prepared statement cache. On PostgreSQL, this
162 /// method automatically performs a `!= ALL()` query if this is possible.
163 /// For cases where this is not possible
164 /// like for example if values is a vector of arrays we
165 /// generate an ordinary `NOT IN` expression instead.
166 ///
167 /// # Example
168 ///
169 /// ```rust
170 /// # include!("../doctest_setup.rs");
171 /// #
172 /// # fn main() {
173 /// # use schema::users::dsl::*;
174 /// # let connection = &mut establish_connection();
175 /// # diesel::sql_query("INSERT INTO users (name) VALUES
176 /// # ('Jim')").execute(connection).unwrap();
177 /// let data = users.select(id).filter(name.ne_all(vec!["Sean", "Jim"]));
178 /// assert_eq!(Ok(vec![2]), data.load(connection));
179 ///
180 /// let data = users.select(id).filter(name.ne_all(vec!["Tess"]));
181 /// assert_eq!(Ok(vec![1, 3]), data.load(connection));
182 ///
183 /// // Calling `ne_any` with an empty array is the same as doing `WHERE 1=1`
184 /// let data = users.select(id).filter(name.ne_all(Vec::<String>::new()));
185 /// assert_eq!(Ok(vec![1, 2, 3]), data.load(connection));
186 /// # }
187 /// ```
188 #[doc(alias = "in")]
189 fn ne_all<T>(self, values: T) -> dsl::NeAny<Self, T>
190 where
191 Self::SqlType: SqlType,
192 T: AsInExpression<Self::SqlType>,
193 {
194 Grouped(NotIn::new(self, values.as_in_expression()))
195 }
196
197 /// Creates a SQL `IS NULL` expression.
198 ///
199 /// # Example
200 ///
201 /// ```rust
202 /// # include!("../doctest_setup.rs");
203 /// #
204 /// # fn main() {
205 /// # run_test().unwrap();
206 /// # }
207 /// #
208 /// # fn run_test() -> QueryResult<()> {
209 /// # use schema::animals::dsl::*;
210 /// # let connection = &mut establish_connection();
211 /// #
212 /// let data = animals
213 /// .select(species)
214 /// .filter(name.is_null())
215 /// .first::<String>(connection)?;
216 /// assert_eq!("spider", data);
217 /// # Ok(())
218 /// # }
219 /// ```
220 // This method is part of the public API,
221 // so we cannot just change the name to appease clippy
222 // (Otherwise it's also named after the `IS NULL` sql expression
223 // so that name is really fine)
224 #[allow(clippy::wrong_self_convention)]
225 fn is_null(self) -> dsl::IsNull<Self> {
226 Grouped(IsNull::new(self))
227 }
228
229 /// Creates a SQL `IS NOT NULL` expression.
230 ///
231 /// # Example
232 ///
233 /// ```rust
234 /// # include!("../doctest_setup.rs");
235 /// #
236 /// # fn main() {
237 /// # run_test().unwrap();
238 /// # }
239 /// #
240 /// # fn run_test() -> QueryResult<()> {
241 /// # use schema::animals::dsl::*;
242 /// # let connection = &mut establish_connection();
243 /// #
244 /// let data = animals
245 /// .select(species)
246 /// .filter(name.is_not_null())
247 /// .first::<String>(connection)?;
248 /// assert_eq!("dog", data);
249 /// # Ok(())
250 /// # }
251 /// ```
252 // This method is part of the public API,
253 // so we cannot just change the name to appease clippy
254 // (Otherwise it's also named after the `IS NOT NULL` sql expression
255 // so that name is really fine)
256 #[allow(clippy::wrong_self_convention)]
257 fn is_not_null(self) -> dsl::IsNotNull<Self> {
258 Grouped(IsNotNull::new(self))
259 }
260
261 /// Creates a SQL `>` expression.
262 ///
263 /// # Example
264 ///
265 /// ```rust
266 /// # include!("../doctest_setup.rs");
267 /// #
268 /// # fn main() {
269 /// # run_test().unwrap();
270 /// # }
271 /// #
272 /// # fn run_test() -> QueryResult<()> {
273 /// # use schema::users::dsl::*;
274 /// # let connection = &mut establish_connection();
275 /// let data = users
276 /// .select(name)
277 /// .filter(id.gt(1))
278 /// .first::<String>(connection)?;
279 /// assert_eq!("Tess", data);
280 /// # Ok(())
281 /// # }
282 /// ```
283 #[doc(alias = ">")]
284 fn gt<T>(self, other: T) -> dsl::Gt<Self, T>
285 where
286 Self::SqlType: SqlType,
287 T: AsExpression<Self::SqlType>,
288 {
289 Grouped(Gt::new(self, other.as_expression()))
290 }
291
292 /// Creates a SQL `>=` expression.
293 ///
294 /// # Example
295 ///
296 /// ```rust
297 /// # include!("../doctest_setup.rs");
298 /// #
299 /// # fn main() {
300 /// # run_test().unwrap();
301 /// # }
302 /// #
303 /// # fn run_test() -> QueryResult<()> {
304 /// # use schema::users::dsl::*;
305 /// # let connection = &mut establish_connection();
306 /// let data = users
307 /// .select(name)
308 /// .filter(id.ge(2))
309 /// .first::<String>(connection)?;
310 /// assert_eq!("Tess", data);
311 /// # Ok(())
312 /// # }
313 /// ```
314 #[doc(alias = ">=")]
315 fn ge<T>(self, other: T) -> dsl::GtEq<Self, T>
316 where
317 Self::SqlType: SqlType,
318 T: AsExpression<Self::SqlType>,
319 {
320 Grouped(GtEq::new(self, other.as_expression()))
321 }
322
323 /// Creates a SQL `<` expression.
324 ///
325 /// # Example
326 ///
327 /// ```rust
328 /// # include!("../doctest_setup.rs");
329 /// #
330 /// # fn main() {
331 /// # run_test().unwrap();
332 /// # }
333 /// #
334 /// # fn run_test() -> QueryResult<()> {
335 /// # use schema::users::dsl::*;
336 /// # let connection = &mut establish_connection();
337 /// let data = users
338 /// .select(name)
339 /// .filter(id.lt(2))
340 /// .first::<String>(connection)?;
341 /// assert_eq!("Sean", data);
342 /// # Ok(())
343 /// # }
344 /// ```
345 #[doc(alias = "<")]
346 fn lt<T>(self, other: T) -> dsl::Lt<Self, T>
347 where
348 Self::SqlType: SqlType,
349 T: AsExpression<Self::SqlType>,
350 {
351 Grouped(Lt::new(self, other.as_expression()))
352 }
353
354 /// Creates a SQL `<=` expression.
355 ///
356 /// # Example
357 ///
358 /// ```rust
359 /// # include!("../doctest_setup.rs");
360 /// #
361 /// # fn main() {
362 /// # run_test().unwrap();
363 /// # }
364 /// #
365 /// # fn run_test() -> QueryResult<()> {
366 /// # use schema::users::dsl::*;
367 /// # let connection = &mut establish_connection();
368 /// let data = users
369 /// .select(name)
370 /// .filter(id.le(2))
371 /// .first::<String>(connection)?;
372 /// assert_eq!("Sean", data);
373 /// # Ok(())
374 /// # }
375 /// ```
376 #[doc(alias = "<=")]
377 fn le<T>(self, other: T) -> dsl::LtEq<Self, T>
378 where
379 Self::SqlType: SqlType,
380 T: AsExpression<Self::SqlType>,
381 {
382 Grouped(LtEq::new(self, other.as_expression()))
383 }
384
385 /// Creates a SQL `BETWEEN` expression using the given lower and upper
386 /// bounds.
387 ///
388 /// # Example
389 ///
390 /// ```rust
391 /// # include!("../doctest_setup.rs");
392 /// #
393 /// # fn main() {
394 /// # use schema::animals::dsl::*;
395 /// # let connection = &mut establish_connection();
396 /// #
397 /// let data = animals
398 /// .select(species)
399 /// .filter(legs.between(2, 6))
400 /// .first(connection);
401 /// #
402 /// assert_eq!(Ok("dog".to_string()), data);
403 /// # }
404 /// ```
405 fn between<T, U>(self, lower: T, upper: U) -> dsl::Between<Self, T, U>
406 where
407 Self::SqlType: SqlType,
408 T: AsExpression<Self::SqlType>,
409 U: AsExpression<Self::SqlType>,
410 {
411 Grouped(Between::new(
412 self,
413 And::new(lower.as_expression(), upper.as_expression()),
414 ))
415 }
416
417 /// Creates a SQL `NOT BETWEEN` expression using the given lower and upper
418 /// bounds.
419 ///
420 /// # Example
421 ///
422 /// ```rust
423 /// # include!("../doctest_setup.rs");
424 /// #
425 /// # fn main() {
426 /// # run_test().unwrap();
427 /// # }
428 /// #
429 /// # fn run_test() -> QueryResult<()> {
430 /// # use schema::animals::dsl::*;
431 /// # let connection = &mut establish_connection();
432 /// #
433 /// let data = animals
434 /// .select(species)
435 /// .filter(legs.not_between(2, 6))
436 /// .first::<String>(connection)?;
437 /// assert_eq!("spider", data);
438 /// # Ok(())
439 /// # }
440 /// ```
441 fn not_between<T, U>(self, lower: T, upper: U) -> dsl::NotBetween<Self, T, U>
442 where
443 Self::SqlType: SqlType,
444 T: AsExpression<Self::SqlType>,
445 U: AsExpression<Self::SqlType>,
446 {
447 Grouped(NotBetween::new(
448 self,
449 And::new(lower.as_expression(), upper.as_expression()),
450 ))
451 }
452
453 /// Generates a `CAST(expr AS sql_type)` expression
454 ///
455 /// It is necessary that the expression's SQL type can be casted to the
456 /// target SQL type (represented by the [`CastsTo`](cast::CastsTo) trait),
457 /// and that we know how the corresponding SQL type is named for the
458 /// specific backend (represented by the
459 /// [`KnownCastSqlTypeName`](cast::KnownCastSqlTypeName) trait).
460 ///
461 /// # Example
462 ///
463 /// ```rust
464 /// # include!("../doctest_setup.rs");
465 /// #
466 /// # fn main() {
467 /// # run_test().unwrap();
468 /// # }
469 /// #
470 /// # fn run_test() -> QueryResult<()> {
471 /// # use schema::animals::dsl::*;
472 /// # let connection = &mut establish_connection();
473 /// #
474 /// use diesel::sql_types;
475 ///
476 /// let data = diesel::select(
477 /// 12_i32
478 /// .into_sql::<sql_types::Int4>()
479 /// .cast::<sql_types::Text>(),
480 /// )
481 /// .first::<String>(connection)?;
482 /// assert_eq!("12", data);
483 /// # Ok(())
484 /// # }
485 /// ```
486 fn cast<ST>(self) -> dsl::Cast<Self, ST>
487 where
488 ST: SingleValue,
489 Self::SqlType: cast::CastsTo<ST>,
490 {
491 cast::Cast::new(self)
492 }
493
494 /// Generates a `CAST(expr AS sql_type)` expression, this version does not check the castability, like [`cast()`](Self::cast).
495 ///
496 /// # Example
497 ///
498 /// ```rust
499 /// # include!("../doctest_setup.rs");
500 /// #
501 /// # fn main() {
502 /// # run_test().unwrap();
503 /// # }
504 /// #
505 /// # fn run_test() -> QueryResult<()> {
506 /// # use schema::animals::dsl::*;
507 /// # let connection = &mut establish_connection();
508 /// #
509 /// use diesel::sql_types;
510 ///
511 /// let data = diesel::select(
512 /// "12".into_sql::<sql_types::Text>()
513 /// .fallible_cast::<sql_types::Int8>(),
514 /// )
515 /// .first::<i64>(connection)?;
516 /// assert_eq!(12i64, data);
517 /// # Ok(())
518 /// # }
519 /// ```
520 fn fallible_cast<ST>(self) -> dsl::Cast<Self, ST>
521 where
522 ST: SingleValue,
523 Self::SqlType: cast::FallibleCastsTo<ST>,
524 {
525 cast::Cast::new(self)
526 }
527
528 /// Creates a SQL `DESC` expression, representing this expression in
529 /// descending order.
530 ///
531 /// # Example
532 ///
533 /// ```rust
534 /// # include!("../doctest_setup.rs");
535 /// #
536 /// # fn main() {
537 /// # run_test().unwrap();
538 /// # }
539 /// #
540 /// # fn run_test() -> QueryResult<()> {
541 /// # use schema::users::dsl::*;
542 /// # let connection = &mut establish_connection();
543 /// #
544 /// let names = users
545 /// .select(name)
546 /// .order(name.desc())
547 /// .load::<String>(connection)?;
548 /// assert_eq!(vec!["Tess", "Sean"], names);
549 /// # Ok(())
550 /// # }
551 /// ```
552 fn desc(self) -> dsl::Desc<Self> {
553 Desc::new(self)
554 }
555
556 /// Creates a SQL `ASC` expression, representing this expression in
557 /// ascending order.
558 ///
559 /// This is the same as leaving the direction unspecified. It is useful if
560 /// you need to provide an unknown ordering, and need to box the return
561 /// value of a function.
562 ///
563 /// # Example
564 ///
565 /// ```rust
566 /// # include!("../doctest_setup.rs");
567 /// # use diesel::expression::expression_types::NotSelectable;
568 /// #
569 /// # fn main() {
570 /// # use schema::users::dsl::*;
571 /// # let order = "name";
572 /// let ordering: Box<dyn BoxableExpression<users, DB, SqlType = NotSelectable>> =
573 /// if order == "name" {
574 /// Box::new(name.desc())
575 /// } else {
576 /// Box::new(id.asc())
577 /// };
578 /// # }
579 /// ```
580 fn asc(self) -> dsl::Asc<Self> {
581 Asc::new(self)
582 }
583}
584
585impl<T> ExpressionMethods for T
586where
587 T: Expression,
588 T::SqlType: SingleValue,
589{
590}
591
592/// Methods present on untyped expressions.
593///
594/// This trait is implemented for expressions where the sql type is [`Untyped`].
595/// This allows calling common operators on these expressions.
596///
597/// This trait is primarily meant to be used for untyped queries in
598/// [`diesel_dynamic_schema`](https://docs.rs/diesel-dynamic-schema/latest/diesel_dynamic_schema/).
599pub trait UntypedExpressionMethods: Sized {
600 /// Creates a SQL `IS NULL` expression.
601 ///
602 /// # Example
603 ///
604 /// ```rust
605 /// # include!("../doctest_setup.rs");
606 /// #
607 /// # fn main() {
608 /// # run_test().unwrap();
609 /// # }
610 /// #
611 /// # fn run_test() -> QueryResult<()> {
612 /// # use schema::animals::dsl::*;
613 /// # let connection = &mut establish_connection();
614 /// #
615 /// use diesel::sql_types::Untyped;
616 /// use diesel::dsl::sql;
617 ///
618 /// let data = animals
619 /// .select(species)
620 /// .filter(sql::<Untyped>("name").is_null())
621 /// .first::<String>(connection)?;
622 /// assert_eq!("spider", data);
623 /// # Ok(())
624 /// # }
625 /// ```
626 #[allow(clippy::wrong_self_convention)]
627 fn is_null(self) -> dsl::IsNull<Self> {
628 Grouped(IsNull::new(self))
629 }
630
631 /// Creates a SQL `IS NOT NULL` expression.
632 ///
633 /// # Example
634 ///
635 /// ```rust
636 /// # include!("../doctest_setup.rs");
637 /// #
638 /// # fn main() {
639 /// # run_test().unwrap();
640 /// # }
641 /// #
642 /// # fn run_test() -> QueryResult<()> {
643 /// # use schema::animals::dsl::*;
644 /// # let connection = &mut establish_connection();
645 /// #
646 /// use diesel::sql_types::Untyped;
647 /// use diesel::dsl::sql;
648 ///
649 /// let data = animals
650 /// .select(species)
651 /// .filter(sql::<Untyped>("name").is_not_null())
652 /// .first::<String>(connection)?;
653 /// assert_eq!("dog", data);
654 /// # Ok(())
655 /// # }
656 /// ```
657 #[allow(clippy::wrong_self_convention)]
658 fn is_not_null(self) -> dsl::IsNotNull<Self> {
659 Grouped(IsNotNull::new(self))
660 }
661
662 /// Creates a SQL `DESC` expression, representing this expression in
663 /// descending order.
664 ///
665 /// # Example
666 ///
667 /// ```rust
668 /// # include!("../doctest_setup.rs");
669 /// #
670 /// # fn main() {
671 /// # run_test().unwrap();
672 /// # }
673 /// #
674 /// # fn run_test() -> QueryResult<()> {
675 /// # use schema::users::dsl::*;
676 /// # let connection = &mut establish_connection();
677 /// #
678 /// use diesel::sql_types::Untyped;
679 /// use diesel::dsl::sql;
680 ///
681 /// let data = users
682 /// .select(name)
683 /// .order(sql::<Untyped>("name").desc())
684 /// .load::<String>(connection)?;
685 /// let expected = vec!["Tess", "Sean"];
686 /// assert_eq!(expected, data);
687 /// # Ok(())
688 /// # }
689 /// ```
690 fn desc(self) -> dsl::Desc<Self> {
691 Desc::new(self)
692 }
693
694 /// Creates a SQL `ASC` expression, representing this expression in
695 /// ascending order.
696 ///
697 /// # Example
698 ///
699 /// ```rust
700 /// # include!("../doctest_setup.rs");
701 /// #
702 /// # fn main() {
703 /// # run_test().unwrap();
704 /// # }
705 /// #
706 /// # fn run_test() -> QueryResult<()> {
707 /// # use schema::users::dsl::*;
708 /// # let connection = &mut establish_connection();
709 /// #
710 /// use diesel::sql_types::Untyped;
711 /// use diesel::dsl::sql;
712 ///
713 /// let data = users
714 /// .select(name)
715 /// .order(sql::<Untyped>("name").asc())
716 /// .load::<String>(connection)?;
717 /// let expected = vec!["Sean", "Tess"];
718 /// assert_eq!(expected, data);
719 /// # Ok(())
720 /// # }
721 /// ```
722 fn asc(self) -> dsl::Asc<Self> {
723 Asc::new(self)
724 }
725}
726
727impl<T> UntypedExpressionMethods for T where T: Expression<SqlType = Untyped> {}
728
729/// Methods present on all expressions
730pub trait NullableExpressionMethods: Expression + Sized {
731 /// Converts this potentially non-null expression into one which is treated
732 /// as nullable. This method has no impact on the generated SQL, and is only
733 /// used to allow certain comparisons that would otherwise fail to compile.
734 ///
735 /// # Example
736 /// ```no_run
737 /// # #![allow(dead_code)]
738 /// # include!("../doctest_setup.rs");
739 /// # use diesel::sql_types::*;
740 /// # use schema::users;
741 /// #
742 /// table! {
743 /// posts {
744 /// id -> Integer,
745 /// user_id -> Integer,
746 /// author_name -> Nullable<VarChar>,
747 /// }
748 /// }
749 /// #
750 /// # joinable!(posts -> users (user_id));
751 /// # allow_tables_to_appear_in_same_query!(posts, users);
752 ///
753 /// fn main() {
754 /// use self::posts::dsl::{author_name, posts};
755 /// use self::users::dsl::*;
756 /// let connection = &mut establish_connection();
757 ///
758 /// let data = users
759 /// .inner_join(posts)
760 /// .filter(name.nullable().eq(author_name))
761 /// .select(name)
762 /// .load::<String>(connection);
763 /// println!("{:?}", data);
764 /// }
765 /// ```
766 fn nullable(self) -> dsl::Nullable<Self> {
767 nullable::Nullable::new(self)
768 }
769
770 /// Converts this potentially nullable expression into one which will be **assumed**
771 /// to be not-null. This method has no impact on the generated SQL, however it will
772 /// enable you to attempt deserialization of the returned value in a non-`Option`.
773 ///
774 /// This is meant to cover for cases where you know that given the `WHERE` clause
775 /// the field returned by the database will never be `NULL`.
776 ///
777 /// This **will cause runtime errors** on `load()` if the "assume" turns out to be incorrect.
778 ///
779 /// # Examples
780 /// ## Normal usage
781 /// ```rust
782 /// # #![allow(dead_code)]
783 /// # include!("../doctest_setup.rs");
784 /// # use diesel::sql_types::*;
785 /// #
786 /// table! {
787 /// animals {
788 /// id -> Integer,
789 /// species -> VarChar,
790 /// legs -> Integer,
791 /// name -> Nullable<VarChar>,
792 /// }
793 /// }
794 ///
795 /// fn main() {
796 /// use self::animals::dsl::*;
797 /// let connection = &mut establish_connection();
798 ///
799 /// let result = animals
800 /// .filter(name.is_not_null())
801 /// .select(name.assume_not_null())
802 /// .load::<String>(connection);
803 /// assert!(result.is_ok());
804 /// }
805 /// ```
806 ///
807 /// ## Incorrect usage
808 /// ```rust
809 /// # #![allow(dead_code)]
810 /// # include!("../doctest_setup.rs");
811 /// # use diesel::sql_types::*;
812 /// #
813 /// table! {
814 /// animals {
815 /// id -> Integer,
816 /// species -> VarChar,
817 /// legs -> Integer,
818 /// name -> Nullable<VarChar>,
819 /// }
820 /// }
821 ///
822 /// fn main() {
823 /// use diesel::result::{Error, UnexpectedNullError};
824 /// use self::animals::dsl::*;
825 /// let connection = &mut establish_connection();
826 ///
827 /// let result = animals
828 /// .select(name.assume_not_null())
829 /// .load::<String>(connection);
830 /// assert!(matches!(
831 /// result,
832 /// Err(Error::DeserializationError(err)) if err.is::<UnexpectedNullError>()
833 /// ));
834 /// }
835 /// ```
836 ///
837 /// ## Advanced usage - use only if you're sure you know what you're doing!
838 ///
839 /// This will cause the `Option` to be `None` where the `left_join` succeeded but the
840 /// `author_name` turned out to be `NULL`, due to how `Option` deserialization works.
841 /// (see [`Queryable` documentation](crate::deserialize::Queryable))
842 ///
843 /// ```rust
844 /// # #![allow(dead_code)]
845 /// # include!("../doctest_setup.rs");
846 /// # use diesel::sql_types::*;
847 /// # use schema::users;
848 /// #
849 /// table! {
850 /// posts {
851 /// id -> Integer,
852 /// user_id -> Integer,
853 /// author_name -> Nullable<Text>,
854 /// }
855 /// }
856 /// #
857 /// # joinable!(posts -> users (user_id));
858 /// # allow_tables_to_appear_in_same_query!(posts, users);
859 ///
860 /// fn main() {
861 /// use self::posts;
862 /// use self::users;
863 /// let connection = &mut establish_connection();
864 ///
865 /// # diesel::sql_query("ALTER TABLE posts ADD COLUMN author_name Text")
866 /// # .execute(connection)
867 /// # .unwrap();
868 /// # diesel::update(posts::table.filter(posts::user_id.eq(1)))
869 /// # .set(posts::author_name.eq("Sean"))
870 /// # .execute(connection);
871 ///
872 /// let result = posts::table
873 /// .left_join(users::table)
874 /// .select((
875 /// posts::id,
876 /// (users::id, posts::author_name.assume_not_null()).nullable(),
877 /// ))
878 /// .order_by(posts::id)
879 /// .load::<(i32, Option<(i32, String)>)>(connection);
880 /// let expected = Ok(vec![
881 /// (1, Some((1, "Sean".to_owned()))),
882 /// (2, Some((1, "Sean".to_owned()))),
883 /// (3, None),
884 /// ]);
885 /// assert_eq!(expected, result);
886 /// }
887 /// ```
888 fn assume_not_null(self) -> dsl::AssumeNotNull<Self> {
889 assume_not_null::AssumeNotNull::new(self)
890 }
891}
892
893impl<T: Expression> NullableExpressionMethods for T {}