Skip to content

Commit

Permalink
Merge pull request #4171 from insky7/main
Browse files Browse the repository at this point in the history
Add support for array_to_string and array_to_string_null array functions
  • Loading branch information
weiznich authored Aug 24, 2024
2 parents 2307f29 + 012ca49 commit cd37481
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 0 deletions.
93 changes: 93 additions & 0 deletions diesel/src/pg/expression/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -865,3 +865,96 @@ define_sql_function! {
/// ```
fn array_remove<Arr: ArrayOrNullableArray<Inner=T> + SingleValue, T: SingleValue>(a: Arr, e: T) -> Arr;
}

#[cfg(feature = "postgres_backend")]
define_sql_function! {
/// Converts each array element to its text representation and concatenates those elements
/// separated by the delimiter string. If `null_string` is provided and is not `NULL`, then `NULL`
/// array entries are represented by that string; otherwise, they are omitted.
///
/// # Example
///
/// ```rust
/// # include!("../../doctest_setup.rs");
/// #
/// # fn main() {
/// # run_test().unwrap();
/// # }
/// #
/// # fn run_test() -> QueryResult<()> {
/// # use diesel::dsl::array_to_string_with_null_string;
/// # use diesel::sql_types::{Nullable, Text, Array};
/// # let connection = &mut establish_connection();
///
/// // Example with `NULL` representation as a string
/// let result: String = diesel::select(array_to_string_with_null_string::<Array<Nullable<Text>>, _, _, _>(
/// vec![Some("first"), None::<&str>, Some("third")], ",", "NULL"))
/// .get_result(connection)?;
/// assert_eq!(result, "first,NULL,third");
///
/// // Example without any `NULL` values
/// let result: String = diesel::select(array_to_string_with_null_string::<Array<Nullable<Text>>, _, _, _>(
/// vec![Some("first"), Some("second")], ",", "NULL"))
/// .get_result(connection)?;
/// assert_eq!(result, "first,second");
///
/// // Example with all `NULL` values
/// let result: String = diesel::select(array_to_string_with_null_string::<Array<Nullable<Text>>, _, _, _>(
/// vec![None::<&str>, None::<&str>], ",", "NULL"))
/// .get_result(connection)?;
/// assert_eq!(result, "NULL,NULL");
///
/// # Ok(())
/// # }
/// ```
#[sql_name = "array_to_string"]
fn array_to_string_with_null_string<Arr: ArrayOrNullableArray + SingleValue>(
array: Arr, del: Text, null: Text
) -> Text;
}

#[cfg(feature = "postgres_backend")]
define_sql_function! {
/// Converts each array element to its text representation and concatenates those elements
/// separated by the delimiter string. `NULL` entries are omitted in this variant.
/// See [array_to_string_with_null_string] for a variant with that argument.
///
/// # Example
///
/// ```rust
/// # include!("../../doctest_setup.rs");
/// #
/// # fn main() {
/// # run_test().unwrap();
/// # }
/// #
/// # fn run_test() -> QueryResult<()> {
/// # use diesel::dsl::array_to_string;
/// # use diesel::sql_types::{Text, Array, Nullable};
/// # let connection = &mut establish_connection();
///
/// // Example with non-null values
/// let result: String = diesel::select(array_to_string::<Array<Nullable<Text>>, _, _>(
/// vec![Some("first"), Some("second")], ","))
/// .get_result(connection)?;
/// assert_eq!(result, "first,second");
///
/// // Example with `NULL` values (omitted in the result)
/// let result: String = diesel::select(array_to_string::<Array<Nullable<Text>>, _, _>(
/// vec![Some("first"), None::<&str>, Some("third")], ","))
/// .get_result(connection)?;
/// assert_eq!(result, "first,third");
///
/// // Example with only `NULL` values (empty result)
/// let result: String = diesel::select(array_to_string::<Array<Nullable<Text>>, _, _>(
/// vec![None::<&str>, None::<&str>], ","))
/// .get_result(connection)?;
/// assert_eq!(result, "");
///
/// # Ok(())
/// # }
/// ```
fn array_to_string<Arr: ArrayOrNullableArray + SingleValue>(
array: Arr, del: Text
) -> Text;
}
20 changes: 20 additions & 0 deletions diesel/src/pg/expression/helper_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,26 @@ pub type NotLikeBinary<Lhs, Rhs> = crate::dsl::NotLike<Lhs, Rhs>;
#[deprecated(note = "Use `dsl::Concat` instead")]
pub type ConcatArray<Lhs, Rhs> = crate::dsl::Concat<Lhs, Rhs>;

/// Return type of [`array_to_string_with_null_string(arr, delim, null_str)`](super::functions::array_to_string_with_null_string)
#[allow(non_camel_case_types)]
#[cfg(feature = "postgres_backend")]
pub type array_to_string_with_null_string<A, D, N> =
super::functions::array_to_string_with_null_string<
SqlTypeOf<A>, // The SQL type of the array
A, // The array itself
D, // The delimiter
N, // The null string
>;

/// Return type of [`array_to_string(arr, delim)`](super::functions::array_to_string)
#[allow(non_camel_case_types)]
#[cfg(feature = "postgres_backend")]
pub type array_to_string<A, D> = super::functions::array_to_string<
SqlTypeOf<A>, // The SQL type of the array
A, // The array itself
D, // The delimiter
>;

/// Return type of [`lower(range)`](super::functions::lower())
#[allow(non_camel_case_types)]
#[cfg(feature = "postgres_backend")]
Expand Down
3 changes: 3 additions & 0 deletions diesel_derives/tests/auto_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ table! {
range -> Range<Integer>,
multirange -> Multirange<Integer>,
timestamptz -> Timestamptz,
name -> Text
}
}

Expand Down Expand Up @@ -417,6 +418,8 @@ fn postgres_functions() -> _ {
array_dims(pg_extras::array),
array_prepend(pg_extras::id, pg_extras::array),
array_remove(pg_extras::array, pg_extras::id),
array_to_string(pg_extras::array, pg_extras::name),
array_to_string_with_null_string(pg_extras::array, pg_extras::name, pg_extras::name),
)
}

Expand Down

0 comments on commit cd37481

Please sign in to comment.