Trouble & Confusion with Diesel and Rust Traits
Asked Answered
P

1

6

I'm trying to use the Diesel crate (version 2.0.2; rustc 1.63.0) for an application and have some code that goes like this:

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

However, this will not compile. The following errors are thrown when I try:

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`

According to Diesel's documentation (specifically this page), deriving Queryable should be enough to run functions like load on entities.

From the error message, I gather that Diesel's FromSqlRow trait is not being implemented, but whenever I try to include that in the derive (and remove the conflicting Queryable derivation), I am only met by another, very similar, set of errors on compilation. A long walk through Diesel's available documentation hasn't helped me understand what is going on or how I might fix it as the typical documentation seems to be "derive it," and a google search is similarly unfruitful. Am I supposed to be implementing any traits by hand here? If so, what might that look like (I cannot find any examples)? Or is there something else I'm missing? More importantly, can anyone explain exactly what this error message is trying to communicate?

EDIT 1: Provide the relevant schema code; had provided it for a different model accidentally.

EDIT 2: Below update with clarified order of properties

Even when I change models.rs to the below to explicitly declare the order in which properties are selected, a similar error (see edit 4) still appears:

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)
    }
}

I have included the proper feature flags in Cargo.toml.

EDIT 3: Verified that versions are compatible; see changelog for Diesel

  • uuid < 0.7.0 not supported; using 1.2.2
  • rustc >= 1.56.0 required; using 1.63.0

EDIT 4: new error that is being thrown on compilation

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
Perfidious answered 8/12, 2022 at 11:36 Comment(0)
K
5

The linked documentation already gives a pretty strong hint what's wrong in your case:

Note: When this trait is derived, it will assume that all fields on your struct matches all fields in the query, including the order and count. This means that field order is significant if you are using #[derive(Queryable)]. Field name has no effect.

In your case the problem is a mismatch between the type of the id field and the corresponding database type. That's u16 on rust side vs Int4 on database side. According to the diesel documentation of Integer (Int4 is a type alias for this type), these two types are not compatible. You need to use a i32 in that position. They are not considered compatible as not all possible database values of a Int4 field fit into a u16

Kozloski answered 8/12, 2022 at 12:30 Comment(2)
Thank you so much for your response @weiznich. Good catch re code not matching; I must've been too tired last night when posting this. I've updated to get the relevant table code in there as well as to show, explicitly, that the order in which the properties are selected is exactly the same as in the struct, however the error still appears. I've also verified that the correct feature flags are present for diesel. I can't find anywhere stating a restriction on the version of the uuid crate to use, but I'm using the latest (1.2.2).Perfidious
@Perfidious I've updated my answer to point out the actual problemKozloski

© 2022 - 2025 — McMap. All rights reserved.