如何在柴油中使用类似 C 的枚举

How to use a C-like enum with diesel

我有一个 users table,我正在尝试使用 Diesel 添加一个 role 字段:

#[derive(Debug, Clone, Queryable, Insertable)]
pub struct User {
    // other fields
    pub role: Role,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, AsExpression)]
#[sql_type = "diesel::sql_types::VarChar"]
pub enum Role {
    User,
    Admin,
}

/// manual impls for FromSql<VarChar, Pg>, ToSql<VarChar, Pg> and FromSqlRow<VarChar, Pg>

出于兼容性原因,我希望这些在数据库中表示为 varchars("user""admin"),但我想在 Rust 端使用枚举作为额外类型安全。

但是,根据我目前的设置,我得到:

error[E0277]: the trait bound `Role: Queryable<Text, Pg>` is not satisfied
  --> src/state/database/users.rs:47:32
   |
47 |         self.exec(|conn| users.load(conn)).await
   |                                ^^^^ the trait `Queryable<Text, Pg>` is not implemented for `Role`
   |
   = note: required because of the requirements on the impl of `Queryable<(diesel::sql_types::Uuid, Text, Text, diesel::sql_types::Timestamp, Text), Pg>` for `(model::types::UserId, model::types::Email, model::types::PasswordHash, NaiveDateTime, Role)`
   = note: 1 redundant requirement hidden
   = note: required because of the requirements on the impl of `Queryable<(diesel::sql_types::Uuid, Text, Text, diesel::sql_types::Timestamp, Text), Pg>` for `user::User`
   = note: required because of the requirements on the impl of `LoadQuery<PooledConnection<diesel::r2d2::ConnectionManager<diesel::PgConnection>>, user::User>` for `schema::users::table`

据我了解,在柴油中,VarCharText 是同一类型(即别名)。如果我将 impls 中的所有 VarChar 更改为 Text,错误仍然存​​在。

我确信这不是另一个 fields/field 命令,因为如果我用普通的 String 替换 Role,它就可以工作。

我觉得我一定错过了什么,这似乎是相当普遍的行为。也许我还需要实现另一个特征?

FWIW,我的用户架构 table 看起来像:

table! {
    users (id) {
        id -> Uuid,
        email -> Varchar,
        password_hash -> Varchar,
        created_at -> Timestamp,
        role -> Varchar,
    }
}

使用 postgres 14,rust 1.57,diesel 1.4.8

您还需要导出 FromSqlRow。它将为您的类型生成必要的 FromSqlRowQueryable impl。