diesel/sqlite/expression/
expression_methods.rs

1//! Sqlite specific expression methods.
2
3pub(in crate::sqlite) use self::private::{
4    BinaryOrNullableBinary, JsonOrNullableJson, JsonOrNullableJsonOrJsonbOrNullableJsonb,
5    MaybeNullableValue, TextOrNullableText, TextOrNullableTextOrBinaryOrNullableBinary,
6};
7use super::operators::*;
8use crate::dsl;
9use crate::expression::grouped::Grouped;
10use crate::expression::{AsExpression, Expression};
11use crate::sql_types::SqlType;
12
13/// Sqlite specific methods which are present on all expressions.
14#[cfg(feature = "sqlite")]
15pub trait SqliteExpressionMethods: Expression + Sized {
16    /// Creates a Sqlite `IS` expression.
17    ///
18    /// The `IS` operator work like = except when one or both of the operands are NULL.
19    /// In this case, if both operands are NULL, then the `IS` operator evaluates to true.
20    /// If one operand is NULL and the other is not, then the `IS` operator evaluates to false.
21    /// It is not possible for an `IS` expression to evaluate to NULL.
22    ///
23    /// # Example
24    ///
25    /// ```rust
26    /// # include!("../../doctest_setup.rs");
27    /// #
28    /// # fn main() {
29    /// #     run_test().unwrap();
30    /// # }
31    /// #
32    /// # fn run_test() -> QueryResult<()> {
33    /// #     use schema::animals::dsl::*;
34    /// #     let connection = &mut establish_connection();
35    /// let jack_is_a_dog = animals
36    ///     .select(name)
37    ///     .filter(species.is("dog"))
38    ///     .get_results::<Option<String>>(connection)?;
39    /// assert_eq!(vec![Some("Jack".to_string())], jack_is_a_dog);
40    /// #     Ok(())
41    /// # }
42    /// ```
43    fn is<T>(self, other: T) -> dsl::Is<Self, T>
44    where
45        Self::SqlType: SqlType,
46        T: AsExpression<Self::SqlType>,
47    {
48        Grouped(Is::new(self, other.as_expression()))
49    }
50
51    /// Creates a Sqlite `IS NOT` expression.
52    ///
53    /// The `IS NOT` operator work like != except when one or both of the operands are NULL.
54    /// In this case, if both operands are NULL, then the `IS NOT` operator evaluates to false.
55    /// If one operand is NULL and the other is not, then the `IS NOT` operator is true.
56    /// It is not possible for an `IS NOT` expression to evaluate to NULL.
57    ///
58    /// # Example
59    ///
60    /// ```rust
61    /// # include!("../../doctest_setup.rs");
62    /// #
63    /// # fn main() {
64    /// #     run_test().unwrap();
65    /// # }
66    /// #
67    /// # fn run_test() -> QueryResult<()> {
68    /// #     use schema::animals::dsl::*;
69    /// #     let connection = &mut establish_connection();
70    /// let jack_is_not_a_spider = animals
71    ///     .select(name)
72    ///     .filter(species.is_not("spider"))
73    ///     .get_results::<Option<String>>(connection)?;
74    /// assert_eq!(vec![Some("Jack".to_string())], jack_is_not_a_spider);
75    /// #     Ok(())
76    /// # }
77    /// ```
78    #[allow(clippy::wrong_self_convention)] // This is named after the sql operator
79    fn is_not<T>(self, other: T) -> dsl::IsNot<Self, T>
80    where
81        Self::SqlType: SqlType,
82        T: AsExpression<Self::SqlType>,
83    {
84        Grouped(IsNot::new(self, other.as_expression()))
85    }
86}
87
88impl<T: Expression> SqliteExpressionMethods for T {}
89
90pub(in crate::sqlite) mod private {
91    use crate::sql_types::{Binary, Json, Jsonb, MaybeNullableType, Nullable, SingleValue, Text};
92
93    #[diagnostic::on_unimplemented(
94        message = "`{Self}` is neither `diesel::sql_types::Text` nor `diesel::sql_types::Nullable<Text>`",
95        note = "try to provide an expression that produces one of the expected sql types"
96    )]
97    pub trait TextOrNullableText {}
98
99    impl TextOrNullableText for Text {}
100    impl TextOrNullableText for Nullable<Text> {}
101
102    #[diagnostic::on_unimplemented(
103        message = "`{Self}` is neither `diesel::sql_types::Binary` nor `diesel::sql_types::Nullable<Binary>`",
104        note = "try to provide an expression that produces one of the expected sql types"
105    )]
106    pub trait BinaryOrNullableBinary {}
107
108    impl BinaryOrNullableBinary for Binary {}
109    impl BinaryOrNullableBinary for Nullable<Binary> {}
110
111    #[diagnostic::on_unimplemented(
112        message = "`{Self}` is neither `diesel::sql_types::Text`, `diesel::sql_types::Nullable<Text>`, `diesel::sql_types::Binary` nor `diesel::sql_types::Nullable<Binary>`",
113        note = "try to provide an expression that produces one of the expected sql types"
114    )]
115    pub trait TextOrNullableTextOrBinaryOrNullableBinary {}
116
117    impl TextOrNullableTextOrBinaryOrNullableBinary for Text {}
118    impl TextOrNullableTextOrBinaryOrNullableBinary for Nullable<Text> {}
119    impl TextOrNullableTextOrBinaryOrNullableBinary for Binary {}
120    impl TextOrNullableTextOrBinaryOrNullableBinary for Nullable<Binary> {}
121
122    #[diagnostic::on_unimplemented(
123        message = "`{Self}` is neither `diesel::sql_types::Json`, `diesel::sql_types::Jsonb`, `diesel::sql_types::Nullable<Json>` nor `diesel::sql_types::Nullable<Jsonb>`",
124        note = "try to provide an expression that produces one of the expected sql types"
125    )]
126    pub trait JsonOrNullableJsonOrJsonbOrNullableJsonb {}
127    impl JsonOrNullableJsonOrJsonbOrNullableJsonb for Json {}
128    impl JsonOrNullableJsonOrJsonbOrNullableJsonb for Nullable<Json> {}
129    impl JsonOrNullableJsonOrJsonbOrNullableJsonb for Jsonb {}
130    impl JsonOrNullableJsonOrJsonbOrNullableJsonb for Nullable<Jsonb> {}
131
132    #[diagnostic::on_unimplemented(
133        message = "`{Self}` is neither `diesel::sql_types::Json` nor `diesel::sql_types::Nullable<Json>`",
134        note = "try to provide an expression that produces one of the expected sql types"
135    )]
136    pub trait JsonOrNullableJson {}
137    impl JsonOrNullableJson for Json {}
138    impl JsonOrNullableJson for Nullable<Json> {}
139
140    pub trait MaybeNullableValue<T>: SingleValue {
141        type Out: SingleValue;
142    }
143
144    impl<T, O> MaybeNullableValue<O> for T
145    where
146        T: SingleValue,
147        T::IsNull: MaybeNullableType<O>,
148        <T::IsNull as MaybeNullableType<O>>::Out: SingleValue,
149    {
150        type Out = <T::IsNull as MaybeNullableType<O>>::Out;
151    }
152}