Thanks to visit codestin.com
Credit goes to docs.rs

postgres_types/
lib.rs

1//! Conversions to and from Postgres types.
2//!
3//! This crate is used by the `tokio-postgres` and `postgres` crates. You normally don't need to depend directly on it
4//! unless you want to define your own `ToSql` or `FromSql` definitions.
5//!
6//! # Derive
7//!
8//! If the `derive` cargo feature is enabled, you can derive `ToSql` and `FromSql` implementations for custom Postgres
9//! types. Explicitly, modify your `Cargo.toml` file to include the following:
10//!
11//! ```toml
12//! [dependencies]
13//! postgres-types = { version = "0.X.X", features = ["derive"] }
14//! ```
15//!
16//! ## Enums
17//!
18//! Postgres enums correspond to C-like enums in Rust:
19//!
20//! ```sql
21//! CREATE TYPE "Mood" AS ENUM (
22//!     'Sad',
23//!     'Ok',
24//!     'Happy'
25//! );
26//! ```
27//!
28//! ```rust
29//! # #[cfg(feature = "derive")]
30//! use postgres_types::{ToSql, FromSql};
31//!
32//! # #[cfg(feature = "derive")]
33//! #[derive(Debug, ToSql, FromSql)]
34//! enum Mood {
35//!     Sad,
36//!     Ok,
37//!     Happy,
38//! }
39//! ```
40//!
41//! ## Domains
42//!
43//! Postgres domains correspond to tuple structs with one member in Rust:
44//!
45//! ```sql
46//! CREATE DOMAIN "SessionId" AS BYTEA CHECK(octet_length(VALUE) = 16);
47//! ```
48//!
49//! ```rust
50//! # #[cfg(feature = "derive")]
51//! use postgres_types::{ToSql, FromSql};
52//!
53//! # #[cfg(feature = "derive")]
54//! #[derive(Debug, ToSql, FromSql)]
55//! struct SessionId(Vec<u8>);
56//! ```
57//!
58//! ## Newtypes
59//!
60//! The `#[postgres(transparent)]` attribute can be used on a single-field tuple struct to create a
61//! Rust-only wrapper type that will use the [`ToSql`] & [`FromSql`] implementation of the inner
62//! value :
63//! ```rust
64//! # #[cfg(feature = "derive")]
65//! use postgres_types::{ToSql, FromSql};
66//!
67//! # #[cfg(feature = "derive")]
68//! #[derive(Debug, ToSql, FromSql)]
69//! #[postgres(transparent)]
70//! struct UserId(i32);
71//! ```
72//!
73//! ## Composites
74//!
75//! Postgres composite types correspond to structs in Rust:
76//!
77//! ```sql
78//! CREATE TYPE "InventoryItem" AS (
79//!     name TEXT,
80//!     supplier_id INT,
81//!     price DOUBLE PRECISION
82//! );
83//! ```
84//!
85//! ```rust
86//! # #[cfg(feature = "derive")]
87//! use postgres_types::{ToSql, FromSql};
88//!
89//! # #[cfg(feature = "derive")]
90//! #[derive(Debug, ToSql, FromSql)]
91//! struct InventoryItem {
92//!     name: String,
93//!     supplier_id: i32,
94//!     price: Option<f64>,
95//! }
96//! ```
97//!
98//! ## Naming
99//!
100//! The derived implementations will enforce exact matches of type, field, and variant names between the Rust and
101//! Postgres types. The `#[postgres(name = "...")]` attribute can be used to adjust the name on a type, variant, or
102//! field:
103//!
104//! ```sql
105//! CREATE TYPE mood AS ENUM (
106//!     'sad',
107//!     'ok',
108//!     'happy'
109//! );
110//! ```
111//!
112//! ```rust
113//! # #[cfg(feature = "derive")]
114//! use postgres_types::{ToSql, FromSql};
115//!
116//! # #[cfg(feature = "derive")]
117//! #[derive(Debug, ToSql, FromSql)]
118//! #[postgres(name = "mood")]
119//! enum Mood {
120//!     #[postgres(name = "sad")]
121//!     Sad,
122//!     #[postgres(name = "ok")]
123//!     Ok,
124//!     #[postgres(name = "happy")]
125//!     Happy,
126//! }
127//! ```
128//!
129//! Alternatively, the `#[postgres(rename_all = "...")]` attribute can be used to rename all fields or variants
130//! with the chosen casing convention. This will not affect the struct or enum's type name. Note that
131//! `#[postgres(name = "...")]` takes precendence when used in conjunction with `#[postgres(rename_all = "...")]`:
132//!
133//! ```rust
134//! # #[cfg(feature = "derive")]
135//! use postgres_types::{ToSql, FromSql};
136//!
137//! # #[cfg(feature = "derive")]
138//! #[derive(Debug, ToSql, FromSql)]
139//! #[postgres(name = "mood", rename_all = "snake_case")]
140//! enum Mood {
141//!     #[postgres(name = "ok")]
142//!     Ok,             // ok
143//!     VeryHappy,      // very_happy
144//! }
145//! ```
146//!
147//! The following case conventions are supported:
148//! - `"lowercase"`
149//! - `"UPPERCASE"`
150//! - `"PascalCase"`
151//! - `"camelCase"`
152//! - `"snake_case"`
153//! - `"SCREAMING_SNAKE_CASE"`
154//! - `"kebab-case"`
155//! - `"SCREAMING-KEBAB-CASE"`
156//! - `"Train-Case"`
157//!
158//! ## Allowing Enum Mismatches
159//!
160//! By default the generated implementation of [`ToSql`] & [`FromSql`] for enums will require an exact match of the enum
161//! variants between the Rust and Postgres types.
162//! To allow mismatches, the `#[postgres(allow_mismatch)]` attribute can be used on the enum definition:
163//!
164//! ```sql
165//! CREATE TYPE mood AS ENUM (
166//!   'Sad',
167//!   'Ok',
168//!   'Happy'
169//! );
170//! ```
171//!
172//! ```rust
173//! # #[cfg(feature = "derive")]
174//! use postgres_types::{ToSql, FromSql};
175//!
176//! # #[cfg(feature = "derive")]
177//! #[derive(Debug, ToSql, FromSql)]
178//! #[postgres(allow_mismatch)]
179//! enum Mood {
180//!    Happy,
181//!    Meh,
182//! }
183//! ```
184#![warn(clippy::all, rust_2018_idioms, missing_docs)]
185use fallible_iterator::FallibleIterator;
186use postgres_protocol::types::{self, ArrayDimension};
187use std::any::type_name;
188use std::borrow::Cow;
189use std::collections::HashMap;
190use std::error::Error;
191use std::fmt;
192use std::hash::BuildHasher;
193use std::net::IpAddr;
194use std::sync::Arc;
195use std::time::{Duration, SystemTime, UNIX_EPOCH};
196
197#[cfg(feature = "derive")]
198pub use postgres_derive::{FromSql, ToSql};
199
200#[cfg(feature = "with-serde_json-1")]
201pub use crate::serde_json_1::Json;
202use crate::type_gen::{Inner, Other};
203
204#[doc(inline)]
205pub use postgres_protocol::Oid;
206
207#[doc(inline)]
208pub use pg_lsn::PgLsn;
209
210pub use crate::special::{Date, Timestamp};
211use bytes::BytesMut;
212
213// Number of seconds from 1970-01-01 to 2000-01-01
214const TIME_SEC_CONVERSION: u64 = 946_684_800;
215const USEC_PER_SEC: u64 = 1_000_000;
216const NSEC_PER_USEC: u64 = 1_000;
217
218/// Generates a simple implementation of `ToSql::accepts` which accepts the
219/// types passed to it.
220#[macro_export]
221macro_rules! accepts {
222    ($($expected:ident),+) => (
223        fn accepts(ty: &$crate::Type) -> bool {
224            matches!(*ty, $($crate::Type::$expected)|+)
225        }
226    )
227}
228
229/// Generates an implementation of `ToSql::to_sql_checked`.
230///
231/// All `ToSql` implementations should use this macro.
232#[macro_export]
233macro_rules! to_sql_checked {
234    () => {
235        fn to_sql_checked(
236            &self,
237            ty: &$crate::Type,
238            out: &mut $crate::private::BytesMut,
239        ) -> ::std::result::Result<
240            $crate::IsNull,
241            Box<dyn ::std::error::Error + ::std::marker::Sync + ::std::marker::Send>,
242        > {
243            $crate::__to_sql_checked(self, ty, out)
244        }
245    };
246}
247
248// WARNING: this function is not considered part of this crate's public API.
249// It is subject to change at any time.
250#[doc(hidden)]
251pub fn __to_sql_checked<T>(
252    v: &T,
253    ty: &Type,
254    out: &mut BytesMut,
255) -> Result<IsNull, Box<dyn Error + Sync + Send>>
256where
257    T: ToSql,
258{
259    if !T::accepts(ty) {
260        return Err(Box::new(WrongType::new::<T>(ty.clone())));
261    }
262    v.to_sql(ty, out)
263}
264
265#[cfg(feature = "with-bit-vec-0_6")]
266mod bit_vec_06;
267#[cfg(feature = "with-chrono-0_4")]
268mod chrono_04;
269#[cfg(feature = "with-cidr-0_2")]
270mod cidr_02;
271#[cfg(feature = "with-cidr-0_3")]
272mod cidr_03;
273#[cfg(feature = "with-eui48-0_4")]
274mod eui48_04;
275#[cfg(feature = "with-eui48-1")]
276mod eui48_1;
277#[cfg(feature = "with-geo-types-0_6")]
278mod geo_types_06;
279#[cfg(feature = "with-geo-types-0_7")]
280mod geo_types_07;
281#[cfg(feature = "with-jiff-0_1")]
282mod jiff_01;
283#[cfg(feature = "with-serde_json-1")]
284mod serde_json_1;
285#[cfg(feature = "with-smol_str-01")]
286mod smol_str_01;
287#[cfg(feature = "with-time-0_2")]
288mod time_02;
289#[cfg(feature = "with-time-0_3")]
290mod time_03;
291#[cfg(feature = "with-uuid-0_8")]
292mod uuid_08;
293#[cfg(feature = "with-uuid-1")]
294mod uuid_1;
295
296// The time::{date, time} macros produce compile errors if the crate package is renamed.
297#[cfg(feature = "with-time-0_2")]
298extern crate time_02 as time;
299
300mod pg_lsn;
301#[doc(hidden)]
302pub mod private;
303mod special;
304mod type_gen;
305
306/// A Postgres type.
307#[derive(PartialEq, Eq, Clone, Hash)]
308pub struct Type(Inner);
309
310impl fmt::Debug for Type {
311    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
312        fmt::Debug::fmt(&self.0, fmt)
313    }
314}
315
316impl fmt::Display for Type {
317    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
318        match self.schema() {
319            "public" | "pg_catalog" => {}
320            schema => write!(fmt, "{}.", schema)?,
321        }
322        fmt.write_str(self.name())
323    }
324}
325
326impl Type {
327    /// Creates a new `Type`.
328    pub fn new(name: String, oid: Oid, kind: Kind, schema: String) -> Type {
329        Type(Inner::Other(Arc::new(Other {
330            name,
331            oid,
332            kind,
333            schema,
334        })))
335    }
336
337    /// Returns the `Type` corresponding to the provided `Oid` if it
338    /// corresponds to a built-in type.
339    pub fn from_oid(oid: Oid) -> Option<Type> {
340        Inner::from_oid(oid).map(Type)
341    }
342
343    /// Returns the OID of the `Type`.
344    pub fn oid(&self) -> Oid {
345        self.0.oid()
346    }
347
348    /// Returns the kind of this type.
349    pub fn kind(&self) -> &Kind {
350        self.0.kind()
351    }
352
353    /// Returns the schema of this type.
354    pub fn schema(&self) -> &str {
355        match self.0 {
356            Inner::Other(ref u) => &u.schema,
357            _ => "pg_catalog",
358        }
359    }
360
361    /// Returns the name of this type.
362    pub fn name(&self) -> &str {
363        self.0.name()
364    }
365}
366
367/// Represents the kind of a Postgres type.
368#[derive(Debug, Clone, PartialEq, Eq, Hash)]
369#[non_exhaustive]
370pub enum Kind {
371    /// A simple type like `VARCHAR` or `INTEGER`.
372    Simple,
373    /// An enumerated type along with its variants.
374    Enum(Vec<String>),
375    /// A pseudo-type.
376    Pseudo,
377    /// An array type along with the type of its elements.
378    Array(Type),
379    /// A range type along with the type of its elements.
380    Range(Type),
381    /// A multirange type along with the type of its elements.
382    Multirange(Type),
383    /// A domain type along with its underlying type.
384    Domain(Type),
385    /// A composite type along with information about its fields.
386    Composite(Vec<Field>),
387}
388
389/// Information about a field of a composite type.
390#[derive(Debug, Clone, PartialEq, Eq, Hash)]
391pub struct Field {
392    name: String,
393    type_: Type,
394}
395
396impl Field {
397    /// Creates a new `Field`.
398    pub fn new(name: String, type_: Type) -> Field {
399        Field { name, type_ }
400    }
401
402    /// Returns the name of the field.
403    pub fn name(&self) -> &str {
404        &self.name
405    }
406
407    /// Returns the type of the field.
408    pub fn type_(&self) -> &Type {
409        &self.type_
410    }
411}
412
413/// An error indicating that a `NULL` Postgres value was passed to a `FromSql`
414/// implementation that does not support `NULL` values.
415#[derive(Debug, Clone, Copy)]
416pub struct WasNull;
417
418impl fmt::Display for WasNull {
419    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
420        fmt.write_str("a Postgres value was `NULL`")
421    }
422}
423
424impl Error for WasNull {}
425
426/// An error indicating that a conversion was attempted between incompatible
427/// Rust and Postgres types.
428#[derive(Debug)]
429pub struct WrongType {
430    postgres: Type,
431    rust: &'static str,
432}
433
434impl fmt::Display for WrongType {
435    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
436        write!(
437            fmt,
438            "cannot convert between the Rust type `{}` and the Postgres type `{}`",
439            self.rust, self.postgres,
440        )
441    }
442}
443
444impl Error for WrongType {}
445
446impl WrongType {
447    /// Creates a new `WrongType` error.
448    pub fn new<T>(ty: Type) -> WrongType {
449        WrongType {
450            postgres: ty,
451            rust: type_name::<T>(),
452        }
453    }
454}
455
456/// A trait for types that can be created from a Postgres value.
457///
458/// # Types
459///
460/// The following implementations are provided by this crate, along with the
461/// corresponding Postgres types:
462///
463/// | Rust type                         | Postgres type(s)                              |
464/// |-----------------------------------|-----------------------------------------------|
465/// | `bool`                            | BOOL                                          |
466/// | `i8`                              | "char"                                        |
467/// | `i16`                             | SMALLINT, SMALLSERIAL                         |
468/// | `i32`                             | INT, SERIAL                                   |
469/// | `u32`                             | OID                                           |
470/// | `i64`                             | BIGINT, BIGSERIAL                             |
471/// | `f32`                             | REAL                                          |
472/// | `f64`                             | DOUBLE PRECISION                              |
473/// | `&str`/`String`                   | VARCHAR, CHAR(n), TEXT, CITEXT, NAME, UNKNOWN |
474/// |                                   | LTREE, LQUERY, LTXTQUERY                      |
475/// | `&[u8]`/`Vec<u8>`                 | BYTEA                                         |
476/// | `HashMap<String, Option<String>>` | HSTORE                                        |
477/// | `SystemTime`                      | TIMESTAMP, TIMESTAMP WITH TIME ZONE           |
478/// | `IpAddr`                          | INET                                          |
479///
480/// In addition, some implementations are provided for types in third party
481/// crates. These are disabled by default; to opt into one of these
482/// implementations, activate the Cargo feature corresponding to the crate's
483/// name prefixed by `with-`. For example, the `with-serde_json-1` feature enables
484/// the implementation for the `serde_json::Value` type.
485///
486/// | Rust type                       | Postgres type(s)                    |
487/// |---------------------------------|-------------------------------------|
488/// | `chrono::NaiveDateTime`         | TIMESTAMP                           |
489/// | `chrono::DateTime<Utc>`         | TIMESTAMP WITH TIME ZONE            |
490/// | `chrono::DateTime<Local>`       | TIMESTAMP WITH TIME ZONE            |
491/// | `chrono::DateTime<FixedOffset>` | TIMESTAMP WITH TIME ZONE            |
492/// | `chrono::NaiveDate`             | DATE                                |
493/// | `chrono::NaiveTime`             | TIME                                |
494/// | `cidr::IpCidr`                  | CIDR                                |
495/// | `cidr::IpInet`                  | INET                                |
496/// | `time::PrimitiveDateTime`       | TIMESTAMP                           |
497/// | `time::OffsetDateTime`          | TIMESTAMP WITH TIME ZONE            |
498/// | `time::Date`                    | DATE                                |
499/// | `time::Time`                    | TIME                                |
500/// | `jiff::civil::Date`             | DATE                                |
501/// | `jiff::civil::DateTime`         | TIMESTAMP                           |
502/// | `jiff::civil::Time`             | TIME                                |
503/// | `jiff::Timestamp`               | TIMESTAMP WITH TIME ZONE            |
504/// | `eui48::MacAddress`             | MACADDR                             |
505/// | `geo_types::Point<f64>`         | POINT                               |
506/// | `geo_types::Rect<f64>`          | BOX                                 |
507/// | `geo_types::LineString<f64>`    | PATH                                |
508/// | `serde_json::Value`             | JSON, JSONB                         |
509/// | `uuid::Uuid`                    | UUID                                |
510/// | `bit_vec::BitVec`               | BIT, VARBIT                         |
511/// | `eui48::MacAddress`             | MACADDR                             |
512/// | `cidr::InetCidr`                | CIDR                                |
513/// | `cidr::InetAddr`                | INET                                |
514/// | `smol_str::SmolStr`             | VARCHAR, CHAR(n), TEXT, CITEXT,     |
515/// |                                 | NAME, UNKNOWN, LTREE, LQUERY,       |
516/// |                                 | LTXTQUERY                           |
517///
518/// # Nullability
519///
520/// In addition to the types listed above, `FromSql` is implemented for
521/// `Option<T>` where `T` implements `FromSql`. An `Option<T>` represents a
522/// nullable Postgres value.
523///
524/// # Arrays
525///
526/// `FromSql` is implemented for `Vec<T>`, `Box<[T]>` and `[T; N]` where `T`
527/// implements `FromSql`, and corresponds to one-dimensional Postgres arrays.
528///
529/// **Note:** the impl for arrays only exist when the Cargo feature `array-impls`
530/// is enabled.
531pub trait FromSql<'a>: Sized {
532    /// Creates a new value of this type from a buffer of data of the specified
533    /// Postgres `Type` in its binary format.
534    ///
535    /// The caller of this method is responsible for ensuring that this type
536    /// is compatible with the Postgres `Type`.
537    fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Self, Box<dyn Error + Sync + Send>>;
538
539    /// Creates a new value of this type from a `NULL` SQL value.
540    ///
541    /// The caller of this method is responsible for ensuring that this type
542    /// is compatible with the Postgres `Type`.
543    ///
544    /// The default implementation returns `Err(Box::new(WasNull))`.
545    #[allow(unused_variables)]
546    fn from_sql_null(ty: &Type) -> Result<Self, Box<dyn Error + Sync + Send>> {
547        Err(Box::new(WasNull))
548    }
549
550    /// A convenience function that delegates to `from_sql` and `from_sql_null` depending on the
551    /// value of `raw`.
552    fn from_sql_nullable(
553        ty: &Type,
554        raw: Option<&'a [u8]>,
555    ) -> Result<Self, Box<dyn Error + Sync + Send>> {
556        match raw {
557            Some(raw) => Self::from_sql(ty, raw),
558            None => Self::from_sql_null(ty),
559        }
560    }
561
562    /// Determines if a value of this type can be created from the specified
563    /// Postgres `Type`.
564    fn accepts(ty: &Type) -> bool;
565}
566
567/// A trait for types which can be created from a Postgres value without borrowing any data.
568///
569/// This is primarily useful for trait bounds on functions.
570pub trait FromSqlOwned: for<'a> FromSql<'a> {}
571
572impl<T> FromSqlOwned for T where T: for<'a> FromSql<'a> {}
573
574impl<'a, T: FromSql<'a>> FromSql<'a> for Option<T> {
575    fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Option<T>, Box<dyn Error + Sync + Send>> {
576        <T as FromSql>::from_sql(ty, raw).map(Some)
577    }
578
579    fn from_sql_null(_: &Type) -> Result<Option<T>, Box<dyn Error + Sync + Send>> {
580        Ok(None)
581    }
582
583    fn accepts(ty: &Type) -> bool {
584        <T as FromSql>::accepts(ty)
585    }
586}
587
588impl<'a, T: FromSql<'a>> FromSql<'a> for Vec<T> {
589    fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Vec<T>, Box<dyn Error + Sync + Send>> {
590        let member_type = match *ty.kind() {
591            Kind::Array(ref member) => member,
592            _ => panic!("expected array type"),
593        };
594
595        let array = types::array_from_sql(raw)?;
596        if array.dimensions().count()? > 1 {
597            return Err("array contains too many dimensions".into());
598        }
599
600        array
601            .values()
602            .map(|v| T::from_sql_nullable(member_type, v))
603            .collect()
604    }
605
606    fn accepts(ty: &Type) -> bool {
607        match *ty.kind() {
608            Kind::Array(ref inner) => T::accepts(inner),
609            _ => false,
610        }
611    }
612}
613
614#[cfg(feature = "array-impls")]
615impl<'a, T: FromSql<'a>, const N: usize> FromSql<'a> for [T; N] {
616    fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Self, Box<dyn Error + Sync + Send>> {
617        let member_type = match *ty.kind() {
618            Kind::Array(ref member) => member,
619            _ => panic!("expected array type"),
620        };
621
622        let array = types::array_from_sql(raw)?;
623        if array.dimensions().count()? > 1 {
624            return Err("array contains too many dimensions".into());
625        }
626
627        let mut values = array.values();
628        let out = array_init::try_array_init(|i| {
629            let v = values
630                .next()?
631                .ok_or_else(|| -> Box<dyn Error + Sync + Send> {
632                    format!("too few elements in array (expected {}, got {})", N, i).into()
633                })?;
634            T::from_sql_nullable(member_type, v)
635        })?;
636        if values.next()?.is_some() {
637            return Err(format!(
638                "excess elements in array (expected {}, got more than that)",
639                N,
640            )
641            .into());
642        }
643
644        Ok(out)
645    }
646
647    fn accepts(ty: &Type) -> bool {
648        match *ty.kind() {
649            Kind::Array(ref inner) => T::accepts(inner),
650            _ => false,
651        }
652    }
653}
654
655impl<'a, T: FromSql<'a>> FromSql<'a> for Box<[T]> {
656    fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Self, Box<dyn Error + Sync + Send>> {
657        Vec::<T>::from_sql(ty, raw).map(Vec::into_boxed_slice)
658    }
659
660    fn accepts(ty: &Type) -> bool {
661        Vec::<T>::accepts(ty)
662    }
663}
664
665impl<'a> FromSql<'a> for Vec<u8> {
666    fn from_sql(_: &Type, raw: &'a [u8]) -> Result<Vec<u8>, Box<dyn Error + Sync + Send>> {
667        Ok(types::bytea_from_sql(raw).to_owned())
668    }
669
670    accepts!(BYTEA);
671}
672
673impl<'a> FromSql<'a> for &'a [u8] {
674    fn from_sql(_: &Type, raw: &'a [u8]) -> Result<&'a [u8], Box<dyn Error + Sync + Send>> {
675        Ok(types::bytea_from_sql(raw))
676    }
677
678    accepts!(BYTEA);
679}
680
681impl<'a> FromSql<'a> for String {
682    fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<String, Box<dyn Error + Sync + Send>> {
683        <&str as FromSql>::from_sql(ty, raw).map(ToString::to_string)
684    }
685
686    fn accepts(ty: &Type) -> bool {
687        <&str as FromSql>::accepts(ty)
688    }
689}
690
691impl<'a> FromSql<'a> for Box<str> {
692    fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Box<str>, Box<dyn Error + Sync + Send>> {
693        <&str as FromSql>::from_sql(ty, raw)
694            .map(ToString::to_string)
695            .map(String::into_boxed_str)
696    }
697
698    fn accepts(ty: &Type) -> bool {
699        <&str as FromSql>::accepts(ty)
700    }
701}
702
703impl<'a> FromSql<'a> for &'a str {
704    fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<&'a str, Box<dyn Error + Sync + Send>> {
705        match *ty {
706            ref ty if ty.name() == "ltree" => types::ltree_from_sql(raw),
707            ref ty if ty.name() == "lquery" => types::lquery_from_sql(raw),
708            ref ty if ty.name() == "ltxtquery" => types::ltxtquery_from_sql(raw),
709            _ => types::text_from_sql(raw),
710        }
711    }
712
713    fn accepts(ty: &Type) -> bool {
714        match *ty {
715            Type::VARCHAR | Type::TEXT | Type::BPCHAR | Type::NAME | Type::UNKNOWN => true,
716            ref ty
717                if (ty.name() == "citext"
718                    || ty.name() == "ltree"
719                    || ty.name() == "lquery"
720                    || ty.name() == "ltxtquery") =>
721            {
722                true
723            }
724            _ => false,
725        }
726    }
727}
728
729macro_rules! simple_from {
730    ($t:ty, $f:ident, $($expected:ident),+) => {
731        impl<'a> FromSql<'a> for $t {
732            fn from_sql(_: &Type, raw: &'a [u8]) -> Result<$t, Box<dyn Error + Sync + Send>> {
733                types::$f(raw)
734            }
735
736            accepts!($($expected),+);
737        }
738    }
739}
740
741simple_from!(bool, bool_from_sql, BOOL);
742simple_from!(i8, char_from_sql, CHAR);
743simple_from!(i16, int2_from_sql, INT2);
744simple_from!(i32, int4_from_sql, INT4);
745simple_from!(u32, oid_from_sql, OID);
746simple_from!(i64, int8_from_sql, INT8);
747simple_from!(f32, float4_from_sql, FLOAT4);
748simple_from!(f64, float8_from_sql, FLOAT8);
749
750impl<'a, S> FromSql<'a> for HashMap<String, Option<String>, S>
751where
752    S: Default + BuildHasher,
753{
754    fn from_sql(
755        _: &Type,
756        raw: &'a [u8],
757    ) -> Result<HashMap<String, Option<String>, S>, Box<dyn Error + Sync + Send>> {
758        types::hstore_from_sql(raw)?
759            .map(|(k, v)| Ok((k.to_owned(), v.map(str::to_owned))))
760            .collect()
761    }
762
763    fn accepts(ty: &Type) -> bool {
764        ty.name() == "hstore"
765    }
766}
767
768impl<'a> FromSql<'a> for SystemTime {
769    fn from_sql(_: &Type, raw: &'a [u8]) -> Result<SystemTime, Box<dyn Error + Sync + Send>> {
770        let time = types::timestamp_from_sql(raw)?;
771        let epoch = UNIX_EPOCH + Duration::from_secs(TIME_SEC_CONVERSION);
772
773        let negative = time < 0;
774        let time = time.unsigned_abs();
775
776        let secs = time / USEC_PER_SEC;
777        let nsec = (time % USEC_PER_SEC) * NSEC_PER_USEC;
778        let offset = Duration::new(secs, nsec as u32);
779
780        let time = if negative {
781            epoch - offset
782        } else {
783            epoch + offset
784        };
785
786        Ok(time)
787    }
788
789    accepts!(TIMESTAMP, TIMESTAMPTZ);
790}
791
792impl<'a> FromSql<'a> for IpAddr {
793    fn from_sql(_: &Type, raw: &'a [u8]) -> Result<IpAddr, Box<dyn Error + Sync + Send>> {
794        let inet = types::inet_from_sql(raw)?;
795        Ok(inet.addr())
796    }
797
798    accepts!(INET);
799}
800
801/// An enum representing the nullability of a Postgres value.
802pub enum IsNull {
803    /// The value is NULL.
804    Yes,
805    /// The value is not NULL.
806    No,
807}
808
809/// A trait for types that can be converted into Postgres values.
810///
811/// # Types
812///
813/// The following implementations are provided by this crate, along with the
814/// corresponding Postgres types:
815///
816/// | Rust type                         | Postgres type(s)                     |
817/// |-----------------------------------|--------------------------------------|
818/// | `bool`                            | BOOL                                 |
819/// | `i8`                              | "char"                               |
820/// | `i16`                             | SMALLINT, SMALLSERIAL                |
821/// | `i32`                             | INT, SERIAL                          |
822/// | `u32`                             | OID                                  |
823/// | `i64`                             | BIGINT, BIGSERIAL                    |
824/// | `f32`                             | REAL                                 |
825/// | `f64`                             | DOUBLE PRECISION                     |
826/// | `&str`/`String`                   | VARCHAR, CHAR(n), TEXT, CITEXT, NAME |
827/// |                                   | LTREE, LQUERY, LTXTQUERY             |
828/// | `&[u8]`/`Vec<u8>`/`[u8; N]`       | BYTEA                                |
829/// | `HashMap<String, Option<String>>` | HSTORE                               |
830/// | `SystemTime`                      | TIMESTAMP, TIMESTAMP WITH TIME ZONE  |
831/// | `IpAddr`                          | INET                                 |
832///
833/// In addition, some implementations are provided for types in third party
834/// crates. These are disabled by default; to opt into one of these
835/// implementations, activate the Cargo feature corresponding to the crate's
836/// name prefixed by `with-`. For example, the `with-serde_json-1` feature enables
837/// the implementation for the `serde_json::Value` type.
838///
839/// | Rust type                       | Postgres type(s)                    |
840/// |---------------------------------|-------------------------------------|
841/// | `chrono::NaiveDateTime`         | TIMESTAMP                           |
842/// | `chrono::DateTime<Utc>`         | TIMESTAMP WITH TIME ZONE            |
843/// | `chrono::DateTime<Local>`       | TIMESTAMP WITH TIME ZONE            |
844/// | `chrono::DateTime<FixedOffset>` | TIMESTAMP WITH TIME ZONE            |
845/// | `chrono::NaiveDate`             | DATE                                |
846/// | `chrono::NaiveTime`             | TIME                                |
847/// | `cidr::IpCidr`                  | CIDR                                |
848/// | `cidr::IpInet`                  | INET                                |
849/// | `time::PrimitiveDateTime`       | TIMESTAMP                           |
850/// | `time::OffsetDateTime`          | TIMESTAMP WITH TIME ZONE            |
851/// | `time::Date`                    | DATE                                |
852/// | `time::Time`                    | TIME                                |
853/// | `eui48::MacAddress`             | MACADDR                             |
854/// | `geo_types::Point<f64>`         | POINT                               |
855/// | `geo_types::Rect<f64>`          | BOX                                 |
856/// | `geo_types::LineString<f64>`    | PATH                                |
857/// | `serde_json::Value`             | JSON, JSONB                         |
858/// | `uuid::Uuid`                    | UUID                                |
859/// | `bit_vec::BitVec`               | BIT, VARBIT                         |
860/// | `eui48::MacAddress`             | MACADDR                             |
861///
862/// # Nullability
863///
864/// In addition to the types listed above, `ToSql` is implemented for
865/// `Option<T>` where `T` implements `ToSql`. An `Option<T>` represents a
866/// nullable Postgres value.
867///
868/// # Arrays
869///
870/// `ToSql` is implemented for `[u8; N]`, `Vec<T>`, `&[T]`, `Box<[T]>` and `[T; N]`
871/// where `T` implements `ToSql` and `N` is const usize, and corresponds to one-dimensional
872/// Postgres arrays with an index offset of 1.
873///
874/// **Note:** the impl for arrays only exist when the Cargo feature `array-impls`
875/// is enabled.
876pub trait ToSql: fmt::Debug {
877    /// Converts the value of `self` into the binary format of the specified
878    /// Postgres `Type`, appending it to `out`.
879    ///
880    /// The caller of this method is responsible for ensuring that this type
881    /// is compatible with the Postgres `Type`.
882    ///
883    /// The return value indicates if this value should be represented as
884    /// `NULL`. If this is the case, implementations **must not** write
885    /// anything to `out`.
886    fn to_sql(&self, ty: &Type, out: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>>
887    where
888        Self: Sized;
889
890    /// Determines if a value of this type can be converted to the specified
891    /// Postgres `Type`.
892    fn accepts(ty: &Type) -> bool
893    where
894        Self: Sized;
895
896    /// An adaptor method used internally by Rust-Postgres.
897    ///
898    /// *All* implementations of this method should be generated by the
899    /// `to_sql_checked!()` macro.
900    fn to_sql_checked(
901        &self,
902        ty: &Type,
903        out: &mut BytesMut,
904    ) -> Result<IsNull, Box<dyn Error + Sync + Send>>;
905
906    /// Specify the encode format
907    fn encode_format(&self, _ty: &Type) -> Format {
908        Format::Binary
909    }
910}
911
912/// Supported Postgres message format types
913///
914/// Using Text format in a message assumes a Postgres `SERVER_ENCODING` of `UTF8`
915#[derive(Clone, Copy, Debug)]
916pub enum Format {
917    /// Text format (UTF-8)
918    Text,
919    /// Compact, typed binary format
920    Binary,
921}
922
923impl<T> ToSql for &T
924where
925    T: ToSql,
926{
927    fn to_sql(
928        &self,
929        ty: &Type,
930        out: &mut BytesMut,
931    ) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
932        (*self).to_sql(ty, out)
933    }
934
935    fn accepts(ty: &Type) -> bool {
936        T::accepts(ty)
937    }
938
939    fn encode_format(&self, ty: &Type) -> Format {
940        (*self).encode_format(ty)
941    }
942
943    to_sql_checked!();
944}
945
946impl<T: ToSql> ToSql for Option<T> {
947    fn to_sql(
948        &self,
949        ty: &Type,
950        out: &mut BytesMut,
951    ) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
952        match *self {
953            Some(ref val) => val.to_sql(ty, out),
954            None => Ok(IsNull::Yes),
955        }
956    }
957
958    fn accepts(ty: &Type) -> bool {
959        <T as ToSql>::accepts(ty)
960    }
961
962    fn encode_format(&self, ty: &Type) -> Format {
963        match self {
964            Some(val) => val.encode_format(ty),
965            None => Format::Binary,
966        }
967    }
968
969    to_sql_checked!();
970}
971
972impl<T: ToSql> ToSql for &[T] {
973    fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
974        let member_type = match *ty.kind() {
975            Kind::Array(ref member) => member,
976            _ => panic!("expected array type"),
977        };
978
979        // Arrays are normally one indexed by default but oidvector and int2vector *require* zero indexing
980        let lower_bound = match *ty {
981            Type::OID_VECTOR | Type::INT2_VECTOR => 0,
982            _ => 1,
983        };
984
985        let dimension = ArrayDimension {
986            len: downcast(self.len())?,
987            lower_bound,
988        };
989
990        types::array_to_sql(
991            Some(dimension),
992            member_type.oid(),
993            self.iter(),
994            |e, w| match e.to_sql(member_type, w)? {
995                IsNull::No => Ok(postgres_protocol::IsNull::No),
996                IsNull::Yes => Ok(postgres_protocol::IsNull::Yes),
997            },
998            w,
999        )?;
1000        Ok(IsNull::No)
1001    }
1002
1003    fn accepts(ty: &Type) -> bool {
1004        match *ty.kind() {
1005            Kind::Array(ref member) => T::accepts(member),
1006            _ => false,
1007        }
1008    }
1009
1010    to_sql_checked!();
1011}
1012
1013impl ToSql for &[u8] {
1014    fn to_sql(&self, _: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1015        types::bytea_to_sql(self, w);
1016        Ok(IsNull::No)
1017    }
1018
1019    accepts!(BYTEA);
1020
1021    to_sql_checked!();
1022}
1023
1024#[cfg(feature = "array-impls")]
1025impl<const N: usize> ToSql for [u8; N] {
1026    fn to_sql(&self, _: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1027        types::bytea_to_sql(&self[..], w);
1028        Ok(IsNull::No)
1029    }
1030
1031    accepts!(BYTEA);
1032
1033    to_sql_checked!();
1034}
1035
1036#[cfg(feature = "array-impls")]
1037impl<T: ToSql, const N: usize> ToSql for [T; N] {
1038    fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1039        <&[T] as ToSql>::to_sql(&&self[..], ty, w)
1040    }
1041
1042    fn accepts(ty: &Type) -> bool {
1043        <&[T] as ToSql>::accepts(ty)
1044    }
1045
1046    to_sql_checked!();
1047}
1048
1049impl<T: ToSql> ToSql for Vec<T> {
1050    fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1051        <&[T] as ToSql>::to_sql(&&**self, ty, w)
1052    }
1053
1054    fn accepts(ty: &Type) -> bool {
1055        <&[T] as ToSql>::accepts(ty)
1056    }
1057
1058    to_sql_checked!();
1059}
1060
1061impl<T: ToSql> ToSql for Box<[T]> {
1062    fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1063        <&[T] as ToSql>::to_sql(&&**self, ty, w)
1064    }
1065
1066    fn accepts(ty: &Type) -> bool {
1067        <&[T] as ToSql>::accepts(ty)
1068    }
1069
1070    to_sql_checked!();
1071}
1072
1073impl ToSql for Cow<'_, [u8]> {
1074    fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1075        <&[u8] as ToSql>::to_sql(&self.as_ref(), ty, w)
1076    }
1077
1078    fn accepts(ty: &Type) -> bool {
1079        <&[u8] as ToSql>::accepts(ty)
1080    }
1081
1082    to_sql_checked!();
1083}
1084
1085impl ToSql for Vec<u8> {
1086    fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1087        <&[u8] as ToSql>::to_sql(&&**self, ty, w)
1088    }
1089
1090    fn accepts(ty: &Type) -> bool {
1091        <&[u8] as ToSql>::accepts(ty)
1092    }
1093
1094    to_sql_checked!();
1095}
1096
1097impl ToSql for &str {
1098    fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1099        match ty.name() {
1100            "ltree" => types::ltree_to_sql(self, w),
1101            "lquery" => types::lquery_to_sql(self, w),
1102            "ltxtquery" => types::ltxtquery_to_sql(self, w),
1103            _ => types::text_to_sql(self, w),
1104        }
1105        Ok(IsNull::No)
1106    }
1107
1108    fn accepts(ty: &Type) -> bool {
1109        matches!(
1110            *ty,
1111            Type::VARCHAR | Type::TEXT | Type::BPCHAR | Type::NAME | Type::UNKNOWN
1112        ) || matches!(ty.name(), "citext" | "ltree" | "lquery" | "ltxtquery")
1113    }
1114
1115    to_sql_checked!();
1116}
1117
1118impl ToSql for Cow<'_, str> {
1119    fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1120        <&str as ToSql>::to_sql(&self.as_ref(), ty, w)
1121    }
1122
1123    fn accepts(ty: &Type) -> bool {
1124        <&str as ToSql>::accepts(ty)
1125    }
1126
1127    to_sql_checked!();
1128}
1129
1130impl ToSql for String {
1131    fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1132        <&str as ToSql>::to_sql(&&**self, ty, w)
1133    }
1134
1135    fn accepts(ty: &Type) -> bool {
1136        <&str as ToSql>::accepts(ty)
1137    }
1138
1139    to_sql_checked!();
1140}
1141
1142impl ToSql for Box<str> {
1143    fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1144        <&str as ToSql>::to_sql(&&**self, ty, w)
1145    }
1146
1147    fn accepts(ty: &Type) -> bool {
1148        <&str as ToSql>::accepts(ty)
1149    }
1150
1151    to_sql_checked!();
1152}
1153
1154macro_rules! simple_to {
1155    ($t:ty, $f:ident, $($expected:ident),+) => {
1156        impl ToSql for $t {
1157            fn to_sql(&self,
1158                      _: &Type,
1159                      w: &mut BytesMut)
1160                      -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1161                types::$f(*self, w);
1162                Ok(IsNull::No)
1163            }
1164
1165            accepts!($($expected),+);
1166
1167            to_sql_checked!();
1168        }
1169    }
1170}
1171
1172simple_to!(bool, bool_to_sql, BOOL);
1173simple_to!(i8, char_to_sql, CHAR);
1174simple_to!(i16, int2_to_sql, INT2);
1175simple_to!(i32, int4_to_sql, INT4);
1176simple_to!(u32, oid_to_sql, OID);
1177simple_to!(i64, int8_to_sql, INT8);
1178simple_to!(f32, float4_to_sql, FLOAT4);
1179simple_to!(f64, float8_to_sql, FLOAT8);
1180
1181impl<H> ToSql for HashMap<String, Option<String>, H>
1182where
1183    H: BuildHasher,
1184{
1185    fn to_sql(&self, _: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1186        types::hstore_to_sql(
1187            self.iter().map(|(k, v)| (&**k, v.as_ref().map(|v| &**v))),
1188            w,
1189        )?;
1190        Ok(IsNull::No)
1191    }
1192
1193    fn accepts(ty: &Type) -> bool {
1194        ty.name() == "hstore"
1195    }
1196
1197    to_sql_checked!();
1198}
1199
1200impl ToSql for SystemTime {
1201    fn to_sql(&self, _: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1202        let epoch = UNIX_EPOCH + Duration::from_secs(TIME_SEC_CONVERSION);
1203
1204        let to_usec =
1205            |d: Duration| d.as_secs() * USEC_PER_SEC + u64::from(d.subsec_nanos()) / NSEC_PER_USEC;
1206
1207        let time = match self.duration_since(epoch) {
1208            Ok(duration) => to_usec(duration) as i64,
1209            Err(e) => -(to_usec(e.duration()) as i64),
1210        };
1211
1212        types::timestamp_to_sql(time, w);
1213        Ok(IsNull::No)
1214    }
1215
1216    accepts!(TIMESTAMP, TIMESTAMPTZ);
1217
1218    to_sql_checked!();
1219}
1220
1221impl ToSql for IpAddr {
1222    fn to_sql(&self, _: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1223        let netmask = match self {
1224            IpAddr::V4(_) => 32,
1225            IpAddr::V6(_) => 128,
1226        };
1227        types::inet_to_sql(*self, netmask, w);
1228        Ok(IsNull::No)
1229    }
1230
1231    accepts!(INET);
1232
1233    to_sql_checked!();
1234}
1235
1236fn downcast(len: usize) -> Result<i32, Box<dyn Error + Sync + Send>> {
1237    if len > i32::MAX as usize {
1238        Err("value too large to transmit".into())
1239    } else {
1240        Ok(len as i32)
1241    }
1242}
1243
1244mod sealed {
1245    pub trait Sealed {}
1246}
1247
1248/// A trait used by clients to abstract over `&dyn ToSql` and `T: ToSql`.
1249///
1250/// This cannot be implemented outside of this crate.
1251pub trait BorrowToSql: sealed::Sealed {
1252    /// Returns a reference to `self` as a `ToSql` trait object.
1253    fn borrow_to_sql(&self) -> &dyn ToSql;
1254}
1255
1256impl sealed::Sealed for &dyn ToSql {}
1257
1258impl BorrowToSql for &dyn ToSql {
1259    #[inline]
1260    fn borrow_to_sql(&self) -> &dyn ToSql {
1261        *self
1262    }
1263}
1264
1265impl sealed::Sealed for Box<dyn ToSql + Sync + '_> {}
1266
1267impl BorrowToSql for Box<dyn ToSql + Sync + '_> {
1268    #[inline]
1269    fn borrow_to_sql(&self) -> &dyn ToSql {
1270        self.as_ref()
1271    }
1272}
1273
1274impl sealed::Sealed for Box<dyn ToSql + Sync + Send + '_> {}
1275impl BorrowToSql for Box<dyn ToSql + Sync + Send + '_> {
1276    #[inline]
1277    fn borrow_to_sql(&self) -> &dyn ToSql {
1278        self.as_ref()
1279    }
1280}
1281
1282impl sealed::Sealed for &(dyn ToSql + Sync) {}
1283
1284/// In async contexts it is sometimes necessary to have the additional
1285/// Sync requirement on parameters for queries since this enables the
1286/// resulting Futures to be Send, hence usable in, e.g., tokio::spawn.
1287/// This instance is provided for those cases.
1288impl BorrowToSql for &(dyn ToSql + Sync) {
1289    #[inline]
1290    fn borrow_to_sql(&self) -> &dyn ToSql {
1291        *self
1292    }
1293}
1294
1295impl<T> sealed::Sealed for T where T: ToSql {}
1296
1297impl<T> BorrowToSql for T
1298where
1299    T: ToSql,
1300{
1301    #[inline]
1302    fn borrow_to_sql(&self) -> &dyn ToSql {
1303        self
1304    }
1305}