-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add (very rudimentary) support for the GROUP BY clause
This is not part of the public API, and will almost certainly have breaking changes made to it when we actually properly support this. This commit only exists to give a more sane workaround for #210.
- Loading branch information
Showing
8 changed files
with
125 additions
and
44 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
simple_clause!(NoGroupByClause, GroupByClause, " GROUP BY "); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,93 +1,108 @@ | ||
use expression::*; | ||
use expression::aliased::Aliased; | ||
use query_builder::{Query, SelectStatement}; | ||
use query_builder::group_by_clause::*; | ||
use query_builder::limit_clause::*; | ||
use query_builder::offset_clause::*; | ||
use query_builder::order_clause::*; | ||
use query_builder::where_clause::*; | ||
use query_dsl::*; | ||
use types::{self, Bool}; | ||
|
||
impl<ST, S, F, W, O, L, Of, Selection, Type> SelectDsl<Selection, Type> | ||
for SelectStatement<ST, S, F, W, O, L, Of> where | ||
impl<ST, S, F, W, O, L, Of, G, Selection, Type> SelectDsl<Selection, Type> | ||
for SelectStatement<ST, S, F, W, O, L, Of, G> where | ||
Selection: Expression, | ||
SelectStatement<Type, Selection, F, W, O, L, Of>: Query<SqlType=Type>, | ||
SelectStatement<Type, Selection, F, W, O, L, Of, G>: Query<SqlType=Type>, | ||
{ | ||
type Output = SelectStatement<Type, Selection, F, W, O, L, Of>; | ||
type Output = SelectStatement<Type, Selection, F, W, O, L, Of, G>; | ||
|
||
fn select(self, selection: Selection) -> Self::Output { | ||
SelectStatement::new(selection, self.from, self.where_clause, self.order, | ||
self.limit, self.offset) | ||
self.limit, self.offset, self.group_by) | ||
} | ||
} | ||
|
||
impl<ST, S, F, W, O, L, Of, Predicate> FilterDsl<Predicate> | ||
for SelectStatement<ST, S, F, W, O, L, Of> where | ||
impl<ST, S, F, W, O, L, Of, G, Predicate> FilterDsl<Predicate> | ||
for SelectStatement<ST, S, F, W, O, L, Of, G> where | ||
Predicate: SelectableExpression<F, SqlType=Bool> + NonAggregate, | ||
W: WhereAnd<Predicate>, | ||
SelectStatement<ST, S, F, W::Output, O, L, Of>: Query, | ||
SelectStatement<ST, S, F, W::Output, O, L, Of, G>: Query, | ||
{ | ||
type Output = SelectStatement<ST, S, F, W::Output, O, L, Of>; | ||
type Output = SelectStatement<ST, S, F, W::Output, O, L, Of, G>; | ||
|
||
fn filter(self, predicate: Predicate) -> Self::Output { | ||
SelectStatement::new(self.select, self.from, self.where_clause.and(predicate), | ||
self.order, self.limit, self.offset) | ||
self.order, self.limit, self.offset, self.group_by) | ||
} | ||
} | ||
|
||
impl<ST, S, F, W, O, L, Of, Expr> OrderDsl<Expr> | ||
for SelectStatement<ST, S, F, W, O, L, Of> where | ||
impl<ST, S, F, W, O, L, Of, G, Expr> OrderDsl<Expr> | ||
for SelectStatement<ST, S, F, W, O, L, Of, G> where | ||
Expr: SelectableExpression<F>, | ||
SelectStatement<ST, S, F, W, OrderClause<Expr>, L, Of>: Query<SqlType=ST>, | ||
SelectStatement<ST, S, F, W, OrderClause<Expr>, L, Of, G>: Query<SqlType=ST>, | ||
{ | ||
type Output = SelectStatement<ST, S, F, W, OrderClause<Expr>, L, Of>; | ||
type Output = SelectStatement<ST, S, F, W, OrderClause<Expr>, L, Of, G>; | ||
|
||
fn order(self, expr: Expr) -> Self::Output { | ||
let order = OrderClause(expr); | ||
SelectStatement::new(self.select, self.from, self.where_clause, order, | ||
self.limit, self.offset) | ||
self.limit, self.offset, self.group_by) | ||
} | ||
} | ||
|
||
#[doc(hidden)] | ||
pub type Limit = <i64 as AsExpression<types::BigInt>>::Expression; | ||
|
||
impl<ST, S, F, W, O, L, Of> LimitDsl for SelectStatement<ST, S, F, W, O, L, Of> where | ||
SelectStatement<ST, S, F, W, O, LimitClause<Limit>, Of>: Query<SqlType=ST>, | ||
impl<ST, S, F, W, O, L, Of, G> LimitDsl for SelectStatement<ST, S, F, W, O, L, Of, G> where | ||
SelectStatement<ST, S, F, W, O, LimitClause<Limit>, Of, G>: Query<SqlType=ST>, | ||
{ | ||
type Output = SelectStatement<ST, S, F, W, O, LimitClause<Limit>, Of>; | ||
type Output = SelectStatement<ST, S, F, W, O, LimitClause<Limit>, Of, G>; | ||
|
||
fn limit(self, limit: i64) -> Self::Output { | ||
let limit_clause = LimitClause(AsExpression::<types::BigInt>::as_expression(limit)); | ||
SelectStatement::new(self.select, self.from, self.where_clause, | ||
self.order, limit_clause, self.offset) | ||
self.order, limit_clause, self.offset, self.group_by) | ||
} | ||
} | ||
|
||
#[doc(hidden)] | ||
pub type Offset = Limit; | ||
|
||
impl<ST, S, F, W, O, L, Of> OffsetDsl for SelectStatement<ST, S, F, W, O, L, Of> where | ||
SelectStatement<ST, S, F, W, O, L, OffsetClause<Offset>>: Query<SqlType=ST>, | ||
impl<ST, S, F, W, O, L, Of, G> OffsetDsl for SelectStatement<ST, S, F, W, O, L, Of, G> where | ||
SelectStatement<ST, S, F, W, O, L, OffsetClause<Offset>, G>: Query<SqlType=ST>, | ||
{ | ||
type Output = SelectStatement<ST, S, F, W, O, L, OffsetClause<Offset>>; | ||
type Output = SelectStatement<ST, S, F, W, O, L, OffsetClause<Offset>, G>; | ||
|
||
fn offset(self, offset: i64) -> Self::Output { | ||
let offset_clause = OffsetClause(AsExpression::<types::BigInt>::as_expression(offset)); | ||
SelectStatement::new(self.select, self.from, self.where_clause, | ||
self.order, self.limit, offset_clause) | ||
self.order, self.limit, offset_clause, self.group_by) | ||
} | ||
} | ||
|
||
impl<'a, ST, S, F, W, O, L, Of, Expr> WithDsl<'a, Expr> | ||
for SelectStatement<ST, S, F, W, O, L, Of> where | ||
SelectStatement<ST, S, WithQuerySource<'a, F, Expr>, W, O, L, Of>: Query, | ||
impl<'a, ST, S, F, W, O, L, Of, G, Expr> WithDsl<'a, Expr> | ||
for SelectStatement<ST, S, F, W, O, L, Of, G> where | ||
SelectStatement<ST, S, WithQuerySource<'a, F, Expr>, W, O, L, Of, G>: Query, | ||
{ | ||
type Output = SelectStatement<ST, S, WithQuerySource<'a, F, Expr>, W, O, L, Of>; | ||
type Output = SelectStatement<ST, S, WithQuerySource<'a, F, Expr>, W, O, L, Of, G>; | ||
|
||
fn with(self, expr: Aliased<'a, Expr>) -> Self::Output { | ||
let source = WithQuerySource::new(self.from, expr); | ||
SelectStatement::new(self.select, source, self.where_clause, | ||
self.order, self.limit, self.offset) | ||
self.order, self.limit, self.offset, self.group_by) | ||
} | ||
} | ||
|
||
impl<ST, S, F, W, O, L, Of, G, Expr> GroupByDsl<Expr> | ||
for SelectStatement<ST, S, F, W, O, L, Of, G> where | ||
SelectStatement<ST, S, F, W, O, L, Of, GroupByClause<Expr>>: Query, | ||
Expr: Expression, | ||
{ | ||
type Output = SelectStatement<ST, S, F, W, O, L, Of, GroupByClause<Expr>>; | ||
|
||
fn group_by(self, expr: Expr) -> Self::Output { | ||
let group_by = GroupByClause(expr); | ||
SelectStatement::new(self.select, self.from, self.where_clause, | ||
self.order, self.limit, self.offset, group_by) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
use expression::Expression; | ||
use query_builder::{Query, AsQuery}; | ||
use query_source::QuerySource; | ||
|
||
pub trait GroupByDsl<Expr: Expression> { | ||
type Output: Query; | ||
|
||
fn group_by(self, expr: Expr) -> Self::Output; | ||
} | ||
|
||
impl<T, Expr> GroupByDsl<Expr> for T where | ||
Expr: Expression, | ||
T: QuerySource + AsQuery, | ||
T::Query: GroupByDsl<Expr>, | ||
{ | ||
type Output = <T::Query as GroupByDsl<Expr>>::Output; | ||
|
||
fn group_by(self, expr: Expr) -> Self::Output { | ||
self.as_query().group_by(expr) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
use schema::*; | ||
use diesel::*; | ||
|
||
#[test] | ||
// This test is a shim for a feature which is not sufficiently implemented. It | ||
// has been added as we have a user who needs a reasonable workaround, but this | ||
// functionality will change and this test is allowed to change post-1.0 | ||
fn group_by_generates_group_by_sql() { | ||
let source = users::table.group_by(users::name).select(users::id).filter(users::hair_color.is_null()); | ||
let expected_sql = "SELECT `users`.`id` FROM `users` \ | ||
WHERE `users`.`hair_color` IS NULL \ | ||
GROUP BY `users`.`name`"; | ||
|
||
assert_eq!(expected_sql, &debug_sql!(source)); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters