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