Skip to content

Commit

Permalink
Merge pull request #4100 from cole-wildcardsoftware/range_is_containe…
Browse files Browse the repository at this point in the history
…d_by

Add is_contained_by to PgRangeExpressionMethods
  • Loading branch information
weiznich committed Jul 9, 2024
2 parents bcbb879 + 4eed3e3 commit 18af06f
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 2 deletions.
52 changes: 52 additions & 0 deletions diesel/src/pg/expression/expression_methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -806,6 +806,58 @@ pub trait PgRangeExpressionMethods: Expression + Sized {
{
Grouped(Contains::new(self, other.as_expression()))
}

/// Creates a PostgreSQL `<@` expression.
///
/// This operator returns whether a range is contained by a specific element
///
/// # Example
///
/// ```rust
/// # include!("../../doctest_setup.rs");
/// #
/// # table! {
/// # posts {
/// # id -> Integer,
/// # versions -> Range<Integer>,
/// # }
/// # }
/// #
/// # fn main() {
/// # run_test().unwrap();
/// # }
/// #
/// # fn run_test() -> QueryResult<()> {
/// # use self::posts::dsl::*;
/// # use std::collections::Bound;
/// # let conn = &mut establish_connection();
/// # diesel::sql_query("DROP TABLE IF EXISTS posts").execute(conn).unwrap();
/// # diesel::sql_query("CREATE TABLE posts (id SERIAL PRIMARY KEY, versions INT4RANGE NOT NULL)").execute(conn).unwrap();
/// #
/// diesel::insert_into(posts)
/// .values(versions.eq((Bound::Included(5), Bound::Unbounded)))
/// .execute(conn)?;
///
/// let cool_posts = posts.select(id)
/// .filter(versions.is_contained_by((Bound::Included(1), Bound::Unbounded)))
/// .load::<i32>(conn)?;
/// assert_eq!(vec![1], cool_posts);
///
/// let amazing_posts = posts.select(id)
/// .filter(versions.is_contained_by((Bound::Included(1), Bound::Included(2))))
/// .load::<i32>(conn)?;
/// assert!(amazing_posts.is_empty());
/// # Ok(())
/// # }
/// ```
#[allow(clippy::wrong_self_convention)] // This is named after the sql operator
fn is_contained_by<T>(self, other: T) -> dsl::IsContainedBy<Self, T>
where
Self::SqlType: SqlType,
T: AsExpression<Self::SqlType>,
{
Grouped(IsContainedBy::new(self, other.as_expression()))
}
}

impl<T> PgRangeExpressionMethods for T
Expand Down
3 changes: 2 additions & 1 deletion diesel/src/pg/expression/helper_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ pub type RangeContains<Lhs, Rhs> = Grouped<
#[cfg(feature = "postgres_backend")]
pub type ContainsRange<Lhs, Rhs> = Contains<Lhs, Rhs>;

/// The return type of [`lhs.is_contained_by(rhs)`](super::expression_methods::PgArrayExpressionMethods::is_contained_by)
/// The return type of [`lhs.range_is_contained_by(rhs)`](super::expression_methods::PgRangeExpressionMethods::is_contained_by)
/// and [`lhs.is_contained_by(rhs)`](super::expression_methods::PgArrayExpressionMethods::is_contained_by)
#[cfg(feature = "postgres_backend")]
pub type IsContainedBy<Lhs, Rhs> = Grouped<super::operators::IsContainedBy<Lhs, AsExpr<Rhs, Lhs>>>;

Expand Down
4 changes: 3 additions & 1 deletion diesel_derives/tests/auto_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,9 @@ fn test_pg_jsonb_expression_methods() -> _ {
fn test_pg_range_expression_methods() -> _ {
let my_range: (Bound<i32>, Bound<i32>) = (Bound::Included(2), Bound::Included(7));

pg_extras::range.contains_range(my_range)
pg_extras::range
.contains_range(my_range)
.and(pg_extras::range.is_contained_by(my_range))
// `.contains()` cannot be supported here as
// the type level constraints are slightly different
// for `Range<>` than for the other types that provide a `contains()`
Expand Down

0 comments on commit 18af06f

Please sign in to comment.