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}