diesel: master: a.and(b) is nullable even though a and b are non nullable
Setup
Versions
- Rust: latest stable - 1.48.0 (7eac88abb 2020-11-16)
- Diesel: latest master (ff8e5b15ea0dfaa22e9c12c5ed2a0e23992b0617)
- Database: postgresql
- Operating System Linux
Feature Flags
- diesel: postgres, chrono
Problem Description
a.and(b) is nullable even though a and b are non nullable
What are you trying to accomplish?
Writing an and condition of which I expect the output to be non-nullable.
What is the expected output?
compiles
What is the actual output?
error[E0271]: type mismatch resolving `<Grouped<diesel::expression::operators::And<diesel::expression::nullable::Nullable<Grouped<diesel::expression::operators::Gt<C, diesel::expression::bound::Bound<Timestamptz, DateTime<Utc>>>>>, diesel::expression::nullable::Nullable<Grouped<diesel::expression::operators::Lt<C, diesel::expression::bound::Bound<Timestamptz, DateTime<Utc>>>>>>> as diesel::Expression>::SqlType == Bool`
--> src/lib.rs:49:29
|
49 | InInterval { gt, lt } => Box::new(column.gt(gt).and(column.lt(lt)))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `Bool`, found struct `diesel::sql_types::Nullable`
|
= note: expected struct `Bool`
found struct `diesel::sql_types::Nullable<Bool>`
= note: required for the cast to the object type `dyn diesel::BoxableExpression<T, Pg, SqlType = Bool>`
Are you seeing any additional errors?
no
Steps to reproduce
git clone https://github.com/Ten0/diesel_2589_repro
cd diesel_2589_repro
cargo check
Code for reference in case that repo is removed later:
use diesel::prelude::*;
pub enum TimestampFilter {
LowerThan(chrono::DateTime<chrono::Utc>),
GreaterThan(chrono::DateTime<chrono::Utc>),
InInterval {
gt: chrono::DateTime<chrono::Utc>,
lt: chrono::DateTime<chrono::Utc>,
},
}
pub trait IntoDieselExpr<SqlType> {
type OutSqlType: diesel::sql_types::SingleValue;
fn into_diesel_expr<T, C>(
self,
column: C,
) -> Box<dyn BoxableExpression<T, diesel::pg::Pg, SqlType = Self::OutSqlType>>
where
T: diesel::Table + 'static,
SqlType: diesel::sql_types::SingleValue,
C: Expression<SqlType = SqlType>
+ diesel::query_builder::QueryFragment<diesel::pg::Pg>
+ diesel::expression::ValidGrouping<(), IsAggregate = diesel::expression::is_aggregate::No>
+ diesel::expression::SelectableExpression<T>
+ Copy
+ 'static;
}
impl IntoDieselExpr<diesel::sql_types::Timestamptz> for TimestampFilter {
type OutSqlType = diesel::sql_types::Bool;
fn into_diesel_expr<T, C>(
self,
column: C,
) -> Box<dyn BoxableExpression<T, diesel::pg::Pg, SqlType = Self::OutSqlType>>
where
T: diesel::Table + 'static,
C: Expression<SqlType = diesel::sql_types::Timestamptz>
+ diesel::query_builder::QueryFragment<diesel::pg::Pg>
+ diesel::expression::ValidGrouping<(), IsAggregate = diesel::expression::is_aggregate::No>
+ diesel::expression::SelectableExpression<T>
+ Copy
+ 'static,
{
use TimestampFilter::*;
match self {
LowerThan(date) => Box::new(column.lt(date)),
GreaterThan(date) => Box::new(column.gt(date)),
InInterval { gt, lt } => Box::new(column.gt(gt).and(column.lt(lt)))
as Box<dyn BoxableExpression<T, diesel::pg::Pg, SqlType = Self::OutSqlType>>,
}
}
}
impl IntoDieselExpr<diesel::sql_types::Nullable<diesel::sql_types::Timestamptz>> for TimestampFilter {
type OutSqlType = diesel::sql_types::Nullable<diesel::sql_types::Bool>;
fn into_diesel_expr<T, C>(
self,
column: C,
) -> Box<dyn BoxableExpression<T, diesel::pg::Pg, SqlType = Self::OutSqlType>>
where
T: diesel::Table + 'static,
C: Expression<SqlType = diesel::sql_types::Nullable<diesel::sql_types::Timestamptz>>
+ diesel::query_builder::QueryFragment<diesel::pg::Pg>
+ diesel::expression::ValidGrouping<(), IsAggregate = diesel::expression::is_aggregate::No>
+ diesel::expression::SelectableExpression<T>
+ Copy
+ 'static,
{
use TimestampFilter::*;
match self {
LowerThan(date) => Box::new(column.lt(date)),
GreaterThan(date) => Box::new(column.gt(date)),
InInterval { gt, lt } => Box::new(column.gt(gt).and(column.lt(lt))),
}
}
}
Checklist
- I have already looked over the issue tracker for similar issues.
- This issue can be reproduced on Rust’s stable channel. (Your issue will be closed if this is not the case)
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Comments: 15 (15 by maintainers)
Commits related to this issue
- Allow ~type inference on `And` and `Or` helper types This is [particularly useful for query fragment functions type inference](https://github.com/diesel-rs/diesel/discussions/3661#discussioncomment-6... — committed to Ten0/diesel by Ten0 a year ago
- Allow ~type inference on `And` and `Or` helper types This is [particularly useful for query fragment functions type inference](https://github.com/diesel-rs/diesel/discussions/3661#discussioncomment-6... — committed to Ten0/diesel by Ten0 a year ago
The point is that strategy is not really possible for
.and()because otherwise you would have afilter()call with quite a lot of.nullable()calls in it. I wouldn’t call that a good API, especially as this was not the case for 1.x.Having thought about this a bit more I think I’ve found a solution that does not require a breaking change. On 1.4.x the impl for
BooleanExpressionMethods::andlooks like this:Now as already elaborated quite a lot of times, just changing that to
is breaking change I’m not really comfortable with, but I think we can easily workaround that by just setting the
STparameter ondsl::AndtoST = Boolas this is the case for all expressions on 1.4 if I correctly see that. If anyone is willing to provide a PR doing that I’m likely fine with that change.