-
I'm trying to query the following struct: #[derive(Debug, Clone, Selectable)]
#[diesel(table_name = users)]
pub struct User {
id: u16,
username: CompactString,
password_hash: [u8; 40]
} From the following schema: diesel::table! {
users (id) {
id -> Unsigned<Smallint>,
username -> Varchar,
password_hash -> Binary,
}
} Using the following impl Queryable<users::SqlType, diesel::mysql::Mysql> for User {
type Row = (u16, *const str, *const [u8]);
fn build(row: Self::Row) -> diesel::deserialize::Result<Self> {
Ok(Self{
id: row.0,
username: unsafe { row.1.as_ref().unwrap().into() },
password_hash: unsafe { row.2.as_ref().unwrap().try_into().unwrap() }
})
}
} But I'm getting the error in the title:
Switching the I thought - based on impls here and here - that this would work, but it seems like I've got a fundamental misunderstanding about the trait impls. I did notice that 2.0.4 went out today and, based on the release notes, possibly fixed this, but I made sure I'm updated to that, and I do have |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments
-
It seems like diesel misses a few trait implementations to support this kind of impl. I've opened #3603 to address that. In the mean time you could use the following code to workaround that limitation and avoid allocations (although that shouldn't matter that much compared to the network calls necessary to execute your query 😉): use compact_str::CompactString;
use diesel::mysql::Mysql;
use diesel::prelude::*;
use diesel::sql_types::Binary;
use diesel::sql_types::Text;
#[derive(Debug, Clone, Selectable, Queryable)]
#[diesel(table_name = users)]
pub struct User {
id: u16,
#[diesel(deserialize_as = CompactStringWrapper)]
username: CompactString,
#[diesel(deserialize_as = ArrayWrapper)]
password_hash: [u8; 40],
}
diesel::table! {
users (id) {
id -> Unsigned<Smallint>,
username -> Varchar,
password_hash -> Binary,
}
}
pub struct CompactStringWrapper(CompactString);
impl Queryable<Text, Mysql> for CompactStringWrapper {
type Row = *const str;
fn build(row: Self::Row) -> diesel::deserialize::Result<Self> {
Ok(Self(unsafe { row.as_ref().unwrap().into() }))
}
}
impl From<CompactStringWrapper> for CompactString {
fn from(value: CompactStringWrapper) -> Self {
value.0
}
}
pub struct ArrayWrapper([u8; 40]);
impl Queryable<Binary, Mysql> for ArrayWrapper {
type Row = *const [u8];
fn build(row: Self::Row) -> diesel::deserialize::Result<Self> {
Ok(Self(unsafe { row.as_ref().unwrap().try_into().unwrap() }))
}
}
impl From<ArrayWrapper> for [u8; 40] {
fn from(value: ArrayWrapper) -> Self {
value.0
}
} |
Beta Was this translation helpful? Give feedback.
-
Haha you are definitely right about the network calls vs allocation. The primary reason I try to minimize allocations is heap fragmentation in long-lived processes rather than performance itself. I don't really think this would make a huge difference (without the workaround I would just use Also, thanks for both the fix and the workaround :) |
Beta Was this translation helpful? Give feedback.
It seems like diesel misses a few trait implementations to support this kind of impl. I've opened #3603 to address that.
In the mean time you could use the following code to workaround that limitation and avoid allocations (although that shouldn't matter that much compared to the network calls necessary to execute your query 😉):