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