Rust Diesel定义PostgreSQL二进制字段遇Expression trait报错求解决
在Rust Diesel中正确定义PostgreSQL二进制数据字段的解决方法
问题场景
使用如下配置的Rust Diesel:
diesel = { version = "2.1.0", features = [ "postgres", "64-column-tables", "chrono", "serde_json", ] }
定义插入模型时编写了以下代码:
#![allow(unused)] #![allow(clippy::all)] use std::ffi::OsString; use actix_multipart::form::tempfile::TempFile; use diesel::sql_types::Bytea; use rust_wheel::common::util::time_util::get_current_millisecond; use rust_wheel::model::user::login_user_info::LoginUserInfo; use serde::Serialize; use serde::Deserialize; use uuid::Uuid; use crate::model::diesel::tex::custom_tex_models::TexTemplate; use crate::model::diesel::tex::tex_schema::*; use crate::model::request::file::add::file_add_req::TexFileAddReq; use crate::model::request::file::add::file_add_ver_req::TexFileVerAddReq; #[derive(Insertable,Queryable,QueryableByName,Debug,Serialize,Deserialize,Default,Clone)] #[diesel(table_name = tex_file_version)] pub struct TexFileVersionAdd { pub name: String, pub created_time: i64, pub updated_time: i64, pub user_id: i64, pub project_id: String, pub file_id: String, pub content: String, pub snapshot: Bytea }
编译时触发错误:
~/source/reddwarf/backend/texhub-server on main! ⌚ 12:29:48 $ cargo b ‹ruby-2.7.2› Compiling texhub-server v0.1.0 (/Users/dolphin/source/reddwarf/backend/texhub-server) error[E0277]: the trait bound `diesel::sql_types::Binary: diesel::Expression` is not satisfied --> src/model/diesel/tex/custom_tex_models.rs:107:9 | 107 | pub snapshot: Bytea, | ^^^^^^^^ the trait `diesel::Expression` is not implemented for `diesel::sql_types::Binary` | = help: the following other types implement trait `diesel::Expression`: &'a T (T0, T1) (T0, T1, T2) (T0, T1, T2, T3) (T0, T1, T2, T3, T4) (T0, T1, T2, T3, T4, T5) (T0, T1, T2, T3, T4, T5, T6) (T0, T1, T2, T3, T4, T5, T6, T7) and 240 others = note: required for `diesel::sql_types::Binary` to implement `AsExpression<diesel::sql_types::Binary>`
解决方法
错误核心是直接用Diesel的SQL类型Bytea作为结构体字段类型,而Diesel要求结构体字段使用对应Rust类型,SQL类型仅用于schema定义或类型注解。
针对PostgreSQL的bytea类型,Diesel映射的标准Rust类型是Vec<u8>,修改步骤如下:
- 将字段类型从
Bytea改为Vec<u8> - 若使用
QueryableByName特性,需给字段添加#[diesel(sql_type = Bytea)]注解,显式绑定对应SQL类型
修改后的代码:
#![allow(unused)] #![allow(clippy::all)] use std::ffi::OsString; use actix_multipart::form::tempfile::TempFile; use diesel::sql_types::Bytea; use rust_wheel::common::util::time_util::get_current_millisecond; use rust_wheel::model::user::login_user_info::LoginUserInfo; use serde::Serialize; use serde::Deserialize; use uuid::Uuid; use crate::model::diesel::tex::custom_tex_models::TexTemplate; use crate::model::diesel::tex::tex_schema::*; use crate::model::request::file::add::file_add_req::TexFileAddReq; use crate::model::request::file::add::file_add_ver_req::TexFileVerAddReq; #[derive(Insertable,Queryable,QueryableByName,Debug,Serialize,Deserialize,Default,Clone)] #[diesel(table_name = tex_file_version)] pub struct TexFileVersionAdd { pub name: String, pub created_time: i64, pub updated_time: i64, pub user_id: i64, pub project_id: String, pub file_id: String, pub content: String, #[diesel(sql_type = Bytea)] pub snapshot: Vec<u8> }
关键说明
Bytea是Diesel定义的SQL类型标识,仅用于声明字段对应的数据库类型,不能直接作为Rust结构体字段类型Vec<u8>是Diesel为PostgreSQLbytea类型提供的默认Rust映射类型,同时兼容Serialize/Deserialize特性- 若通过
diesel print-schema生成数据库schema,生成的代码中bytea字段会自动对应Vec<u8>,结构体字段只需保持一致即可
内容的提问来源于stack exchange,提问作者Dolphin
相关产品推荐
相关产品推荐

