Let's say I have a very simple Insertable struct containing a custom struct:
#[derive(Identifiable, Queryable, Insertable)]
#[table_name = "my_temp_table"]
#[primary_key(id)]
pub struct MyTempTable {
pub id: i32,
pub non_optional: MyText,
pub optional: Option<MyText>,
}
pub struct MyText(pub String);
And the corresponding schema:
table! {
my_temp_table (id) {
id -> Integer,
non_optional -> Text,
optional -> Nullable<Text>,
}
}
I would get an error :
error[E0277]: the trait bound `MyText: diesel::Expression` is not satisfied
--> my_cool_file.rs:66:35
|
66 | #[derive(Identifiable, Queryable, Insertable)]
| ^^^^^^^^^^ the trait `diesel::Expression` is not implemented for `MyText`
|
= help: the following other types implement trait `diesel::Expression`:
Box<T>
migrations_internals::schema::__diesel_schema_migrations::columns::star
migrations_internals::schema::__diesel_schema_migrations::columns::version
migrations_internals::schema::__diesel_schema_migrations::columns::run_on
and 484 others
= note: required for `MyText` to implement `diesel::expression::AsExpression<diesel::sql_types::Text>`
= note: this error originates in the derive macro `Insertable` (in Nightly builds, run with -Z macro-backtrace for more info)
It makes sense, I need to implement AsExpression for MyText :
impl AsExpression<Text> for MyText {
type Expression = AsExprOf<String, Text>;
fn as_expression(self) -> Self::Expression {
<String as AsExpression<Text>>::as_expression(self.0)
}
}
impl<'a> AsExpression<Text> for &'a MyText {
type Expression = AsExprOf<String, Text>;
fn as_expression(self) -> Self::Expression {
<String as AsExpression<Text>>::as_expression(self.0.to_owned())
}
}
but even after doing that I still have a very similar error:
error[E0277]: the trait bound `MyText: diesel::Expression` is not satisfied
--> my_cool_file.rs:66:35
|
66 | #[derive(Identifiable, Queryable, Insertable)]
| ^^^^^^^^^^ the trait `diesel::Expression` is not implemented for `MyText`
|
= help: the following other types implement trait `diesel::Expression`:
Box<T>
migrations_internals::schema::__diesel_schema_migrations::columns::star
migrations_internals::schema::__diesel_schema_migrations::columns::version
migrations_internals::schema::__diesel_schema_migrations::columns::run_on
and 484 others
= note: required for `&'insert MyText` to implement `diesel::Expression`
= note: required for `&'insert MyText` to implement `diesel::expression::AsExpression<diesel::sql_types::Nullable<diesel::sql_types::Text>>`
= note: this error originates in the derive macro `Insertable` (in Nightly builds, run with -Z macro-backtrace for more info)
This confuses me as I would have expected the Option<Foo> <-> Nullable<SQLType> to work out of the box if Foo <-> SQLType works but I still need to implement
impl AsExpression<Nullable<Text>> for MyText
impl<'a> AsExpression<Nullable<Text>> for &'a MyText
And same for ToSql and FromSql traits if I need them.
Is it expected that I need to implement the Nullable case explicitly too or should it work out of the box and I missed something?
I am using Diesel 1.4.8.
This behavior is somewhat expected. The documentation of ToSql states:
This derive would then generate all necessary implementations of
AsExpressionfor you.Now this derives is (as you already noticed) not really documented for diesel 1.4. Given that this diesel version is outdated for more than 2 years I would suggest that you update to diesel 2.x and then work with the documentation there. That documentation also contains a full list of impls that are generated.