Skip to content

Commit

Permalink
extend pg lower function to support Multirange
Browse files Browse the repository at this point in the history
  • Loading branch information
guissalustiano committed Aug 17, 2024
1 parent cee97fb commit 64c9302
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 26 deletions.
31 changes: 28 additions & 3 deletions diesel/src/pg/expression/expression_methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
pub(in crate::pg) use self::private::{
ArrayOrNullableArray, InetOrCidr, JsonIndex, JsonOrNullableJsonOrJsonbOrNullableJsonb,
JsonRemoveIndex, JsonbOrNullableJsonb, RangeHelper, RangeOrNullableRange, TextOrNullableText,
JsonRemoveIndex, JsonbOrNullableJsonb, MultirangeOrRangeMaybeNullable, RangeHelper,
RangeOrNullableRange, TextOrNullableText,
};
use super::date_and_time::{AtTimeZone, DateTimeLike};
use super::operators::*;
Expand Down Expand Up @@ -3416,8 +3417,8 @@ where

pub(in crate::pg) mod private {
use crate::sql_types::{
Array, Binary, Cidr, Inet, Integer, Json, Jsonb, Nullable, Range, SingleValue, SqlType,
Text,
Array, Binary, Cidr, Inet, Integer, Json, Jsonb, Multirange, Nullable, Range, SingleValue,
SqlType, Text,
};
use crate::{Expression, IntoSql};

Expand Down Expand Up @@ -3489,6 +3490,30 @@ pub(in crate::pg) mod private {
impl<ST> RangeOrNullableRange for Range<ST> {}
impl<ST> RangeOrNullableRange for Nullable<Range<ST>> {}

/// Marker trait used to implement `PgRangeExpressionMethods` on the appropriate
/// types. Once coherence takes associated types into account, we can remove
/// this trait.
#[diagnostic::on_unimplemented(
message = "`{Self}` is neither `diesel::sql_types::Range<_>` nor `diesel::sql_types::Multirange<_>`",
note = "try to provide an expression that produces one of the expected sql types"
)]
pub trait MultirangeOrRangeMaybeNullable {
type Inner: SingleValue;
}

impl<ST: SingleValue> MultirangeOrRangeMaybeNullable for Range<ST> {
type Inner = ST;
}
impl<ST: SingleValue> MultirangeOrRangeMaybeNullable for Nullable<Range<ST>> {
type Inner = ST;
}
impl<ST: SingleValue> MultirangeOrRangeMaybeNullable for Multirange<ST> {
type Inner = ST;
}
impl<ST: SingleValue> MultirangeOrRangeMaybeNullable for Nullable<Multirange<ST>> {
type Inner = ST;
}

/// Marker trait used to implement `PgJsonbExpressionMethods` on the appropriate types.
#[diagnostic::on_unimplemented(
message = "`{Self}` is neither `diesel::sql_types::Jsonb` nor `diesel::sql_types::Nullable<Jsonb>`",
Expand Down
38 changes: 16 additions & 22 deletions diesel/src/pg/expression/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use super::expression_methods::InetOrCidr;
use super::expression_methods::RangeHelper;
use crate::expression::functions::define_sql_function;
use crate::pg::expression::expression_methods::ArrayOrNullableArray;
use crate::pg::expression::expression_methods::MultirangeOrRangeMaybeNullable;
use crate::sql_types::*;

define_sql_function! {
Expand Down Expand Up @@ -75,39 +76,32 @@ define_sql_function! {
/// ```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 diesel::pg::sql_types::{Range, Multirange};
/// # use diesel::dsl::lower;
/// # 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();
/// #
/// use diesel::dsl::lower;
/// diesel::insert_into(posts)
/// .values(&[
/// versions.eq((Bound::Included(5), Bound::Included(7))),
/// versions.eq((Bound::Unbounded, Bound::Included(7)))
/// ]).execute(conn)?;
/// # use diesel::sql_types::{Nullable, Integer, Array};
/// # let connection = &mut establish_connection();
/// let int = diesel::select(lower::<Range<_>, Integer, _>(1..2)).get_result::<Option<i32>>(connection)?;
/// assert_eq!(Some(1), int);
///
/// let cool_posts = posts.select(lower(versions))
/// .load::<Option<i32>>(conn)?;
/// assert_eq!(vec![Some(5), None], cool_posts);
/// let int = diesel::select(lower::<Range<_>, Integer, _>(..2)).get_result::<Option<i32>>(connection)?;
/// assert_eq!(None, int);
///
/// let int = diesel::select(lower::<Nullable<Range<_>>, Integer, _>(None::<std::ops::Range<i32>>)).get_result::<Option<i32>>(connection)?;
/// assert_eq!(None, int);
///
/// let int = diesel::select(lower::<Multirange<_>, Integer, _>(vec![(Bound::Included(5), Bound::Included(7))])).get_result::<Option<i32>>(connection)?;
/// assert_eq!(Some(5), int);
/// # Ok(())
/// # }
/// ```
#[cfg(feature = "postgres_backend")]
fn lower<T: RangeHelper>(range: T) -> Nullable<<T as RangeHelper>::Inner>;
fn lower<Rang: MultirangeOrRangeMaybeNullable<Inner=T> + SingleValue, T: SingleValue>(range: Rang) -> Nullable<T>;
}

define_sql_function! {
Expand Down
2 changes: 1 addition & 1 deletion diesel/src/pg/expression/helper_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ pub type ConcatArray<Lhs, Rhs> = crate::dsl::Concat<Lhs, Rhs>;
/// Return type of [`lower(range)`](super::functions::lower())
#[allow(non_camel_case_types)]
#[cfg(feature = "postgres_backend")]
pub type lower<R> = super::functions::lower<SqlTypeOf<R>, R>;
pub type lower<R, T> = super::functions::lower<SqlTypeOf<R>, SqlTypeOf<T>, R>;

/// Return type of [`upper(range)`](super::functions::upper())
#[allow(non_camel_case_types)]
Expand Down

0 comments on commit 64c9302

Please sign in to comment.