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-eui48-0_4")]
272mod eui48_04;
273#[cfg(feature = "with-eui48-1")]
274mod eui48_1;
275#[cfg(feature = "with-geo-types-0_6")]
276mod geo_types_06;
277#[cfg(feature = "with-geo-types-0_7")]
278mod geo_types_07;
279#[cfg(feature = "with-jiff-0_1")]
280mod jiff_01;
281#[cfg(feature = "with-serde_json-1")]
282mod serde_json_1;
283#[cfg(feature = "with-smol_str-01")]
284mod smol_str_01;
285#[cfg(feature = "with-time-0_2")]
286mod time_02;
287#[cfg(feature = "with-time-0_3")]
288mod time_03;
289#[cfg(feature = "with-uuid-0_8")]
290mod uuid_08;
291#[cfg(feature = "with-uuid-1")]
292mod uuid_1;
293
294// The time::{date, time} macros produce compile errors if the crate package is renamed.
295#[cfg(feature = "with-time-0_2")]
296extern crate time_02 as time;
297
298mod pg_lsn;
299#[doc(hidden)]
300pub mod private;
301mod special;
302mod type_gen;
303
304/// A Postgres type.
305#[derive(PartialEq, Eq, Clone, Hash)]
306pub struct Type(Inner);
307
308impl fmt::Debug for Type {
309    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
310        fmt::Debug::fmt(&self.0, fmt)
311    }
312}
313
314impl fmt::Display for Type {
315    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
316        match self.schema() {
317            "public" | "pg_catalog" => {}
318            schema => write!(fmt, "{}.", schema)?,
319        }
320        fmt.write_str(self.name())
321    }
322}
323
324impl Type {
325    /// Creates a new `Type`.
326    pub fn new(name: String, oid: Oid, kind: Kind, schema: String) -> Type {
327        Type(Inner::Other(Arc::new(Other {
328            name,
329            oid,
330            kind,
331            schema,
332        })))
333    }
334
335    /// Returns the `Type` corresponding to the provided `Oid` if it
336    /// corresponds to a built-in type.
337    pub fn from_oid(oid: Oid) -> Option<Type> {
338        Inner::from_oid(oid).map(Type)
339    }
340
341    /// Returns the OID of the `Type`.
342    pub fn oid(&self) -> Oid {
343        self.0.oid()
344    }
345
346    /// Returns the kind of this type.
347    pub fn kind(&self) -> &Kind {
348        self.0.kind()
349    }
350
351    /// Returns the schema of this type.
352    pub fn schema(&self) -> &str {
353        match self.0 {
354            Inner::Other(ref u) => &u.schema,
355            _ => "pg_catalog",
356        }
357    }
358
359    /// Returns the name of this type.
360    pub fn name(&self) -> &str {
361        self.0.name()
362    }
363}
364
365/// Represents the kind of a Postgres type.
366#[derive(Debug, Clone, PartialEq, Eq, Hash)]
367#[non_exhaustive]
368pub enum Kind {
369    /// A simple type like `VARCHAR` or `INTEGER`.
370    Simple,
371    /// An enumerated type along with its variants.
372    Enum(Vec<String>),
373    /// A pseudo-type.
374    Pseudo,
375    /// An array type along with the type of its elements.
376    Array(Type),
377    /// A range type along with the type of its elements.
378    Range(Type),
379    /// A multirange type along with the type of its elements.
380    Multirange(Type),
381    /// A domain type along with its underlying type.
382    Domain(Type),
383    /// A composite type along with information about its fields.
384    Composite(Vec<Field>),
385}
386
387/// Information about a field of a composite type.
388#[derive(Debug, Clone, PartialEq, Eq, Hash)]
389pub struct Field {
390    name: String,
391    type_: Type,
392}
393
394impl Field {
395    /// Creates a new `Field`.
396    pub fn new(name: String, type_: Type) -> Field {
397        Field { name, type_ }
398    }
399
400    /// Returns the name of the field.
401    pub fn name(&self) -> &str {
402        &self.name
403    }
404
405    /// Returns the type of the field.
406    pub fn type_(&self) -> &Type {
407        &self.type_
408    }
409}
410
411/// An error indicating that a `NULL` Postgres value was passed to a `FromSql`
412/// implementation that does not support `NULL` values.
413#[derive(Debug, Clone, Copy)]
414pub struct WasNull;
415
416impl fmt::Display for WasNull {
417    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
418        fmt.write_str("a Postgres value was `NULL`")
419    }
420}
421
422impl Error for WasNull {}
423
424/// An error indicating that a conversion was attempted between incompatible
425/// Rust and Postgres types.
426#[derive(Debug)]
427pub struct WrongType {
428    postgres: Type,
429    rust: &'static str,
430}
431
432impl fmt::Display for WrongType {
433    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
434        write!(
435            fmt,
436            "cannot convert between the Rust type `{}` and the Postgres type `{}`",
437            self.rust, self.postgres,
438        )
439    }
440}
441
442impl Error for WrongType {}
443
444impl WrongType {
445    /// Creates a new `WrongType` error.
446    pub fn new<T>(ty: Type) -> WrongType {
447        WrongType {
448            postgres: ty,
449            rust: type_name::<T>(),
450        }
451    }
452}
453
454/// A trait for types that can be created from a Postgres value.
455///
456/// # Types
457///
458/// The following implementations are provided by this crate, along with the
459/// corresponding Postgres types:
460///
461/// | Rust type                         | Postgres type(s)                              |
462/// |-----------------------------------|-----------------------------------------------|
463/// | `bool`                            | BOOL                                          |
464/// | `i8`                              | "char"                                        |
465/// | `i16`                             | SMALLINT, SMALLSERIAL                         |
466/// | `i32`                             | INT, SERIAL                                   |
467/// | `u32`                             | OID                                           |
468/// | `i64`                             | BIGINT, BIGSERIAL                             |
469/// | `f32`                             | REAL                                          |
470/// | `f64`                             | DOUBLE PRECISION                              |
471/// | `&str`/`String`                   | VARCHAR, CHAR(n), TEXT, CITEXT, NAME, UNKNOWN |
472/// |                                   | LTREE, LQUERY, LTXTQUERY                      |
473/// | `&[u8]`/`Vec<u8>`                 | BYTEA                                         |
474/// | `HashMap<String, Option<String>>` | HSTORE                                        |
475/// | `SystemTime`                      | TIMESTAMP, TIMESTAMP WITH TIME ZONE           |
476/// | `IpAddr`                          | INET                                          |
477///
478/// In addition, some implementations are provided for types in third party
479/// crates. These are disabled by default; to opt into one of these
480/// implementations, activate the Cargo feature corresponding to the crate's
481/// name prefixed by `with-`. For example, the `with-serde_json-1` feature enables
482/// the implementation for the `serde_json::Value` type.
483///
484/// | Rust type                       | Postgres type(s)                    |
485/// |---------------------------------|-------------------------------------|
486/// | `chrono::NaiveDateTime`         | TIMESTAMP                           |
487/// | `chrono::DateTime<Utc>`         | TIMESTAMP WITH TIME ZONE            |
488/// | `chrono::DateTime<Local>`       | TIMESTAMP WITH TIME ZONE            |
489/// | `chrono::DateTime<FixedOffset>` | TIMESTAMP WITH TIME ZONE            |
490/// | `chrono::NaiveDate`             | DATE                                |
491/// | `chrono::NaiveTime`             | TIME                                |
492/// | `time::PrimitiveDateTime`       | TIMESTAMP                           |
493/// | `time::OffsetDateTime`          | TIMESTAMP WITH TIME ZONE            |
494/// | `time::Date`                    | DATE                                |
495/// | `time::Time`                    | TIME                                |
496/// | `jiff::civil::Date`             | DATE                                |
497/// | `jiff::civil::DateTime`         | TIMESTAMP                           |
498/// | `jiff::civil::Time`             | TIME                                |
499/// | `jiff::Timestamp`               | TIMESTAMP WITH TIME ZONE            |
500/// | `eui48::MacAddress`             | MACADDR                             |
501/// | `geo_types::Point<f64>`         | POINT                               |
502/// | `geo_types::Rect<f64>`          | BOX                                 |
503/// | `geo_types::LineString<f64>`    | PATH                                |
504/// | `serde_json::Value`             | JSON, JSONB                         |
505/// | `uuid::Uuid`                    | UUID                                |
506/// | `bit_vec::BitVec`               | BIT, VARBIT                         |
507/// | `eui48::MacAddress`             | MACADDR                             |
508/// | `cidr::InetCidr`                | CIDR                                |
509/// | `cidr::InetAddr`                | INET                                |
510/// | `smol_str::SmolStr`             | VARCHAR, CHAR(n), TEXT, CITEXT,     |
511/// |                                 | NAME, UNKNOWN, LTREE, LQUERY,       |
512/// |                                 | LTXTQUERY                           |
513///
514/// # Nullability
515///
516/// In addition to the types listed above, `FromSql` is implemented for
517/// `Option<T>` where `T` implements `FromSql`. An `Option<T>` represents a
518/// nullable Postgres value.
519///
520/// # Arrays
521///
522/// `FromSql` is implemented for `Vec<T>`, `Box<[T]>` and `[T; N]` where `T`
523/// implements `FromSql`, and corresponds to one-dimensional Postgres arrays.
524///
525/// **Note:** the impl for arrays only exist when the Cargo feature `array-impls`
526/// is enabled.
527pub trait FromSql<'a>: Sized {
528    /// Creates a new value of this type from a buffer of data of the specified
529    /// Postgres `Type` in its binary format.
530    ///
531    /// The caller of this method is responsible for ensuring that this type
532    /// is compatible with the Postgres `Type`.
533    fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Self, Box<dyn Error + Sync + Send>>;
534
535    /// Creates a new value of this type from a `NULL` SQL value.
536    ///
537    /// The caller of this method is responsible for ensuring that this type
538    /// is compatible with the Postgres `Type`.
539    ///
540    /// The default implementation returns `Err(Box::new(WasNull))`.
541    #[allow(unused_variables)]
542    fn from_sql_null(ty: &Type) -> Result<Self, Box<dyn Error + Sync + Send>> {
543        Err(Box::new(WasNull))
544    }
545
546    /// A convenience function that delegates to `from_sql` and `from_sql_null` depending on the
547    /// value of `raw`.
548    fn from_sql_nullable(
549        ty: &Type,
550        raw: Option<&'a [u8]>,
551    ) -> Result<Self, Box<dyn Error + Sync + Send>> {
552        match raw {
553            Some(raw) => Self::from_sql(ty, raw),
554            None => Self::from_sql_null(ty),
555        }
556    }
557
558    /// Determines if a value of this type can be created from the specified
559    /// Postgres `Type`.
560    fn accepts(ty: &Type) -> bool;
561}
562
563/// A trait for types which can be created from a Postgres value without borrowing any data.
564///
565/// This is primarily useful for trait bounds on functions.
566pub trait FromSqlOwned: for<'a> FromSql<'a> {}
567
568impl<T> FromSqlOwned for T where T: for<'a> FromSql<'a> {}
569
570impl<'a, T: FromSql<'a>> FromSql<'a> for Option<T> {
571    fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Option<T>, Box<dyn Error + Sync + Send>> {
572        <T as FromSql>::from_sql(ty, raw).map(Some)
573    }
574
575    fn from_sql_null(_: &Type) -> Result<Option<T>, Box<dyn Error + Sync + Send>> {
576        Ok(None)
577    }
578
579    fn accepts(ty: &Type) -> bool {
580        <T as FromSql>::accepts(ty)
581    }
582}
583
584impl<'a, T: FromSql<'a>> FromSql<'a> for Vec<T> {
585    fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Vec<T>, Box<dyn Error + Sync + Send>> {
586        let member_type = match *ty.kind() {
587            Kind::Array(ref member) => member,
588            _ => panic!("expected array type"),
589        };
590
591        let array = types::array_from_sql(raw)?;
592        if array.dimensions().count()? > 1 {
593            return Err("array contains too many dimensions".into());
594        }
595
596        array
597            .values()
598            .map(|v| T::from_sql_nullable(member_type, v))
599            .collect()
600    }
601
602    fn accepts(ty: &Type) -> bool {
603        match *ty.kind() {
604            Kind::Array(ref inner) => T::accepts(inner),
605            _ => false,
606        }
607    }
608}
609
610#[cfg(feature = "array-impls")]
611impl<'a, T: FromSql<'a>, const N: usize> FromSql<'a> for [T; N] {
612    fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Self, Box<dyn Error + Sync + Send>> {
613        let member_type = match *ty.kind() {
614            Kind::Array(ref member) => member,
615            _ => panic!("expected array type"),
616        };
617
618        let array = types::array_from_sql(raw)?;
619        if array.dimensions().count()? > 1 {
620            return Err("array contains too many dimensions".into());
621        }
622
623        let mut values = array.values();
624        let out = array_init::try_array_init(|i| {
625            let v = values
626                .next()?
627                .ok_or_else(|| -> Box<dyn Error + Sync + Send> {
628                    format!("too few elements in array (expected {}, got {})", N, i).into()
629                })?;
630            T::from_sql_nullable(member_type, v)
631        })?;
632        if values.next()?.is_some() {
633            return Err(format!(
634                "excess elements in array (expected {}, got more than that)",
635                N,
636            )
637            .into());
638        }
639
640        Ok(out)
641    }
642
643    fn accepts(ty: &Type) -> bool {
644        match *ty.kind() {
645            Kind::Array(ref inner) => T::accepts(inner),
646            _ => false,
647        }
648    }
649}
650
651impl<'a, T: FromSql<'a>> FromSql<'a> for Box<[T]> {
652    fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Self, Box<dyn Error + Sync + Send>> {
653        Vec::<T>::from_sql(ty, raw).map(Vec::into_boxed_slice)
654    }
655
656    fn accepts(ty: &Type) -> bool {
657        Vec::<T>::accepts(ty)
658    }
659}
660
661impl<'a> FromSql<'a> for Vec<u8> {
662    fn from_sql(_: &Type, raw: &'a [u8]) -> Result<Vec<u8>, Box<dyn Error + Sync + Send>> {
663        Ok(types::bytea_from_sql(raw).to_owned())
664    }
665
666    accepts!(BYTEA);
667}
668
669impl<'a> FromSql<'a> for &'a [u8] {
670    fn from_sql(_: &Type, raw: &'a [u8]) -> Result<&'a [u8], Box<dyn Error + Sync + Send>> {
671        Ok(types::bytea_from_sql(raw))
672    }
673
674    accepts!(BYTEA);
675}
676
677impl<'a> FromSql<'a> for String {
678    fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<String, Box<dyn Error + Sync + Send>> {
679        <&str as FromSql>::from_sql(ty, raw).map(ToString::to_string)
680    }
681
682    fn accepts(ty: &Type) -> bool {
683        <&str as FromSql>::accepts(ty)
684    }
685}
686
687impl<'a> FromSql<'a> for Box<str> {
688    fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Box<str>, Box<dyn Error + Sync + Send>> {
689        <&str as FromSql>::from_sql(ty, raw)
690            .map(ToString::to_string)
691            .map(String::into_boxed_str)
692    }
693
694    fn accepts(ty: &Type) -> bool {
695        <&str as FromSql>::accepts(ty)
696    }
697}
698
699impl<'a> FromSql<'a> for &'a str {
700    fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<&'a str, Box<dyn Error + Sync + Send>> {
701        match *ty {
702            ref ty if ty.name() == "ltree" => types::ltree_from_sql(raw),
703            ref ty if ty.name() == "lquery" => types::lquery_from_sql(raw),
704            ref ty if ty.name() == "ltxtquery" => types::ltxtquery_from_sql(raw),
705            _ => types::text_from_sql(raw),
706        }
707    }
708
709    fn accepts(ty: &Type) -> bool {
710        match *ty {
711            Type::VARCHAR | Type::TEXT | Type::BPCHAR | Type::NAME | Type::UNKNOWN => true,
712            ref ty
713                if (ty.name() == "citext"
714                    || ty.name() == "ltree"
715                    || ty.name() == "lquery"
716                    || ty.name() == "ltxtquery") =>
717            {
718                true
719            }
720            _ => false,
721        }
722    }
723}
724
725macro_rules! simple_from {
726    ($t:ty, $f:ident, $($expected:ident),+) => {
727        impl<'a> FromSql<'a> for $t {
728            fn from_sql(_: &Type, raw: &'a [u8]) -> Result<$t, Box<dyn Error + Sync + Send>> {
729                types::$f(raw)
730            }
731
732            accepts!($($expected),+);
733        }
734    }
735}
736
737simple_from!(bool, bool_from_sql, BOOL);
738simple_from!(i8, char_from_sql, CHAR);
739simple_from!(i16, int2_from_sql, INT2);
740simple_from!(i32, int4_from_sql, INT4);
741simple_from!(u32, oid_from_sql, OID);
742simple_from!(i64, int8_from_sql, INT8);
743simple_from!(f32, float4_from_sql, FLOAT4);
744simple_from!(f64, float8_from_sql, FLOAT8);
745
746impl<'a, S> FromSql<'a> for HashMap<String, Option<String>, S>
747where
748    S: Default + BuildHasher,
749{
750    fn from_sql(
751        _: &Type,
752        raw: &'a [u8],
753    ) -> Result<HashMap<String, Option<String>, S>, Box<dyn Error + Sync + Send>> {
754        types::hstore_from_sql(raw)?
755            .map(|(k, v)| Ok((k.to_owned(), v.map(str::to_owned))))
756            .collect()
757    }
758
759    fn accepts(ty: &Type) -> bool {
760        ty.name() == "hstore"
761    }
762}
763
764impl<'a> FromSql<'a> for SystemTime {
765    fn from_sql(_: &Type, raw: &'a [u8]) -> Result<SystemTime, Box<dyn Error + Sync + Send>> {
766        let time = types::timestamp_from_sql(raw)?;
767        let epoch = UNIX_EPOCH + Duration::from_secs(TIME_SEC_CONVERSION);
768
769        let negative = time < 0;
770        let time = time.unsigned_abs();
771
772        let secs = time / USEC_PER_SEC;
773        let nsec = (time % USEC_PER_SEC) * NSEC_PER_USEC;
774        let offset = Duration::new(secs, nsec as u32);
775
776        let time = if negative {
777            epoch - offset
778        } else {
779            epoch + offset
780        };
781
782        Ok(time)
783    }
784
785    accepts!(TIMESTAMP, TIMESTAMPTZ);
786}
787
788impl<'a> FromSql<'a> for IpAddr {
789    fn from_sql(_: &Type, raw: &'a [u8]) -> Result<IpAddr, Box<dyn Error + Sync + Send>> {
790        let inet = types::inet_from_sql(raw)?;
791        Ok(inet.addr())
792    }
793
794    accepts!(INET);
795}
796
797/// An enum representing the nullability of a Postgres value.
798pub enum IsNull {
799    /// The value is NULL.
800    Yes,
801    /// The value is not NULL.
802    No,
803}
804
805/// A trait for types that can be converted into Postgres values.
806///
807/// # Types
808///
809/// The following implementations are provided by this crate, along with the
810/// corresponding Postgres types:
811///
812/// | Rust type                         | Postgres type(s)                     |
813/// |-----------------------------------|--------------------------------------|
814/// | `bool`                            | BOOL                                 |
815/// | `i8`                              | "char"                               |
816/// | `i16`                             | SMALLINT, SMALLSERIAL                |
817/// | `i32`                             | INT, SERIAL                          |
818/// | `u32`                             | OID                                  |
819/// | `i64`                             | BIGINT, BIGSERIAL                    |
820/// | `f32`                             | REAL                                 |
821/// | `f64`                             | DOUBLE PRECISION                     |
822/// | `&str`/`String`                   | VARCHAR, CHAR(n), TEXT, CITEXT, NAME |
823/// |                                   | LTREE, LQUERY, LTXTQUERY             |
824/// | `&[u8]`/`Vec<u8>`/`[u8; N]`       | BYTEA                                |
825/// | `HashMap<String, Option<String>>` | HSTORE                               |
826/// | `SystemTime`                      | TIMESTAMP, TIMESTAMP WITH TIME ZONE  |
827/// | `IpAddr`                          | INET                                 |
828///
829/// In addition, some implementations are provided for types in third party
830/// crates. These are disabled by default; to opt into one of these
831/// implementations, activate the Cargo feature corresponding to the crate's
832/// name prefixed by `with-`. For example, the `with-serde_json-1` feature enables
833/// the implementation for the `serde_json::Value` type.
834///
835/// | Rust type                       | Postgres type(s)                    |
836/// |---------------------------------|-------------------------------------|
837/// | `chrono::NaiveDateTime`         | TIMESTAMP                           |
838/// | `chrono::DateTime<Utc>`         | TIMESTAMP WITH TIME ZONE            |
839/// | `chrono::DateTime<Local>`       | TIMESTAMP WITH TIME ZONE            |
840/// | `chrono::DateTime<FixedOffset>` | TIMESTAMP WITH TIME ZONE            |
841/// | `chrono::NaiveDate`             | DATE                                |
842/// | `chrono::NaiveTime`             | TIME                                |
843/// | `time::PrimitiveDateTime`       | TIMESTAMP                           |
844/// | `time::OffsetDateTime`          | TIMESTAMP WITH TIME ZONE            |
845/// | `time::Date`                    | DATE                                |
846/// | `time::Time`                    | TIME                                |
847/// | `eui48::MacAddress`             | MACADDR                             |
848/// | `geo_types::Point<f64>`         | POINT                               |
849/// | `geo_types::Rect<f64>`          | BOX                                 |
850/// | `geo_types::LineString<f64>`    | PATH                                |
851/// | `serde_json::Value`             | JSON, JSONB                         |
852/// | `uuid::Uuid`                    | UUID                                |
853/// | `bit_vec::BitVec`               | BIT, VARBIT                         |
854/// | `eui48::MacAddress`             | MACADDR                             |
855///
856/// # Nullability
857///
858/// In addition to the types listed above, `ToSql` is implemented for
859/// `Option<T>` where `T` implements `ToSql`. An `Option<T>` represents a
860/// nullable Postgres value.
861///
862/// # Arrays
863///
864/// `ToSql` is implemented for `[u8; N]`, `Vec<T>`, `&[T]`, `Box<[T]>` and `[T; N]`
865/// where `T` implements `ToSql` and `N` is const usize, and corresponds to one-dimensional
866/// Postgres arrays with an index offset of 1.
867///
868/// **Note:** the impl for arrays only exist when the Cargo feature `array-impls`
869/// is enabled.
870pub trait ToSql: fmt::Debug {
871    /// Converts the value of `self` into the binary format of the specified
872    /// Postgres `Type`, appending it to `out`.
873    ///
874    /// The caller of this method is responsible for ensuring that this type
875    /// is compatible with the Postgres `Type`.
876    ///
877    /// The return value indicates if this value should be represented as
878    /// `NULL`. If this is the case, implementations **must not** write
879    /// anything to `out`.
880    fn to_sql(&self, ty: &Type, out: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>>
881    where
882        Self: Sized;
883
884    /// Determines if a value of this type can be converted to the specified
885    /// Postgres `Type`.
886    fn accepts(ty: &Type) -> bool
887    where
888        Self: Sized;
889
890    /// An adaptor method used internally by Rust-Postgres.
891    ///
892    /// *All* implementations of this method should be generated by the
893    /// `to_sql_checked!()` macro.
894    fn to_sql_checked(
895        &self,
896        ty: &Type,
897        out: &mut BytesMut,
898    ) -> Result<IsNull, Box<dyn Error + Sync + Send>>;
899
900    /// Specify the encode format
901    fn encode_format(&self, _ty: &Type) -> Format {
902        Format::Binary
903    }
904}
905
906/// Supported Postgres message format types
907///
908/// Using Text format in a message assumes a Postgres `SERVER_ENCODING` of `UTF8`
909#[derive(Clone, Copy, Debug)]
910pub enum Format {
911    /// Text format (UTF-8)
912    Text,
913    /// Compact, typed binary format
914    Binary,
915}
916
917impl<'a, T> ToSql for &'a T
918where
919    T: ToSql,
920{
921    fn to_sql(
922        &self,
923        ty: &Type,
924        out: &mut BytesMut,
925    ) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
926        (*self).to_sql(ty, out)
927    }
928
929    fn accepts(ty: &Type) -> bool {
930        T::accepts(ty)
931    }
932
933    fn encode_format(&self, ty: &Type) -> Format {
934        (*self).encode_format(ty)
935    }
936
937    to_sql_checked!();
938}
939
940impl<T: ToSql> ToSql for Option<T> {
941    fn to_sql(
942        &self,
943        ty: &Type,
944        out: &mut BytesMut,
945    ) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
946        match *self {
947            Some(ref val) => val.to_sql(ty, out),
948            None => Ok(IsNull::Yes),
949        }
950    }
951
952    fn accepts(ty: &Type) -> bool {
953        <T as ToSql>::accepts(ty)
954    }
955
956    fn encode_format(&self, ty: &Type) -> Format {
957        match self {
958            Some(ref val) => val.encode_format(ty),
959            None => Format::Binary,
960        }
961    }
962
963    to_sql_checked!();
964}
965
966impl<'a, T: ToSql> ToSql for &'a [T] {
967    fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
968        let member_type = match *ty.kind() {
969            Kind::Array(ref member) => member,
970            _ => panic!("expected array type"),
971        };
972
973        // Arrays are normally one indexed by default but oidvector and int2vector *require* zero indexing
974        let lower_bound = match *ty {
975            Type::OID_VECTOR | Type::INT2_VECTOR => 0,
976            _ => 1,
977        };
978
979        let dimension = ArrayDimension {
980            len: downcast(self.len())?,
981            lower_bound,
982        };
983
984        types::array_to_sql(
985            Some(dimension),
986            member_type.oid(),
987            self.iter(),
988            |e, w| match e.to_sql(member_type, w)? {
989                IsNull::No => Ok(postgres_protocol::IsNull::No),
990                IsNull::Yes => Ok(postgres_protocol::IsNull::Yes),
991            },
992            w,
993        )?;
994        Ok(IsNull::No)
995    }
996
997    fn accepts(ty: &Type) -> bool {
998        match *ty.kind() {
999            Kind::Array(ref member) => T::accepts(member),
1000            _ => false,
1001        }
1002    }
1003
1004    to_sql_checked!();
1005}
1006
1007impl<'a> ToSql for &'a [u8] {
1008    fn to_sql(&self, _: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1009        types::bytea_to_sql(self, w);
1010        Ok(IsNull::No)
1011    }
1012
1013    accepts!(BYTEA);
1014
1015    to_sql_checked!();
1016}
1017
1018#[cfg(feature = "array-impls")]
1019impl<const N: usize> ToSql for [u8; N] {
1020    fn to_sql(&self, _: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1021        types::bytea_to_sql(&self[..], w);
1022        Ok(IsNull::No)
1023    }
1024
1025    accepts!(BYTEA);
1026
1027    to_sql_checked!();
1028}
1029
1030#[cfg(feature = "array-impls")]
1031impl<T: ToSql, const N: usize> ToSql for [T; N] {
1032    fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1033        <&[T] as ToSql>::to_sql(&&self[..], ty, w)
1034    }
1035
1036    fn accepts(ty: &Type) -> bool {
1037        <&[T] as ToSql>::accepts(ty)
1038    }
1039
1040    to_sql_checked!();
1041}
1042
1043impl<T: ToSql> ToSql for Vec<T> {
1044    fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1045        <&[T] as ToSql>::to_sql(&&**self, ty, w)
1046    }
1047
1048    fn accepts(ty: &Type) -> bool {
1049        <&[T] as ToSql>::accepts(ty)
1050    }
1051
1052    to_sql_checked!();
1053}
1054
1055impl<T: ToSql> ToSql for Box<[T]> {
1056    fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1057        <&[T] as ToSql>::to_sql(&&**self, ty, w)
1058    }
1059
1060    fn accepts(ty: &Type) -> bool {
1061        <&[T] as ToSql>::accepts(ty)
1062    }
1063
1064    to_sql_checked!();
1065}
1066
1067impl<'a> ToSql for Cow<'a, [u8]> {
1068    fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1069        <&[u8] as ToSql>::to_sql(&self.as_ref(), ty, w)
1070    }
1071
1072    fn accepts(ty: &Type) -> bool {
1073        <&[u8] as ToSql>::accepts(ty)
1074    }
1075
1076    to_sql_checked!();
1077}
1078
1079impl ToSql for Vec<u8> {
1080    fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1081        <&[u8] as ToSql>::to_sql(&&**self, ty, w)
1082    }
1083
1084    fn accepts(ty: &Type) -> bool {
1085        <&[u8] as ToSql>::accepts(ty)
1086    }
1087
1088    to_sql_checked!();
1089}
1090
1091impl<'a> ToSql for &'a str {
1092    fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1093        match ty.name() {
1094            "ltree" => types::ltree_to_sql(self, w),
1095            "lquery" => types::lquery_to_sql(self, w),
1096            "ltxtquery" => types::ltxtquery_to_sql(self, w),
1097            _ => types::text_to_sql(self, w),
1098        }
1099        Ok(IsNull::No)
1100    }
1101
1102    fn accepts(ty: &Type) -> bool {
1103        matches!(
1104            *ty,
1105            Type::VARCHAR | Type::TEXT | Type::BPCHAR | Type::NAME | Type::UNKNOWN
1106        ) || matches!(ty.name(), "citext" | "ltree" | "lquery" | "ltxtquery")
1107    }
1108
1109    to_sql_checked!();
1110}
1111
1112impl<'a> ToSql for Cow<'a, str> {
1113    fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1114        <&str as ToSql>::to_sql(&self.as_ref(), ty, w)
1115    }
1116
1117    fn accepts(ty: &Type) -> bool {
1118        <&str as ToSql>::accepts(ty)
1119    }
1120
1121    to_sql_checked!();
1122}
1123
1124impl ToSql for String {
1125    fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1126        <&str as ToSql>::to_sql(&&**self, ty, w)
1127    }
1128
1129    fn accepts(ty: &Type) -> bool {
1130        <&str as ToSql>::accepts(ty)
1131    }
1132
1133    to_sql_checked!();
1134}
1135
1136impl ToSql for Box<str> {
1137    fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1138        <&str as ToSql>::to_sql(&&**self, ty, w)
1139    }
1140
1141    fn accepts(ty: &Type) -> bool {
1142        <&str as ToSql>::accepts(ty)
1143    }
1144
1145    to_sql_checked!();
1146}
1147
1148macro_rules! simple_to {
1149    ($t:ty, $f:ident, $($expected:ident),+) => {
1150        impl ToSql for $t {
1151            fn to_sql(&self,
1152                      _: &Type,
1153                      w: &mut BytesMut)
1154                      -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1155                types::$f(*self, w);
1156                Ok(IsNull::No)
1157            }
1158
1159            accepts!($($expected),+);
1160
1161            to_sql_checked!();
1162        }
1163    }
1164}
1165
1166simple_to!(bool, bool_to_sql, BOOL);
1167simple_to!(i8, char_to_sql, CHAR);
1168simple_to!(i16, int2_to_sql, INT2);
1169simple_to!(i32, int4_to_sql, INT4);
1170simple_to!(u32, oid_to_sql, OID);
1171simple_to!(i64, int8_to_sql, INT8);
1172simple_to!(f32, float4_to_sql, FLOAT4);
1173simple_to!(f64, float8_to_sql, FLOAT8);
1174
1175impl<H> ToSql for HashMap<String, Option<String>, H>
1176where
1177    H: BuildHasher,
1178{
1179    fn to_sql(&self, _: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1180        types::hstore_to_sql(
1181            self.iter().map(|(k, v)| (&**k, v.as_ref().map(|v| &**v))),
1182            w,
1183        )?;
1184        Ok(IsNull::No)
1185    }
1186
1187    fn accepts(ty: &Type) -> bool {
1188        ty.name() == "hstore"
1189    }
1190
1191    to_sql_checked!();
1192}
1193
1194impl ToSql for SystemTime {
1195    fn to_sql(&self, _: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1196        let epoch = UNIX_EPOCH + Duration::from_secs(TIME_SEC_CONVERSION);
1197
1198        let to_usec =
1199            |d: Duration| d.as_secs() * USEC_PER_SEC + u64::from(d.subsec_nanos()) / NSEC_PER_USEC;
1200
1201        let time = match self.duration_since(epoch) {
1202            Ok(duration) => to_usec(duration) as i64,
1203            Err(e) => -(to_usec(e.duration()) as i64),
1204        };
1205
1206        types::timestamp_to_sql(time, w);
1207        Ok(IsNull::No)
1208    }
1209
1210    accepts!(TIMESTAMP, TIMESTAMPTZ);
1211
1212    to_sql_checked!();
1213}
1214
1215impl ToSql for IpAddr {
1216    fn to_sql(&self, _: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1217        let netmask = match self {
1218            IpAddr::V4(_) => 32,
1219            IpAddr::V6(_) => 128,
1220        };
1221        types::inet_to_sql(*self, netmask, w);
1222        Ok(IsNull::No)
1223    }
1224
1225    accepts!(INET);
1226
1227    to_sql_checked!();
1228}
1229
1230fn downcast(len: usize) -> Result<i32, Box<dyn Error + Sync + Send>> {
1231    if len > i32::MAX as usize {
1232        Err("value too large to transmit".into())
1233    } else {
1234        Ok(len as i32)
1235    }
1236}
1237
1238mod sealed {
1239    pub trait Sealed {}
1240}
1241
1242/// A trait used by clients to abstract over `&dyn ToSql` and `T: ToSql`.
1243///
1244/// This cannot be implemented outside of this crate.
1245pub trait BorrowToSql: sealed::Sealed {
1246    /// Returns a reference to `self` as a `ToSql` trait object.
1247    fn borrow_to_sql(&self) -> &dyn ToSql;
1248}
1249
1250impl sealed::Sealed for &dyn ToSql {}
1251
1252impl BorrowToSql for &dyn ToSql {
1253    #[inline]
1254    fn borrow_to_sql(&self) -> &dyn ToSql {
1255        *self
1256    }
1257}
1258
1259impl<'a> sealed::Sealed for Box<dyn ToSql + Sync + 'a> {}
1260
1261impl<'a> BorrowToSql for Box<dyn ToSql + Sync + 'a> {
1262    #[inline]
1263    fn borrow_to_sql(&self) -> &dyn ToSql {
1264        self.as_ref()
1265    }
1266}
1267
1268impl<'a> sealed::Sealed for Box<dyn ToSql + Sync + Send + 'a> {}
1269impl<'a> BorrowToSql for Box<dyn ToSql + Sync + Send + 'a> {
1270    #[inline]
1271    fn borrow_to_sql(&self) -> &dyn ToSql {
1272        self.as_ref()
1273    }
1274}
1275
1276impl sealed::Sealed for &(dyn ToSql + Sync) {}
1277
1278/// In async contexts it is sometimes necessary to have the additional
1279/// Sync requirement on parameters for queries since this enables the
1280/// resulting Futures to be Send, hence usable in, e.g., tokio::spawn.
1281/// This instance is provided for those cases.
1282impl BorrowToSql for &(dyn ToSql + Sync) {
1283    #[inline]
1284    fn borrow_to_sql(&self) -> &dyn ToSql {
1285        *self
1286    }
1287}
1288
1289impl<T> sealed::Sealed for T where T: ToSql {}
1290
1291impl<T> BorrowToSql for T
1292where
1293    T: ToSql,
1294{
1295    #[inline]
1296    fn borrow_to_sql(&self) -> &dyn ToSql {
1297        self
1298    }
1299}