Deriving FromRow for structs with third-party types
Opening an issue for this as discussed on Discord.
#[derive(FromRow)]
struct CustomType {
a: String,
b: i32,
third_party: ThirdParty,
}
It would be convenient if there were a way to make this work like with serde's with field attributes: https://serde.rs/field-attrs.html#serialize_with
In my case ThirdParty implements from_str
Until this is possible, I've gone ahead and manually implemented FromRow for my situation
A related thing to add that I'm facing is to derive FromRow on an imported struct.
use some_create::ThirdParty;
#[derive(FromRow)] // for ThirdParty;
I'm looking for a reasonable solution but can't find it yet.
I just stumbled upon the same issue and found this ticket. It would be really nice if we could do it.
A related thing to add that I'm facing is to derive FromRow on an imported struct.
That is unfortunately not possible in Rust because of its orphan rules.
+1'ing this, I'd like to implement Type and sqlx(transparent) for some third-party type. For now, I'm using a workaround with try_from:
#[derive(sqlx::Type)]
#[sqlx(transparent, no_pg_array)]
struct UserIdDbParser(i64);
impl From<UserIdDbParser> for UserId {
fn from(value: UserIdDbParser) -> Self {
Self(value.0 as u64)
}
}
// in my structs:
#[derive(Clone, sqlx::FromRow)]
pub struct User {
#[sqlx(try_from = "UserIdDbParser")]
pub id: UserId,
}
Here's a macro I came up with for defining the above parser quickly, and some usage examples:
macro_rules! impl_db_parser {
{
$( $name:ident ( $db_ty:ty ) => $ty:ty, $conv:expr $(,)? );+ $(;)?
} => {
mod convert {
$( impl_db_parser!(@impl $name ($db_ty) => $ty, $conv); )+
}
mod convert_opt {
$( impl_db_parser!(@impl @opt $name ($db_ty) => $ty, $conv); )+
}
};
(@impl $name:ident ( $db_ty:ty ) => $ty:ty, $conv:expr) => {
#[derive(sqlx::Type)]
#[sqlx(transparent)]
pub struct $name($db_ty);
impl From<$name> for $ty {
fn from(value: $name) -> Self {
$conv(value.0)
}
}
};
(@impl @opt $name:ident ( $db_ty:ty ) => $ty:ty, $conv:expr) => {
#[derive(sqlx::Type)]
#[sqlx(transparent)]
pub struct $name(Option<$db_ty>);
impl From<$name> for Option<$ty> {
fn from(value: $name) -> Self {
value.0.map($conv)
}
}
}
}
impl_db_parser!{
U8(i8) => u8, |x| x as u8;
U16(i16) => u16, |x| x as u16;
U32(i32) => u32, |x| x as u32;
U64(i64) => u64, |x| x as u64;
UserId(i64) => teloxide::types::UserId, |x| teloxide::types::UserId(x as u64);
ChatId(i64) => teloxide::types::ChatId, teloxide::types::ChatId;
}