diesel-derive-enum

crates.io Build Status

Use Rust enums directly with diesel ORM.

The latest release, 2.0.0-rc.0, is tested against diesel 2.0.0-rc.0 and rustc 1.51.0.

Note: The master branch of this repository tracks diesel master, and will not work with diesel 1.x. In addition, the API has changed somewhat - if you are using diesel 1.x please refer to the README in the diesel-1 branch. What follows will _only work for diesel 2.0.

Setup

Postgres

Cargo.toml: toml [dependencies] diesel-derive-enum = { version = "2.0.0-rc.0", features = ["postgres"] }

As of diesel-2.0.0-rc, we recommend using diesel-cli to generate correct SQL <-> Rust bindings.

Suppose your project has the following diesel.toml:

toml [print_schema] file = "src/schema.rs"

And the following SQL: ```sql CREATE TYPE myenum AS ENUM ('foo', 'bar', 'bazquxx');

CREATE TABLE mytable ( id SERIAL PRIMARY KEY, someenum my_enum NOT NULL ); ```

Then diesel-cli will generate something like the following:

```rust // src/schema.rs

pub mod sqltypes { #[derive(diesel::sqltypes::SqlType)] #[diesel(postgrestype(name = "myenum"))] pub struct MyEnum; }

table! { use diesel::types::Integer; use super::sql_types::MyEnum;

my_table {
    id -> Integer,
    some_enum -> MyEnum
}

} `` Now we can usediesel-derive-enum` to hook in our own enum:

```rust // src/my_code.rs

[derive(dieselderiveenum::DbEnum)]

[DieselTypePath = "crate::schema::sql_types::MyEnum"]

pub enum MyEnum { Foo, Bar, BazQuxx, } ```

MySQL

Cargo.toml: toml [dependencies] diesel-derive-enum = { version = "2.0.0-rc.0", features = ["mysql"] }

SQL: sql CREATE TABLE my_table ( id SERIAL PRIMARY KEY, my_enum enum('foo', 'bar', 'baz_quxx') NOT NULL -- note: snake_case );

Rust: ```rust

[derive(dieselderiveenum::DbEnum)]

pub enum MyEnum { Foo, Bar, BazQuxx, }

// define your table table! { use diesel::types::Integer; use super::MyEnumMapping; mytable { id -> Integer, someenum -> MyEnumMapping, // Generated Diesel type - see below for explanation } } ```

sqlite

Cargo.toml: toml [dependencies] diesel-derive-enum = { version = "2.0.0-rc.0", features = ["sqlite"] }

SQL: sql CREATE TABLE my_table ( id SERIAL PRIMARY KEY, my_enum TEXT CHECK(my_enum IN ('foo', 'bar', 'baz_quxx')) NOT NULL -- note: snake_case );

Rust: ``` rust

[derive(dieselderiveenum::DbEnum)]

pub enum MyEnum { Foo, Bar, BazQuxx, }

// define your table table! { use diesel::types::Integer; use super::MyEnumMapping; mytable { id -> Integer, someenum -> MyEnumMapping, // Generated Diesel type - see below for explanation } } ```

Usage

Usage is similar regardless of your chosen database. We can define a struct with which to populate/query the table:

``` rust

[derive(Insertable, Queryable, Identifiable, Debug, PartialEq)]

[diesel(tablename = mytable)]

struct MyRow { id: i32, some_enum: MyEnum, } ```

And use it in the natural way:

rust let data = vec![ MyRow { id: 1, some_enum: MyEnum::Foo, }, MyRow { id: 2, some_enum: MyEnum::BazQuxx, }, ]; let connection = PgConnection::establish(/*...*/).unwrap(); let inserted = insert_into(my_table::table) .values(&data) .get_results(&connection) .unwrap(); assert_eq!(data, inserted); Postgres arrays work too! See this example.

Enums Representations

Enums are not part of the SQL standard and have database-specific implementations.

How It Works

Diesel maintains a set of internal types which correspond one-to-one to the types available in various relational databases. Each internal type in turn maps to some kind of Rust native type. e.g. Postgres INTEGER maps to diesel::types::Integer maps to i32.

For postgres only, as of diesel-2.0.0-rc.0, diesel will create the 'dummy' internal enum type as part of the schema generation process. This crate will attempt to locate this dummy type at the the default path of crate::schema::sql_types::{enum_name}. This location can be overridden with the DieselTypePath attribute.

For mysql and sqlite, the intenal type is not automatically generated, so this macro will instead create it with the default name {enum_name}Mapping. This name can be overridden with the DieselType attribute.

In either case, this macro will then implement various traits on the internal type. This macro will also implement various traits on the user-defined enum type. The net result of this is that the user-defined enum can be directly inserted into (and retrieved from) the diesel database.

Note that by default we assume that the possible SQL ENUM variants are simply the Rust enum variants translated to snake_case. These can be renamed with the inline annotation #[db_rename = "..."].

See this test for an example of renaming.

You can override the snake_case assumption for the entire enum using the #[DbValueStyle = "..."] attribute. Individual variants can still be renamed using #[db_rename = "..."].

| DbValueStyle | Variant | Value | |:-------------------:|:---------:|:---| | camelCase | BazQuxx | "bazQuxx" | | kebab-case | BazQuxx | "baz-quxx" | | PascalCase | BazQuxx | "BazQuxx" | | SCREAMINGSNAKECASE | BazQuxx | "BAZQUXX" | | UPPERCASE | BazQuxx | "BAZQUXX" | | snakecase | BazQuxx | "baz_quxx" | | verbatim | Bazquxx | "Bazquxx" |

See this test for an example of changing the output style.

License

Licensed under either of these: