diff --git a/diesel/src/pg/expression/expression_methods.rs b/diesel/src/pg/expression/expression_methods.rs index 43ca9d0a243d..e5dfdfdb58d8 100644 --- a/diesel/src/pg/expression/expression_methods.rs +++ b/diesel/src/pg/expression/expression_methods.rs @@ -2,7 +2,7 @@ pub(in crate::pg) use self::private::{ ArrayOrNullableArray, InetOrCidr, JsonIndex, JsonOrNullableJsonOrJsonbOrNullableJsonb, - JsonRemoveIndex, JsonbOrNullableJsonb, MultirangeOrNullableMultirange, + JsonRemoveIndex, JsonbOrNullableJsonb, MaybeNullableValue, MultirangeOrNullableMultirange, MultirangeOrRangeMaybeNullable, RangeHelper, RangeOrNullableRange, TextOrNullableText, }; use super::date_and_time::{AtTimeZone, DateTimeLike}; @@ -3417,8 +3417,8 @@ where pub(in crate::pg) mod private { use crate::sql_types::{ - Array, Binary, Cidr, Inet, Integer, Json, Jsonb, Multirange, Nullable, Range, SingleValue, - SqlType, Text, + Array, Binary, Cidr, Inet, Integer, Json, Jsonb, MaybeNullableType, Multirange, Nullable, + Range, SingleValue, SqlType, Text, }; use crate::{Expression, IntoSql}; @@ -3699,4 +3699,17 @@ pub(in crate::pg) mod private { impl BinaryOrNullableBinary for Binary {} impl BinaryOrNullableBinary for Nullable {} + + pub trait MaybeNullableValue: SingleValue { + type Out: SingleValue; + } + + impl MaybeNullableValue for T + where + T: SingleValue, + T::IsNull: MaybeNullableType, + >::Out: SingleValue, + { + type Out = >::Out; + } } diff --git a/diesel/src/pg/expression/functions.rs b/diesel/src/pg/expression/functions.rs index f7efce2a5c74..f88342a9ec79 100644 --- a/diesel/src/pg/expression/functions.rs +++ b/diesel/src/pg/expression/functions.rs @@ -3,6 +3,7 @@ use super::expression_methods::InetOrCidr; use crate::expression::functions::define_sql_function; use crate::pg::expression::expression_methods::ArrayOrNullableArray; +use crate::pg::expression::expression_methods::MaybeNullableValue; use crate::pg::expression::expression_methods::MultirangeOrNullableMultirange; use crate::pg::expression::expression_methods::MultirangeOrRangeMaybeNullable; use crate::pg::expression::expression_methods::RangeOrNullableRange; @@ -1423,3 +1424,49 @@ define_sql_function! { /// ``` fn array_upper(array: Arr, dimension: Integer) -> Nullable; } + +#[cfg(feature = "postgres_backend")] +define_sql_function! { + /// Converts any SQL value to json + /// + /// # Example + /// + /// ```rust + /// # include!("../../doctest_setup.rs"); + /// # + /// # fn main() { + /// # #[cfg(feature = "serde_json")] + /// # run_test().unwrap(); + /// # } + /// # + /// # #[cfg(feature = "serde_json")] + /// # fn run_test() -> QueryResult<()> { + /// # use diesel::dsl::to_json; + /// # use serde_json::{json, Value}; + /// # use diesel::sql_types::{Integer, Array, Json, Text, Nullable}; + /// # let connection = &mut establish_connection(); + /// let result = diesel::select(to_json::(1)) + /// .get_result::(connection)?; + /// + /// assert_eq!(json!(1), result); + /// + /// let result = diesel::select(to_json::, _>(vec!["abc", "xyz"])) + /// .get_result::(connection)?; + /// + /// assert_eq!(json!(["abc", "xyz"]), result); + /// + /// let result = diesel::select(to_json::>, _>(Vec::::new())) + /// .get_result::(connection)?; + /// + /// assert_eq!(json!([]), result); + /// + /// let result = diesel::select(to_json::, _>(None::)) + /// .get_result::>(connection)?; + /// + /// assert!(result.is_none()); + /// + /// # Ok(()) + /// # } + /// ``` + fn to_json>(e: E) -> E::Out; +} diff --git a/diesel/src/pg/expression/helper_types.rs b/diesel/src/pg/expression/helper_types.rs index 63c5ddac9bd9..b0f16a21d318 100644 --- a/diesel/src/pg/expression/helper_types.rs +++ b/diesel/src/pg/expression/helper_types.rs @@ -461,3 +461,8 @@ pub type array_positions = #[allow(non_camel_case_types)] #[cfg(feature = "postgres_backend")] pub type array_ndims = super::functions::array_ndims, A>; + +/// Return type of [`to_json(element)`](super::functions::to_json()) +#[allow(non_camel_case_types)] +#[cfg(feature = "postgres_backend")] +pub type to_json = super::functions::to_json, E>; diff --git a/diesel_derives/tests/auto_type.rs b/diesel_derives/tests/auto_type.rs index e0d853b23c6f..7e829d0d3618 100644 --- a/diesel_derives/tests/auto_type.rs +++ b/diesel_derives/tests/auto_type.rs @@ -432,6 +432,7 @@ fn postgres_functions() -> _ { array_position_with_subscript(pg_extras::array, pg_extras::id, pg_extras::id), array_positions(pg_extras::array, pg_extras::id), array_ndims(pg_extras::array), + to_json(pg_extras::id), ) }