Skip to content

Commit

Permalink
Add the ability to work with boxed expressions
Browse files Browse the repository at this point in the history
There's a few limitations that I'm not happy with at the moment:

- The type of the expression has to be repeated twice
  (https://github.com/rust-lang/rust/isues/30056)
- It won't work with joins yet. I might be able to work around this in
  the short term, but it may require
  rust-lang/rust#29864 or specialization to
  express properly
  • Loading branch information
sgrif committed Nov 25, 2015
1 parent 32d07e0 commit 8a10486
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 1 deletion.
31 changes: 31 additions & 0 deletions src/expression/mod.rs
Expand Up @@ -119,6 +119,18 @@ pub trait Expression {
}
}

impl<T: Expression + ?Sized> Expression for Box<T> {
type SqlType = T::SqlType;

fn to_sql(&self, out: &mut QueryBuilder) -> BuildQueryResult {
Expression::to_sql(&**self, out)
}

fn to_insert_sql(&self, out: &mut QueryBuilder) -> BuildQueryResult {
Expression::to_insert_sql(&**self, out)
}
}

pub trait AsExpression<T: NativeSqlType> {
type Expression: Expression<SqlType=T>;

Expand All @@ -139,5 +151,24 @@ pub trait SelectableExpression<
>: Expression {
}

impl<T: ?Sized, ST, QS> SelectableExpression<QS, ST> for Box<T> where
T: SelectableExpression<QS, ST>,
ST: NativeSqlType,
Box<T>: Expression,
{
}

pub trait NonAggregate: Expression {
}

impl<T: NonAggregate + ?Sized> NonAggregate for Box<T> {
}

pub trait BoxableExpression<QS, ST: NativeSqlType>: Expression + SelectableExpression<QS, ST> + NonAggregate {
}

impl<QS, T, ST> BoxableExpression<QS, ST> for T where
ST: NativeSqlType,
T: Expression + SelectableExpression<QS, ST> + NonAggregate,
{
}
2 changes: 1 addition & 1 deletion src/lib.rs
Expand Up @@ -25,7 +25,7 @@ pub mod helper_types {
mod macros;

pub use connection::{Connection, Cursor};
pub use expression::{Expression, SelectableExpression};
pub use expression::{Expression, SelectableExpression, BoxableExpression};
pub use query_dsl::*;
pub use query_source::{QuerySource, Queriable, Table, Column, JoinTo};
pub use result::{TransactionError, TransactionResult, ConnectionError, ConnectionResult};
20 changes: 20 additions & 0 deletions tests/filter.rs
Expand Up @@ -230,3 +230,23 @@ fn or_doesnt_mess_with_precidence_of_previous_statements() {

assert_eq!(Some(0), count);
}

sql_function!(lower, lower_t, (x: VarChar) -> VarChar);

#[test]
fn filter_by_boxed_predicate() {
fn by_name(name: &str) -> Box<BoxableExpression<users::table, types::Bool, SqlType=types::Bool>> {
Box::new(lower(users::name).eq(name.to_string()))
}

let connection = connection_with_sean_and_tess_in_users_table();
let sean = User::new(1, "Sean");
let tess = User::new(2, "Tess");
let queried_sean = users::table.filter(by_name("sean")).first(&connection)
.unwrap();
let queried_tess = users::table.filter(by_name("tess")).first(&connection)
.unwrap();

assert_eq!(Some(sean), queried_sean);
assert_eq!(Some(tess), queried_tess);
}

0 comments on commit 8a10486

Please sign in to comment.