Rust -我可以让这个diesel函数更通用吗?

xe55xuns  于 2023-10-20  发布在  其他
关注(0)|答案(1)|浏览(130)

我有一个函数,它使用diesel根据给定的ID从DB中获取对象:

fn get_db_site(pool: web::Data<Pool>, site_id: u32) -> Result<Site, diesel::result::Error> {
    let conn = pool.get().unwrap();                                                           
    dsl::site.find(site_id).get_result::<Site>(&conn)                                         
}

这个函数对于我想运行的每个表都是完全相同的,所以我希望把它放在自己的utils文件中,这样我就不必每次都输入相同的内容。唯一的问题是,为了调用find,我需要执行crate::schema::site::dsl::site.find,我不确定如何使该调用泛型化,以接受任何类型。我知道有类型参数,但我不认为这在这里起作用

d8tt03nd

d8tt03nd1#

我通常建议不要让柴油的东西更通用,因为这会导致非常复杂的性状界限相当快。你通常不想在应用程序代码中这样做。(对于需要泛型的库来说,这是另一回事)。我通常将这种情况与普通SQL进行比较。例如,如果有人抱怨users::table.find(pk)感觉像是重复,问自己以下问题:你会觉得SELECT … FROM users在相应的查询SELECT … FROM users WHERE id = $中是重复的吗?(柴油机的说法基本相同)。
所以为了回答你的实际问题,泛型函数需要看起来像这样:(不确定我是否在没有测试的情况下得到了所有的界限)

fn get_db_thing<'a, T, PK, U>(conn: &mut SqliteConnection, pk: PK) -> QueryResult<U>
where
    T: HasTable<Table = T> + FindDsl<PK>,
    U: Queryable<SqlTypeOf<Find<T, PK>>, Sqlite>,
    <T as FindDsl<PK>>::Output: Expression + LoadQuery<'a, SqliteConnection, U>,
{
    T::table().find(pk).get_result(conn)
}

正如你所看到的,trait边界的列表已经比在相应的函数中内联加载要长得多。此外,在构造查询时添加的所有细节现在都需要作为泛型函数参数。至少T的类型不能被编译器推断出来,所以从代码大小的Angular 来看,这个解决方案并不比不使其泛型更“简单”。

相关问题