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