diff --git a/.travis.yml b/.travis.yml index 9d270009..ca95e871 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,13 +2,16 @@ language: rust env: global: - secure: Dl8GH7HCtwf0iG0EiBlQprZ5wQ7Wz8lfsMGxCSfTCjWoCbYK5+B5xuPnSaj8UYbrbXHmaZms23kSc5ZgQixuKs3zMCRDuEX1safT+t3AlhY/5/T3uyUWd1bv2Brw4TZg7M0Dubsu+3+3jNcDYv6vp+YWUNlKUcxjcX4EPrY0FKI= + matrix: + - FEATURES="" + - FEATURES="uuid_type" addons: postgresql: 9.3 before_script: - ./.travis/setup.sh script: - - cargo test - - cargo doc --no-deps + - cargo test --features "$FEATURES" + - cargo doc --no-deps --features "uuid_type" after_script: - mv target/doc . - curl http://www.rust-ci.org/artifacts/put?t=$RUSTCI_TOKEN | sh diff --git a/Cargo.toml b/Cargo.toml index 2c381a56..0a2ba673 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,9 @@ test = false name = "test" path = "tests/test.rs" +[features] +uuid_type = ["uuid"] + [dependencies.openssl] git = "https://github.com/sfackler/rust-openssl" @@ -21,5 +24,10 @@ git = "https://github.com/sfackler/rust-phf" [dependencies.phf_mac] git = "https://github.com/sfackler/rust-phf" +[dependencies.uuid] +git = "https://github.com/rust-lang/uuid" +optional = true + [dev-dependencies.url] git = "https://github.com/servo/rust-url" + diff --git a/src/types/mod.rs b/src/types/mod.rs index 5172740f..d4415717 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -1,6 +1,9 @@ //! Traits dealing with Postgres data types #![macro_escape] +#[cfg(feature = "uuid_type")] +extern crate uuid; + use serialize::json; use std::collections::HashMap; use std::io::{AsRefReader, MemWriter, BufReader}; @@ -49,6 +52,8 @@ const TIMESTAMPOID: Oid = 1114; const TIMESTAMPARRAYOID: Oid = 1115; const TIMESTAMPZOID: Oid = 1184; const TIMESTAMPZARRAYOID: Oid = 1185; +const UUIDOID: Oid = 2950; +const UUIDARRAYOID: Oid = 2951; const INT4RANGEOID: Oid = 3904; const INT4RANGEARRAYOID: Oid = 3905; const TSRANGEOID: Oid = 3908; @@ -175,6 +180,10 @@ make_postgres_type!( TIMESTAMPZOID => TimestampTZ, #[doc="TIMESTAMP WITH TIME ZONE[]"] TIMESTAMPZARRAYOID => TimestampTZArray member TimestampTZ, + #[doc="UUID"] + UUIDOID => Uuid, + #[doc="UUID[]"] + UUIDARRAYOID => UuidArray member Uuid, #[doc="CHAR(n)/CHARACTER(n)"] BPCHAROID => CharN, #[doc="VARCHAR/CHARACTER VARYING"] @@ -269,6 +278,16 @@ impl RawFromSql for Timespec { } } +#[cfg(feature = "uuid_type")] +impl RawFromSql for uuid::Uuid { + fn raw_from_sql(raw: &mut R) -> Result { + match uuid::Uuid::from_bytes(try_pg!(raw.read_to_end())[]) { + Some(u) => Ok(u), + None => Err(PgBadData), + } + } +} + macro_rules! from_range_impl( ($t:ty) => ( impl RawFromSql for Range<$t> { @@ -372,6 +391,8 @@ from_raw_from_impl!(Int4, i32) from_raw_from_impl!(Int8, i64) from_raw_from_impl!(Float4, f32) from_raw_from_impl!(Float8, f64) +#[cfg(feature = "uuid_type")] +from_raw_from_impl!(Uuid, uuid::Uuid) from_raw_from_impl!(Json, json::Json) from_raw_from_impl!(Timestamp | TimestampTZ, Timespec) @@ -422,6 +443,8 @@ from_array_impl!(Int4Array, i32) from_array_impl!(TextArray | CharNArray | VarcharArray | NameArray, String) from_array_impl!(Int8Array, i64) from_array_impl!(TimestampArray | TimestampTZArray, Timespec) +#[cfg(feature = "uuid_type")] +from_array_impl!(UuidArray, uuid::Uuid) from_array_impl!(JsonArray, json::Json) from_array_impl!(Float4Array, f32) from_array_impl!(Float8Array, f64) @@ -540,6 +563,13 @@ impl RawToSql for Timespec { } } +#[cfg(feature = "uuid_type")] +impl RawToSql for uuid::Uuid { + fn raw_to_sql(&self, w: &mut W) -> Result<()> { + Ok(try_pg!(w.write(self.as_bytes()))) + } +} + macro_rules! to_range_impl( ($t:ty) => ( impl RawToSql for Range<$t> { @@ -648,6 +678,8 @@ macro_rules! to_raw_to_impl( to_raw_to_impl!(Bool, bool) to_raw_to_impl!(ByteA, Vec) to_raw_to_impl!(Varchar | Text | CharN | Name, String) +#[cfg(feature = "uuid_type")] +to_raw_to_impl!(Uuid, uuid::Uuid) to_raw_to_impl!(Json, json::Json) to_raw_to_impl!(Char, i8) to_raw_to_impl!(Int2, i16) @@ -729,6 +761,8 @@ to_array_impl!(Float8Array, f64) to_array_impl!(Int4RangeArray, Range) to_array_impl!(TsRangeArray | TstzRangeArray, Range) to_array_impl!(Int8RangeArray, Range) +#[cfg(feature = "uuid_type")] +to_array_impl!(UuidArray, uuid::Uuid) to_array_impl!(JsonArray, json::Json) impl ToSql for HashMap> { diff --git a/tests/types/mod.rs b/tests/types/mod.rs index 062e46b8..57240f32 100644 --- a/tests/types/mod.rs +++ b/tests/types/mod.rs @@ -1,3 +1,6 @@ +#[cfg(feature = "uuid_type")] +extern crate uuid; + use serialize::json; use std::collections::HashMap; use std::f32; @@ -122,6 +125,15 @@ fn test_json_params() { (None, "NULL")]) } +#[test] +#[cfg(feature = "uuid_type")] +fn test_uuid_params() { + test_type("UUID", [(Some(uuid::Uuid::parse_str("a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11").unwrap()), + "'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11'"), + (None, "NULL")]) +} + + #[test] fn test_tm_params() { fn make_check<'a>(time: &'a str) -> (Option, &'a str) { @@ -290,6 +302,18 @@ fn test_int4rangearray_params() { range!('(', 10i32 ')'), "\"(,10)\""); } +#[test] +#[cfg(feature = "uuid_type")] +fn test_uuidarray_params() { + fn make_check<'a>(uuid: &'a str) -> (uuid::Uuid, &'a str) { + (uuid::Uuid::parse_str(uuid).unwrap(), uuid) + } + let (v1, s1) = make_check("a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11"); + let (v2, s2) = make_check("00000000-0000-0000-0000-000000000000"); + let (v3, s3) = make_check("a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11"); + test_array_params!("UUID", v1, s1, v2, s2, v3, s3); +} + #[test] fn test_tsrangearray_params() { fn make_check<'a>(time: &'a str) -> (Timespec, &'a str) {