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

* Add Support For PostgreSQL Arrays In FromQueryResult Implementation Of JsonValue

* Add support for root arrays in JSON in SeaORM #1517

* Refactoring

* Only when `postgres-array` is enabled

* Add test cases

---------

Co-authored-by: Billy Chan <ccw.billy.123@gmail.com>
This commit is contained in:
Anshul Sanghi 2023-08-02 00:12:16 +05:30 committed by GitHub
parent 63d8cdf7e5
commit 5fa2c1c28c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 70 additions and 2 deletions

View File

@ -77,6 +77,7 @@ impl FromQueryResult for JsonValue {
crate::QueryResultRow::SqlxPostgres(row) => { crate::QueryResultRow::SqlxPostgres(row) => {
use serde_json::json; use serde_json::json;
use sqlx::{postgres::types::Oid, Column, Postgres, Row, Type}; use sqlx::{postgres::types::Oid, Column, Postgres, Row, Type};
for column in row.columns() { for column in row.columns() {
let col = if !column.name().starts_with(pre) { let col = if !column.name().starts_with(pre) {
continue; continue;
@ -84,13 +85,25 @@ impl FromQueryResult for JsonValue {
column.name().replacen(pre, "", 1) column.name().replacen(pre, "", 1)
}; };
let col_type = column.type_info(); let col_type = column.type_info();
macro_rules! match_postgres_type { macro_rules! match_postgres_type {
( $type: ty ) => { ( $type: ty ) => {
match col_type.kind() {
#[cfg(feature = "postgres-array")]
sqlx::postgres::PgTypeKind::Array(_) => {
if <Vec<$type> as Type<Postgres>>::type_info().eq(col_type) {
try_get_type!(Vec<$type>, col);
}
}
_ => {
if <$type as Type<Postgres>>::type_info().eq(col_type) { if <$type as Type<Postgres>>::type_info().eq(col_type) {
try_get_type!($type, col) try_get_type!($type, col);
}
}
} }
}; };
} }
match_postgres_type!(bool); match_postgres_type!(bool);
match_postgres_type!(i8); match_postgres_type!(i8);
match_postgres_type!(i16); match_postgres_type!(i16);
@ -126,9 +139,15 @@ impl FromQueryResult for JsonValue {
match_postgres_type!(rust_decimal::Decimal); match_postgres_type!(rust_decimal::Decimal);
#[cfg(feature = "with-json")] #[cfg(feature = "with-json")]
try_get_type!(serde_json::Value, col); try_get_type!(serde_json::Value, col);
#[cfg(all(feature = "with-json", feature = "postgres-array"))]
try_get_type!(Vec<serde_json::Value>, col);
try_get_type!(String, col); try_get_type!(String, col);
#[cfg(feature = "postgres-array")]
try_get_type!(Vec<String>, col);
#[cfg(feature = "with-uuid")] #[cfg(feature = "with-uuid")]
try_get_type!(uuid::Uuid, col); try_get_type!(uuid::Uuid, col);
#[cfg(all(feature = "with-uuid", feature = "postgres-array"))]
try_get_type!(Vec<uuid::Uuid>, col);
try_get_type!(Vec<u8>, col); try_get_type!(Vec<u8>, col);
} }
Ok(JsonValue::Object(map)) Ok(JsonValue::Object(map))

View File

@ -5,6 +5,7 @@ use pretty_assertions::assert_eq;
use sea_orm::{ use sea_orm::{
entity::prelude::*, entity::*, DatabaseConnection, DerivePartialModel, FromQueryResult, entity::prelude::*, entity::*, DatabaseConnection, DerivePartialModel, FromQueryResult,
}; };
use serde_json::json;
#[sea_orm_macros::test] #[sea_orm_macros::test]
#[cfg(all(feature = "sqlx-postgres", feature = "postgres-array"))] #[cfg(all(feature = "sqlx-postgres", feature = "postgres-array"))]
@ -114,6 +115,54 @@ pub async fn insert_collection(db: &DatabaseConnection) -> Result<(), DbErr> {
} }
); );
assert_eq!(
Entity::find_by_id(1).into_json().one(db).await?,
Some(json!({
"id": 1,
"name": "Collection 1",
"integers": [1, 2, 3],
"integers_opt": [1, 2, 3],
"teas": ["BreakfastTea"],
"teas_opt": ["BreakfastTea"],
"colors": [0],
"colors_opt": [0],
"uuid": [uuid],
"uuid_hyphenated": [uuid.hyphenated()],
}))
);
assert_eq!(
Entity::find_by_id(2).into_json().one(db).await?,
Some(json!({
"id": 2,
"name": "Collection 2",
"integers": [10, 9],
"integers_opt": null,
"teas": ["BreakfastTea"],
"teas_opt": null,
"colors": [0],
"colors_opt": null,
"uuid": [uuid],
"uuid_hyphenated": [uuid.hyphenated()],
}))
);
assert_eq!(
Entity::find_by_id(3).into_json().one(db).await?,
Some(json!({
"id": 3,
"name": "Collection 3",
"integers": [],
"integers_opt": [],
"teas": [],
"teas_opt": [],
"colors": [],
"colors_opt": [],
"uuid": [uuid],
"uuid_hyphenated": [uuid.hyphenated()],
}))
);
Ok(()) Ok(())
} }