Skip to content

Commit 4dfb934

Browse files
authored
Merge pull request diesel-rs#2738 from hi-rustin/rustin-patch-SQLITE
Added support for SQLite's `IS` and `IS NOT`
2 parents e6dccc2 + 639168e commit 4dfb934

11 files changed

Lines changed: 127 additions & 10 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ for Rust libraries in [RFC #1105](https://github.com/rust-lang/rfcs/blob/master/
5858

5959
* Added ability to create custom collation functions in SQLite.
6060

61+
* Added support for SQLite's `IS` and `IS NOT`.
62+
6163
### Removed
6264

6365
* All previously deprecated items have been removed.

diesel/src/expression/helper_types.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,3 +119,7 @@ pub use super::functions::helper_types::*;
119119
#[doc(inline)]
120120
#[cfg(feature = "postgres")]
121121
pub use crate::pg::expression::helper_types::*;
122+
123+
#[doc(inline)]
124+
#[cfg(feature = "sqlite")]
125+
pub use crate::sqlite::expression::helper_types::*;

diesel/src/expression_methods/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,7 @@ pub use self::text_expression_methods::TextExpressionMethods;
2424
#[cfg(feature = "postgres")]
2525
#[doc(inline)]
2626
pub use crate::pg::expression::expression_methods::*;
27+
28+
#[cfg(feature = "sqlite")]
29+
#[doc(inline)]
30+
pub use crate::sqlite::expression::expression_methods::*;
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
//! Sqlite specific expression methods.
2+
3+
use super::operators::*;
4+
use crate::dsl;
5+
use crate::expression::grouped::Grouped;
6+
use crate::expression::{AsExpression, Expression};
7+
use crate::sql_types::SqlType;
8+
9+
/// Sqlite specific methods which are present on all expressions.
10+
pub trait SqliteExpressionMethods: Expression + Sized {
11+
/// Creates a Sqlite `IS` expression.
12+
///
13+
/// The `IS` operator work like = except when one or both of the operands are NULL.
14+
/// In this case, if both operands are NULL, then the `IS` operator evaluates to true.
15+
/// If one operand is NULL and the other is not, then the `IS` operator evaluates to false.
16+
/// It is not possible for an `IS` expression to evaluate to NULL.
17+
///
18+
/// # Example
19+
///
20+
/// ```rust
21+
/// # include!("../../doctest_setup.rs");
22+
/// #
23+
/// # fn main() {
24+
/// # run_test().unwrap();
25+
/// # }
26+
/// #
27+
/// # fn run_test() -> QueryResult<()> {
28+
/// # use schema::animals::dsl::*;
29+
/// # let connection = establish_connection();
30+
/// let jack_is_a_dog = animals
31+
/// .select(name)
32+
/// .filter(species.is("dog"))
33+
/// .get_results::<Option<String>>(&connection)?;
34+
/// assert_eq!(vec![Some("Jack".to_string())], jack_is_a_dog);
35+
/// # Ok(())
36+
/// # }
37+
/// ```
38+
fn is<T>(self, other: T) -> dsl::Is<Self, T>
39+
where
40+
Self::SqlType: SqlType,
41+
T: AsExpression<Self::SqlType>,
42+
{
43+
Grouped(Is::new(self, other.as_expression()))
44+
}
45+
46+
/// Creates a Sqlite `IS NOT` expression.
47+
///
48+
/// The `IS NOT` operator work like != except when one or both of the operands are NULL.
49+
/// In this case, if both operands are NULL, then the `IS NOT` operator evaluates to false.
50+
/// If one operand is NULL and the other is not, then the `IS NOT` operator is true.
51+
/// It is not possible for an `IS NOT` expression to evaluate to NULL.
52+
///
53+
/// # Example
54+
///
55+
/// ```rust
56+
/// # include!("../../doctest_setup.rs");
57+
/// #
58+
/// # fn main() {
59+
/// # run_test().unwrap();
60+
/// # }
61+
/// #
62+
/// # fn run_test() -> QueryResult<()> {
63+
/// # use schema::animals::dsl::*;
64+
/// # let connection = establish_connection();
65+
/// let jack_is_not_a_spider = animals
66+
/// .select(name)
67+
/// .filter(species.is_not("spider"))
68+
/// .get_results::<Option<String>>(&connection)?;
69+
/// assert_eq!(vec![Some("Jack".to_string())], jack_is_not_a_spider);
70+
/// # Ok(())
71+
/// # }
72+
/// ```
73+
fn is_not<T>(self, other: T) -> dsl::IsNot<Self, T>
74+
where
75+
Self::SqlType: SqlType,
76+
T: AsExpression<Self::SqlType>,
77+
{
78+
Grouped(IsNot::new(self, other.as_expression()))
79+
}
80+
}
81+
82+
impl<T: Expression> SqliteExpressionMethods for T {}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
use crate::dsl::AsExpr;
2+
use crate::expression::grouped::Grouped;
3+
4+
/// The return type of `lhs.is(rhs)`.
5+
pub type Is<Lhs, Rhs> = Grouped<super::operators::Is<Lhs, AsExpr<Rhs, Lhs>>>;
6+
7+
/// The return type of `lhs.is_not(rhs)`.
8+
pub type IsNot<Lhs, Rhs> = Grouped<super::operators::IsNot<Lhs, AsExpr<Rhs, Lhs>>>;
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
//! Sqlite related query builder extensions.
2+
//!
3+
//! Everything in this module is re-exported from database agnostic locations.
4+
//! You should rely on the re-exports rather than this module directly. It is
5+
//! kept separate purely for documentation purposes.
6+
7+
pub(crate) mod expression_methods;
8+
#[doc(hidden)]
9+
pub mod helper_types;
10+
#[doc(hidden)]
11+
pub mod operators;
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
use crate::sql_types::Bool;
2+
use crate::sqlite::Sqlite;
3+
4+
__diesel_infix_operator!(Is, " IS ", ConstantNullability Bool, backend: Sqlite);
5+
__diesel_infix_operator!(IsNot, " IS NOT ", ConstantNullability Bool, backend: Sqlite);

diesel/src/sqlite/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
77
mod backend;
88
mod connection;
9+
pub(crate) mod expression;
910
mod types;
1011

1112
pub mod query_builder;

diesel_compile_tests/tests/fail/array_expressions_must_be_same_type.stderr

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ error[E0277]: the trait bound `{integer}: SelectableExpression<()>` is not satis
110110
<(A, B) as SelectableExpression<QS>>
111111
<(A, B, C) as SelectableExpression<QS>>
112112
<(A, B, C, D) as SelectableExpression<QS>>
113-
and 125 others
113+
and 127 others
114114
= note: required because of the requirements on the impl of `SelectableExpression<()>` for `({integer}, diesel::expression::bound::Bound<diesel::sql_types::Double, f64>)`
115115
= note: 1 redundant requirements hidden
116116
= note: required because of the requirements on the impl of `SelectableExpression<()>` for `diesel::pg::expression::array::ArrayLiteral<({integer}, diesel::expression::bound::Bound<diesel::sql_types::Double, f64>), diesel::sql_types::Double>`
@@ -132,7 +132,7 @@ error[E0277]: the trait bound `{integer}: ValidGrouping<()>` is not satisfied
132132
<(A, B) as ValidGrouping<__GroupByClause>>
133133
<(A, B, C) as ValidGrouping<__GroupByClause>>
134134
<(A, B, C, D) as ValidGrouping<__GroupByClause>>
135-
and 120 others
135+
and 122 others
136136
= note: required because of the requirements on the impl of `ValidGrouping<()>` for `({integer}, diesel::expression::bound::Bound<diesel::sql_types::Double, f64>)`
137137
= note: 1 redundant requirements hidden
138138
= note: required because of the requirements on the impl of `ValidGrouping<()>` for `diesel::pg::expression::array::ArrayLiteral<({integer}, diesel::expression::bound::Bound<diesel::sql_types::Double, f64>), diesel::sql_types::Double>`
@@ -149,7 +149,7 @@ error[E0277]: the trait bound `{integer}: SelectableExpression<()>` is not satis
149149
<(A, B) as SelectableExpression<QS>>
150150
<(A, B, C) as SelectableExpression<QS>>
151151
<(A, B, C, D) as SelectableExpression<QS>>
152-
and 125 others
152+
and 127 others
153153
= note: required because of the requirements on the impl of `SelectableExpression<()>` for `({integer}, diesel::expression::bound::Bound<diesel::sql_types::Double, f64>)`
154154
= note: 1 redundant requirements hidden
155155
= note: required because of the requirements on the impl of `SelectableExpression<()>` for `diesel::pg::expression::array::ArrayLiteral<({integer}, diesel::expression::bound::Bound<diesel::sql_types::Double, f64>), diesel::sql_types::Double>`
@@ -168,7 +168,7 @@ error[E0277]: the trait bound `{integer}: ValidGrouping<()>` is not satisfied
168168
<(A, B) as ValidGrouping<__GroupByClause>>
169169
<(A, B, C) as ValidGrouping<__GroupByClause>>
170170
<(A, B, C, D) as ValidGrouping<__GroupByClause>>
171-
and 120 others
171+
and 122 others
172172
= note: required because of the requirements on the impl of `ValidGrouping<()>` for `({integer}, diesel::expression::bound::Bound<diesel::sql_types::Double, f64>)`
173173
= note: 1 redundant requirements hidden
174174
= note: required because of the requirements on the impl of `ValidGrouping<()>` for `diesel::pg::expression::array::ArrayLiteral<({integer}, diesel::expression::bound::Bound<diesel::sql_types::Double, f64>), diesel::sql_types::Double>`
@@ -186,7 +186,7 @@ error[E0277]: the trait bound `{integer}: QueryId` is not satisfied
186186
<() as QueryId>
187187
<(A, B) as QueryId>
188188
<(A, B, C) as QueryId>
189-
and 186 others
189+
and 188 others
190190
= note: required because of the requirements on the impl of `QueryId` for `({integer}, diesel::expression::bound::Bound<diesel::sql_types::Double, f64>)`
191191
= note: 3 redundant requirements hidden
192192
= note: required because of the requirements on the impl of `QueryId` for `SelectStatement<(), diesel::query_builder::select_clause::SelectClause<diesel::pg::expression::array::ArrayLiteral<({integer}, diesel::expression::bound::Bound<diesel::sql_types::Double, f64>), diesel::sql_types::Double>>>`
@@ -203,7 +203,7 @@ error[E0277]: the trait bound `{integer}: QueryFragment<_>` is not satisfied
203203
<() as QueryFragment<DB>>
204204
<(A, B) as QueryFragment<__DB>>
205205
<(A, B, C) as QueryFragment<__DB>>
206-
and 216 others
206+
and 218 others
207207
= note: required because of the requirements on the impl of `QueryFragment<_>` for `({integer}, diesel::expression::bound::Bound<diesel::sql_types::Double, f64>)`
208208
= note: 2 redundant requirements hidden
209209
= note: required because of the requirements on the impl of `QueryFragment<_>` for `diesel::pg::expression::array::ArrayLiteral<({integer}, diesel::expression::bound::Bound<diesel::sql_types::Double, f64>), diesel::sql_types::Double>`
@@ -228,7 +228,7 @@ error[E0277]: the trait bound `{integer}: diesel::Expression` is not satisfied
228228
<(A, B) as diesel::Expression>
229229
<(A, B, C) as diesel::Expression>
230230
<(A, B, C, D) as diesel::Expression>
231-
and 101 others
231+
and 103 others
232232
= note: required because of the requirements on the impl of `AsExpression<diesel::sql_types::Double>` for `{integer}`
233233
= note: required because of the requirements on the impl of `AsExpressionList<diesel::sql_types::Double>` for `({integer}, f64)`
234234

diesel_compile_tests/tests/fail/find_requires_correct_type.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ error[E0277]: the trait bound `{integer}: diesel::Expression` is not satisfied
3131
<(A, B) as diesel::Expression>
3232
<(A, B, C) as diesel::Expression>
3333
<(A, B, C, D) as diesel::Expression>
34-
and 105 others
34+
and 107 others
3535
= note: required because of the requirements on the impl of `diesel::Expression` for `diesel::expression::operators::Eq<string_primary_key::columns::id, {integer}>`
3636
= note: required because of the requirements on the impl of `FilterDsl<Grouped<diesel::expression::operators::Eq<string_primary_key::columns::id, {integer}>>>` for `SelectStatement<string_primary_key::table>`
3737

@@ -46,6 +46,6 @@ error[E0277]: the trait bound `{integer}: ValidGrouping<()>` is not satisfied
4646
<(A, B) as ValidGrouping<__GroupByClause>>
4747
<(A, B, C) as ValidGrouping<__GroupByClause>>
4848
<(A, B, C, D) as ValidGrouping<__GroupByClause>>
49-
and 126 others
49+
and 128 others
5050
= note: required because of the requirements on the impl of `ValidGrouping<()>` for `diesel::expression::operators::Eq<string_primary_key::columns::id, {integer}>`
5151
= note: required because of the requirements on the impl of `FilterDsl<Grouped<diesel::expression::operators::Eq<string_primary_key::columns::id, {integer}>>>` for `SelectStatement<string_primary_key::table>`

0 commit comments

Comments
 (0)