Skip to content

Commit

Permalink
Add support for COUNT(*)
Browse files Browse the repository at this point in the history
The resulting API is more consise, and will result in a more efficient
query than what we had before.

I considered re-using the `Count` struct, and having some weird type
that represented `*` in the context that a value isn't being used, but I
don't think that concept exists outside of `COUNT`, and would require
the same amount of code duplication.
  • Loading branch information
sgrif committed Oct 1, 2015
1 parent 5d4b8fe commit c5ebe30
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 7 deletions.
25 changes: 21 additions & 4 deletions src/expression/count.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,20 @@ use query_source::QuerySource;
use super::{Expression, SelectableExpression};
use types::BigInt;

pub struct Count<T: Expression> {
target: T,
}

pub fn count<T: Expression>(t: T) -> Count<T> {
Count {
target: t,
}
}

pub fn count_star() -> CountStar {
CountStar
}

pub struct Count<T: Expression> {
target: T,
}

impl<T: Expression> Expression for Count<T> {
type SqlType = BigInt;

Expand All @@ -22,3 +26,16 @@ impl<T: Expression> Expression for Count<T> {

impl<T: Expression, QS: QuerySource> SelectableExpression<QS> for Count<T> {
}

pub struct CountStar;

impl Expression for CountStar {
type SqlType = BigInt;

fn to_sql(&self) -> String {
"COUNT(*)".to_string()
}
}

impl<QS: QuerySource> SelectableExpression<QS> for CountStar {
}
2 changes: 1 addition & 1 deletion src/expression/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
mod count;

pub use self::count::count;
pub use self::count::{count, count_star};

use query_source::QuerySource;
use types::NativeSqlType;
Expand Down
8 changes: 6 additions & 2 deletions src/query_source/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
mod joins;
mod select;

use expression::{Expression, SelectableExpression};
use expression::{Expression, SelectableExpression, count_star};
pub use self::joins::{InnerJoinSource, LeftOuterJoinSource};
use self::select::SelectSqlQuerySource;
use std::convert::Into;
use types::{FromSqlRow, NativeSqlType};
use types::{self, FromSqlRow, NativeSqlType};

pub use self::joins::JoinTo;

Expand All @@ -28,6 +28,10 @@ pub trait QuerySource: Sized {
self.select_sql_inner(expr.to_sql())
}

fn count(self) -> SelectSqlQuerySource<types::BigInt, Self> {
self.select(count_star())
}

fn select_sql<A: NativeSqlType>(self, columns: &str)
-> SelectSqlQuerySource<A, Self>
{
Expand Down
12 changes: 12 additions & 0 deletions tests/expressions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,15 @@ fn test_count_counts_the_rows() {
connection.insert_without_return(&users, vec![NewUser::new("Sean", None)]).unwrap();
assert_eq!(Some(1), connection.query_one(&source).unwrap());
}

#[test]
fn test_count_star() {
let connection = connection();
setup_users_table(&connection);
let source = users.count();

assert_eq!(Some(0), connection.query_one(&source).unwrap());
connection.insert_without_return(&users, vec![NewUser::new("Sean", None)]).unwrap();
assert_eq!(Some(1), connection.query_one(&source).unwrap());
assert_eq!("COUNT(*)", source.select_clause());
}

0 comments on commit c5ebe30

Please sign in to comment.