You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Rust sqlx宏查询PostgreSQL时遇_badge类型不支持问题求助

解决sqlx query_as!宏不支持自定义枚举数组类型的问题

问题根源

query_as!是编译时宏,需要明确的类型映射信息来匹配PostgreSQL列和Rust结构体字段。对于自定义枚举的数组类型(如badge[]),宏无法自动推断对应的PostgreSQL数组类型标识符_badge,同时你的User结构体缺少sqlx::FromRow派生,这是宏生成代码的必要条件。

解决方案

  1. 给User结构体派生sqlx::FromRow
  2. 在badges字段上添加#[sqlx(type_name = "_badge")]属性,明确指定对应的PostgreSQL数组类型

修改后的代码

use sqlx::{FromRow, PgHasArrayType, PgTypeInfo};
use serde::{Serialize, Deserialize};
use uuid::Uuid;
use chrono::{DateTime, Utc};
use std::fmt::Display;

#[derive(sqlx::Type, Serialize, Deserialize, Display)]
#[sqlx(type_name = "badge")]
pub enum Badge {
    Sponsored,
    Founder,
    Developer,
}

impl PgHasArrayType for Badge {
    fn array_type_info() -> PgTypeInfo {
        PgTypeInfo::with_name("_badge")
    }

    fn array_compatible(ty: &PgTypeInfo) -> bool {
        ty.name() == "_badge"
    }
}

#[derive(Serialize, Deserialize, FromRow)]
pub struct User {
    uuid: Uuid,
    date_joined: DateTime<Utc>,
    name: String,
    #[sqlx(type_name = "_badge")]
    badges: Vec<Badge>,
    articles: Vec<String>,
    followers: i64,
}

关键说明

  • #[derive(FromRow)]:query_as!宏依赖这个trait生成数据库行到结构体的映射代码,非宏版本可能通过动态查询绕过了编译时检查,但宏必须显式拥有该trait。
  • #[sqlx(type_name = "_badge")]:告诉宏该字段对应的PostgreSQL类型是_badge(badge枚举的数组类型),直接解决编译时类型不匹配的错误。
  • 优化array_compatible方法:将原有的true改为精确匹配类型名称,避免潜在的类型兼容问题。

验证

修改后重新执行你的查询代码:

query_as!(User, r#"SELECT * FROM users WHERE name ILIKE $1"#, name)

编译错误应该会消失,宏可以正确识别并映射badge[]列到Vec<Badge>字段。

内容的提问来源于stack exchange,提问作者ImajinDevon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 15:20:32