通用池类型sqlx

问题描述 投票:0回答:1

我正在尝试设置 sqlx 来生成具有通用数据库类型的特征的

Pool
,但是遇到了问题。我确实想尽可能避免使用
AnyPool
,因为以下回复中提出了多个要点:https://stackoverflow.com/a/70573732/14896203

我当前的特征实现:

use sqlx::postgres::PgRow;
use sqlx::{Database, Error, Pool, Postgres};

pub trait DatabaseTraits {
    fn get_address(&self) -> String;

    async fn connect<DB: Database>(&self) -> Result<Pool<DB>, Error>;

    async fn read(&self, schema: String, table: String) -> Result<PgRow, Error> {
        let conn = self.connect().await?;
        let query_string = format!("SELECT * FROM {}.{}", schema, table);
        let rows = sqlx::query(&query_string).fetch_one(&conn).await?;
        Ok(rows)
    }
}

我尝试将 DB 用作数据库的“通用类型”,因为我看到它实现了 Postgres、SQLite 等,但是,我觉得我错过了重要的逻辑点,因为我收到的错误是预期的:

sqlx::Pool<DB> 
发现
sqlx::Pool<Postgres>
:

impl DatabaseTraits for PostgresConnection {
    fn get_address(&self) -> String {
        self.address.to_string()
    }

    async fn connect<DB: Database>(&self) -> Result<Pool<DB>, Error>
    {
        let conn: Pool<DB> = PgPoolOptions::new()
            .max_connections(5)
            .connect(&self.get_address())
            .await?.into();

        Ok(conn)
    }
}

完整代码:https://hastebin.com/share/yiwemedome.rust

rust rust-sqlx
1个回答
4
投票

问题在于您如何定义

connect
函数:

async fn connect<DB: Database>(&self) -> Result<Pool<DB>, Error>

这允许函数的 caller 决定

DB
应该是什么具体类型 - 但在你的情况下,是 implementation 做出这个选择。
connect
impl DatabaseTraits for PostgresConnection
实现将 always 返回
sqlx::Pool<Postgres>
,并且调用者无法更改它。

当您的特征需要以这种方式实现定义的占位符类型时,正确使用的工具是关联类型

pub trait DatabaseTraits {
    type DB: Database;

    async fn connect(&self) -> Result<Pool<Self::DB>, Error>;

    // ...
}

然后您可以在实现中设置类型,如下所示:

impl DatabaseTraits for PostgresConnection {
    type DB = Postgres;

    // ...
}
© www.soinside.com 2019 - 2024. All rights reserved.