I have an SQL table that I want to work with through Diesel:
CREATE TABLE records (
id BIGSERIAL PRIMARY KEY,
record_type SMALLINT NOT NULL,
valu
Sometimes, the easiest way to understand what a macro does (derives are just a different form of macros) is to ask the compiler for the expanded code. With a nightly compiler, you can do this using this command:
cargo rustc -- -Z unstable-options --pretty expanded > expanded.rs
This will output the expanded code in expanded.rs.
We can now look at this file to see what #[derive(Insertable)] expands to. Naturally, I first changed the definition of Record to match the types that Diesel. After some cleaning up, this is the generated code:
impl<'insert> diesel::insertable::Insertable for &'insert Record {
type Values = <(
Option>,
Option>,
Option>
) as diesel::insertable::Insertable>::Values;
#[allow(non_shorthand_field_patterns)]
fn values(self) -> Self::Values {
let Record {
id: ref id,
record_type: ref record_type,
value: ref value,
} = *self;
diesel::insertable::Insertable::values((
Some(::ExpressionMethods::eq(records::id, id)),
Some(::ExpressionMethods::eq(records::record_type, record_type)),
Some(::ExpressionMethods::eq(records::value, value))))
}
}
impl diesel::query_builder::UndecoratedInsertRecord for Record {
}
We can now adapt the Insertable implementation for our custom types. Notice that I've changed the Values associated type to return values directly rather than references to the values, because for two of them, the value is created in the values method, so we couldn't return a reference, and for the other one, returning a reference doesn't gain much in terms of performance.
impl<'insert> diesel::insertable::Insertable for &'insert Record {
type Values = <(
Option>,
Option>,
Option>
) as diesel::insertable::Insertable>::Values;
#[allow(non_shorthand_field_patterns)]
fn values(self) -> Self::Values {
let Record {
id: ref id,
record_type: ref record_type,
value: ref value,
} = *self;
let record_type = match *record_type {
RecordType::A => 1,
RecordType::B => 2,
};
let value: BigDecimal = value.to_string().parse().unwrap();
diesel::insertable::Insertable::values((
Some(::ExpressionMethods::eq(records::id, *id)),
Some(::ExpressionMethods::eq(records::record_type, record_type)),
Some(::ExpressionMethods::eq(records::value, value))))
}
}