Skip to content

Commit

Permalink
Merge pull request #4250 from anna-ahmed19/add_json_typeof
Browse files Browse the repository at this point in the history
`json_typeof` and `jsonb_typeof` function
  • Loading branch information
weiznich authored Sep 12, 2024
2 parents f78e6b8 + b6107fc commit 97898ec
Show file tree
Hide file tree
Showing 4 changed files with 143 additions and 4 deletions.
13 changes: 9 additions & 4 deletions diesel/src/pg/expression/expression_methods.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
//! PostgreSQL specific expression methods
pub(in crate::pg) use self::private::{
ArrayOrNullableArray, InetOrCidr, JsonIndex, JsonOrNullableJsonOrJsonbOrNullableJsonb,
JsonRemoveIndex, JsonbOrNullableJsonb, MaybeNullableValue, MultirangeOrNullableMultirange,
MultirangeOrRangeMaybeNullable, RangeHelper, RangeOrNullableRange,
TextArrayOrNullableTextArray, TextOrNullableText,
ArrayOrNullableArray, InetOrCidr, JsonIndex, JsonOrNullableJson,
JsonOrNullableJsonOrJsonbOrNullableJsonb, JsonRemoveIndex, JsonbOrNullableJsonb,
MaybeNullableValue, MultirangeOrNullableMultirange, MultirangeOrRangeMaybeNullable,
RangeHelper, RangeOrNullableRange, TextArrayOrNullableTextArray, TextOrNullableText,
};
use super::date_and_time::{AtTimeZone, DateTimeLike};
use super::operators::*;
Expand Down Expand Up @@ -3552,6 +3552,11 @@ pub(in crate::pg) mod private {
impl JsonbOrNullableJsonb for Jsonb {}
impl JsonbOrNullableJsonb for Nullable<Jsonb> {}

pub trait JsonOrNullableJson {}

impl JsonOrNullableJson for Json {}
impl JsonOrNullableJson for Nullable<Json> {}

/// A trait that describes valid json indices used by postgresql
pub trait JsonRemoveIndex {
/// The Expression node created by this index type
Expand Down
122 changes: 122 additions & 0 deletions diesel/src/pg/expression/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
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::JsonOrNullableJson;
use crate::pg::expression::expression_methods::JsonbOrNullableJsonb;
use crate::pg::expression::expression_methods::MaybeNullableValue;
use crate::pg::expression::expression_methods::MultirangeOrNullableMultirange;
use crate::pg::expression::expression_methods::MultirangeOrRangeMaybeNullable;
Expand Down Expand Up @@ -1634,3 +1636,123 @@ define_sql_function! {
text_array: Arr,
) -> Arr::Out;
}

#[cfg(feature = "postgres_backend")]
define_sql_function! {
/// Returns the type of the top-level json value as a text-string
///
/// # 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::json_typeof;
/// # use serde_json::{json, Value};
/// # use diesel::sql_types::{Json, Nullable};
/// # let connection = &mut establish_connection();
/// let result = diesel::select(json_typeof::<Json, _>(json!({"a": "b", "c": 1})))
/// .get_result::<String>(connection)?;
///
/// assert_eq!("object".to_string(), result);
///
/// let result = diesel::select(json_typeof::<Json, _>(json!([1,2,3])))
/// .get_result::<String>(connection)?;
///
/// assert_eq!("array".to_string(), result);
///
/// let result = diesel::select(json_typeof::<Json, _>(json!("abc")))
/// .get_result::<String>(connection)?;
///
/// assert_eq!("string".to_string(), result);
///
/// let result = diesel::select(json_typeof::<Json, _>(json!(-123.4)))
/// .get_result::<String>(connection)?;
///
/// assert_eq!("number".to_string(), result);
///
/// let result = diesel::select(json_typeof::<Json, _>(json!(true)))
/// .get_result::<String>(connection)?;
///
/// assert_eq!("boolean".to_string(), result);
///
/// let result = diesel::select(json_typeof::<Json, _>(json!(null)))
/// .get_result::<String>(connection)?;
///
/// assert_eq!("null".to_string(), result);
///
/// let result = diesel::select(json_typeof::<Nullable<Json>, _>(None::<Value>))
/// .get_result::<Option<String>>(connection)?;
///
/// assert!(result.is_none());
/// # Ok(())
/// # }
/// ```
fn json_typeof<E: JsonOrNullableJson + SingleValue + MaybeNullableValue<Text>>(e: E) -> E::Out;
}

#[cfg(feature = "postgres_backend")]
define_sql_function! {
/// Returns the type of the top-level jsonb value as a text-string
///
/// # 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::jsonb_typeof;
/// # use serde_json::{json, Value};
/// # use diesel::sql_types::{Jsonb, Nullable};
/// # let connection = &mut establish_connection();
/// let result = diesel::select(jsonb_typeof::<Jsonb, _>(json!({"a": "b", "c": 1})))
/// .get_result::<String>(connection)?;
///
/// assert_eq!("object".to_string(), result);
///
/// let result = diesel::select(jsonb_typeof::<Jsonb, _>(json!([1,2,3])))
/// .get_result::<String>(connection)?;
///
/// assert_eq!("array".to_string(), result);
///
/// let result = diesel::select(jsonb_typeof::<Jsonb, _>(json!("abc")))
/// .get_result::<String>(connection)?;
///
/// assert_eq!("string".to_string(), result);
///
/// let result = diesel::select(jsonb_typeof::<Jsonb, _>(json!(-123.4)))
/// .get_result::<String>(connection)?;
///
/// assert_eq!("number".to_string(), result);
///
/// let result = diesel::select(jsonb_typeof::<Jsonb, _>(json!(true)))
/// .get_result::<String>(connection)?;
///
/// assert_eq!("boolean".to_string(), result);
///
/// let result = diesel::select(jsonb_typeof::<Jsonb, _>(json!(null)))
/// .get_result::<String>(connection)?;
///
/// assert_eq!("null".to_string(), result);
///
/// let result = diesel::select(jsonb_typeof::<Nullable<Jsonb>, _>(None::<Value>))
/// .get_result::<Option<String>>(connection)?;
///
/// assert!(result.is_none());
/// # Ok(())
/// # }
/// ```
fn jsonb_typeof<E: JsonbOrNullableJsonb + SingleValue + MaybeNullableValue<Text>>(e: E) -> E::Out;
}
10 changes: 10 additions & 0 deletions diesel/src/pg/expression/helper_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -486,3 +486,13 @@ pub type to_jsonb<E> = super::functions::to_jsonb<SqlTypeOf<E>, E>;
#[allow(non_camel_case_types)]
#[cfg(feature = "postgres_backend")]
pub type json_object<A> = super::functions::json_object<SqlTypeOf<A>, A>;

/// Return type of [`json_typeof(json)`](super::functions::json_typeof())
#[allow(non_camel_case_types)]
#[cfg(feature = "postgres_backend")]
pub type json_typeof<E> = super::functions::json_typeof<SqlTypeOf<E>, E>;

/// Return type of [`jsonb_typeof(jsonb)`](super::functions::jsonb_typeof())
#[allow(non_camel_case_types)]
#[cfg(feature = "postgres_backend")]
pub type jsonb_typeof<E> = super::functions::jsonb_typeof<SqlTypeOf<E>, E>;
2 changes: 2 additions & 0 deletions diesel_derives/tests/auto_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,8 @@ fn postgres_functions() -> _ {
to_json(pg_extras::id),
to_jsonb(pg_extras::id),
json_object(pg_extras::text_array),
json_typeof(pg_extras::json),
jsonb_typeof(pg_extras::jsonb),
)
}

Expand Down

0 comments on commit 97898ec

Please sign in to comment.