为泛型类型编写Diesel CRUD操作 [英] Writing Diesel CRUD operations for generic types

查看:51
本文介绍了为泛型类型编写Diesel CRUD操作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编写一个Rust板条箱,当使用柴油

I am trying to write a Rust crate which removes some boilerplate code from the user when creating simple CRUD operations with Diesel

例如,如果您有这样的柴油机 Insertable :

For instance, if you have a Diesel Insertable like this one:

#[derive(Insertable)]
#[table_name = "users"]
pub struct UserCreate<'a> {
    pub email: String,
    pub hash: &'a [u8],
    pub first_name: Option<String>,
    pub family_name: Option<String>,
}

我希望板条箱用户只编写 create< UserCreate>(模型,池),以将struct字段插入数据库行中.

I want the crate user to just write create<UserCreate>(model, pool), to insert the struct fields into a database row.

为此,我编写了以下函数签名(例如,经过简化):

To do so, I've written the following function signature (simplified for example):

fn create<'a, C: 'a>(model: C, pool: DBPool)
where
    C: diesel::Identifiable,
    &'a C: diesel::Insertable<C::Table>,
{
    let conn = pool.get().unwrap();
    diesel::insert_into(C::table())
        .values(&model)
        .execute(&conn);
}

问题在于,编译器抱怨在 .execute(& conn) C & C 缺少某些特征范围而且我不太确定如何将它们放在 where 子句中,也许还有一种我不知道的更简单的方法.任何提示都非常欢迎!

The issue is that the compiler complains about some missing trait bounds for C and &C at .execute(&conn) and I am not quite sure how to place them in the where clause, there may be also a simpler way of doing this which I am not aware of. Any hint is very welcome!

编译器输出:

error[E0277]: the trait bound `<<C as diesel::associations::HasTable>::Table as diesel::QuerySource>::FromClause: diesel::query_builder::QueryFragment<_>` is not satisfied
  --> database/src/users/models.rs:46:10
   |
46 |         .execute(&conn);
   |          ^^^^^^^ the trait `diesel::query_builder::QueryFragment<_>` is not implemented for `<<C as diesel::associations::HasTable>::Table as diesel::QuerySource>::FromClause`
   |
   = help: the following implementations were found:
             <&'a T as diesel::query_builder::QueryFragment<DB>>
   = note: required because of the requirements on the impl of `diesel::query_builder::QueryFragment<_>` for `diesel::query_builder::InsertStatement<<C as diesel::associations::HasTable>::Table, <&C as diesel::Insertable<<C as diesel::associations::HasTable>::Table>>::Values>`
   = note: required because of the requirements on the impl of `diesel::query_dsl::load_dsl::ExecuteDsl<_, _>` for `diesel::query_builder::InsertStatement<<C as diesel::associations::HasTable>::Table, <&C as diesel::Insertable<<C as diesel::associations::HasTable>::Table>>::Values>`

error[E0277]: the trait bound `<&C as diesel::Insertable<<C as diesel::associations::HasTable>::Table>>::Values: diesel::query_builder::QueryFragment<_>` is not satisfied
  --> database/src/users/models.rs:46:10
   |
46 |         .execute(&conn);
   |          ^^^^^^^ the trait `diesel::query_builder::QueryFragment<_>` is not implemented for `<&C as diesel::Insertable<<C as diesel::associations::HasTable>::Table>>::Values`
   |
   = help: the following implementations were found:
             <&'a T as diesel::query_builder::QueryFragment<DB>>
   = note: required because of the requirements on the impl of `diesel::query_builder::QueryFragment<_>` for `diesel::query_builder::InsertStatement<<C as diesel::associations::HasTable>::Table, <&C as diesel::Insertable<<C as diesel::associations::HasTable>::Table>>::Values>`
   = note: required because of the requirements on the impl of `diesel::query_dsl::load_dsl::ExecuteDsl<_, _>` for `diesel::query_builder::InsertStatement<<C as diesel::associations::HasTable>::Table, <&C as diesel::Insertable<<C as diesel::associations::HasTable>::Table>>::Values>`

error[E0277]: the trait bound `<&C as diesel::Insertable<<C as diesel::associations::HasTable>::Table>>::Values: diesel::insertable::CanInsertInSingleQuery<_>` is not satisfied
  --> database/src/users/models.rs:46:10
   |
46 |         .execute(&conn);
   |          ^^^^^^^ the trait `diesel::insertable::CanInsertInSingleQuery<_>` is not implemented for `<&C as diesel::Insertable<<C as diesel::associations::HasTable>::Table>>::Values`
   |
   = help: the following implementations were found:
             <&'a T as diesel::insertable::CanInsertInSingleQuery<DB>>
   = note: required because of the requirements on the impl of `diesel::query_builder::QueryFragment<_>` for `diesel::query_builder::InsertStatement<<C as diesel::associations::HasTable>::Table, <&C as diesel::Insertable<<C as diesel::associations::HasTable>::Table>>::Values>`
   = note: required because of the requirements on the impl of `diesel::query_dsl::load_dsl::ExecuteDsl<_, _>` for `diesel::query_builder::InsertStatement<<C as diesel::associations::HasTable>::Table, <&C as diesel::Insertable<<C as diesel::associations::HasTable>::Table>>::Values>`

error: aborting due to 3 previous errors

非常感谢!

推荐答案

我终于通过定义以下特征范围来解决了!

I've finally solved by defining the following trait bounds!

fn create<C, T>(model: C, pool: DBPool)
where
    T: diesel::associations::HasTable,
    <T::Table as diesel::QuerySource>::FromClause:
        diesel::query_builder::QueryFragment<diesel::pg::Pg>,
    C: diesel::Insertable<T::Table>,
    C::Values: diesel::insertable::CanInsertInSingleQuery<diesel::pg::Pg>
        + diesel::query_builder::QueryFragment<diesel::pg::Pg>,
{
    let conn = pool.get().unwrap();

    diesel::insert_into(T::table())
        .values(model)
        .execute(&conn);
}

create::<UserCreate, users::table>(user, pool);

基本上,您需要为 Table Insertable 设置一对额外的边界.如果可以直接从 Insertable 获取表,以避免在函数定义中使用其他类型,那将是很好的,但是我可以使用它:)

Basically, you need a pair of extra bounds for the Table and the Insertable. It would be nice if it was possible to get the table directly from the Insertable, to avoid using another type in the function definition, but I can work with that :)

这篇关于为泛型类型编写Diesel CRUD操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