diesel/pg/types/
mod.rs

1//! PostgreSQL specific types
2
3mod array;
4#[doc(hidden)]
5pub mod date_and_time;
6#[doc(hidden)]
7pub mod floats;
8mod integers;
9#[cfg(feature = "serde_json")]
10mod json;
11#[doc(hidden)]
12pub mod money;
13#[cfg(feature = "network-address")]
14mod network_address;
15mod numeric;
16mod primitives;
17mod ranges;
18mod record;
19#[cfg(feature = "uuid")]
20mod uuid;
21#[cfg(feature = "uuidv07")]
22mod uuid_v0_7;
23
24/// PostgreSQL specific SQL types
25///
26/// Note: All types in this module can be accessed through `diesel::sql_types`
27pub mod sql_types {
28    /// The `OID` SQL type. This is a PostgreSQL specific type.
29    ///
30    /// ### [`ToSql`] impls
31    ///
32    /// - [`u32`]
33    ///
34    /// ### [`FromSql`] impls
35    ///
36    /// - [`u32`]
37    ///
38    /// [`ToSql`]: ../../../serialize/trait.ToSql.html
39    /// [`FromSql`]: ../../../deserialize/trait.FromSql.html
40    /// [`u32`]: https://doc.rust-lang.org/nightly/std/primitive.u32.html
41    #[derive(Debug, Clone, Copy, Default, QueryId, SqlType)]
42    #[postgres(oid = "26", array_oid = "1018")]
43    pub struct Oid;
44
45    /// The "timestamp with time zone" SQL type, which PostgreSQL abbreviates
46    /// to `timestamptz`.
47    ///
48    /// ### [`ToSql`] impls
49    ///
50    /// - [`PgTimestamp`]
51    /// - [`chrono::NaiveDateTime`] with `feature = "chrono"`
52    /// - [`chrono::DateTime`] with `feature = "chrono"`
53    ///
54    /// ### [`FromSql`] impls
55    ///
56    /// - [`PgTimestamp`]
57    /// - [`chrono::NaiveDateTime`] with `feature = "chrono"`
58    /// - [`chrono::DateTime`] with `feature = "chrono"`
59    ///
60    /// [`ToSql`]: ../../../serialize/trait.ToSql.html
61    /// [`FromSql`]: ../../../deserialize/trait.FromSql.html
62    /// [`PgTimestamp`]: ../../data_types/struct.PgTimestamp.html
63    /// [`chrono::NaiveDateTime`]: ../../../../chrono/naive/struct.NaiveDateTime.html
64    /// [`chrono::DateTime`]: ../../../../chrono/struct.DateTime.html
65    #[derive(Debug, Clone, Copy, Default, QueryId, SqlType)]
66    #[postgres(oid = "1184", array_oid = "1185")]
67    pub struct Timestamptz;
68
69    /// The `Array` SQL type.
70    ///
71    /// This wraps another type to represent a SQL array of that type.
72    /// Multidimensional arrays are not supported,
73    /// nor are arrays containing null.
74    ///
75    /// ### [`ToSql`] impls
76    ///
77    /// - [`Vec<T>`][Vec] for any `T` which implements `ToSql<ST>`
78    /// - [`&[T]`][slice] for any `T` which implements `ToSql<ST>`
79    ///
80    /// ### [`FromSql`] impls
81    ///
82    /// - [`Vec<T>`][Vec] for any `T` which implements `ToSql<ST>`
83    ///
84    /// [`ToSql`]: ../../../serialize/trait.ToSql.html
85    /// [`FromSql`]: ../../../deserialize/trait.FromSql.html
86    /// [Vec]: https://doc.rust-lang.org/nightly/std/vec/struct.Vec.html
87    /// [slice]: https://doc.rust-lang.org/nightly/std/primitive.slice.html
88    #[derive(Debug, Clone, Copy, Default, QueryId, SqlType)]
89    pub struct Array<ST>(ST);
90
91    /// The `Range` SQL type.
92    ///
93    /// This wraps another type to represent a SQL range of that type.
94    ///
95    /// ### [`ToSql`] impls
96    ///
97    /// - [`(Bound<T>, Bound<T>)`][bound] for any `T` which implements `ToSql<ST>`.
98    ///
99    /// ### [`FromSql`] impls
100    ///
101    /// - [`(Bound<T>, Bound<T>)`][bound] for any `T` which implements `FromSql<ST>`.
102    ///
103    /// [`ToSql`]: ../../../serialize/trait.ToSql.html
104    /// [`FromSql`]: ../../../deserialize/trait.FromSql.html
105    /// [bound]: https://doc.rust-lang.org/std/collections/enum.Bound.html
106    #[derive(Debug, Clone, Copy, Default, QueryId, SqlType)]
107    pub struct Range<ST>(ST);
108
109    #[doc(hidden)]
110    pub type Int4range = Range<::sql_types::Int4>;
111    #[doc(hidden)]
112    pub type Int8range = Range<::sql_types::Int8>;
113    #[doc(hidden)]
114    pub type Daterange = Range<::sql_types::Date>;
115    #[doc(hidden)]
116    pub type Numrange = Range<::sql_types::Numeric>;
117    #[doc(hidden)]
118    pub type Tsrange = Range<::sql_types::Timestamp>;
119    #[doc(hidden)]
120    pub type Tstzrange = Range<::sql_types::Timestamptz>;
121
122    /// The `Record` (a.k.a. tuple) SQL type.
123    ///
124    /// ### [`ToSql`] impls
125    ///
126    /// - Any tuple which can be serialized to each of the elements
127    ///   (note: There are major caveats, see the section below)
128    ///
129    /// ### [`FromSql`] impls
130    ///
131    /// - Any tuple which can be deserialized from each of the elements.
132    ///
133    /// [`ToSql`]: ../../../serialize/trait.ToSql.html
134    /// [`FromSql`]: ../../../deserialize/trait.FromSql.html
135    ///
136    /// ### Caveats about serialization
137    ///
138    /// Typically in the documentation for SQL types, we use "`FromSql` impls"
139    /// as a shorthand for "Rust types that you can use to represent this type".
140    /// For every other type, that means there is specifically an implementation
141    /// of the `FromSql` trait.
142    ///
143    /// However, PostgreSQL does not support transmission of anonymous record
144    /// types as bind parameters. It only supports transmission for named
145    /// composite types. For this reason, if you tried to do
146    /// `int_tuple_col.eq((1, 2))`, we will generate the SQL `int_tuple_col =
147    /// ($1, $2)` rather than `int_tuple_col = $1` as we would for anything
148    /// else.
149    ///
150    /// This should not be visible during normal usage. The only time this would
151    /// affect you is if you were attempting to use `sql_query` with tuples.
152    /// Your code would not compile in that case, as the `ToSql` trait itself is
153    /// not implemented.
154    ///
155    /// You can implement `ToSql` for named composite types. See [`WriteTuple`]
156    /// for details.
157    ///
158    /// [`WriteTuple`]: ../../../serialize/trait.WriteTuple.html
159    #[derive(Debug, Clone, Copy, Default, QueryId, SqlType)]
160    #[postgres(oid = "2249", array_oid = "2287")]
161    pub struct Record<ST>(ST);
162
163    /// Alias for `SmallInt`
164    pub type SmallSerial = ::sql_types::SmallInt;
165
166    /// Alias for `Integer`
167    pub type Serial = ::sql_types::Integer;
168
169    /// Alias for `BigInt`
170    pub type BigSerial = ::sql_types::BigInt;
171
172    /// The `UUID` SQL type. This type can only be used with `feature = "uuid"`
173    ///
174    /// ### [`ToSql`] impls
175    ///
176    /// - [`uuid::Uuid`][Uuid]
177    ///
178    /// ### [`FromSql`] impls
179    ///
180    /// - [`uuid::Uuid`][Uuid]
181    ///
182    /// [`ToSql`]: ../../../serialize/trait.ToSql.html
183    /// [`FromSql`]: ../../../deserialize/trait.FromSql.html
184    /// [Uuid]: https://doc.rust-lang.org/uuid/uuid/struct.Uuid.html
185    #[derive(Debug, Clone, Copy, Default, QueryId, SqlType)]
186    #[postgres(oid = "2950", array_oid = "2951")]
187    pub struct Uuid;
188
189    /// Alias for `Binary`, to ensure `infer_schema!` works
190    #[doc(hidden)]
191    pub type Bytea = ::sql_types::Binary;
192
193    #[doc(hidden)]
194    pub type Bpchar = ::sql_types::VarChar;
195
196    /// The JSON SQL type.  This type can only be used with `feature =
197    /// "serde_json"`
198    ///
199    /// Normally you should prefer [`Jsonb`](struct.Jsonb.html) instead, for the reasons
200    /// discussed there.
201    ///
202    /// ### [`ToSql`] impls
203    ///
204    /// - [`serde_json::Value`]
205    ///
206    /// ### [`FromSql`] impls
207    ///
208    /// - [`serde_json::Value`]
209    ///
210    /// [`ToSql`]: ../../../serialize/trait.ToSql.html
211    /// [`FromSql`]: ../../../deserialize/trait.FromSql.html
212    /// [`serde_json::Value`]: ../../../../serde_json/value/enum.Value.html
213    #[derive(Debug, Clone, Copy, Default, QueryId, SqlType)]
214    #[postgres(oid = "114", array_oid = "199")]
215    pub struct Json;
216
217    /// The `jsonb` SQL type.  This type can only be used with `feature =
218    /// "serde_json"`
219    ///
220    /// `jsonb` offers [several advantages][adv] over regular JSON:
221    ///
222    /// > There are two JSON data types: `json` and `jsonb`. They accept almost
223    /// > identical sets of values as input. The major practical difference
224    /// > is one of efficiency. The `json` data type stores an exact copy of
225    /// > the input text, which processing functions must reparse on each
226    /// > execution; while `jsonb` data is stored in a decomposed binary format
227    /// > that makes it slightly slower to input due to added conversion
228    /// > overhead, but significantly faster to process, since no reparsing
229    /// > is needed. `jsonb` also supports indexing, which can be a significant
230    /// > advantage.
231    /// >
232    /// > ...In general, most applications should prefer to store JSON data as
233    /// > `jsonb`, unless there are quite specialized needs, such as legacy
234    /// > assumptions about ordering of object keys.
235    ///
236    /// [adv]: https://www.postgresql.org/docs/9.6/static/datatype-json.html
237    ///
238    /// ### [`ToSql`] impls
239    ///
240    /// - [`serde_json::Value`]
241    ///
242    /// ### [`FromSql`] impls
243    ///
244    /// - [`serde_json::Value`]
245    ///
246    /// [`ToSql`]: ../../../serialize/trait.ToSql.html
247    /// [`FromSql`]: ../../../deserialize/trait.FromSql.html
248    /// [`serde_json::Value`]: ../../../../serde_json/value/enum.Value.html
249    ///
250    /// # Examples
251    ///
252    /// ```rust
253    /// # #![allow(dead_code)]
254    /// extern crate serde_json;
255    /// # #[macro_use] extern crate diesel;
256    /// # include!("../../doctest_setup.rs");
257    /// #
258    /// table! {
259    ///     contacts {
260    ///         id -> Integer,
261    ///         name -> VarChar,
262    ///         address -> Jsonb,
263    ///     }
264    /// }
265    ///
266    /// # fn main() {
267    /// #     use diesel::insert_into;
268    /// #     use contacts::dsl::*;
269    /// #     let connection = connection_no_data();
270    /// #     connection.execute("CREATE TABLE contacts (
271    /// #         id SERIAL PRIMARY KEY,
272    /// #         name VARCHAR NOT NULL,
273    /// #         address JSONB NOT NULL
274    /// #     )").unwrap();
275    /// let santas_address: serde_json::Value = serde_json::from_str(r#"{
276    ///     "street": "Article Circle Expressway 1",
277    ///     "city": "North Pole",
278    ///     "postcode": "99705",
279    ///     "state": "Alaska"
280    /// }"#).unwrap();
281    /// let inserted_address = insert_into(contacts)
282    ///     .values((name.eq("Claus"), address.eq(&santas_address)))
283    ///     .returning(address)
284    ///     .get_result(&connection);
285    /// assert_eq!(Ok(santas_address), inserted_address);
286    /// # }
287    /// ```
288    #[derive(Debug, Clone, Copy, Default, QueryId, SqlType)]
289    #[postgres(oid = "3802", array_oid = "3807")]
290    pub struct Jsonb;
291
292    /// The PostgreSQL [Money](https://www.postgresql.org/docs/9.1/static/datatype-money.html) type.
293    ///
294    /// ### [`ToSql`] impls
295    ///
296    /// - [`Cents` (also aliased as `PgMoney`)][PgMoney]
297    ///
298    /// ### [`FromSql`] impls
299    ///
300    /// - [`Cents` (also aliased as `PgMoney`)][PgMoney]
301    ///
302    /// [`ToSql`]: ../../../serialize/trait.ToSql.html
303    /// [`FromSql`]: ../../../deserialize/trait.FromSql.html
304    /// [PgMoney]: ../../data_types/struct.PgMoney.html
305    ///
306    /// # Examples
307    ///
308    /// ```rust
309    /// # #![allow(dead_code)]
310    /// # #[macro_use] extern crate diesel;
311    /// # include!("../../doctest_setup.rs");
312    /// use diesel::data_types::Cents;
313    ///
314    /// table! {
315    ///     items {
316    ///         id -> Integer,
317    ///         name -> VarChar,
318    ///         price -> Money,
319    ///     }
320    /// }
321    ///
322    /// # fn main() {
323    /// #     use diesel::insert_into;
324    /// #     use items::dsl::*;
325    /// #     let connection = connection_no_data();
326    /// #     connection.execute("CREATE TABLE items (
327    /// #         id SERIAL PRIMARY KEY,
328    /// #         name VARCHAR NOT NULL,
329    /// #         price MONEY NOT NULL
330    /// #     )").unwrap();
331    /// let inserted_price = insert_into(items)
332    ///     .values((name.eq("Shiny Thing"), price.eq(Cents(123_456))))
333    ///     .returning(price)
334    ///     .get_result(&connection);
335    /// assert_eq!(Ok(Cents(123_456)), inserted_price);
336    /// # }
337    /// ```
338    #[derive(Debug, Clone, Copy, Default, QueryId, SqlType)]
339    #[postgres(oid = "790", array_oid = "791")]
340    pub struct Money;
341
342    /// The [`MACADDR`](https://www.postgresql.org/docs/9.6/static/datatype-net-types.html) SQL type. This type can only be used with `feature = "network-address"`
343    ///
344    /// ### [`ToSql`] impls
345    ///
346    /// - `[u8; 6]`
347    ///
348    /// ### [`FromSql`] impls
349    ///
350    /// - `[u8; 6]`
351    ///
352    /// [`ToSql`]: ../../../serialize/trait.ToSql.html
353    /// [`FromSql`]: ../../../deserialize/trait.FromSql.html
354    ///
355    /// # Examples
356    ///
357    /// ```rust
358    /// # #![allow(dead_code)]
359    /// # #[macro_use] extern crate diesel;
360    /// # include!("../../doctest_setup.rs");
361    /// table! {
362    ///     devices {
363    ///         id -> Integer,
364    ///         macaddr -> MacAddr,
365    ///     }
366    /// }
367    ///
368    /// # fn main() {
369    /// #     use diesel::insert_into;
370    /// #     use devices::dsl::*;
371    /// #     let connection = connection_no_data();
372    /// #     connection.execute("CREATE TABLE devices (
373    /// #         id SERIAL PRIMARY KEY,
374    /// #         macaddr MACADDR NOT NULL
375    /// #     )").unwrap();
376    /// let inserted_macaddr = insert_into(devices)
377    ///     .values(macaddr.eq([0x08, 0x00, 0x2b, 0x01, 0x02, 0x03]))
378    ///     .returning(macaddr)
379    ///     .get_result(&connection);
380    /// assert_eq!(Ok([0x08, 0x00, 0x2b, 0x01, 0x02, 0x03]), inserted_macaddr);
381    /// # }
382    /// ```
383    #[derive(Debug, Clone, Copy, Default, QueryId, SqlType)]
384    #[postgres(oid = "829", array_oid = "1040")]
385    pub struct MacAddr;
386
387    #[doc(hidden)]
388    /// Alias for `MacAddr` to be able to use it with `infer_schema`.
389    pub type Macaddr = MacAddr;
390
391    /// 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"`
392    ///
393    /// ### [`ToSql`] impls
394    ///
395    /// - [`ipnetwork::IpNetwork`][IpNetwork]
396    ///
397    /// ### [`FromSql`] impls
398    ///
399    /// - [`ipnetwork::IpNetwork`][IpNetwork]
400    ///
401    /// [`ToSql`]: ../../../serialize/trait.ToSql.html
402    /// [`FromSql`]: ../../../deserialize/trait.FromSql.html
403    /// [IpNetwork]: ../../../../ipnetwork/enum.IpNetwork.html
404    ///
405    /// # Examples
406    ///
407    /// ```rust
408    /// # #![allow(dead_code)]
409    /// # #[macro_use] extern crate diesel;
410    /// # include!("../../doctest_setup.rs");
411    /// #
412    /// extern crate ipnetwork;
413    /// use ipnetwork::IpNetwork;
414    ///
415    /// table! {
416    ///     clients {
417    ///         id -> Integer,
418    ///         ip_address -> Inet,
419    ///     }
420    /// }
421    ///
422    /// # fn main() {
423    /// #     use diesel::insert_into;
424    /// #     use clients::dsl::*;
425    /// #     use std::str::FromStr;
426    /// #     let connection = connection_no_data();
427    /// #     connection.execute("CREATE TABLE clients (
428    /// #         id SERIAL PRIMARY KEY,
429    /// #         ip_address INET NOT NULL
430    /// #     )").unwrap();
431    /// let addr = IpNetwork::from_str("10.1.9.32/32").unwrap();
432    /// let inserted_address = insert_into(clients)
433    ///     .values(ip_address.eq(&addr))
434    ///     .returning(ip_address)
435    ///     .get_result(&connection);
436    /// assert_eq!(Ok(addr), inserted_address);
437    /// # }
438    /// ```
439    #[derive(Debug, Clone, Copy, Default, QueryId, SqlType)]
440    #[postgres(oid = "869", array_oid = "1041")]
441    pub struct Inet;
442
443    /// 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"`
444    ///
445    /// ### [`ToSql`] impls
446    ///
447    /// - [`ipnetwork::IpNetwork`][IpNetwork]
448    ///
449    /// ### [`FromSql`] impls
450    ///
451    /// - [`ipnetwork::IpNetwork`][IpNetwork]
452    ///
453    /// [`ToSql`]: ../../../serialize/trait.ToSql.html
454    /// [`FromSql`]: ../../../deserialize/trait.FromSql.html
455    /// [IpNetwork]: ../../../../ipnetwork/enum.IpNetwork.html
456    ///
457    /// # Examples
458    ///
459    /// ```rust
460    /// # #![allow(dead_code)]
461    /// # #[macro_use] extern crate diesel;
462    /// # include!("../../doctest_setup.rs");
463    /// extern crate ipnetwork;
464    /// use ipnetwork::IpNetwork;
465    ///
466    /// table! {
467    ///     clients {
468    ///         id -> Integer,
469    ///         ip_address -> Cidr,
470    ///     }
471    /// }
472    ///
473    /// # fn main() {
474    /// #     use diesel::insert_into;
475    /// #     use clients::dsl::*;
476    /// #     use std::str::FromStr;
477    /// #     let connection = connection_no_data();
478    /// #     connection.execute("CREATE TABLE clients (
479    /// #         id SERIAL PRIMARY KEY,
480    /// #         ip_address CIDR NOT NULL
481    /// #     )").unwrap();
482    /// let addr = IpNetwork::from_str("10.1.9.32/32").unwrap();
483    /// let inserted_addr = insert_into(clients)
484    ///     .values(ip_address.eq(&addr))
485    ///     .returning(ip_address)
486    ///     .get_result(&connection);
487    /// assert_eq!(Ok(addr), inserted_addr);
488    /// # }
489    /// ```
490    #[derive(Debug, Clone, Copy, Default, QueryId, SqlType)]
491    #[postgres(oid = "650", array_oid = "651")]
492    pub struct Cidr;
493}
494
495mod ops {
496    use super::sql_types::*;
497    use sql_types::ops::*;
498    use sql_types::Interval;
499
500    impl Add for Timestamptz {
501        type Rhs = Interval;
502        type Output = Timestamptz;
503    }
504
505    impl Sub for Timestamptz {
506        type Rhs = Interval;
507        type Output = Timestamptz;
508    }
509}