This crate allows one to automatically derive the Diesel boilerplate necessary to use Rust enums directly with Postgres databases.
It is a fairly literal translation of this code from the Diesel test suite.
```rust // define your enum
pub enum MyEnum { // All enum variants must be fieldless 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 } }
// define a struct with which to populate/query the table
struct MyRow { id: i32, some_enum: MyEnum, } ```
SQL to create corresponding table:
```sql -- by default the postgres ENUM values correspond to snakecased Rust enum variant names CREATE TYPE myenum AS ENUM ('foo', 'bar', 'baz_quxx');
CREATE TABLE mytable ( id SERIAL PRIMARY KEY, someenum my_enum NOT NULL ); ```
Now we can insert and retrieve MyEnum directly:
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);
See this test for a full working example.
Diesel maintains a set of internal types which correspond one-to-one to the types available in Postgres (and other databases). Each internal type then maps to some kind of Rust native type. e.g. diesel::types::Integer
maps to i32
. So, when we create a new type in Postgres with CREATE TYPE ...
, we must also create a corresponding type in Diesel, and then create a mapping to some native Rust type (our enum). Hence there are three types we need to be aware of.
By default, the Postgres and Diesel internal types are inferred from the name of the Rust enum. Specifically, we assume MyEnum
corresponds to my_enum
in Postgres and MyEnumMapping
in Diesel. (The Diesel type is created by the plugin, the Postgres type must be created in SQL).
These defaults can be overridden with the attributes #[PgType = "..."]
and #[DieselType = "..."]
.
Similarly, we assume that the Postgres ENUM variants are simply the Rust enum variants translated to snake_case
. These can be renamed with the inline annotation #[pg_rename = "..."]
.
See this test for an example of renaming.
infer_schema!
and print-schema
The infer_schema!
macro and print-schema
command (from diesel_cli
) each attempt to connect to an existing DB and generate a correct mapping of Postgres columns to Diesel internal types. If a custom ENUM exists in the database, Diesel will simply assume that the internal mapping type is the ENUM name, Title-cased (e.g. my_enum
-> My_enum
). Therefore the derived mapping name must also be corrected with the DieselType
attribute e.g. #[DieselType] = "My_enum"]
.
Licensed under either of these: