柴油和生锈特性的问题和困惑

Thi*_*olf 5 traits rust rust-diesel

我正在尝试将 Diesel crate (版本 2.0.2;rustc 1.63.0)用于应用程序,并有一些如下所示的代码:

src/models.rs

use uuid::Uuid;
use diesel::prelude::*;

use crate::schema::entities::dsl::entities;

type DB = diesel::pg::Pg;

#[derive(Queryable, PartialEq, Debug)]
#[diesel(table_name = entities)]
pub struct Entity {
    pub id: u16,
    pub uuid: Uuid,
    pub username: Option<String>
}

impl Entity {
    pub fn get_all(connection: &mut PgConnection) -> QueryResult<Vec<Entity>> {
        entities.load::<Entity>(connection)
    }
}
Run Code Online (Sandbox Code Playgroud)

src/schema.rs

// @generated automatically by Diesel CLI.

diesel::table! {
    entities (id) {
        id -> Int4,
        uuid -> Uuid,
        username -> Nullable<Text>,
    }
}

diesel::allow_tables_to_appear_in_same_query!(
    entities,
);
Run Code Online (Sandbox Code Playgroud)

但是,这不会编译。当我尝试时会抛出以下错误:

error[E0277]: the trait bound `(Integer, diesel::sql_types::Uuid, diesel::sql_types::Nullable<diesel::sql_types::Text>): load_dsl::private::CompatibleType<Entity, _>` is not satisfied
    --> src/models.rs:20:18
     |
20   |         entities.load::<Entity>(connection)
     |                  ^^^^ the trait `load_dsl::private::CompatibleType<Entity, _>` is not implemented for `(Integer, diesel::sql_types::Uuid, diesel::sql_types::Nullable<diesel::sql_types::Text>)`
     |
     = help: the following other types implement trait `load_dsl::private::CompatibleType<U, DB>`:
               (ST0, ST1)
               (ST0, ST1, ST2)
               (ST0, ST1, ST2, ST3)
               (ST0, ST1, ST2, ST3, ST4)
               (ST0, ST1, ST2, ST3, ST4, ST5)
               (ST0, ST1, ST2, ST3, ST4, ST5, ST6)
               (ST0, ST1, ST2, ST3, ST4, ST5, ST6, ST7)
               (ST0, ST1, ST2, ST3, ST4, ST5, ST6, ST7, ST8)
             and 24 others
     = note: required because of the requirements on the impl of `LoadQuery<'_, _, Entity>` for `entities::table`
note: required by a bound in `diesel::RunQueryDsl::load`
    --> /home/username/.cargo/registry/src/github.com-1ecc6299db9ec823/diesel-2.0.2/src/query_dsl/mod.rs:1499:15
     |
1499 |         Self: LoadQuery<'query, Conn, U>,
     |               ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `diesel::RunQueryDsl::load`

error[E0277]: the trait bound `Entity: FromSqlRow<_, _>` is not satisfied
    --> src/models.rs:20:18
     |
20   |         entities.load::<Entity>(connection)
     |                  ^^^^ the trait `FromSqlRow<_, _>` is not implemented for `Entity`
     |
     = help: the following other types implement trait `FromSqlRow<ST, DB>`:
               <(T1, T0) as FromSqlRow<(ST1, Untyped), __DB>>
               <(T1, T2, T0) as FromSqlRow<(ST1, ST2, Untyped), __DB>>
               <(T1, T2, T3, T0) as FromSqlRow<(ST1, ST2, ST3, Untyped), __DB>>
               <(T1, T2, T3, T4, T0) as FromSqlRow<(ST1, ST2, ST3, ST4, Untyped), __DB>>
               <(T1, T2, T3, T4, T5, T0) as FromSqlRow<(ST1, ST2, ST3, ST4, ST5, Untyped), __DB>>
               <(T1, T2, T3, T4, T5, T6, T0) as FromSqlRow<(ST1, ST2, ST3, ST4, ST5, ST6, Untyped), __DB>>
               <(T1, T2, T3, T4, T5, T6, T7, T0) as FromSqlRow<(ST1, ST2, ST3, ST4, ST5, ST6, ST7, Untyped), __DB>>
               <(T1, T2, T3, T4, T5, T6, T7, T8, T0) as FromSqlRow<(ST1, ST2, ST3, ST4, ST5, ST6, ST7, ST8, Untyped), __DB>>
             and 23 others
     = note: required because of the requirements on the impl of `LoadQuery<'_, _, Entity>` for `entities::table`
