问题描述
我有一个将用户数据插入数据库的查询。它工作正常,但 users
表在 username
上有一个唯一索引,因此当尝试使用已存在的用户名创建行时,它会引发错误:
pub async fn create(user: UserRequest,pool: &PgPool) -> anyhow::Result<User> {
let new_user = sqlx::query_as!(
User,r#"
INSERT INTO users (first_name,username)
VALUES ($1,$2)
RETURNING id,first_name,username
"#,&user.first_name,&user.username,)
.fetch_one(&pool.clone())
.await?;
Ok(User {
id: new_user.id,first_name: new_user.first_name,username: new_user.username,})
}
pub struct UserRequest {
pub first_name: String,pub username: String,}
使用此函数的端点使用 match
来检查它是否是 Ok(user)
或其他任何东西,并返回其响应:
pub async fn create_user(
user: web::Json<UserRequest>,pool: Data<PgPool>,) -> impl Responder {
let new_user = User::create(user.into_inner(),pool.get_ref()).await;
match new_user {
Ok(user) => HttpResponse::Ok().json(user),_ => HttpResponse::BadRequest().body(ERROR_MESSAGE),}
}
当由于行试图被复制而出现错误时,我该怎么做才能捕获这种情况?这种情况是我需要在发生这种情况时返回不同的 HTTP 状态。
解决方法
您可以使用 get_code
检查错误代码。
match new_user {
Ok(user) => HttpResponse::Ok().json(user),Err(err) if err.get_code() == "23505" {
// returns unique constraint violation response.
},_ => HttpResponse::BadRequest().body(ERROR_MESSAGE),}
为了使这项工作如@MichaelAnderson 在评论中指出的那样,
您需要将 create 的返回类型更改为 Result<User,sqlx::postgres::PgDatabaseError>
,或者您可以使用 anyhow::Error::downcast
或其相关函数返回 {{ 1}}