Crates.io | postgres-derive-codegen |
lib.rs | postgres-derive-codegen |
version | 0.2.2 |
source | src |
created_at | 2016-02-20 22:06:38.983983 |
updated_at | 2016-11-19 21:05:30.307427 |
description | Deriving codegen support for Postgres enum, domain, and composite types |
homepage | |
repository | https://github.com/sfackler/rust-postgres-derive |
max_upload_size | |
id | 4229 |
size | 3,919 |
Syntax extensions to automatically derive FromSql
and ToSql
implementations for Postgres enum,
domain, and composite types.
The generated code requires rust-postgres 0.12.0 or higher and Rust 1.10.0 or higher.
postgres-derive can be used both as a syntax extension with a nightly build of the compiler, or as a code generator with stable builds.
Simply depend on the postgres-derive-macros
crate and register it as a plugin:
Cargo.toml
# ...
[dependencies]
postgres-derive-macros = "0.2"
postgres = "0.12"
lib.rs
#![feature(proc_macro)]
#[macro_use]
extern crate postgres;
#[macro_use]
extern crate postgres_derive;
#[derive(Debug, ToSql, FromSql)]
pub enum Mood {
Sad,
Ok,
Happy,
}
// ...
Use postgres-derive-codegen
in a build script:
Cargo.toml
[package]
# ...
build = "build.rs"
[build-dependencies]
postgres-derive-codegen = "0.2"
[dependencies]
postgres = "0.12"
build.rs
extern crate postgres_derive_codegen;
use std::env;
use std::path::Path;
pub fn main() {
let out_dir = env::var_os("OUT_DIR").unwrap();
let src = Path::new("src/types.rs.in");
let dst = Path::new(&out_dir).join("types.rs");
postgres_derive_codegen::expand(src, dst).unwrap();
}
types.rs.in
#[derive(Debug, ToSql, FromSql)]
pub enum Mood {
Sad,
Ok,
Happy,
}
lib.rs
#[macro_use]
extern crate postgres;
include!(concat!(env!("OUT_DIR"), "/types.rs"));
// ...
Postgres enums correspond to C-like enums in Rust:
CREATE TYPE "Mood" AS ENUM (
'Sad',
'Ok',
'Happy'
);
#[derive(Debug, ToSql, FromSql)]
enum Mood {
Sad,
Ok,
Happy,
}
The implementations will expect exact matches between the type names and variants. The
#[postgres(...)]
attribute can be used to adjust the names used on the Postgres side:
CREATE TYPE mood AS ENUM (
'sad',
'ok',
'happy'
);
#[derive(Debug, ToSql, FromSql)]
#[postgres(name = "mood")]
enum Mood {
#[postgres(name = "sad")]
Sad,
#[postgres(name = "ok")]
Ok,
#[postgres(name = "happy")]
Happy,
}
Postgres domains correspond to tuple structs with one member in Rust:
CREATE DOMAIN "SessionId" AS BYTEA CHECK(octet_length(VALUE) = 16);
#[derive(Debug, FromSql, ToSql)]
struct SessionId(Vec<u8>);
As above, the implementations will expect an exact match between the Rust and Postgres type names,
and the #[postgres(...)]
attribute can be used to adjust that behavior:
CREATE DOMAIN session_id AS BYTEA CHECK(octet_length(VALUE) = 16);
#[derive(Debug, FromSql, ToSql)]
#[postgres(name = "session_id")]
struct SessionId(Vec<u8>);
Postgres composite types correspond to structs in Rust:
CREATE TYPE "InventoryItem" AS (
name TEXT,
supplier_id INT,
price DOUBLE PRECISION
);
#[derive(Debug, FromSql, ToSql)]
struct InventoryItem {
name: String,
supplier_id: i32,
price: Option<f64>,
}
Again, the implementations will expect an exact match between the names of the Rust and Postgres
types and fields, which can be adjusted via the #[postgres(...)]
attribute:
CREATE TYPE inventory_item AS (
name TEXT,
supplier_id INT,
the_price DOUBLE PRECISION
);
#[derive(Debug, FromSql, ToSql)]
#[postgres(name = "inventory_item")]
struct InventoryItem {
name: String,
supplier_id: i32,
#[postgres(name = "the_price")]
price: Option<f64>,
}
Licensed under either of
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.