柴油和铁锈特征的麻烦和混乱



我正在尝试使用Diesel crate (version 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)
}
}

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,
);

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

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`

根据Diesel的文档(特别是本页),派生Queryable应该足以在entities上运行像load这样的函数。

从错误消息中,我收集到Diesel的FromSqlRow特性没有被实现,但是每当我试图将其包含在派生中(并删除冲突的Queryable派生)时,我只会遇到另一个非常相似的编译错误集。长时间浏览Diesel的可用文档并没有帮助我理解发生了什么,或者我该如何修复它,因为典型的文档似乎是"派生它",";谷歌搜索也同样没有结果。我应该在这里手工实现任何特性吗?如果是这样,那会是什么样子(我找不到任何例子)?还是我还漏掉了什么?更重要的是,有人能解释一下这个错误消息到底想要传达什么信息吗?

EDIT 1:提供相关的模式代码;不小心把它提供给了别的型号。

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

即使我改变模型。如果执行下面的命令来显式声明选择属性的顺序,仍然会出现类似的错误(参见编辑4):

use uuid::Uuid;
use diesel::prelude::*;
use crate::schema::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::dsl::entities
.select((entities::id, entities::uuid, entities::username))
.load::<Entity>(connection)
}
}

我已经在Cargo.toml中包含了适当的特性标志。

EDIT 3:已验证版本兼容;参见Diesel的变更日志

  • uuid & lt;不支持0.7.0;使用1.2.2
  • rust>= 1.56.0 required;使用1.63.0

EDIT 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

链接的文档已经给出了一个非常强烈的提示,在您的情况下是什么问题:

注意:当这个trait被派生时,它会假设你的结构体上的所有字段都匹配查询中的所有字段,包括顺序和计数。这意味着如果使用#[派生(可查询)],字段顺序很重要。字段名没有作用

在您的示例中,问题是id字段的类型与相应的数据库类型之间的不匹配。这就是rust端的u16和数据库端的Int4。根据Integer的diesel文档(Int4是该类型的类型别名),这两种类型不兼容。你需要在那个位置使用i32。它们不被认为是兼容的,因为并非Int4字段的所有可能的数据库值都适合u16

最新更新