Merge pull request #27 from derekprior/dp-is-null

Implement `IS NULL` and `IS NOT NULL`
This commit is contained in:
Sean Griffin 2015-11-28 18:51:19 -07:00
commit ac9f71bcd6
3 changed files with 89 additions and 0 deletions

View File

@ -16,6 +16,14 @@ pub trait ExpressionMethods: Expression + Sized {
NotEq::new(self, other.as_expression())
}
fn is_null(self) -> IsNull<Self> {
IsNull::new(self)
}
fn is_not_null(self) -> IsNotNull<Self> {
IsNotNull::new(self)
}
fn gt<T: AsExpression<Self::SqlType>>(self, other: T) -> Gt<Self, T::Expression> {
Gt::new(self, other.as_expression())
}

View File

@ -47,6 +47,50 @@ macro_rules! infix_predicate {
}
}
#[macro_export]
macro_rules! postfix_predicate {
($name:ident, $operator:expr) => {
postfix_predicate!($name, $operator, $crate::types::Bool);
};
($name:ident, $operator:expr, $return_type:ty) => {
#[derive(Debug, Clone, Copy)]
pub struct $name<T> {
expr: T,
}
impl<T> $name<T> {
pub fn new(expr: T) -> Self {
$name {
expr: expr,
}
}
}
impl<T> $crate::expression::Expression for $name<T> where
T: $crate::expression::Expression,
{
type SqlType = $return_type;
fn to_sql(&self, out: &mut $crate::query_builder::QueryBuilder) -> $crate::query_builder::BuildQueryResult {
try!(self.expr.to_sql(out));
out.push_sql($operator);
Ok(())
}
}
impl<T, QS> $crate::expression::SelectableExpression<QS> for $name<T> where
T: $crate::expression::SelectableExpression<QS>,
{
}
impl<T> $crate::expression::NonAggregate for $name<T> where
T: $crate::expression::NonAggregate,
{
}
}
}
infix_predicate!(And, " AND ");
infix_predicate!(Between, " BETWEEN ");
infix_predicate!(Eq, " = ");
@ -60,6 +104,9 @@ infix_predicate!(NotEq, " != ");
infix_predicate!(NotLike, " NOT LIKE ");
infix_predicate!(Or, " OR ");
postfix_predicate!(IsNull, " IS NULL");
postfix_predicate!(IsNotNull, " IS NOT NULL");
use query_source::Column;
use query_builder::*;
use super::{Expression, SelectableExpression};

View File

@ -49,6 +49,40 @@ fn filter_by_equality_on_nullable_columns() {
assert_eq!(vec![tess], source.load(&connection).unwrap().collect::<Vec<_>>());
}
#[test]
fn filter_by_is_not_null_on_nullable_columns() {
use schema::users::dsl::*;
let connection = connection();
setup_users_table(&connection);
let data = vec![
NewUser::new("Derek", Some("red")),
NewUser::new("Gordon", None),
];
connection.insert_returning_count(&users, &data).unwrap();
let derek = User::with_hair_color(1, "Derek", "red");
let source = users.filter(hair_color.is_not_null());
assert_eq!(vec![derek], source.load(&connection).unwrap().collect::<Vec<_>>());
}
#[test]
fn filter_by_is_null_on_nullable_columns() {
use schema::users::dsl::*;
let connection = connection();
setup_users_table(&connection);
let data = vec![
NewUser::new("Derek", Some("red")),
NewUser::new("Gordon", None),
];
connection.insert_returning_count(&users, &data).unwrap();
let gordon = User::new(2, "Gordon");
let source = users.filter(hair_color.is_null());
assert_eq!(vec![gordon], source.load(&connection).unwrap().collect::<Vec<_>>());
}
#[test]
fn filter_after_joining() {
use schema::users::name;