简体   繁体   中英

How do I implement sqlx::FromRow trait maually?

I am trying to manually implement sqlx::FrowRow instead of using derive , since some custom initialization logic is needed (ex. convert integer i16 to enum).

Default impl is generated like this:

use sqlx::FromRow;

impl FromRow for User {
    fn from_row(row: &'r R) -> Result<Self, sqlx::Error> {
        todo!()
    }
}

But it's unclear, what lifetime and type should I use.

The FromRow trait is extremely generic since it is used for different backend databases that may support different types. You can see how many generic constraints are needed to implement a simple struct by looking at what #[derive(FromRow)] generates (via cargo expand ):

use sqlx::FromRow;

#[derive(FromRow)]
struct User {
    name: String,
    status: i16,
}

// generates

impl<'a, R: ::sqlx::Row> ::sqlx::FromRow<'a, R> for User
where
    &'a ::std::primitive::str: ::sqlx::ColumnIndex<R>,
    String: ::sqlx::decode::Decode<'a, R::Database>,
    String: ::sqlx::types::Type<R::Database>,
    i16: ::sqlx::decode::Decode<'a, R::Database>,
    i16: ::sqlx::types::Type<R::Database>,
{
    fn from_row(row: &'a R) -> ::sqlx::Result<Self> {
        let name: String = row.try_get("name")?;
        let status: i16 = row.try_get("status")?;
        ::std::result::Result::Ok(User { name, status })
    }
}

It has to constrain that the columns can be indexed by name as well as constrain that String and i16 are valid and can be decoded from the database.

Doing it yourself, you're probably better off picking which database Row type you intend to use ( AnyRow , MssqlRow , MySqlRow , PgRow , SqliteRow ) and implement it for that. Here using PgRow for postgres:

use sqlx::{Row, FromRow, Error};
use sqlx::postgres::PgRow;

struct User {
    name: String,
    status: i16,
}

impl<'r> FromRow<'r, PgRow> for User {
    fn from_row(row: &'r PgRow) -> Result<Self, Error> {
        let name = row.try_get("name")?;
        let status = row.try_get("status")?;

        Ok(User{ name, status })
    }
}

I do wonder though if there's a different recommendation for doing custom transformations (via a DTO or some other mechanism).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM