在 Diesel 中创建自定义类型包装器时出错
Error Creating Custom Type Wrappers in Diesel
我正在尝试围绕 H160 and U256 创建自定义类型,以便我可以将它们与 Diesel 一起使用。
这是我用来创建自定义类型的代码:
use diesel::deserialize::{self, FromSql};
use diesel::pg::Pg;
use diesel::serialize::{self, Output, ToSql};
use diesel::sql_types::*;
use diesel::{backend::Backend, expression::AsExpression};
use ethers::{
prelude::{Address as EthereumAddress, U256 as Eth256, *},
};
use serde::Serialize;
use std::io;
use std::io::Write;
table! {
ethbalances (id) {
id -> Int4,
account -> Varchar,
balance -> Int4,
last_updated -> Text,
holder -> Bool,
}
}
#[derive(AsExpression, FromSqlRow, Debug, Copy, Clone, Serialize)]
#[sql_type = "Varchar"]
pub struct Address {
value: EthereumAddress,
}
// Something to do with incompatible type
//
//
//
//
impl ToSql<VarChar, Pg> for Address {
fn to_sql<W: Write>(&self, out: &mut Output<W, Pg>) -> serialize::Result {
<VarChar as ToSql<VarChar, Pg>>::to_sql(&self.value, out)
}
}
impl<DB: Backend<RawValue = [u8]>> FromSql<Varchar, DB> for Address {
fn from_sql(bytes: Option<&DB::RawValue>) -> deserialize::Result<Self> {
<VarChar as FromSql<VarChar, Pg>>::from_sql(bytes).map(|value| Address { value })
}
}
#[derive(AsExpression, FromSqlRow, Debug, Copy, Clone, Serialize)]
#[sql_type = "Integer"]
pub struct U256 {
value: Eth256,
}
// Something to do with incompatible type
impl ToSql<Integer, Pg> for U256 {
fn to_sql<W: Write>(&self, out: &mut Output<W, Pg>) -> serialize::Result {
<Integer as ToSql<Integer, Pg>>::to_sql(&self.value, out)
}
}
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)
}
}
impl<DB: Backend<RawValue = [u8]>> FromSql<Integer, DB> for U256 {
fn from_sql(bytes: Option<&DB::RawValue>) -> deserialize::Result<Self> {
<Integer as FromSql<Integer, Pg>>::from_sql(bytes).map(|value| U256 { value })
}
}
#[derive(Queryable, Insertable, Serialize)]
#[table_name = "ethbalances"]
pub struct ETHRioBalance {
id: i32,
account: Address,
balance: U256,
holder: bool,
}
这是生成 table!
宏的 up.sql 文件
CREATE TABLE ethbalances (
id SERIAL PRIMARY KEY,
account NOT NULL,
balance INTEGER NOT NULL,
last_updated TEXT NOT NULL,
holder BOOLEAN NOT NUll
)
不幸的是,我收到以下错误
error[E0277]: the trait bound `diesel::sql_types::Text: ToSql<diesel::sql_types::Text, Pg>` is not satisfied
--> src/schema.rs:48:9
|
48 | <VarChar as ToSql<VarChar, Pg>>::to_sql(&self.value, out)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `ToSql<diesel::sql_types::Text, Pg>` is not implemented for `diesel::sql_types::Text`
error[E0308]: mismatched types
--> src/schema.rs:48:49
|
48 | <VarChar as ToSql<VarChar, Pg>>::to_sql(&self.value, out)
| ^^^^^^^^^^^ expected struct `diesel::sql_types::Text`, found struct `H160`
|
= note: expected reference `&diesel::sql_types::Text`
found reference `&H160`
error[E0277]: the trait bound `diesel::sql_types::Text: FromSql<diesel::sql_types::Text, Pg>` is not satisfied
--> src/schema.rs:54:29
|
54 | <VarChar as FromSql<VarChar, Pg>>::from_sql(bytes).map(|value| Address { value })
| ^^^^^^^ the trait `FromSql<diesel::sql_types::Text, Pg>` is not implemented for `diesel::sql_types::Text`
error[E0308]: mismatched types
--> src/schema.rs:54:82
|
54 | <VarChar as FromSql<VarChar, Pg>>::from_sql(bytes).map(|value| Address { value })
| ^^^^^ expected struct `H160`, found struct `diesel::sql_types::Text`
error[E0277]: the trait bound `diesel::sql_types::Integer: ToSql<diesel::sql_types::Integer, Pg>` is not satisfied
--> src/schema.rs:66:9
|
66 | <Integer as ToSql<Integer, Pg>>::to_sql(&self.value, out)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `ToSql<diesel::sql_types::Integer, Pg>` is not implemented for `diesel::sql_types::Integer`
error[E0308]: mismatched types
--> src/schema.rs:66:49
|
66 | <Integer as ToSql<Integer, Pg>>::to_sql(&self.value, out)
| ^^^^^^^^^^^ expected struct `diesel::sql_types::Integer`, found struct `ethers::prelude::U256`
|
= note: expected reference `&diesel::sql_types:x:Integer`
found reference `ðers::prelude::U256`
error[E0277]: the trait bound `diesel::sql_types::Integer: FromSql<diesel::sql_types::Integer, Pg>` is not satisfied
--> src/schema.rs:78:29
|
78 | <Integer as FromSql<Integer, Pg>>::from_sql(bytes).map(|value| U256 { value })
| ^^^^^^^ the trait `FromSql<diesel::sql_types::Integer, Pg>` is not implemented for `diesel::sql_types::Integer`
error[E0308]: mismatched types
--> src/schema.rs:78:79
|
78 | <Integer as FromSql<Integer, Pg>>::from_sql(bytes).map(|value| U256 { value })
| ^^^^^ expected struct `ethers::prelude::U256`, found struct `diesel::sql_types::Integer`
对于我做错的任何指导,我将不胜感激。
为自定义类型实现 ToSql
和 FromSql
的最简单方法是将其简单地转换为 diesel-known 类型并推迟到其实现。这是使用 String
作为中介的 ethers::Address
的工作示例:
#[derive(AsExpression, FromSqlRow, Debug, Copy, Clone, Serialize)]
#[sql_type = "Varchar"]
pub struct Address {
value: EthereumAddress,
}
impl ToSql<VarChar, Pg> for Address {
fn to_sql<W: Write>(&self, out: &mut Output<W, Pg>) -> serialize::Result {
<String as ToSql<VarChar, Pg>>::to_sql(&self.value.to_string(), out)
}
}
impl<DB: Backend<RawValue = [u8]>> FromSql<Varchar, DB> for Address {
fn from_sql(bytes: Option<&DB::RawValue>) -> deserialize::Result<Self> {
<String as FromSql<VarChar, Pg>>::from_sql(bytes).map(|s| Address { value: s.parse().unwrap() })
}
}
我正在尝试围绕 H160 and U256 创建自定义类型,以便我可以将它们与 Diesel 一起使用。
这是我用来创建自定义类型的代码:
use diesel::deserialize::{self, FromSql};
use diesel::pg::Pg;
use diesel::serialize::{self, Output, ToSql};
use diesel::sql_types::*;
use diesel::{backend::Backend, expression::AsExpression};
use ethers::{
prelude::{Address as EthereumAddress, U256 as Eth256, *},
};
use serde::Serialize;
use std::io;
use std::io::Write;
table! {
ethbalances (id) {
id -> Int4,
account -> Varchar,
balance -> Int4,
last_updated -> Text,
holder -> Bool,
}
}
#[derive(AsExpression, FromSqlRow, Debug, Copy, Clone, Serialize)]
#[sql_type = "Varchar"]
pub struct Address {
value: EthereumAddress,
}
// Something to do with incompatible type
//
//
//
//
impl ToSql<VarChar, Pg> for Address {
fn to_sql<W: Write>(&self, out: &mut Output<W, Pg>) -> serialize::Result {
<VarChar as ToSql<VarChar, Pg>>::to_sql(&self.value, out)
}
}
impl<DB: Backend<RawValue = [u8]>> FromSql<Varchar, DB> for Address {
fn from_sql(bytes: Option<&DB::RawValue>) -> deserialize::Result<Self> {
<VarChar as FromSql<VarChar, Pg>>::from_sql(bytes).map(|value| Address { value })
}
}
#[derive(AsExpression, FromSqlRow, Debug, Copy, Clone, Serialize)]
#[sql_type = "Integer"]
pub struct U256 {
value: Eth256,
}
// Something to do with incompatible type
impl ToSql<Integer, Pg> for U256 {
fn to_sql<W: Write>(&self, out: &mut Output<W, Pg>) -> serialize::Result {
<Integer as ToSql<Integer, Pg>>::to_sql(&self.value, out)
}
}
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)
}
}
impl<DB: Backend<RawValue = [u8]>> FromSql<Integer, DB> for U256 {
fn from_sql(bytes: Option<&DB::RawValue>) -> deserialize::Result<Self> {
<Integer as FromSql<Integer, Pg>>::from_sql(bytes).map(|value| U256 { value })
}
}
#[derive(Queryable, Insertable, Serialize)]
#[table_name = "ethbalances"]
pub struct ETHRioBalance {
id: i32,
account: Address,
balance: U256,
holder: bool,
}
这是生成 table!
宏的 up.sql 文件
CREATE TABLE ethbalances (
id SERIAL PRIMARY KEY,
account NOT NULL,
balance INTEGER NOT NULL,
last_updated TEXT NOT NULL,
holder BOOLEAN NOT NUll
)
不幸的是,我收到以下错误
error[E0277]: the trait bound `diesel::sql_types::Text: ToSql<diesel::sql_types::Text, Pg>` is not satisfied
--> src/schema.rs:48:9
|
48 | <VarChar as ToSql<VarChar, Pg>>::to_sql(&self.value, out)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `ToSql<diesel::sql_types::Text, Pg>` is not implemented for `diesel::sql_types::Text`
error[E0308]: mismatched types
--> src/schema.rs:48:49
|
48 | <VarChar as ToSql<VarChar, Pg>>::to_sql(&self.value, out)
| ^^^^^^^^^^^ expected struct `diesel::sql_types::Text`, found struct `H160`
|
= note: expected reference `&diesel::sql_types::Text`
found reference `&H160`
error[E0277]: the trait bound `diesel::sql_types::Text: FromSql<diesel::sql_types::Text, Pg>` is not satisfied
--> src/schema.rs:54:29
|
54 | <VarChar as FromSql<VarChar, Pg>>::from_sql(bytes).map(|value| Address { value })
| ^^^^^^^ the trait `FromSql<diesel::sql_types::Text, Pg>` is not implemented for `diesel::sql_types::Text`
error[E0308]: mismatched types
--> src/schema.rs:54:82
|
54 | <VarChar as FromSql<VarChar, Pg>>::from_sql(bytes).map(|value| Address { value })
| ^^^^^ expected struct `H160`, found struct `diesel::sql_types::Text`
error[E0277]: the trait bound `diesel::sql_types::Integer: ToSql<diesel::sql_types::Integer, Pg>` is not satisfied
--> src/schema.rs:66:9
|
66 | <Integer as ToSql<Integer, Pg>>::to_sql(&self.value, out)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `ToSql<diesel::sql_types::Integer, Pg>` is not implemented for `diesel::sql_types::Integer`
error[E0308]: mismatched types
--> src/schema.rs:66:49
|
66 | <Integer as ToSql<Integer, Pg>>::to_sql(&self.value, out)
| ^^^^^^^^^^^ expected struct `diesel::sql_types::Integer`, found struct `ethers::prelude::U256`
|
= note: expected reference `&diesel::sql_types:x:Integer`
found reference `ðers::prelude::U256`
error[E0277]: the trait bound `diesel::sql_types::Integer: FromSql<diesel::sql_types::Integer, Pg>` is not satisfied
--> src/schema.rs:78:29
|
78 | <Integer as FromSql<Integer, Pg>>::from_sql(bytes).map(|value| U256 { value })
| ^^^^^^^ the trait `FromSql<diesel::sql_types::Integer, Pg>` is not implemented for `diesel::sql_types::Integer`
error[E0308]: mismatched types
--> src/schema.rs:78:79
|
78 | <Integer as FromSql<Integer, Pg>>::from_sql(bytes).map(|value| U256 { value })
| ^^^^^ expected struct `ethers::prelude::U256`, found struct `diesel::sql_types::Integer`
对于我做错的任何指导,我将不胜感激。
为自定义类型实现 ToSql
和 FromSql
的最简单方法是将其简单地转换为 diesel-known 类型并推迟到其实现。这是使用 String
作为中介的 ethers::Address
的工作示例:
#[derive(AsExpression, FromSqlRow, Debug, Copy, Clone, Serialize)]
#[sql_type = "Varchar"]
pub struct Address {
value: EthereumAddress,
}
impl ToSql<VarChar, Pg> for Address {
fn to_sql<W: Write>(&self, out: &mut Output<W, Pg>) -> serialize::Result {
<String as ToSql<VarChar, Pg>>::to_sql(&self.value.to_string(), out)
}
}
impl<DB: Backend<RawValue = [u8]>> FromSql<Varchar, DB> for Address {
fn from_sql(bytes: Option<&DB::RawValue>) -> deserialize::Result<Self> {
<String as FromSql<VarChar, Pg>>::from_sql(bytes).map(|s| Address { value: s.parse().unwrap() })
}
}