Derive Macro diesel::prelude::Insertable

source ·
#[derive(Insertable)]
{
    // Attributes available to this derive:
    #[diesel]
    #[table_name]
    #[column_name]
}
Expand description

Implements Insertable

To implement Insertable this derive needs to know the corresponding table type. By default it uses the snake_case type name with an added s from the current scope. It is possible to change this default by using #[diesel(table_name = something)].

If a field name of your struct differs from the name of the corresponding column, you can annotate the field with #[diesel(column_name = some_column_name)].

Your struct can also contain fields which implement Insertable. This is useful when you want to have one field map to more than one column (for example, an enum that maps to a label and a value column). Add #[diesel(embed)] to any such fields.

To provide custom serialization behavior for a field, you can use #[diesel(serialize_as = SomeType)]. If this attribute is present, Diesel will call .into on the corresponding field and serialize the instance of SomeType, rather than the actual field on your struct. This can be used to add custom behavior for a single field, or use types that are otherwise unsupported by Diesel. Using #[diesel(serialize_as)] is incompatible with #[diesel(embed)]. Normally, Diesel produces two implementations of the Insertable trait for your struct using this derive: one for an owned version and one for a borrowed version. Using #[diesel(serialize_as)] implies a conversion using .into which consumes the underlying value. Hence, once you use #[diesel(serialize_as)], Diesel can no longer insert borrowed versions of your struct.

Attributes

Optional container attributes

  • #[diesel(table_name = path::to::table)], specifies a path to the table this type is insertable into. The path is relative to the current module. If this attribute is not used, the type name converted to snake_case with an added s is used as table name
  • #[diesel(treat_none_as_default_value = false)], specifies that None values should be converted to NULL values on SQL side instead of being treated as DEFAULT value primitive. Note: This option may control if your query is stored in the prepared statement cache or not*

Optional field attributes

  • #[diesel(column_name = some_column_name)], overrides the column the current field maps to some_column_name. By default the field name is used as column name
  • #[diesel(embed)], specifies that the current field maps not only to single database field, but is a struct that implements Insertable
  • #[diesel(serialize_as = SomeType)], instead of serializing the actual field type, Diesel will convert the field into SomeType using .into and serialize that instead. By default this derive will serialize directly using the actual field type.

Examples

If we want to customize the serialization during insert, we can use #[diesel(serialize_as)].

#[derive(Debug, FromSqlRow, AsExpression)]
#[diesel(sql_type = sql_types::Text)]
struct UppercaseString(pub String);

impl Into<UppercaseString> for String {
    fn into(self) -> UppercaseString {
        UppercaseString(self.to_uppercase())
    }
}

impl<DB> ToSql<sql_types::Text, DB> for UppercaseString
    where
        DB: Backend,
        String: ToSql<sql_types::Text, DB>,
{
    fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, DB>) -> serialize::Result {
        self.0.to_sql(out)
    }
}

#[derive(Insertable, PartialEq, Debug)]
#[diesel(table_name = users)]
struct InsertableUser {
    id: i32,
    #[diesel(serialize_as = UppercaseString)]
    name: String,
}

let user = InsertableUser {
    id: 1,
    name: "thomas".to_string(),
};

diesel::insert_into(users)
    .values(user)
    .execute(connection)
    .unwrap();

assert_eq!(
    Ok("THOMAS".to_string()),
    users.select(name).first(connection)
);