具有定制包装类型的柴油
Posted
技术标签:
【中文标题】具有定制包装类型的柴油【英文标题】:Diesel with custom wrapper types 【发布时间】:2020-10-26 00:22:42 【问题描述】:我有自定义类型,可用作 Diesel 中安全使用的其他类型的包装器:
use uuid::Uuid;
pub schema Post
id: PostId,
title: String,
body: String
pub schema PostId value: Uuid
我无法将这些自定义包装器与 Diesel 一起使用。我得到的错误信息如下:
#[derive(Insertable)]
the trait `diesel::Expression` is not implemented for `models::PostId`
我试图寻找有关转换自定义类型的示例,到目前为止,我看到的两种方法是实现 AsExpression
特征或 FromSql
和 ToSql
特征,但是我的示例'到目前为止看到的是枚举类型,我无法推断这两种方法之间的区别是什么,除了前者似乎是一种较旧的方式,也不知道这些特征的预期实现是什么。
【问题讨论】:
不幸的是,柴油(以及我尝试过的其他生锈剂)中的自定义类型非常痛苦。我最近写了一个post 一个更简单的案例,希望它可以帮助。 很难回答您的问题,因为它不包含minimal reproducible example。我们无法分辨代码中存在哪些 crate(及其版本)、类型、特征、字段等。如果您尝试在Rust Playground 上重现您的错误,如果可能的话,这将使我们更容易为您提供帮助,否则在全新的 Cargo 项目中,然后在edit 您的问题中包含附加信息。您可以使用Rust-specific MRE tips 来减少您在此处发布的原始代码。谢谢! 感谢 Shepmaster 的编辑!我添加了一些可能解释问题的额外信息,但感谢 Weiznich 的回答,我终于解决了问题! 【参考方案1】:您需要实现上述三个特征 + 更多特征。 AsExpression
+ FromSqlRow
由相应的派生实现。 FromSql
和 ToSql
需要手动实现。
use diesel::deserialize::self, FromSql;
use diesel::pg::Pg;
use diesel::serialize::self, ToSql;
use std::io::Write;
#[derive(AsExpression, FromSqlRow)]
#[sql_type = "diesel::sql_types::Uuid"]
pub schema PostId
value: uuid::Uuid,
impl FromSql<diesel::sql_types::Uuid, Pg> for PostId
fn from_sql(bytes: Option<&DB::RawValue>) -> deserialize::Result<Self>
<uuid::Uuid as FromSql<diesel::sql_types::Uuid, Pg>>::from_sql(bytes)
.map(|value| PostId value )
impl ToSql<diesel::sql_types::Uuid, Pg> for PostId
fn to_sql<W: Write>(&self, out: &mut Output<W, DB>) -> serialize::Result
<uuid::Uuid as ToSql<diesel::sql_types::Uuid, Pg>>::to_sql(&self.0, out)
【讨论】:
感谢您的回答@weiznich!我不得不稍微修改一下,但所有功劳都归你所有!【参考方案2】:根据 weiznich 的回答,我想出了以下用于序列化/反序列化我的自定义包装器类型的解决方案:
use uuid::Uuid;
use super::schema::posts;
use diesel::serialize::self, IsNull, Output, ToSql;
use std::io::Write;
use diesel::deserialize::self, FromSql;
use diesel::backend::Backend;
use diesel::pg::Pg;
#[derive(Queryable, Debug)]
pub struct Post
pub id: PostId,
pub body: String,
pub title: String
#[derive(Insertable)]
#[table_name="posts"]
pub struct NewPost<'a>
pub id: PostId,
pub body: &'a str,
pub title: &'a str
#[derive(AsExpression, FromSqlRow, Debug)]
#[sql_type = "diesel::sql_types::Uuid"]
pub struct PostIdpub value: Uuid
impl<DB: Backend<RawValue=[u8]>> FromSql<diesel::sql_types::Uuid, DB> for PostId
fn from_sql(bytes: Option<&DB::RawValue>) -> deserialize::Result<Self>
<uuid::Uuid as FromSql<diesel::sql_types::Uuid, Pg>>::from_sql(bytes).map(|value| PostId value )
impl ToSql<diesel::sql_types::Uuid, Pg> for PostId
fn to_sql<W: Write>(&self, out: &mut Output<W, Pg>) -> serialize::Result
<uuid::Uuid as ToSql<diesel::sql_types::Uuid, Pg>>::to_sql(&self.value, out)
【讨论】:
以上是关于具有定制包装类型的柴油的主要内容,如果未能解决你的问题,请参考以下文章