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

Conversation

valkrypton
Copy link
Contributor

added support for json_object under #4216

@valkrypton
Copy link
Contributor Author

@weiznich what value should i pass it in auto_type.rs as pg_extras::array is of type Array<Integer>?

@weiznich
Copy link
Member

weiznich commented Sep 3, 2024

@valkrypton I would suggest to just define a new column with the type Array<Text> in the pg_extras table.

@weiznich weiznich requested a review from a team September 3, 2024 17:08
Copy link
Contributor

@guissalustiano guissalustiano left a comment

Choose a reason for hiding this comment

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

Thanks for open the PR!

I have some comments about the type signature and also request the other variant of this function

/// assert_eq!(expected,json);
///
/// let json = diesel::select(json_object(vec!["hello","world","John","Doe"])).get_result::<Value>(connection)?;
/// let expected:Value = serde_json::from_str(r#"{"hello":"world","John":"Doe"}"#).unwrap();
Copy link
Contributor

Choose a reason for hiding this comment

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

Could we use the serde_json::json! macro instead to construct the expected values?

/// # Ok(())
/// # }
/// ```
fn json_object(text_array:Array<Text>)->Json;
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.

Arrays in diesel are always generate arrays with nullable elements, with will make impossible to use this methods with array columns from tables. But this method breaks if we pass a array to them.
I would like @weiznich opinion here

Copy link
Member

Choose a reason for hiding this comment

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

I would just accept both variants here. That might require an additional helper trait that is implemented for both Array<Text> and Array<Nullable<Text>>. Additionally what's about Nullable<Array<_>> here?

@@ -1423,3 +1423,38 @@ define_sql_function! {
/// ```
fn array_upper<Arr: ArrayOrNullableArray + SingleValue>(array: Arr, dimension: Integer) -> Nullable<Integer>;
}

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

@valkrypton
Copy link
Contributor Author

@guissalustiano can you take a look at the type signature now?

@guissalustiano
Copy link
Contributor

guissalustiano commented Sep 6, 2024

Sure!
The signature fn json_object(text_array:Nullable<Array<Text>>)->Json; is broken because if you call SELECT json_object(NULL) it returns NULL, but the function signatures don't tell you that.

A signature like fn json_object(text_array:Nullable<Array<Text>>)->Nullable<Json>; would fix that, but is annoying to have this extra Nullable<_> when you use that with non-nullable inputs. On to_json we use a helper trait to handle this.

We also would like to support an Nullable<Array<Nullable<Text>>> because diesel always generates columns as Array<Nullable<_>>, and so not supporting that would mean that json_object couldn't be used with a table, only literal values.

Could you also please remove the extra files in the commit? You can keep the branch out-of-date, don't worry, or use rebase to avoid showing the news commits in your PR

@valkrypton
Copy link
Contributor Author

@guissalustiano take a look now, also i tried but couldn't figure out how to remove the extra files in the commit

Copy link
Member

@weiznich weiznich left a comment

Choose a reason for hiding this comment

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

I've added a comment explaining how to get the right function signature. Hopefully that helps to cleanup the confusion there.

Also I would like to see some cleanup of the changes in this PR. The diff looks really wired, it seems like there is some half broken merge in there. Let me know if you need help to figure out how to solve that.

/// # Ok(())
/// # }
/// ```
fn json_object<Arr:MaybeNullableValue<Array<Nullable<Text>>>>(text_array:Arr) -> Nullable<Json>;
Copy link
Member

Choose a reason for hiding this comment

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

I'm sorry but this is still not correct. The correct signature would be:

Suggested change
fn json_object<Arr:MaybeNullableValue<Array<Nullable<Text>>>>(text_array:Arr) -> Nullable<Json>;
fn json_object<Arr:ArrayOrNullableArray + MaybeNullableValue<Json>>(text_array:Arr) -> Arr::Out where Arr::Inner: TextOrNullableText;

To explain the bounds:

  • Arr: ArrayOrNullableArray says the input type is either Array<T> or Nullable<Array<T>>
  • Arr: MaybeNullableValue<Json> says that the output values has the same nullability as the input value. That means Nullable<Array<T>> evaluates to Nullable<Json> and Array<T> evaluates to Json via the Arr::Out return type.
  • Arr::Inner: TextOrNullableText says that the inner type of the array is either Text or Nullable<Text>

Now the bad thing is that the declare_sql_function!() macro does not support where clauses, so we need to have a new helper trait for this. For that we need to declare:

trait TextArrayOrNullableTextArray {}

and implement it for the following types:

  • Array<Text>
  • Nullable<Array<Text>>
  • Array<Nullable<Text>>
  • Nullable<Array<Nullable<Text>>>

(which essentially only lists the supported argument types)

That gives us then the following function signature:

Suggested change
fn json_object<Arr:MaybeNullableValue<Array<Nullable<Text>>>>(text_array:Arr) -> Nullable<Json>;
fn json_object<Arr:TextArrayOrNullableTextArray + MaybeNullableValue<Json>>>(text_array:Arr) -> Arr:Out;

``

@valkrypton
Copy link
Contributor Author

Thanks for the detailed explanation, i appreciate it.
The pr got messed up when i rebased this branch onto the updated master, i had no idea the previous commits would show up here as well. I tried to fix but couldn't figure it out, so if you could help me I'd appreciate it.

@valkrypton valkrypton force-pushed the feat/add/json_object branch 2 times, most recently from ce549b0 to 3340b6f Compare September 10, 2024 07:24
Ali Tariq and others added 4 commits September 10, 2024 18:04
* Add `#[diagnostic::on_unimplemented]` for new helper trait
* Fix formatting
Copy link
Member

@weiznich weiznich left a comment

Choose a reason for hiding this comment

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

Thanks for the update. The signature looks good now.

I just rebased this PR again to resolve the merge conflicts, but the history already looked right before that. So either it was a github issue before or you already fixed it 🙏

I also added a #[diagnostic::on_unimplemented] attribute to the new helper trait to improve the compiler error message if some user passes in a wrong typed value.

@weiznich weiznich added this pull request to the merge queue Sep 10, 2024
Merged via the queue into diesel-rs:master with commit f78e6b8 Sep 10, 2024
48 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants