extern crate time_ as time; use std::ops::Bound; use sqlx::postgres::types::{Oid, PgInterval, PgMoney, PgRange}; use sqlx::postgres::Postgres; use sqlx_test::{test_decode_type, test_prepared_type, test_type}; use std::str::FromStr; test_type!(null>(Postgres, "NULL::int2" == None:: )); test_type!(null_vec>>(Postgres, "array[10,NULL,50]::int2[]" == vec![Some(10_i16), None, Some(50)], )); test_type!(null_array<[Option; 3]>(Postgres, "array[10,NULL,50]::int2[]" == vec![Some(10_i16), None, Some(50)], )); test_type!(bool(Postgres, "false::boolean" == false, "true::boolean" == true )); test_type!(bool_vec>(Postgres, "array[true,false,true]::bool[]" == vec![true, false, true], )); test_type!(bool_array<[bool; 3]>(Postgres, "array[true,false,true]::bool[]" == vec![true, false, true], )); test_type!(byte_vec>(Postgres, "E'\\\\xDEADBEEF'::bytea" == vec![0xDE_u8, 0xAD, 0xBE, 0xEF], "E'\\\\x'::bytea" == Vec::::new(), "E'\\\\x0000000052'::bytea" == vec![0_u8, 0, 0, 0, 0x52] )); // BYTEA cannot be decoded by-reference from a simple query as postgres sends it as hex test_prepared_type!(byte_slice<&[u8]>(Postgres, "E'\\\\xDEADBEEF'::bytea" == &[0xDE_u8, 0xAD, 0xBE, 0xEF][..], "E'\\\\x0000000052'::bytea" == &[0_u8, 0, 0, 0, 0x52][..] )); test_type!(byte_array_empty<[u8; 0]>(Postgres, "E'\\\\x'::bytea" == [0_u8; 0], )); test_type!(byte_array<[u8; 4]>(Postgres, "E'\\\\xDEADBEEF'::bytea" == [0xDE_u8, 0xAD, 0xBE, 0xEF], )); test_type!(str<&str>(Postgres, "'this is foo'" == "this is foo", "''" == "", "'identifier'::name" == "identifier", "'five'::char(4)" == "five", "'more text'::varchar" == "more text", )); test_type!(string(Postgres, "'this is foo'" == format!("this is foo"), )); test_type!(string_vec>(Postgres, "array['one','two','three']::text[]" == vec!["one","two","three"], "array['', '\"']::text[]" == vec!["", "\""], "array['Hello, World', '', 'Goodbye']::text[]" == vec!["Hello, World", "", "Goodbye"] )); test_type!(string_array<[String; 3]>(Postgres, "array['one','two','three']::text[]" == ["one","two","three"], )); test_type!(i8( Postgres, "0::\"char\"" == 0_i8, "120::\"char\"" == 120_i8, )); test_type!(Oid(Postgres, "325235::oid" == Oid(325235),)); test_type!(i16( Postgres, "-2144::smallint" == -2144_i16, "821::smallint" == 821_i16, )); test_type!(i32( Postgres, "94101::int" == 94101_i32, "-5101::int" == -5101_i32 )); test_type!(i32_vec>(Postgres, "'{5,10,50,100}'::int[]" == vec![5_i32, 10, 50, 100], "'{1050}'::int[]" == vec![1050_i32], "'{}'::int[]" == Vec::::new(), "'{1,3,-5}'::int[]" == vec![1_i32, 3, -5] )); test_type!(i32_array_empty<[i32; 0]>(Postgres, "'{}'::int[]" == [0_i32; 0], )); test_type!(i32_array<[i32; 4]>(Postgres, "'{5,10,50,100}'::int[]" == [5_i32, 10, 50, 100], )); test_type!(i64(Postgres, "9358295312::bigint" == 9358295312_i64)); test_type!(f32(Postgres, "9419.122::real" == 9419.122_f32)); test_type!(f64( Postgres, "939399419.1225182::double precision" == 939399419.1225182_f64 )); test_type!(f64_vec>(Postgres, "'{939399419.1225182,-12.0}'::float8[]" == vec![939399419.1225182_f64, -12.0] )); test_decode_type!(bool_tuple<(bool,)>(Postgres, "row(true)" == (true,))); test_decode_type!(num_tuple<(i32, i64, f64,)>(Postgres, "row(10,515::int8,3.124::float8)" == (10,515,3.124))); test_decode_type!(empty_tuple<()>(Postgres, "row()" == ())); test_decode_type!(string_tuple<(String, String, String)>(Postgres, "row('one','two','three')" == ("one".to_string(), "two".to_string(), "three".to_string()), "row('', '\"', '\"\"\"\"\"\"')" == ("".to_string(), "\"".to_string(), "\"\"\"\"\"\"".to_string()), "row('Hello, World', '', 'Goodbye')" == ("Hello, World".to_string(), "".to_string(), "Goodbye".to_string()) )); #[cfg(feature = "uuid")] test_type!(uuid(Postgres, "'b731678f-636f-4135-bc6f-19440c13bd19'::uuid" == sqlx::types::Uuid::parse_str("b731678f-636f-4135-bc6f-19440c13bd19").unwrap(), "'00000000-0000-0000-0000-000000000000'::uuid" == sqlx::types::Uuid::parse_str("00000000-0000-0000-0000-000000000000").unwrap() )); #[cfg(feature = "uuid")] test_type!(uuid_vec>(Postgres, "'{b731678f-636f-4135-bc6f-19440c13bd19,00000000-0000-0000-0000-000000000000}'::uuid[]" == vec![ sqlx::types::Uuid::parse_str("b731678f-636f-4135-bc6f-19440c13bd19").unwrap(), sqlx::types::Uuid::parse_str("00000000-0000-0000-0000-000000000000").unwrap() ] )); #[cfg(feature = "ipnetwork")] test_type!(ipnetwork(Postgres, "'127.0.0.1'::inet" == "127.0.0.1" .parse::() .unwrap(), "'8.8.8.8/24'::inet" == "8.8.8.8/24" .parse::() .unwrap(), "'::ffff:1.2.3.0'::inet" == "::ffff:1.2.3.0" .parse::() .unwrap(), "'2001:4f8:3:ba::/64'::inet" == "2001:4f8:3:ba::/64" .parse::() .unwrap(), "'192.168'::cidr" == "192.168.0.0/24" .parse::() .unwrap(), "'::ffff:1.2.3.0/120'::cidr" == "::ffff:1.2.3.0/120" .parse::() .unwrap(), )); #[cfg(feature = "mac_address")] test_type!(mac_address(Postgres, "'00:01:02:03:04:05'::macaddr" == "00:01:02:03:04:05" .parse::() .unwrap() )); #[cfg(feature = "bit-vec")] test_type!(bitvec( Postgres, // A full byte VARBIT "B'01101001'" == sqlx::types::BitVec::from_bytes(&[0b0110_1001]), // A VARBIT value missing five bits from a byte "B'110'" == { let mut bit_vec = sqlx::types::BitVec::with_capacity(4); bit_vec.push(true); bit_vec.push(true); bit_vec.push(false); bit_vec }, // A BIT value "B'01101'::bit(5)" == { let mut bit_vec = sqlx::types::BitVec::with_capacity(5); bit_vec.push(false); bit_vec.push(true); bit_vec.push(true); bit_vec.push(false); bit_vec.push(true); bit_vec }, )); #[cfg(feature = "ipnetwork")] test_type!(ipnetwork_vec>(Postgres, "'{127.0.0.1,8.8.8.8/24}'::inet[]" == vec![ "127.0.0.1".parse::().unwrap(), "8.8.8.8/24".parse::().unwrap() ] )); #[cfg(feature = "mac_address")] test_type!(mac_address_vec>(Postgres, "'{01:02:03:04:05:06,FF:FF:FF:FF:FF:FF}'::macaddr[]" == vec![ "01:02:03:04:05:06".parse::().unwrap(), "FF:FF:FF:FF:FF:FF".parse::().unwrap() ] )); #[cfg(feature = "chrono")] mod chrono { use super::*; use sqlx::types::chrono::{ DateTime, FixedOffset, NaiveDate, NaiveDateTime, NaiveTime, TimeZone, Utc, }; type PgTimeTz = sqlx::postgres::types::PgTimeTz; test_type!(chrono_date(Postgres, "DATE '2001-01-05'" == NaiveDate::from_ymd(2001, 1, 5), "DATE '2050-11-23'" == NaiveDate::from_ymd(2050, 11, 23) )); test_type!(chrono_time(Postgres, "TIME '05:10:20.115100'" == NaiveTime::from_hms_micro(5, 10, 20, 115100) )); test_type!(chrono_date_time(Postgres, "'2019-01-02 05:10:20'::timestamp" == NaiveDate::from_ymd(2019, 1, 2).and_hms(5, 10, 20) )); test_type!(chrono_date_time_vec>(Postgres, "array['2019-01-02 05:10:20']::timestamp[]" == vec![NaiveDate::from_ymd(2019, 1, 2).and_hms(5, 10, 20)] )); test_type!(chrono_date_time_tz_utc>(Postgres, "TIMESTAMPTZ '2019-01-02 05:10:20.115100'" == DateTime::::from_utc( NaiveDate::from_ymd(2019, 1, 2).and_hms_micro(5, 10, 20, 115100), Utc, ) )); test_type!(chrono_date_time_tz>(Postgres, "TIMESTAMPTZ '2019-01-02 05:10:20.115100+06:30'" == FixedOffset::east(60 * 60 * 6 + 1800).ymd(2019, 1, 2).and_hms_micro(5, 10, 20, 115100) )); test_type!(chrono_date_time_tz_vec>>(Postgres, "array['2019-01-02 05:10:20.115100']::timestamptz[]" == vec![ DateTime::::from_utc( NaiveDate::from_ymd(2019, 1, 2).and_hms_micro(5, 10, 20, 115100), Utc, ) ] )); test_type!(chrono_time_tz(Postgres, "TIMETZ '05:10:20.115100+00'" == PgTimeTz { time: NaiveTime::from_hms_micro(5, 10, 20, 115100), offset: FixedOffset::east(0) }, "TIMETZ '05:10:20.115100+06:30'" == PgTimeTz { time: NaiveTime::from_hms_micro(5, 10, 20, 115100), offset: FixedOffset::east(60 * 60 * 6 + 1800) }, "TIMETZ '05:10:20.115100-05'" == PgTimeTz { time: NaiveTime::from_hms_micro(5, 10, 20, 115100), offset: FixedOffset::west(60 * 60 * 5) }, "TIMETZ '05:10:20+02'" == PgTimeTz { time: NaiveTime::from_hms(5, 10, 20), offset: FixedOffset::east(60 * 60 * 2 )} )); } #[cfg(feature = "time")] mod time_tests { use super::*; use sqlx::types::time::{Date, OffsetDateTime, PrimitiveDateTime, Time, UtcOffset}; use time::macros::{date, time}; type PgTimeTz = sqlx::postgres::types::PgTimeTz; test_type!(time_date( Postgres, "DATE '2001-01-05'" == date!(2001 - 1 - 5), "DATE '2050-11-23'" == date!(2050 - 11 - 23) )); test_type!(time_time