diff --git a/diesel/src/pg/expression/functions.rs b/diesel/src/pg/expression/functions.rs index a00e1728339c..09d1e874b26e 100644 --- a/diesel/src/pg/expression/functions.rs +++ b/diesel/src/pg/expression/functions.rs @@ -865,3 +865,96 @@ define_sql_function! { /// ``` fn array_remove + 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::>, _, _, _>( + /// 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::>, _, _, _>( + /// 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::>, _, _, _>( + /// 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( + 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::>, _, _>( + /// 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::>, _, _>( + /// 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::>, _, _>( + /// vec![None::<&str>, None::<&str>], ",")) + /// .get_result(connection)?; + /// assert_eq!(result, ""); + /// + /// # Ok(()) + /// # } + /// ``` + fn array_to_string( + array: Arr, del: Text + ) -> Text; +} diff --git a/diesel/src/pg/expression/helper_types.rs b/diesel/src/pg/expression/helper_types.rs index bd931f363c8c..beb1c2e31c7a 100644 --- a/diesel/src/pg/expression/helper_types.rs +++ b/diesel/src/pg/expression/helper_types.rs @@ -308,6 +308,26 @@ pub type NotLikeBinary = crate::dsl::NotLike; #[deprecated(note = "Use `dsl::Concat` instead")] pub type ConcatArray = crate::dsl::Concat; +/// 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 = + super::functions::array_to_string_with_null_string< + SqlTypeOf, // 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 = super::functions::array_to_string< + SqlTypeOf, // 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")] @@ -361,7 +381,8 @@ pub type array_append = super::functions::array_append, SqlTy /// Return type of [`array_replace(array, element, replace_with)`](super::functions::array_replace()) #[allow(non_camel_case_types)] #[cfg(feature = "postgres_backend")] -pub type array_replace = super::functions::array_replace, SqlTypeOf, A, E, R>; +pub type array_replace = + super::functions::array_replace, SqlTypeOf, A, E, R>; /// Return type of [`array_dims(array)`](super::functions::array_append()) #[allow(non_camel_case_types)] @@ -376,4 +397,4 @@ pub type array_prepend = super::functions::array_prepend, Sql /// Return type of [`array_remove(array, element)`](super::functions::array_remove()) #[allow(non_camel_case_types)] #[cfg(feature = "postgres_backend")] -pub type array_remove = super::functions::array_remove, SqlTypeOf, A, E>; \ No newline at end of file +pub type array_remove = super::functions::array_remove, SqlTypeOf, A, E>; diff --git a/diesel_cli/src/cli.rs b/diesel_cli/src/cli.rs index 3c07bd937a39..345e3e880e20 100644 --- a/diesel_cli/src/cli.rs +++ b/diesel_cli/src/cli.rs @@ -210,23 +210,15 @@ pub fn build_cli() -> Command { .alias("db") .arg(migration_dir_arg()) .about("A group of commands for setting up and resetting your database.") - .subcommand( - Command::new("setup") - .arg(no_default_migration_arg()) - .about( - "Creates the database specified in your DATABASE_URL, and \ + .subcommand(Command::new("setup").arg(no_default_migration_arg()).about( + "Creates the database specified in your DATABASE_URL, and \ then runs any existing migrations.", - ) - ) - .subcommand( - Command::new("reset") - .arg(no_default_migration_arg()) - .about( - "Resets your database by dropping the database specified \ + )) + .subcommand(Command::new("reset").arg(no_default_migration_arg()).about( + "Resets your database by dropping the database specified \ in your DATABASE_URL and then running `diesel database \ setup`.", - ) - ) + )) .subcommand( Command::new("drop") .about("Drops the database specified in your DATABASE_URL.") diff --git a/diesel_cli/tests/database_setup.rs b/diesel_cli/tests/database_setup.rs index f0d3762c4c6e..c38a5eed1951 100644 --- a/diesel_cli/tests/database_setup.rs +++ b/diesel_cli/tests/database_setup.rs @@ -271,7 +271,8 @@ fn database_setup_no_default_migrations() { // sanity check assert!(!db.exists()); - let result = p.command("database") + let result = p + .command("database") .arg("setup") .arg("--no-default-migration") .run(); diff --git a/diesel_derives/tests/auto_type.rs b/diesel_derives/tests/auto_type.rs index b9e6946ffb72..d26396f90ac5 100644 --- a/diesel_derives/tests/auto_type.rs +++ b/diesel_derives/tests/auto_type.rs @@ -51,6 +51,7 @@ table! { range -> Range, multirange -> Multirange, timestamptz -> Timestamptz, + name -> Text } } @@ -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), ) }