I'm trying to use Rust and sqlx (v0.6.2) to retrieve from DB structs with nested structs.
I tried using the below code but I found out that there is a limit of 9 fields in tuple that I can use with FromRow
.
Note:
As you can see I'm using a Box<T>
for struct fields.
use sqlx::{postgres::PgRow, FromRow, QueryBuilder, Row};
#[derive(Debug, Default, sqlx::FromRow)]
pub struct PgCoach { //PgCoach has ONLY scalar values
pub team_id: String,
pub id: String,
pub created_at: Time::OffsetDateTime,
pub updated_at: Option<Time::OffsetDateTime>,
pub firstname: Option<String>,
pub lastname: Option<String>,
pub motto: Option<String>,
pub first_case: Option<String>,
pub second_case: Option<String>,
pub third_case: Option<String>,
pub birth_date: Option<Time::OffsetDateTime>,
pub sex: Option<i64>,
pub phone: Option<String>,
pub email_address: Option<String>,
pub address: Option<String>,
pub picture: Option<String>,
pub notes: Option<String>,
}
#[derive(Debug, Default)]
pub struct PgPlayer {
pub team_id: String,
pub id: String,
pub created_at: Time::OffsetDateTime,
pub updated_at: Option<Time::OffsetDateTime>,
pub score: i64,
pub birth_date: Time::OffsetDateTime,
pub code: String,
pub payed: bool,
pub coach_id: String,
pub coach: Option<Box<PgCoach>>,
pub skills: Option<Vec<PgSkill>>,
}
impl FromRow<'_, PgRow> for PgPlayer {
fn from_row(row: &PgRow) -> sqlx::Result<Self> {
let mut res = Self {
team_id: row.get("team_id"),
id: row.get("id"),
created_at: row.get("created_at"),
updated_at: row.get("updated_at"),
score: row.get("score"),
birth_date: row.get("birth_date"),
code: row.get("code"),
payed: row.get("payed"),
coach_id: row.get("coach_id"),
..Default::default()
};
if row.try_get_raw("coach").is_ok() {
res.coach = Some(Box::new(PgCoach {
id: row.try_get::<PgCoach, &str>("coach")?.1,
firstname: row.try_get::<PgCoach, &str>("coach")?.4,
lastname: row.try_get::<PgCoach, &str>("coach")?.5,
..Default::default()
}));
}
Ok(res)
}
}
The error is:
error[E0277]: the trait bound `pg::PgCoach: sqlx::Decode<'_, sqlx::Postgres>` is not satisfied
--> src\crates\project\pg.rs:656:21
|
656 | id: row.try_get::<PgCoach, &str>("coach")?.id,
| ^^^ ------- required by a bound introduced by this call
| |
| the trait `sqlx::Decode<'_, sqlx::Postgres>` is not implemented for `pg::PgCoach`
|
= help: the following other types implement trait `sqlx::Decode<'r, DB>`:
<&'r [u8] as sqlx::Decode<'r, sqlx::Postgres>>
<&'r [u8] as sqlx::Decode<'r, sqlx_core::any::database::Any>>
<&'r sqlx::types::JsonRawValue as sqlx::Decode<'r, DB>>
<&'r str as sqlx::Decode<'r, sqlx::Postgres>>
<&'r str as sqlx::Decode<'r, sqlx_core::any::database::Any>>
<() as sqlx::Decode<'r, sqlx::Postgres>>
<(T1, T2) as sqlx::Decode<'r, sqlx::Postgres>>
<(T1, T2, T3) as sqlx::Decode<'r, sqlx::Postgres>>
and 43 others
note: required by a bound in `sqlx::Row::try_get`
--> C:\Users\Fred\.cargo\registry\src\github.com-1ecc6299db9ec823\sqlx-core-0.6.2\src\row.rs:114:12
|
114 | T: Decode<'r, Self::Database> + Type<Self::Database>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `sqlx::Row::try_get`
I can use whatever SQL query the method needs.
I can return tuple from DB or single columns, I don't care. I only need a way to query with sqlx structs with nested Box<Struct>
and I cannot understand how.
How can I retrieve these structs?