-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Description
I'm trying to read/write enums to/from a varchar not null
column in Postgres. This issue may also exhibit in other databases, but I haven't tested them. As far as I can see from the docs, creating an enum like the following should allow me to use it in a query:
#[derive(
serde_derive::Deserialize, serde_derive::Serialize, sqlx::Type,
)]
#[sqlx(rename = "TEXT")]
pub enum UserType {
#[sqlx(rename = "users_normal")]
Normal,
#[sqlx(rename = "users_admin")]
Admin,
}
My insert statement looks like this:
let user: User = sqlx::query_as(
"insert into users
(id, name, user_type)
values
($1, $2, $3)
on conflict (id) do update set
name = excluded.name,
user_type = excluded.user_type
returning *
",
)
.bind(user_id)
.bind("Bobby Beans".to_string())
.bind(UserType::Normal)
.fetch_one(&postgres)
.await
.unwrap();
The record is never created in the database, and the insert panics with this message:
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: RowNotFound'
Removing the UserType
enum from the insert lets it work as normal, and inserts the record into the database.
I've tried changing #[sqlx(rename = "TEXT")]
to #[sqlx(rename = "varchar not null")]
to mirror the column type to no avail (see case below).
Is this a bug, or am I not following the docs properly? I found some stuff in CHANGELOG.md
about this but it's not very clear.
This is the reduced (as much as possible) test case.
Note that removing all serde
stuff doesn't fix the issue, so it's not serde messing with things.
use sqlx::{postgres::PgQueryAs, PgPool};
use uuid::Uuid;
#[derive(
serde_derive::Deserialize, serde_derive::Serialize, Debug, Copy, Clone, PartialEq, sqlx::Type,
)]
#[sqlx(rename = "TEXT")]
pub enum UserType {
#[serde(rename = "users_normal")]
#[sqlx(rename = "users_normal")]
Normal,
#[serde(rename = "users_admin")]
#[sqlx(rename = "users_admin")]
Admin,
}
#[derive(
serde_derive::Deserialize, serde_derive::Serialize, Debug, Clone, PartialEq, sqlx::FromRow,
)]
pub struct User {
id: Uuid,
name: String,
user_type: UserType,
}
#[async_std::test]
async fn enum_text_type() {
let postgres = PgPool::new(&std::env::var("DATABASE_URL").unwrap())
.await
.expect("Error creating postgres pool");
sqlx::query(
r#"
create table if not exists users (
id uuid primary key,
name varchar not null,
user_type varchar not null
);
"#,
)
.execute(&postgres)
.await
.expect("Failed to create users table");
let user_id = Uuid::new_v4();
let user: User = sqlx::query_as(
"insert into users
(id, name, user_type)
values
($1, $2, $3)
on conflict (id) do update set
name = excluded.name,
user_type = excluded.user_type
returning *
",
)
.bind(user_id)
.bind("Bobby Beans".to_string())
.bind(UserType::Normal)
.fetch_one(&postgres)
.await
.unwrap();
assert_eq!(
user,
User {
id: user_id,
name: "Bobby Beans".to_string(),
user_type: UserType::Normal
}
)
}
Cc @Istar-Eldritch who's been helping me fight this issue.