postgresql 如何在Rust SQLx中创建自定义Postgres枚举类型?

vc6uscn9  于 2023-06-22  发布在  PostgreSQL
关注(0)|答案(1)|浏览(229)

我正在尝试在Postgres中创建一个自定义枚举类型,并且已经成功完成。我的迁移看起来像这样:

CREATE TYPE role AS ENUM ('admin', 'user');

ALTER TABLE users
ADD role role DEFAULT 'user';

然后我在Rust中创建了枚举类型,如下所示:

#[derive(Serialize, Deserialize, Debug, sqlx::Type)]
#[sqlx(type_name = "role", rename_all = "lowercase")] 
pub enum Role {
    ADMIN,
    USER
}

我还改变了用户模型:

#[derive(sqlx::FromRow, Debug)]
pub struct User {
    pub id: i32,
    pub email: String,
    pub username: String,
    pub password: String,
    pub role: Role,
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
}

但是现在当我尝试像这样查询数据库时:

let user = match sqlx::query_as!(
    User,
    "SELECT * FROM users WHERE email = $1 AND password = $2",
    &email,
    &password,
)

我得到这个错误:unsupported type role of column #7 ("role")
我做错了什么?
我试过玩宏观部分
#[sqlx(type_name = "role", rename_all = "lowercase")]
但这似乎没有帮助。
以下是cargo check的完整错误:

error: unsupported type role of column #7 ("role")
   --> src/routes/auth/mod.rs:140:20
    |
140 |           let user = match sqlx::query_as!(
    |  __________________________^
141 | |             User,
142 | |             "SELECT * FROM users WHERE email = $1 AND password = $2",
143 | |             &payload.email,
144 | |             &hash,
145 | |         )
    | |_________^
    |
    = note: this error originates in the macro `$crate::sqlx_macros::expand_query` which comes from the expansion of the macro `sqlx::query_as` (in Nightly builds, run with -Z macro-backtrace for more info)

error: could not compile `rust-api-example` (bin "rust-api-example") due to previous error
ipakzgxi

ipakzgxi1#

我目前的情况与你非常相似,你的问题实际上帮助解决了我的问题。在我的例子中,将#[sqlx(type_name = "user_role")]添加到我的枚举中解决了我的问题。我将发布我所有相关的代码,现在工作。希望这也能帮助解决你的问题。
我相信你的问题与使用query_as宏有关。宏在自动Map自定义类型时有问题,因此当您SELECT * 时,它不知道如何Map结果。我不得不在我的sql查询中手动指定类型。user_role AS "user_role!: UserRole。我是postgres的新手,所以除了使用AS子句修复它之外,我不知道太多。
这些帖子更详细:
https://github.com/launchbadge/sqlx/issues/235
https://users.rust-lang.org/t/sqlx-postgres-how-to-insert-a-enum-value/53044/2
以下是我的SQL表/类型:

-- Create the enumeration type
CREATE TYPE user_role AS ENUM ('admin', 'user');

-- Create the roles table
CREATE TABLE
    roles (
        id SERIAL PRIMARY KEY,
        name user_role NOT NULL,
        created_at TIMESTAMP NOT NULL DEFAULT NOW ()
    );

-- Create the users table
CREATE TABLE
    users (
        id SERIAL PRIMARY KEY,
        username TEXT NOT NULL UNIQUE,
        password_hash TEXT NOT NULL,
        email TEXT NOT NULL UNIQUE,
        user_role user_role NOT NULL,
        created_at TIMESTAMP
        WITH
            TIME ZONE DEFAULT NOW (),
        updated_at TIMESTAMP
        WITH
            TIME ZONE DEFAULT NOW () 
    );

这是我的模特

#[derive(Clone, Debug, PartialEq, PartialOrd, sqlx::Type, Deserialize, Serialize)]
#[sqlx(type_name = "user_role", rename_all = "lowercase")]
pub enum UserRole {
    Admin,
    User,
}

#[derive(Debug, sqlx::FromRow, Deserialize, Serialize)]
#[allow(non_snake_case)]
pub struct UserModel {
    pub id: i32,
    pub username: String,
    pub password_hash: String,
    pub email: String, 
    pub user_role: UserRole,
    #[serde(rename = "createdAt")]
    pub created_at: Option<chrono::DateTime<chrono::Utc>>,
    #[serde(rename = "updatedAt")]
    pub updated_at: Option<chrono::DateTime<chrono::Utc>>,
}

下面是我的insert函数:

let query_result = sqlx::query_as!(
        UserModel,
        r#"INSERT INTO users (username,password_hash,email,user_role) VALUES ($1, $2, $3, $4) RETURNING id,username,password_hash,email,user_role AS "user_role!: UserRole", created_at, updated_at"#,
        body.username.to_string(),
        body.password.to_string(),
        body.email.to_string(),
        UserRole::User as UserRole
    )
    .fetch_one(&data.db)
    .await;

相关问题