note: required by a bound in `diesel::RunQueryDsl::load`
    --> /home/username/.cargo/registry/src/github.com-1ecc6299db9ec823/diesel-2.0.2/src/query_dsl/mod.rs:1499:15
     |
1499 |         Self: LoadQuery<'query, Conn, U>,
     |               ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `diesel::RunQueryDsl::load`
Run Code Online (Sandbox Code Playgroud)

根据 Diesel 的文档(特别是本页),派生 Queryable 应该足以运行loadon等函数entities

从错误消息中,我了解到 Diesel 的FromSqlRow特征没有被实现,但是每当我尝试将其包含在派生中(并删除冲突的Queryable派生)时,我只会在编译时遇到另一组非常相似的错误。长时间浏览 Diesel 的可用文档并不能帮助我理解正在发生的事情或如何修复它,因为典型的文档似乎是“派生它”,并且谷歌搜索同样没有结果。我应该在这里手动实现任何特征吗?如果是这样,那会是什么样子(我找不到任何例子)?还是我还缺少其他东西?更重要的是,任何人都可以准确解释此错误消息试图传达什么信息吗?

编辑1:提供相关的模式代码;无意中为不同的型号提供了它。

编辑 2:下面更新了澄清的属性顺序

即使我将 models.rs 更改为以下内容以显式声明选择属性的顺序,仍然会出现类似的错误(请参阅编辑 4):

error[E0277]: the trait bound `(Integer, diesel::sql_types::Uuid, diesel::sql_types::Nullable<diesel::sql_types::Text>): load_dsl::private::CompatibleType<Entity, _>` is not satisfied
    --> src/models.rs:20:18
     |
20   |         entities.load::<Entity>(connection)
     |                  ^^^^ the trait `load_dsl::private::CompatibleType<Entity, _>` is not implemented for `(Integer, diesel::sql_types::Uuid, diesel::sql_types::Nullable<diesel::sql_types::Text>)`
     |
     = help: the following other types implement trait `load_dsl::private::CompatibleType<U, DB>`:
               (ST0, ST1)
               (ST0, ST1, ST2)
               (ST0, ST1, ST2, ST3)
               (ST0, ST1, ST2, ST3, ST4)
               (ST0, ST1, ST2, ST3, ST4, ST5)
               (ST0, ST1, ST2, ST3, ST4, ST5, ST6)
               (ST0, ST1, ST2, ST3, ST4, ST5, ST6, ST7)
               (ST0, ST1, ST2, ST3, ST4, ST5, ST6, ST7, ST8)
             and 24 others
     = note: required because of the requirements on the impl of `LoadQuery<'_, _, Entity>` for `entities::table`
note: required by a bound in `diesel::RunQueryDsl::load`
    --> /home/username/.cargo/registry/src/github.com-1ecc6299db9ec823/diesel-2.0.2/src/query_dsl/mod.rs:1499:15
     |
1499 |         Self: LoadQuery<'query, Conn, U>,
     |               ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `diesel::RunQueryDsl::load`

error[E0277]: the trait bound `Entity: FromSqlRow<_, _>` is not satisfied
    --> src/models.rs:20:18
     |
