在Diesel中为带字段的PostgreSQL复合类型实现ToSql和 FromSql

后端开发 2026-07-11

所以我在Postgres中有一个 "user" 复合类型:

CREATE TYPE "user" AS (
    username varchar(20),
    password text
    );

在一个表中曾经有一个字段

CREATE TABLE foo (
    ...
    users "user"[] NOT NULL,
    ...
);

user 类型的Diesel模式是:

pub mod sql_types {
    #[derive(diesel::query_builder::QueryId, Clone, diesel::sql_types::SqlType)]
    #[diesel(postgres_type(name = "user"))]
    pub struct User;
}

而模型是:

#[derive(Debug, Clone, diesel::FromSqlRow, diesel::AsExpression)]
#[diesel(sql_type = schema::sql_types::User)]
pub struct User {
    pub username: String,
    pub password: String,
}

我现在想为 User 编写 diesel::serialize::ToSqldiesel::deserialize::FromSql 的实现。我在网上尝试查找关于Diesel的自定义Postgres类型的示例,但我只能找到枚举的示例,而没有自定义类型包含字段的示例。

我该如何为我的类型实现 ToSqlFromSql

解决方案

我找到了 这个示例 以及 WriteTuple 文档 这也对我帮助很大。我已经用Diesel写出了下面这些,看起来可用:

type PgUserTuple = (Text, Text);
type PgUser = Record<PgUserTuple>

impl ToSql<schema::sql_types::User, Pg> for User {
    fn to_sql<'b>(
        &'b self,
        out: &mut serialize::Output<'b, '_, Pg>,
    ) -> serialize::Result {
        WriteTuple::<PgUserTuple>::write_tuple(
            &(self.username.clone(), self.password.clone()), &mut out.reborrow()
        )
    }
}

impl FromSql<schema::sql_types::User, Pg> for User {
    fn from_sql(
        bytes: PgValue,
    ) -> deserialize::Result<Self> {
        let (username, password) = FromSql::<PgUser, Pg>::from_sql(bytes)?;
        Ok(Self { username, password })
    }
}

Record 是与元组SQL类型(复合类型)相对应的Diesel类型。WriteTuple 是一个用于为命名的复合类型编写 ToSql 实现的辅助trait。我已经定义了将 User 转换为Postgres类型的类型(PgUserTuplePgUser)。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章