Skip to content

Commit 8f149f9

Browse files
authored
Merge pull request diesel-rs#2636 from weiznich/fix/1641
Fix diesel-rs#1641
2 parents 9635290 + c48f406 commit 8f149f9

14 files changed

Lines changed: 215 additions & 6 deletions

CHANGELOG.md

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

188188
* Parenthesis are now inserted around all infix operations provided by diesel's `ExpressionMethods` traits
189189

190+
* Queries containing a `distinct on` clause check now on compile time that a compatible order clause was set.
191+
190192
### Deprecated
191193

192194
* `diesel_(prefix|postfix|infix)_operator!` have been deprecated. These macros

diesel/src/pg/query_builder/distinct_on.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,26 @@
11
use crate::expression::SelectableExpression;
22
use crate::pg::Pg;
3+
use crate::query_builder::order_clause::{NoOrderClause, OrderClause};
34
use crate::query_builder::{AstPass, QueryFragment, QueryId, SelectQuery, SelectStatement};
45
use crate::query_dsl::methods::DistinctOnDsl;
6+
use crate::query_dsl::order_dsl::ValidOrderingForDistinct;
57
use crate::result::QueryResult;
8+
use crate::sql_types::SingleValue;
9+
use crate::Expression;
610

711
/// Represents `DISTINCT ON (...)`
812
#[derive(Debug, Clone, Copy, QueryId)]
913
pub struct DistinctOnClause<T>(pub(crate) T);
1014

15+
impl<T> ValidOrderingForDistinct<DistinctOnClause<T>> for NoOrderClause {}
16+
impl<T> ValidOrderingForDistinct<DistinctOnClause<T>> for OrderClause<(T,)> {}
17+
impl<T> ValidOrderingForDistinct<DistinctOnClause<T>> for OrderClause<T>
18+
where
19+
T: Expression,
20+
T::SqlType: SingleValue,
21+
{
22+
}
23+
1124
impl<T> QueryFragment<Pg> for DistinctOnClause<T>
1225
where
1326
T: QueryFragment<Pg>,
@@ -24,7 +37,9 @@ impl<ST, F, S, D, W, O, LOf, G, Selection> DistinctOnDsl<Selection>
2437
for SelectStatement<F, S, D, W, O, LOf, G>
2538
where
2639
Selection: SelectableExpression<F>,
40+
Selection::SqlType: SingleValue,
2741
Self: SelectQuery<SqlType = ST>,
42+
O: ValidOrderingForDistinct<DistinctOnClause<Selection>>,
2843
SelectStatement<F, S, DistinctOnClause<Selection>, W, O, LOf, G>: SelectQuery<SqlType = ST>,
2944
{
3045
type Output = SelectStatement<F, S, DistinctOnClause<Selection>, W, O, LOf, G>;

diesel/src/query_builder/distinct_clause.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::backend::Backend;
22
use crate::query_builder::*;
3+
use crate::query_dsl::order_dsl::ValidOrderingForDistinct;
34
use crate::result::QueryResult;
45

56
#[derive(Debug, Clone, Copy, QueryId)]
@@ -20,5 +21,8 @@ impl<DB: Backend> QueryFragment<DB> for DistinctClause {
2021
}
2122
}
2223

24+
impl<O> ValidOrderingForDistinct<NoDistinctClause> for O {}
25+
impl<O> ValidOrderingForDistinct<DistinctClause> for O {}
26+
2327
#[cfg(feature = "postgres")]
2428
pub use crate::pg::DistinctOnClause;

diesel/src/query_builder/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ pub(crate) mod locking_clause;
2525
#[doc(hidden)]
2626
pub mod nodes;
2727
pub(crate) mod offset_clause;
28-
mod order_clause;
28+
pub(crate) mod order_clause;
2929
mod returning_clause;
3030
pub(crate) mod select_clause;
3131
mod select_statement;

