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

Add Support For PostgreSQL Arrays In FromQueryResult Implementation Of JsonValue #1598

Merged
merged 9 commits into from
Aug 1, 2023
Merged

Conversation

anshap1719
Copy link
Contributor

@anshap1719 anshap1719 commented Apr 14, 2023

I wanted to add tests and I tried to as well, but this particular change isn't testable with Mock database because with Mock database, the into_json works as expected even without this change since it directly serializes any rust type into json without matching column type for various backends.

PR Info

Bug Fixes

  • If a PostgreSQL Model contains array fields, and is serialized as json while querying (using into_json()), the array fields are always skipped. This is because the current implementation of FromQueryResult for JsonValue doesn't handle postgres arrays at all. This PR adds support for the same.

For example, consider the following model (I'm skipping the obvious stuff like derive macros):

pub struct Pizza {
    #[sea_orm(primary_key, auto_increment = false)]
    pub id: i64,
    pub name: String,
    pub toppings: Vec<String>,
}

We also assume that the toppings field is not an empty array in the db for any rows.

If we query this model and expect a json result:

let result = pizza::Entity::find().into_json().all(db).await?;

The final JSON output is always:

{
    "id": 1,
    "name": "Pepperoni"
}

but the expected output is:

{
    "id": 1,
    "name": "Pepperoni",
    "toppings": ["Cheese", "Pepperoni"]
}

@anshap1719
Copy link
Contributor Author

anshap1719 commented Apr 30, 2023

Hello guys, is anything lacking in this PR? This is a fix that we need for our project and have to hack around with it right now.

If you feel like something is missing or incorrectly done, let me know.

@Sharpiro
Copy link

root json arrays would be very helpful to me as well, thanks @anshap1719

Copy link
Member

@billy1624 billy1624 left a comment

Choose a reason for hiding this comment

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

Hey @anshap1719, thanks for the great PR!! Sorry for the delay.

I just refactored it: 75ee167
And make sure it only implement Vec<T> if and only if postgres-array feature is enabled: 0163814
Please check :P

@billy1624 billy1624 requested a review from tyt2y3 May 3, 2023 08:47
@anshap1719
Copy link
Contributor Author

@billy1624 Thanks for the updates. Didn't realise that I could test it like you added. Thanks!

Copy link
Member

@billy1624 billy1624 left a comment

Choose a reason for hiding this comment

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

Thanks!! @anshap1719

@anshap1719
Copy link
Contributor Author

HI @tyt2y3, can you please review this PR? Thanks.

@billy1624
Copy link
Member

@tyt2y3 wanna take a look?

@anshap1719
Copy link
Contributor Author

@billy1624 @tyt2y3 Guys?

@billy1624
Copy link
Member

Hey @anshap1719, sorry, we will revisit this tonight :)

@anshap1719
Copy link
Contributor Author

@billy1624 Any updates?

@tyt2y3
Copy link
Member

tyt2y3 commented Jun 22, 2023

For some reason it missed my inbox. Sorry for that. However this seems to have touched a deep and quite difficult part of the library.
Need a fresh pair of eyes to review. Even though it looks promising at first glance, concerning the impact I can't make an approval right now.

It might help if you can write a dissection on the implementation.

@anshap1719
Copy link
Contributor Author

@tyt2y3 Totally understandable. Would it be okay if I just add comments to changes in the "Files changed" view?

@tyt2y3
Copy link
Member

tyt2y3 commented Jun 26, 2023

@tyt2y3 Totally understandable. Would it be okay if I just add comments to changes in the "Files changed" view?

Sure, that'd be appreciated.

for column in row.columns() {
let col = if !column.name().starts_with(pre) {
continue;
} else {
column.name().replacen(pre, "", 1)
};
let col_type = column.type_info();

macro_rules! match_postgres_type {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The macro is used for matching primitives against column types, but doesn't consider the fact that postgres columns can be of type array (of a primitive).

macro_rules! match_postgres_type {
( $type: ty ) => {
if <$type as Type<Postgres>>::type_info().eq(col_type) {
try_get_type!($type, col)
match col_type.kind() {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

We try to conditionally match if the column is of type array, or not.

match col_type.kind() {
#[cfg(feature = "postgres-array")]
sqlx::postgres::PgTypeKind::Array(_) => {
if <Vec<$type> as Type<Postgres>>::type_info().eq(col_type) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

If column is indeed of type array, and postgres-array feature is enabled, match the column type against Vec<primitive> instead.

try_get_type!(Vec<$type>, col);
}
}
_ => {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Otherwise, match column with given primitive type (original logic)

@@ -126,9 +139,15 @@ impl FromQueryResult for JsonValue {
match_postgres_type!(rust_decimal::Decimal);
#[cfg(feature = "with-json")]
try_get_type!(serde_json::Value, col);
#[cfg(all(feature = "with-json", feature = "postgres-array"))]
try_get_type!(Vec<serde_json::Value>, col);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Since postgres also supports arrays of json or jsonb, we need to add explicit matching for it in addition to primitive arrays.

try_get_type!(String, col);
#[cfg(feature = "postgres-array")]
try_get_type!(Vec<String>, col);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Add explicit check for String array, since it's not a primitive

#[cfg(feature = "with-uuid")]
try_get_type!(uuid::Uuid, col);
#[cfg(all(feature = "with-uuid", feature = "postgres-array"))]
try_get_type!(Vec<uuid::Uuid>, col);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Add explicit check for UUID array, since it's not a primitive

@anshap1719
Copy link
Contributor Author

@tyt2y3 Done. Hope that helps.

@anshap1719
Copy link
Contributor Author

@tyt2y3 Did you get a chance to review this again yet?

@anshap1719 anshap1719 closed this Jul 11, 2023
@anshap1719 anshap1719 reopened this Jul 11, 2023
@anshap1719
Copy link
Contributor Author

@tyt2y3 Sorry, I accidentally hit "Close with comment" for my last comment 😅

@anshap1719
Copy link
Contributor Author

@tyt2y3 Any updates on this one? Would really appreciate it if we can get this into the next release whenever that happens.

@anshap1719
Copy link
Contributor Author

@billy1624 @tyt2y3 Guys?

@tyt2y3
Copy link
Member

tyt2y3 commented Jul 31, 2023

Got you. I'll put this on my pipeline

@anshap1719
Copy link
Contributor Author

Thanks @tyt2y3

Copy link
Member

@tyt2y3 tyt2y3 left a comment

Choose a reason for hiding this comment

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

Nicely done!

@tyt2y3
Copy link
Member

tyt2y3 commented Aug 1, 2023

Thank you for your patience.

@tyt2y3 tyt2y3 merged commit 5fa2c1c into SeaQL:master Aug 1, 2023
@anshap1719
Copy link
Contributor Author

Awesome, thanks for your efforts as well @billy1624 that improved the PR.

@github-actions
Copy link

github-actions bot commented Aug 4, 2023

🎉 Released In 0.12.2 🎉

Thank you everyone for the contribution!
This feature is now available in the latest release. Now is a good time to upgrade!
Your participation is what makes us unique; your adoption is what drives us forward.
You can support SeaQL 🌊 by starring our repos, sharing our libraries and becoming a sponsor ⭐.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

4 participants