| //! PostgreSQL specific types |
| |
| mod array; |
| #[doc(hidden)] |
| pub mod date_and_time; |
| #[doc(hidden)] |
| pub mod floats; |
| mod integers; |
| #[cfg(feature = "serde_json")] |
| mod json; |
| mod mac_addr; |
| #[doc(hidden)] |
| pub mod money; |
| #[cfg(feature = "network-address")] |
| mod network_address; |
| mod numeric; |
| mod primitives; |
| mod ranges; |
| mod record; |
| #[cfg(feature = "uuid")] |
| mod uuid; |
| |
| /// PostgreSQL specific SQL types |
| /// |
| /// Note: All types in this module can be accessed through `diesel::sql_types` |
| pub mod sql_types { |
| /// The `OID` SQL type. This is a PostgreSQL specific type. |
| /// |
| /// ### [`ToSql`] impls |
| /// |
| /// - [`u32`] |
| /// |
| /// ### [`FromSql`] impls |
| /// |
| /// - [`u32`] |
| /// |
| /// [`ToSql`]: ../../../serialize/trait.ToSql.html |
| /// [`FromSql`]: ../../../deserialize/trait.FromSql.html |
| /// [`u32`]: https://doc.rust-lang.org/nightly/std/primitive.u32.html |
| #[derive(Debug, Clone, Copy, Default, QueryId, SqlType)] |
| #[postgres(oid = "26", array_oid = "1018")] |
| pub struct Oid; |
| |
| /// The "timestamp with time zone" SQL type, which PostgreSQL abbreviates |
| /// to `timestamptz`. |
| /// |
| /// ### [`ToSql`] impls |
| /// |
| /// - [`PgTimestamp`] |
| /// - [`chrono::NaiveDateTime`] with `feature = "chrono"` |
| /// - [`chrono::DateTime`] with `feature = "chrono"` |
| /// |
| /// ### [`FromSql`] impls |
| /// |
| /// - [`PgTimestamp`] |
| /// - [`chrono::NaiveDateTime`] with `feature = "chrono"` |
| /// - [`chrono::DateTime`] with `feature = "chrono"` |
| /// |
| /// [`ToSql`]: ../../../serialize/trait.ToSql.html |
| /// [`FromSql`]: ../../../deserialize/trait.FromSql.html |
| /// [`PgTimestamp`]: ../../data_types/struct.PgTimestamp.html |
| /// [`chrono::NaiveDateTime`]: ../../../../chrono/naive/struct.NaiveDateTime.html |
| /// [`chrono::DateTime`]: ../../../../chrono/struct.DateTime.html |
| #[derive(Debug, Clone, Copy, Default, QueryId, SqlType)] |
| #[postgres(oid = "1184", array_oid = "1185")] |
| pub struct Timestamptz; |
| |
| /// The `Array` SQL type. |
| /// |
| /// This wraps another type to represent a SQL array of that type. |
| /// Multidimensional arrays are not supported, |
| /// nor are arrays containing null. |
| /// |
| /// ### [`ToSql`] impls |
| /// |
| /// - [`Vec<T>`][Vec] for any `T` which implements `ToSql<ST>` |
| /// - [`&[T]`][slice] for any `T` which implements `ToSql<ST>` |
| /// |
| /// ### [`FromSql`] impls |
| /// |
| /// - [`Vec<T>`][Vec] for any `T` which implements `ToSql<ST>` |
| /// |
| /// [`ToSql`]: ../../../serialize/trait.ToSql.html |
| /// [`FromSql`]: ../../../deserialize/trait.FromSql.html |
| /// [Vec]: https://doc.rust-lang.org/nightly/std/vec/struct.Vec.html |
| /// [slice]: https://doc.rust-lang.org/nightly/std/primitive.slice.html |
| #[derive(Debug, Clone, Copy, Default, QueryId, SqlType)] |
| pub struct Array<ST>(ST); |
| |
| /// The `Range` SQL type. |
| /// |
| /// This wraps another type to represent a SQL range of that type. |
| /// |
| /// ### [`ToSql`] impls |
| /// |
| /// - [`(Bound<T>, Bound<T>)`][bound] for any `T` which implements `ToSql<ST>`. |
| /// |
| /// ### [`FromSql`] impls |
| /// |
| /// - [`(Bound<T>, Bound<T>)`][bound] for any `T` which implements `FromSql<ST>`. |
| /// |
| /// [`ToSql`]: ../../../serialize/trait.ToSql.html |
| /// [`FromSql`]: ../../../deserialize/trait.FromSql.html |
| /// [bound]: https://doc.rust-lang.org/std/collections/enum.Bound.html |
| #[derive(Debug, Clone, Copy, Default, QueryId, SqlType)] |
| pub struct Range<ST>(ST); |
| |
| #[doc(hidden)] |
| pub type Int4range = Range<crate::sql_types::Int4>; |
| #[doc(hidden)] |
| pub type Int8range = Range<crate::sql_types::Int8>; |
| #[doc(hidden)] |
| pub type Daterange = Range<crate::sql_types::Date>; |
| #[doc(hidden)] |
| pub type Numrange = Range<crate::sql_types::Numeric>; |
| #[doc(hidden)] |
| pub type Tsrange = Range<crate::sql_types::Timestamp>; |
| #[doc(hidden)] |
| pub type Tstzrange = Range<crate::sql_types::Timestamptz>; |
| |
| /// The `Record` (a.k.a. tuple) SQL type. |
| /// |
| /// ### [`ToSql`] impls |
| /// |
| /// - Any tuple which can be serialized to each of the elements |
| /// (note: There are major caveats, see the section below) |
| /// |
| /// ### [`FromSql`] impls |
| /// |
| /// - Any tuple which can be deserialized from each of the elements. |
| /// |
| /// [`ToSql`]: ../../../serialize/trait.ToSql.html |
| /// [`FromSql`]: ../../../deserialize/trait.FromSql.html |
| /// |
| /// ### Caveats about serialization |
| /// |
| /// Typically in the documentation for SQL types, we use "`FromSql` impls" |
| /// as a shorthand for "Rust types that you can use to represent this type". |
| /// For every other type, that means there is specifically an implementation |
| /// of the `FromSql` trait. |
| /// |
| /// However, PostgreSQL does not support transmission of anonymous record |
| /// types as bind parameters. It only supports transmission for named |
| /// composite types. For this reason, if you tried to do |
| /// `int_tuple_col.eq((1, 2))`, we will generate the SQL `int_tuple_col = |
| /// ($1, $2)` rather than `int_tuple_col = $1` as we would for anything |
| /// else. |
| /// |
| /// This should not be visible during normal usage. The only time this would |
| /// affect you is if you were attempting to use `sql_query` with tuples. |
| /// Your code would not compile in that case, as the `ToSql` trait itself is |
| /// not implemented. |
| /// |
| /// You can implement `ToSql` for named composite types. See [`WriteTuple`] |
| /// for details. |
| /// |
| /// [`WriteTuple`]: ../../../serialize/trait.WriteTuple.html |
| #[derive(Debug, Clone, Copy, Default, QueryId, SqlType)] |
| #[postgres(oid = "2249", array_oid = "2287")] |
| pub struct Record<ST>(ST); |
| |
| /// Alias for `SmallInt` |
| pub type SmallSerial = crate::sql_types::SmallInt; |
| |
| /// Alias for `Integer` |
| pub type Serial = crate::sql_types::Integer; |
| |
| /// Alias for `BigInt` |
| pub type BigSerial = crate::sql_types::BigInt; |
| |
| /// The `UUID` SQL type. This type can only be used with `feature = "uuid"` |
| /// (uuid <=0.6) or `feature = "uuidv07"` (uuid = 0.7) |
| /// |
| /// ### [`ToSql`] impls |
| /// |
| /// - [`uuid::Uuid`][Uuid] |
| /// |
| /// ### [`FromSql`] impls |
| /// |
| /// - [`uuid::Uuid`][Uuid] |
| /// |
| /// [`ToSql`]: ../../../serialize/trait.ToSql.html |
| /// [`FromSql`]: ../../../deserialize/trait.FromSql.html |
| /// [Uuid]: https://doc.rust-lang.org/uuid/uuid/struct.Uuid.html |
| #[derive(Debug, Clone, Copy, Default, QueryId, SqlType)] |
| #[postgres(oid = "2950", array_oid = "2951")] |
| pub struct Uuid; |
| |
| /// Alias for `Binary`, to ensure `infer_schema!` works |
| #[doc(hidden)] |
| pub type Bytea = crate::sql_types::Binary; |
| |
| #[doc(hidden)] |
| pub type Bpchar = crate::sql_types::VarChar; |
| |
| /// The JSON SQL type. This type can only be used with `feature = |
| /// "serde_json"` |
| /// |
| /// Normally you should prefer [`Jsonb`](struct.Jsonb.html) instead, for the reasons |
| /// discussed there. |
| /// |
| /// ### [`ToSql`] impls |
| /// |
| /// - [`serde_json::Value`] |
| /// |
| /// ### [`FromSql`] impls |
| /// |
| /// - [`serde_json::Value`] |
| /// |
| /// [`ToSql`]: ../../../serialize/trait.ToSql.html |
| /// [`FromSql`]: ../../../deserialize/trait.FromSql.html |
| /// [`serde_json::Value`]: ../../../../serde_json/value/enum.Value.html |
| #[derive(Debug, Clone, Copy, Default, QueryId, SqlType)] |
| #[postgres(oid = "114", array_oid = "199")] |
| pub struct Json; |
| |
| /// The `jsonb` SQL type. This type can only be used with `feature = |
| /// "serde_json"` |
| /// |
| /// `jsonb` offers [several advantages][adv] over regular JSON: |
| /// |
| /// > There are two JSON data types: `json` and `jsonb`. They accept almost |
| /// > identical sets of values as input. The major practical difference |
| /// > is one of efficiency. The `json` data type stores an exact copy of |
| /// > the input text, which processing functions must reparse on each |
| /// > execution; while `jsonb` data is stored in a decomposed binary format |
| /// > that makes it slightly slower to input due to added conversion |
| /// > overhead, but significantly faster to process, since no reparsing |
| /// > is needed. `jsonb` also supports indexing, which can be a significant |
| /// > advantage. |
| /// > |
| /// > ...In general, most applications should prefer to store JSON data as |
| /// > `jsonb`, unless there are quite specialized needs, such as legacy |
| /// > assumptions about ordering of object keys. |
| /// |
| /// [adv]: https://www.postgresql.org/docs/9.6/static/datatype-json.html |
| /// |
| /// ### [`ToSql`] impls |
| /// |
| /// - [`serde_json::Value`] |
| /// |
| /// ### [`FromSql`] impls |
| /// |
| /// - [`serde_json::Value`] |
| /// |
| /// [`ToSql`]: ../../../serialize/trait.ToSql.html |
| /// [`FromSql`]: ../../../deserialize/trait.FromSql.html |
| /// [`serde_json::Value`]: ../../../../serde_json/value/enum.Value.html |
| /// |
| /// # Examples |
| /// |
| /// ```rust |
| /// # #![allow(dead_code)] |
| /// # #[macro_use] extern crate diesel; |
| /// # include!("../../doctest_setup.rs"); |
| /// # |
| /// table! { |
| /// contacts { |
| /// id -> Integer, |
| /// name -> VarChar, |
| /// address -> Jsonb, |
| /// } |
| /// } |
| /// |
| /// # #[cfg(feature = "serde_json")] |
| /// # fn main() -> Result<(), Box<dyn std::error::Error>> { |
| /// # use diesel::insert_into; |
| /// # use self::contacts::dsl::*; |
| /// # let connection = connection_no_data(); |
| /// # diesel::sql_query("CREATE TABLE contacts ( |
| /// # id SERIAL PRIMARY KEY, |
| /// # name VARCHAR NOT NULL, |
| /// # address JSONB NOT NULL |
| /// # )").execute(&connection)?; |
| /// let santas_address: serde_json::Value = serde_json::from_str(r#"{ |
| /// "street": "Article Circle Expressway 1", |
| /// "city": "North Pole", |
| /// "postcode": "99705", |
| /// "state": "Alaska" |
| /// }"#)?; |
| /// let inserted_address = insert_into(contacts) |
| /// .values((name.eq("Claus"), address.eq(&santas_address))) |
| /// .returning(address) |
| /// .get_result::<serde_json::Value>(&connection)?; |
| /// assert_eq!(santas_address, inserted_address); |
| /// # Ok(()) |
| /// # } |
| /// # #[cfg(not(feature = "serde_json"))] |
| /// # fn main() {} |
| /// ``` |
| #[derive(Debug, Clone, Copy, Default, QueryId, SqlType)] |
| #[postgres(oid = "3802", array_oid = "3807")] |
| pub struct Jsonb; |
| |
| /// The PostgreSQL [Money](https://www.postgresql.org/docs/9.1/static/datatype-money.html) type. |
| /// |
| /// ### [`ToSql`] impls |
| /// |
| /// - [`Cents` (also aliased as `PgMoney`)][PgMoney] |
| /// |
| /// ### [`FromSql`] impls |
| /// |
| /// - [`Cents` (also aliased as `PgMoney`)][PgMoney] |
| /// |
| /// [`ToSql`]: ../../../serialize/trait.ToSql.html |
| /// [`FromSql`]: ../../../deserialize/trait.FromSql.html |
| /// [PgMoney]: ../../data_types/struct.PgMoney.html |
| /// |
| /// # Examples |
| /// |
| /// ```rust |
| /// # #[macro_use] extern crate diesel; |
| /// # include!("../../doctest_setup.rs"); |
| /// use diesel::data_types::Cents; |
| /// |
| /// table! { |
| /// items { |
| /// id -> Integer, |
| /// name -> VarChar, |
| /// price -> Money, |
| /// } |
| /// } |
| /// |
| /// # fn main() { |
| /// # use diesel::insert_into; |
| /// # use self::items::dsl::*; |
| /// # let connection = connection_no_data(); |
| /// # connection.execute("CREATE TABLE items ( |
| /// # id SERIAL PRIMARY KEY, |
| /// # name VARCHAR NOT NULL, |
| /// # price MONEY NOT NULL |
| /// # )").unwrap(); |
| /// let inserted_price = insert_into(items) |
| /// .values((name.eq("Shiny Thing"), price.eq(Cents(123_456)))) |
| /// .returning(price) |
| /// .get_result(&connection); |
| /// assert_eq!(Ok(Cents(123_456)), inserted_price); |
| /// # } |
| /// ``` |
| #[derive(Debug, Clone, Copy, Default, QueryId, SqlType)] |
| #[postgres(oid = "790", array_oid = "791")] |
| pub struct Money; |
| |
| /// The [`MACADDR`](https://www.postgresql.org/docs/9.6/static/datatype-net-types.html) SQL type. |
| /// |
| /// ### [`ToSql`] impls |
| /// |
| /// - `[u8; 6]` |
| /// |
| /// ### [`FromSql`] impls |
| /// |
| /// - `[u8; 6]` |
| /// |
| /// [`ToSql`]: ../../../serialize/trait.ToSql.html |
| /// [`FromSql`]: ../../../deserialize/trait.FromSql.html |
| /// |
| /// # Examples |
| /// |
| /// ```rust |
| /// # #[macro_use] extern crate diesel; |
| /// # include!("../../doctest_setup.rs"); |
| /// table! { |
| /// devices { |
| /// id -> Integer, |
| /// macaddr -> MacAddr, |
| /// } |
| /// } |
| /// |
| /// # fn main() -> Result<(), Box<dyn std::error::Error>> { |
| /// # use diesel::insert_into; |
| /// # use self::devices::dsl::*; |
| /// # let connection = connection_no_data(); |
| /// # diesel::sql_query("CREATE TABLE devices ( |
| /// # id SERIAL PRIMARY KEY, |
| /// # macaddr MACADDR NOT NULL |
| /// # )").execute(&connection)?; |
| /// let inserted_macaddr = insert_into(devices) |
| /// .values(macaddr.eq([0x08, 0x00, 0x2b, 0x01, 0x02, 0x03])) |
| /// .returning(macaddr) |
| /// .get_result::<[u8; 6]>(&connection)?; |
| /// assert_eq!([0x08, 0x00, 0x2b, 0x01, 0x02, 0x03], inserted_macaddr); |
| /// # Ok(()) |
| /// # } |
| /// ``` |
| #[derive(Debug, Clone, Copy, Default, QueryId, SqlType)] |
| #[postgres(oid = "829", array_oid = "1040")] |
| pub struct MacAddr; |
| |
| #[doc(hidden)] |
| /// Alias for `MacAddr` to be able to use it with `infer_schema`. |
| pub type Macaddr = MacAddr; |
| |
| /// The [`INET`](https://www.postgresql.org/docs/9.6/static/datatype-net-types.html) SQL type. This type can only be used with `feature = "network-address"` |
| /// |
| /// ### [`ToSql`] impls |
| /// |
| /// - [`ipnetwork::IpNetwork`][IpNetwork] |
| /// |
| /// ### [`FromSql`] impls |
| /// |
| /// - [`ipnetwork::IpNetwork`][IpNetwork] |
| /// |
| /// [`ToSql`]: ../../../serialize/trait.ToSql.html |
| /// [`FromSql`]: ../../../deserialize/trait.FromSql.html |
| /// [IpNetwork]: ../../../../ipnetwork/enum.IpNetwork.html |
| /// |
| /// # Examples |
| /// |
| /// ```rust |
| /// # #[macro_use] extern crate diesel; |
| /// # include!("../../doctest_setup.rs"); |
| /// # |
| /// table! { |
| /// clients { |
| /// id -> Integer, |
| /// ip_address -> Inet, |
| /// } |
| /// } |
| /// |
| /// # #[cfg(feature = "network-address")] |
| /// # fn main() -> Result<(), Box<dyn std::error::Error>> { |
| /// use ipnetwork::IpNetwork; |
| /// |
| /// # use diesel::insert_into; |
| /// # use self::clients::dsl::*; |
| /// # let connection = connection_no_data(); |
| /// # diesel::sql_query("CREATE TABLE clients ( |
| /// # id SERIAL PRIMARY KEY, |
| /// # ip_address INET NOT NULL |
| /// # )").execute(&connection)?; |
| /// let addr = "10.1.9.32/32".parse::<IpNetwork>()?; |
| /// let inserted_address = insert_into(clients) |
| /// .values(ip_address.eq(&addr)) |
| /// .returning(ip_address) |
| /// .get_result(&connection)?; |
| /// assert_eq!(addr, inserted_address); |
| /// # Ok(()) |
| /// # } |
| /// # |
| /// # #[cfg(not(feature = "network-address"))] |
| /// # fn main() {} |
| /// ``` |
| #[derive(Debug, Clone, Copy, Default, QueryId, SqlType)] |
| #[postgres(oid = "869", array_oid = "1041")] |
| pub struct Inet; |
| |
| /// The [`CIDR`](https://www.postgresql.org/docs/9.6/static/datatype-net-types.html) SQL type. This type can only be used with `feature = "network-address"` |
| /// |
| /// ### [`ToSql`] impls |
| /// |
| /// - [`ipnetwork::IpNetwork`][IpNetwork] |
| /// |
| /// ### [`FromSql`] impls |
| /// |
| /// - [`ipnetwork::IpNetwork`][IpNetwork] |
| /// |
| /// [`ToSql`]: ../../../serialize/trait.ToSql.html |
| /// [`FromSql`]: ../../../deserialize/trait.FromSql.html |
| /// [IpNetwork]: ../../../../ipnetwork/enum.IpNetwork.html |
| /// |
| /// # Examples |
| /// |
| /// ```rust |
| /// # #![allow(dead_code)] |
| /// # #[macro_use] extern crate diesel; |
| /// # include!("../../doctest_setup.rs"); |
| /// table! { |
| /// clients { |
| /// id -> Integer, |
| /// ip_address -> Cidr, |
| /// } |
| /// } |
| /// |
| /// # #[cfg(feature = "network-address")] |
| /// # fn main() -> Result<(), Box<dyn std::error::Error>> { |
| /// use ipnetwork::IpNetwork; |
| /// |
| /// # use diesel::insert_into; |
| /// # use self::clients::dsl::*; |
| /// # let connection = connection_no_data(); |
| /// # diesel::sql_query("CREATE TABLE clients ( |
| /// # id SERIAL PRIMARY KEY, |
| /// # ip_address CIDR NOT NULL |
| /// # )").execute(&connection)?; |
| /// let addr = "10.1.9.32/32".parse::<IpNetwork>()?; |
| /// let inserted_addr = insert_into(clients) |
| /// .values(ip_address.eq(&addr)) |
| /// .returning(ip_address) |
| /// .get_result(&connection)?; |
| /// assert_eq!(addr, inserted_addr); |
| /// # Ok(()) |
| /// # } |
| /// # #[cfg(not(feature = "network-address"))] |
| /// # fn main() {} |
| /// ``` |
| #[derive(Debug, Clone, Copy, Default, QueryId, SqlType)] |
| #[postgres(oid = "650", array_oid = "651")] |
| pub struct Cidr; |
| } |
| |
| mod ops { |
| use super::sql_types::*; |
| use crate::sql_types::ops::*; |
| use crate::sql_types::Interval; |
| |
| impl Add for Timestamptz { |
| type Rhs = Interval; |
| type Output = Timestamptz; |
| } |
| |
| impl Sub for Timestamptz { |
| type Rhs = Interval; |
| type Output = Timestamptz; |
| } |
| } |