简体   繁体   English

如何实现 sqlx::FromRow 特征?

[英]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).我正在尝试手动实现sqlx::FrowRow derive不是使用 derived ,因为需要一些自定义初始化逻辑(例如将 integer i16转换为枚举)。

Default impl is generated like this:默认 impl 生成如下:

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. FromRow trait 非常通用,因为它用于可能支持不同类型的不同后端数据库。 You can see how many generic constraints are needed to implement a simple struct by looking at what #[derive(FromRow)] generates (via cargo expand ):通过查看#[derive(FromRow)]生成的内容(通过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.它必须限制列可以按名称索引,并限制Stringi16有效并且可以从数据库中解码。

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.自己做,你最好选择你打算使用的数据库Row类型AnyRowMssqlRowMySqlRowPgRowSqliteRow )并为此实现它。 Here using PgRow for postgres:这里将PgRow用于 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).我确实想知道是否有不同的建议来进行自定义转换(通过 DTO 或其他机制)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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