diesel/src/query_builder/select_statement/dsl_impls.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use crate::query_builder::{
2222
};
2323
use crate::query_dsl::boxed_dsl::BoxedDsl;
2424
use crate::query_dsl::methods::*;
25+
use crate::query_dsl::order_dsl::ValidOrderingForDistinct;
2526
use crate::query_dsl::*;
2627
use crate::query_source::joins::{Join, JoinOn, JoinTo};
2728
use crate::query_source::QuerySource;
@@ -159,7 +160,7 @@ where
159160
impl<ST, F, S, D, W, O, LOf, G, LC, Expr> OrderDsl<Expr>
160161
for SelectStatement<F, S, D, W, O, LOf, G, LC>
161162
where
162-
Expr: AppearsOnTable<F>,
163+
Expr: AppearsOnTable<F> + ValidOrderingForDistinct<D>,
163164
Self: SelectQuery<SqlType = ST>,
164165
SelectStatement<F, S, D, W, OrderClause<Expr>, LOf, G, LC>: SelectQuery<SqlType = ST>,
165166
{

diesel/src/query_builder/select_statement/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ use crate::expression::subselect::ValidSubselect;
3030
use crate::expression::*;
3131
use crate::query_builder::limit_offset_clause::LimitOffsetClause;
3232
use crate::query_builder::{QueryId, SelectQuery};
33+
use crate::query_dsl::order_dsl::ValidOrderingForDistinct;
3334
use crate::query_source::joins::{AppendSelection, Inner, Join};
3435
use crate::query_source::*;
3536
use crate::result::QueryResult;
@@ -113,6 +114,7 @@ where
113114
impl<F, S, D, W, O, LOf, G, LC> SelectQuery for SelectStatement<F, S, D, W, O, LOf, G, LC>
114115
where
115116
S: SelectClauseExpression<F>,
117+
O: ValidOrderingForDistinct<D>,
116118
{
117119
type SqlType = S::SelectClauseSqlType;
118120
}

diesel/src/query_dsl/distinct_dsl.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@ use crate::dsl;
33
use crate::expression::SelectableExpression;
44
use crate::expression::TypedExpressionType;
55
use crate::expression::ValidGrouping;
6-
use crate::query_builder::AsQuery;
7-
use crate::query_builder::SelectStatement;
6+
use crate::query_builder::{AsQuery, SelectStatement};
87
use crate::query_source::Table;
98
use crate::Expression;
109

@@ -57,6 +56,7 @@ impl<T, Selection> DistinctOnDsl<Selection> for T
5756
where
5857
Selection: SelectableExpression<T>,
5958
T: Table + AsQuery<Query = SelectStatement<T>>,
59+
SelectStatement<T>: DistinctOnDsl<Selection>,
6060
T::DefaultSelection: Expression<SqlType = T::SqlType> + ValidGrouping<()>,
6161
T::SqlType: TypedExpressionType,
6262
{

diesel/src/query_dsl/mod.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ pub mod load_dsl;
3838
mod locking_dsl;
3939
mod nullable_select_dsl;
4040
mod offset_dsl;
41-
mod order_dsl;
41+
pub(crate) mod order_dsl;
4242
#[doc(hidden)]
4343
pub mod positional_order_dsl;
4444
mod save_changes_dsl;
@@ -152,7 +152,10 @@ pub trait QueryDsl: Sized {
152152
/// .execute(&connection)
153153
/// .unwrap();
154154
/// let all_animals = animals.select((species, name, legs)).load(&connection);
155-
/// let distinct_animals = animals.select((species, name, legs)).distinct_on(species).load(&connection);
155+
/// let distinct_animals = animals
156+
/// .select((species, name, legs))
157+
/// .order_by((species, legs))
158+
/// .distinct_on(species).load(&connection);
156159
///
157160
/// assert_eq!(Ok(vec![Animal::new("dog", Some("Jack"), 4),
158161
/// Animal::new("dog", None, 4),

diesel/src/query_dsl/order_dsl.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,5 @@ where
5656
self.as_query().then_order_by(expr)
5757
}
5858
}
59+
60+
pub trait ValidOrderingForDistinct<D> {}

diesel/src/type_impls/tuples.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,10 @@ macro_rules! tuple_impls {
316316
}
317317
}
318318

319+
#[cfg(feature = "postgres")]
320+
impl<__D, $($T,)*> crate::query_dsl::order_dsl::ValidOrderingForDistinct<crate::pg::DistinctOnClause<__D>>
321+
for crate::query_builder::order_clause::OrderClause<(__D, $($T,)*)> {}
322+
319323
)+
320324
}
321325
}

0 commit comments

Comments
 (0)