20   |         entities.load::<Entity>(connection)
     |                  ^^^^ the trait `FromSqlRow<_, _>` is not implemented for `Entity`
     |
     = help: the following other types implement trait `FromSqlRow<ST, DB>`:
               <(T1, T0) as FromSqlRow<(ST1, Untyped), __DB>>
               <(T1, T2, T0) as FromSqlRow<(ST1, ST2, Untyped), __DB>>
               <(T1, T2, T3, T0) as FromSqlRow<(ST1, ST2, ST3, Untyped), __DB>>
               <(T1, T2, T3, T4, T0) as FromSqlRow<(ST1, ST2, ST3, ST4, Untyped), __DB>>
               <(T1, T2, T3, T4, T5, T0) as FromSqlRow<(ST1, ST2, ST3, ST4, ST5, Untyped), __DB>>
               <(T1, T2, T3, T4, T5, T6, T0) as FromSqlRow<(ST1, ST2, ST3, ST4, ST5, ST6, Untyped), __DB>>
               <(T1, T2, T3, T4, T5, T6, T7, T0) as FromSqlRow<(ST1, ST2, ST3, ST4, ST5, ST6, ST7, Untyped), __DB>>
               <(T1, T2, T3, T4, T5, T6, T7, T8, T0) as FromSqlRow<(ST1, ST2, ST3, ST4, ST5, ST6, ST7, ST8, Untyped), __DB>>
             and 23 others
     = note: required because of the requirements on the impl of `LoadQuery<'_, _, Entity>` for `entities::table`
note: required by a bound in `diesel::RunQueryDsl::load`
    --> /home/username/.cargo/registry/src/github.com-1ecc6299db9ec823/diesel-2.0.2/src/query_dsl/mod.rs:1499:15
     |
1499 |         Self: LoadQuery<'query, Conn, U>,
     |               ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `diesel::RunQueryDsl::load`
Run Code Online (Sandbox Code Playgroud)

我已在 Cargo.toml 中包含了适当的功能标志。

编辑3:验证版本是否兼容;请参阅柴油机的变更日志

  • 不支持 uuid < 0.7.0;使用1.2.2
  • 需要 rustc >= 1.56.0;使用1.63.0

编辑4:编译时抛出的新错误

error[E0277]: the trait bound `(u16, uuid::Uuid, Option<String>): FromStaticSqlRow<(Integer, diesel::sql_types::Uuid, diesel::sql_types::Nullable<diesel::sql_types::Text>), Pg>` is not satisfied
    --> src/models.rs:22:14
     |
22   |             .load(connection)
     |              ^^^^ the trait `FromStaticSqlRow<(Integer, diesel::sql_types::Uuid, diesel::sql_types::Nullable<diesel::sql_types::Text>), Pg>` is not implemented for `(u16, uuid::Uuid, Option<String>)`
     |
     = help: the following other types implement trait `FromStaticSqlRow<ST, DB>`:
               <(T0,) as FromStaticSqlRow<(ST0,), __DB>>
               <(T1, T0) as FromStaticSqlRow<(ST1, ST0), __DB>>
               <(T1, T2, T0) as FromStaticSqlRow<(ST1, ST2, ST0), __DB>>
               <(T1, T2, T3, T0) as FromStaticSqlRow<(ST1, ST2, ST3, ST0), __DB>>
               <(T1, T2, T3, T4, T0) as FromStaticSqlRow<(ST1, ST2, ST3, ST4, ST0), __DB>>
               <(T1, T2, T3, T4, T5, T0) as FromStaticSqlRow<(ST1, ST2, ST3, ST4, ST5, ST0), __DB>>
               <(T1, T2, T3, T4, T5, T6, T0) as FromStaticSqlRow<(ST1, ST2, ST3, ST4, ST5, ST6, ST0), __DB>>
               <(T1, T2, T3, T4, T5, T6, T7, T0) as FromStaticSqlRow<(ST1, ST2, ST3, ST4, ST5, ST6, ST7, ST0), __DB>>
             and 24 others
Run Code Online (Sandbox Code Playgroud)

wei*_*ich 5

链接的文档已经给出了非常强烈的提示,说明您的情况出了什么问题:

注意:当派生此特征时,它将假设结构上的所有字段都与查询中的所有字段匹配,包括顺序和计数。这意味着如果您使用#[derive(Queryable)],则字段顺序很重要。字段名称没有任何作用。

在您的情况下,问题是 id 字段的类型与相应的数据库类型不匹配。这是u16Rust 方面与Int4数据库方面的区别。根据IntegerInt4是该类型的类型别名)的柴油文档,这两种类型不兼容。您需要i32在该位置使用 a 。它们不被认为是兼容的,因为并非字段的所有可能的数据库值都Int4适合u16