Skip to content

Commit

Permalink
Merge pull request #3895 from obsoleszenz/fix_boxed_expression_for_ha…
Browse files Browse the repository at this point in the history
…ving

Fix BoxedExpression for having
  • Loading branch information
weiznich authored Jan 5, 2024
2 parents bb3bd2a + b0e938b commit e05ea8d
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 11 deletions.
3 changes: 2 additions & 1 deletion diesel/src/query_builder/select_statement/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -507,8 +507,9 @@ where
}

impl<'a, ST, QS, DB, GB, Predicate> HavingDsl<Predicate>
for BoxedSelectStatement<'a, ST, QS, DB, GB>
for BoxedSelectStatement<'a, ST, FromClause<QS>, DB, GB>
where
QS: QuerySource,
DB: Backend,
GB: Expression,
HavingClause<Predicate>: QueryFragment<DB> + Send + 'a,
Expand Down
6 changes: 4 additions & 2 deletions diesel/src/query_builder/select_statement/dsl_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -662,13 +662,15 @@ where
}

impl<F, S, D, W, O, LOf, G, H, Predicate> HavingDsl<Predicate>
for SelectStatement<F, S, D, W, O, LOf, GroupByClause<G>, H>
for SelectStatement<FromClause<F>, S, D, W, O, LOf, GroupByClause<G>, H>
where
F: QuerySource,
Predicate: AppearsOnTable<F>,
Predicate: Expression,
Predicate::SqlType: BoolOrNullableBool,
{
type Output = SelectStatement<F, S, D, W, O, LOf, GroupByClause<G>, HavingClause<Predicate>>;
type Output =
SelectStatement<FromClause<F>, S, D, W, O, LOf, GroupByClause<G>, HavingClause<Predicate>>;

fn having(self, predicate: Predicate) -> Self::Output {
SelectStatement::new(
Expand Down
2 changes: 1 addition & 1 deletion diesel_compile_tests/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ error[E0277]: the trait bound `SelectStatement<FromClause<users::table>, diesel:
26 | users::table.select(users::name).having(users::id.gt(1)).load(&mut conn);
| ^^^^^^ the trait `HavingDsl<_>` is not implemented for `SelectStatement<FromClause<users::table>, diesel::query_builder::select_clause::SelectClause<users::columns::name>>`
|
= help: the trait `HavingDsl<Predicate>` is implemented for `SelectStatement<F, S, D, W, O, LOf, diesel::query_builder::group_by_clause::GroupByClause<G>, H>`
= help: the trait `HavingDsl<Predicate>` is implemented for `SelectStatement<FromClause<F>, S, D, W, O, LOf, diesel::query_builder::group_by_clause::GroupByClause<G>, H>`

error[E0277]: the trait bound `(): diesel::Expression` is not satisfied
--> tests/fail/having_cant_be_used_without_group_by.rs:28:31
Expand All @@ -24,32 +24,32 @@ error[E0277]: the trait bound `(): diesel::Expression` is not satisfied
and $N others
= note: required for `BoxedSelectStatement<'_, (diesel::sql_types::Integer, diesel::sql_types::Text), FromClause<users::table>, _>` to implement `HavingDsl<_>`

error[E0271]: type mismatch resolving `<FromClause<table> as AppearsInFromClause<table>>::Count == Once`
error[E0271]: type mismatch resolving `<table as AppearsInFromClause<table>>::Count == Once`
--> tests/fail/having_cant_be_used_without_group_by.rs:30:58
|
30 | users::table.select(users::name).group_by(users::id).having(posts::id.eq(42)).load(&mut conn);
| ^^^^^^ expected `Never`, found `Once`
|
note: required for `posts::columns::id` to implement `AppearsOnTable<FromClause<users::table>>`
note: required for `posts::columns::id` to implement `AppearsOnTable<users::table>`
--> tests/fail/having_cant_be_used_without_group_by.rs:14:9
|
14 | id -> Integer,
| ^^
= note: 2 redundant requirements hidden
= note: required for `Grouped<Eq<id, Bound<Integer, i32>>>` to implement `AppearsOnTable<FromClause<users::table>>`
= note: required for `Grouped<Eq<id, Bound<Integer, i32>>>` to implement `AppearsOnTable<users::table>`
= note: required for `SelectStatement<FromClause<table>, SelectClause<name>, NoDistinctClause, NoWhereClause, ..., ..., ...>` to implement `HavingDsl<diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<posts::columns::id, diesel::expression::bound::Bound<diesel::sql_types::Integer, i32>>>>`

error[E0271]: type mismatch resolving `<FromClause<table> as AppearsInFromClause<table>>::Count == Once`
error[E0271]: type mismatch resolving `<table as AppearsInFromClause<table>>::Count == Once`
--> tests/fail/having_cant_be_used_without_group_by.rs:32:71
|
32 | users::table.select(users::name).group_by(users::id).into_boxed().having(posts::id.eq(42)).load(&mut conn);
| ^^^^^^ expected `Never`, found `Once`
|
note: required for `posts::columns::id` to implement `AppearsOnTable<FromClause<users::table>>`
note: required for `posts::columns::id` to implement `AppearsOnTable<users::table>`
--> tests/fail/having_cant_be_used_without_group_by.rs:14:9
|
14 | id -> Integer,
| ^^
= note: 2 redundant requirements hidden
= note: required for `Grouped<Eq<id, Bound<Integer, i32>>>` to implement `AppearsOnTable<FromClause<users::table>>`
= note: required for `Grouped<Eq<id, Bound<Integer, i32>>>` to implement `AppearsOnTable<users::table>`
= note: required for `BoxedSelectStatement<'_, diesel::sql_types::Text, FromClause<users::table>, _, users::columns::id>` to implement `HavingDsl<diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<posts::columns::id, diesel::expression::bound::Bound<diesel::sql_types::Integer, i32>>>>`
45 changes: 45 additions & 0 deletions diesel_tests/tests/boxed_queries.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use super::schema::*;
use diesel::expression::is_aggregate;
use diesel::*;

#[test]
Expand Down Expand Up @@ -179,3 +180,47 @@ fn can_box_query_with_boxable_expression() {
let expected = vec![find_user_by_name("Sean", connection)];
assert_eq!(Ok(expected), data);
}

#[test]
fn can_box_query_having_with_boxable_expression() {
let connection = &mut connection_with_sean_and_tess_in_users_table();

let expr: Box<
dyn BoxableExpression<
users::table,
crate::schema::TestBackend,
users::id,
is_aggregate::Yes,
SqlType = _,
>,
> = Box::new(count(users::id).eq(1)) as _;

use diesel::dsl::count;

let data = users::table
.select(count(users::id))
.group_by(users::id)
.having(expr)
.load::<i64>(connection)
.expect("db error");
assert_eq!(data, [1, 1]);

let expr: Box<
dyn BoxableExpression<
users::table,
crate::schema::TestBackend,
users::id,
is_aggregate::Yes,
SqlType = _,
>,
> = Box::new(count(users::id).eq(1)) as _;

let data = users::table
.select(count(users::id))
.group_by(users::id)
.into_boxed()
.having(expr)
.load::<i64>(connection)
.expect("db error");
assert_eq!(data, [1, 1]);
}

0 comments on commit e05ea8d

Please sign in to comment.