如何手动实现 sqlx::FromRow 特征?

Fel*_*ean 7 rust rust-sqlx

我尝试手动实现sqlx::FrowRow而不是使用derive,因为需要一些自定义初始化逻辑(例如将整数转换i16为枚举)。

默认的 impl 是这样生成的:

use sqlx::FromRow;

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

但尚不清楚我应该使用什么生命周期和类型。

kmd*_*eko 10

FromRow特征非常通用,因为它用于可能支持不同类型的不同后端数据库。您可以通过查看生成的内容来了解​​实现一个简单结构需要多少通用约束#[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 })
    }
}
Run Code Online (Sandbox Code Playgroud)

它必须约束列可以按名称索引,并约束列String有效i16并且可以从数据库中解码。

如果您自己进行操作,您可能最好选择您打算使用的数据库Row类型AnyRow( 、MssqlRowMySqlRowPgRowSqliteRow)并为此实现它。这里用于PgRowpostgres:

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 })
    }
}
Run Code Online (Sandbox Code Playgroud)

我确实想知道是否有不同的建议来进行自定义转换(通过 DTO 或其他机制)。