-
-
Notifications
You must be signed in to change notification settings - Fork 520
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
Conversation
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. |
root json arrays would be very helpful to me as well, thanks @anshap1719 |
There was a problem hiding this 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 Thanks for the updates. Didn't realise that I could test it like you added. Thanks! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!! @anshap1719
HI @tyt2y3, can you please review this PR? Thanks. |
@tyt2y3 wanna take a look? |
@billy1624 @tyt2y3 Guys? |
Hey @anshap1719, sorry, we will revisit this tonight :) |
@billy1624 Any updates? |
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. It might help if you can write a dissection on the implementation. |
@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 { |
There was a problem hiding this comment.
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() { |
There was a problem hiding this comment.
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) { |
There was a problem hiding this comment.
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); | ||
} | ||
} | ||
_ => { |
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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
@tyt2y3 Done. Hope that helps. |
@tyt2y3 Did you get a chance to review this again yet? |
@tyt2y3 Sorry, I accidentally hit "Close with comment" for my last comment 😅 |
@tyt2y3 Any updates on this one? Would really appreciate it if we can get this into the next release whenever that happens. |
@billy1624 @tyt2y3 Guys? |
Got you. I'll put this on my pipeline |
Thanks @tyt2y3 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nicely done!
Thank you for your patience. |
Awesome, thanks for your efforts as well @billy1624 that improved the PR. |
🎉 Released In 0.12.2 🎉Thank you everyone for the contribution! |
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
json
while querying (usinginto_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):
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:
The final JSON output is always:
but the expected output is: