Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implement json_object #4230

Merged
merged 4 commits into from
Sep 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion diesel/src/pg/expression/expression_methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
pub(in crate::pg) use self::private::{
ArrayOrNullableArray, InetOrCidr, JsonIndex, JsonOrNullableJsonOrJsonbOrNullableJsonb,
JsonRemoveIndex, JsonbOrNullableJsonb, MaybeNullableValue, MultirangeOrNullableMultirange,
MultirangeOrRangeMaybeNullable, RangeHelper, RangeOrNullableRange, TextOrNullableText,
MultirangeOrRangeMaybeNullable, RangeHelper, RangeOrNullableRange,
TextArrayOrNullableTextArray, TextOrNullableText,
};
use super::date_and_time::{AtTimeZone, DateTimeLike};
use super::operators::*;
Expand Down Expand Up @@ -3712,4 +3713,16 @@ pub(in crate::pg) mod private {
{
type Out = <T::IsNull as MaybeNullableType<O>>::Out;
}

#[diagnostic::on_unimplemented(
message = "`{Self}` is neither `Array<Text>`, `Array<Nullable<Text>>`,\
`Nullable<Array<Text>>` nor `diesel::sql_types::Nullable<Array<Nullable<Text>>>`",
note = "try to provide an expression that produces one of the expected sql types"
)]
pub trait TextArrayOrNullableTextArray {}

impl TextArrayOrNullableTextArray for Array<Text> {}
impl TextArrayOrNullableTextArray for Array<Nullable<Text>> {}
impl TextArrayOrNullableTextArray for Nullable<Array<Text>> {}
impl TextArrayOrNullableTextArray for Nullable<Array<Nullable<Text>>> {}
}
46 changes: 46 additions & 0 deletions diesel/src/pg/expression/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ 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;
use crate::pg::expression::expression_methods::TextArrayOrNullableTextArray;
use crate::sql_types::*;

define_sql_function! {
Expand Down Expand Up @@ -1546,3 +1547,48 @@ define_sql_function! {
/// ```
fn to_jsonb<E: MaybeNullableValue<Jsonb>>(e: E) -> E::Out;
}

define_sql_function! {
Copy link
Contributor

@guissalustiano guissalustiano Sep 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function also support a form jsonb_object(keys text[], values text[]), whitch takes keys and values pairwise from two separate arrays. Could you implement that too?
You can use #[sql_name ="..."] like in array_to_string definition and you also need to add some docs in the base function (exemple)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes sure ill implement that too

/// Builds a JSON object out of a text array. The array must have an even number of members,
/// in which case they are taken as alternating key/value pairs
///
/// # Example
///
/// ```rust
/// # include!("../../doctest_setup.rs");
/// #
/// # fn main() {
/// # run_test().unwrap();
/// # }
/// #
/// # fn run_test() -> QueryResult<()> {
/// # use diesel::dsl::json_object;
/// # use diesel::sql_types::{Array, Json, Nullable, Text};
/// # use serde_json::Value;
/// # let connection = &mut establish_connection();
/// let json = diesel::select(json_object::<Array<Text>,_>(vec!["hello","world"]))
/// .get_result::<Value>(connection)?;
/// let expected:Value = serde_json::json!({"hello":"world"});
/// assert_eq!(expected,json);
///
/// let json = diesel::select(json_object::<Array<Text>,_>(vec!["hello","world","John","Doe"]))
/// .get_result::<Value>(connection)?;
/// let expected:Value = serde_json::json!({"hello":"world","John":"Doe"});
/// assert_eq!(expected,json);
///
/// let json = diesel::select(json_object::<Array<Text>,_>(vec!["hello","world","John"]))
/// .get_result::<Value>(connection);
/// assert!(json.is_err());
///
/// let empty:Vec<String> = Vec::new();
/// let json = diesel::select(json_object::<Array<Nullable<Text>>,_>(empty))
/// .get_result::<Value>(connection);
/// assert!(json.is_err());
///
/// # Ok(())
/// # }
/// ```
fn json_object<Arr: TextArrayOrNullableTextArray + MaybeNullableValue<Json>>(
text_array: Arr,
) -> Arr::Out;
}
5 changes: 5 additions & 0 deletions diesel/src/pg/expression/helper_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -476,3 +476,8 @@ pub type to_json<E> = super::functions::to_json<SqlTypeOf<E>, E>;
#[allow(non_camel_case_types)]
#[cfg(feature = "postgres_backend")]
pub type to_jsonb<E> = super::functions::to_jsonb<SqlTypeOf<E>, E>;

/// Return type of [`json_object(text_array)`](super::functions::json_object())
#[allow(non_camel_case_types)]
#[cfg(feature = "postgres_backend")]
pub type json_object<A> = super::functions::json_object<SqlTypeOf<A>, A>;
4 changes: 3 additions & 1 deletion diesel_derives/tests/auto_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ table! {
range -> Range<Integer>,
multirange -> Multirange<Integer>,
timestamptz -> Timestamptz,
name -> Text
name -> Text,
text_array -> Array<Text>
}
}

Expand Down Expand Up @@ -435,6 +436,7 @@ fn postgres_functions() -> _ {
array_shuffle(pg_extras::array),
to_json(pg_extras::id),
to_jsonb(pg_extras::id),
json_object(pg_extras::text_array),
)
}

Expand Down
Loading