Skip to content

Commit fe87242

Browse files
authored
Merge pull request diesel-rs#2272 from weiznich/feature/pg_range_ops
Add a `contains` method for postgres range types
2 parents 968e7f7 + 683a263 commit fe87242

1 file changed

Lines changed: 69 additions & 1 deletion

File tree

diesel/src/pg/expression/expression_methods.rs

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
use super::operators::*;
44
use crate::expression::{AsExpression, Expression};
5-
use crate::sql_types::{Array, Nullable, Text};
5+
use crate::sql_types::{Array, Nullable, Range, Text};
66

77
/// PostgreSQL specific methods which are present on all expressions.
88
pub trait PgExpressionMethods: Expression + Sized {
@@ -486,3 +486,71 @@ where
486486
T::SqlType: TextOrNullableText,
487487
{
488488
}
489+
490+
#[doc(hidden)]
491+
/// Marker trait used to extract the inner type
492+
/// of our `Range<T>` sql type, used to implement `PgRangeExpressionMethods`
493+
pub trait RangeHelper {
494+
type Inner;
495+
}
496+
497+
impl<ST> RangeHelper for Range<ST> {
498+
type Inner = ST;
499+
}
500+
501+
/// PostgreSQL specific methods present on range expressions.
502+
pub trait PgRangeExpressionMethods: Expression + Sized {
503+
/// Creates a PostgreSQL `@>` expression.
504+
///
505+
/// This operator returns whether a range contains an specific element
506+
///
507+
/// # Example
508+
///
509+
/// ```rust
510+
/// # #[macro_use] extern crate diesel;
511+
/// # include!("../../doctest_setup.rs");
512+
/// #
513+
/// # table! {
514+
/// # posts {
515+
/// # id -> Integer,
516+
/// # versions -> Range<Integer>,
517+
/// # }
518+
/// # }
519+
/// #
520+
/// # fn main() {
521+
/// # run_test().unwrap();
522+
/// # }
523+
/// #
524+
/// # fn run_test() -> QueryResult<()> {
525+
/// # use self::posts::dsl::*;
526+
/// # use std::collections::Bound;
527+
/// # let conn = establish_connection();
528+
/// # conn.execute("DROP TABLE IF EXISTS posts").unwrap();
529+
/// # conn.execute("CREATE TABLE posts (id SERIAL PRIMARY KEY, versions INT4RANGE NOT NULL)").unwrap();
530+
/// #
531+
/// diesel::insert_into(posts)
532+
/// .values(versions.eq((Bound::Included(5), Bound::Unbounded)))
533+
/// .execute(&conn)?;
534+
///
535+
/// let cool_posts = posts.select(id)
536+
/// .filter(versions.contains(42))
537+
/// .load::<i32>(&conn)?;
538+
/// assert_eq!(vec![1], cool_posts);
539+
///
540+
/// let amazing_posts = posts.select(id)
541+
/// .filter(versions.contains(1))
542+
/// .load::<i32>(&conn)?;
543+
/// assert!(amazing_posts.is_empty());
544+
/// # Ok(())
545+
/// # }
546+
/// ```
547+
fn contains<T>(self, other: T) -> Contains<Self, T::Expression>
548+
where
549+
Self::SqlType: RangeHelper,
550+
T: AsExpression<<Self::SqlType as RangeHelper>::Inner>,
551+
{
552+
Contains::new(self, other.as_expression())
553+
}
554+
}
555+
556+
impl<T, ST> PgRangeExpressionMethods for T where T: Expression<SqlType = Range<ST>> {}

0 commit comments

Comments
 (0)