1#![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
213const TIME_SEC_CONVERSION: u64 = 946_684_800;
215const USEC_PER_SEC: u64 = 1_000_000;
216const NSEC_PER_USEC: u64 = 1_000;
217
218#[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#[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#[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-bit-vec-0_9")]
272mod bit_vec_09;
273#[cfg(feature = "with-chrono-0_4")]
274mod chrono_04;
275#[cfg(feature = "with-cidr-0_2")]
276mod cidr_02;
277#[cfg(feature = "with-cidr-0_3")]
278mod cidr_03;
279#[cfg(feature = "with-eui48-0_4")]
280mod eui48_04;
281#[cfg(feature = "with-eui48-1")]
282mod eui48_1;
283#[cfg(feature = "with-geo-types-0_6")]
284mod geo_types_06;
285#[cfg(feature = "with-geo-types-0_7")]
286mod geo_types_07;
287#[cfg(feature = "with-jiff-0_1")]
288mod jiff_01;
289#[cfg(feature = "with-jiff-0_2")]
290mod jiff_02;
291#[cfg(feature = "with-serde_json-1")]
292mod serde_json_1;
293#[cfg(feature = "with-smol_str-01")]
294mod smol_str_01;
295#[cfg(feature = "with-time-0_2")]
296mod time_02;
297#[cfg(feature = "with-time-0_3")]
298mod time_03;
299#[cfg(feature = "with-uuid-0_8")]
300mod uuid_08;
301#[cfg(feature = "with-uuid-1")]
302mod uuid_1;
303
304#[cfg(feature = "with-time-0_2")]
306extern crate time_02 as time;
307
308mod pg_lsn;
309#[doc(hidden)]
310pub mod private;
311mod special;
312mod type_gen;
313
314#[derive(PartialEq, Eq, Clone, Hash)]
316pub struct Type(Inner);
317
318impl fmt::Debug for Type {
319 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
320 fmt::Debug::fmt(&self.0, fmt)
321 }
322}
323
324impl fmt::Display for Type {
325 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
326 match self.schema() {
327 "public" | "pg_catalog" => {}
328 schema => write!(fmt, "{schema}.")?,
329 }
330 fmt.write_str(self.name())
331 }
332}
333
334impl Type {
335 pub fn new(name: String, oid: Oid, kind: Kind, schema: String) -> Type {
337 Type(Inner::Other(Arc::new(Other {
338 name,
339 oid,
340 kind,
341 schema,
342 })))
343 }
344
345 pub fn from_oid(oid: Oid) -> Option<Type> {
348 Inner::from_oid(oid).map(Type)
349 }
350
351 pub fn oid(&self) -> Oid {
353 self.0.oid()
354 }
355
356 pub fn kind(&self) -> &Kind {
358 self.0.kind()
359 }
360
361 pub fn schema(&self) -> &str {
363 match self.0 {
364 Inner::Other(ref u) => &u.schema,
365 _ => "pg_catalog",
366 }
367 }
368
369 pub fn name(&self) -> &str {
371 self.0.name()
372 }
373}
374
375#[derive(Debug, Clone, PartialEq, Eq, Hash)]
377#[non_exhaustive]
378pub enum Kind {
379 Simple,
381 Enum(Vec<String>),
383 Pseudo,
385 Array(Type),
387 Range(Type),
389 Multirange(Type),
391 Domain(Type),
393 Composite(Vec<Field>),
395}
396
397#[derive(Debug, Clone, PartialEq, Eq, Hash)]
399pub struct Field {
400 name: String,
401 type_: Type,
402}
403
404impl Field {
405 pub fn new(name: String, type_: Type) -> Field {
407 Field { name, type_ }
408 }
409
410 pub fn name(&self) -> &str {
412 &self.name
413 }
414
415 pub fn type_(&self) -> &Type {
417 &self.type_
418 }
419}
420
421#[derive(Debug, Clone, Copy)]
424pub struct WasNull;
425
426impl fmt::Display for WasNull {
427 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
428 fmt.write_str("a Postgres value was `NULL`")
429 }
430}
431
432impl Error for WasNull {}
433
434#[derive(Debug)]
437pub struct WrongType {
438 postgres: Type,
439 rust: &'static str,
440}
441
442impl fmt::Display for WrongType {
443 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
444 write!(
445 fmt,
446 "cannot convert between the Rust type `{}` and the Postgres type `{}`",
447 self.rust, self.postgres,
448 )
449 }
450}
451
452impl Error for WrongType {}
453
454impl WrongType {
455 pub fn new<T>(ty: Type) -> WrongType {
457 WrongType {
458 postgres: ty,
459 rust: type_name::<T>(),
460 }
461 }
462}
463
464pub trait FromSql<'a>: Sized {
540 fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Self, Box<dyn Error + Sync + Send>>;
546
547 #[allow(unused_variables)]
554 fn from_sql_null(ty: &Type) -> Result<Self, Box<dyn Error + Sync + Send>> {
555 Err(Box::new(WasNull))
556 }
557
558 fn from_sql_nullable(
561 ty: &Type,
562 raw: Option<&'a [u8]>,
563 ) -> Result<Self, Box<dyn Error + Sync + Send>> {
564 match raw {
565 Some(raw) => Self::from_sql(ty, raw),
566 None => Self::from_sql_null(ty),
567 }
568 }
569
570 fn accepts(ty: &Type) -> bool;
573}
574
575pub trait FromSqlOwned: for<'a> FromSql<'a> {}
579
580impl<T> FromSqlOwned for T where T: for<'a> FromSql<'a> {}
581
582impl<'a, T: FromSql<'a>> FromSql<'a> for Option<T> {
583 fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Option<T>, Box<dyn Error + Sync + Send>> {
584 <T as FromSql>::from_sql(ty, raw).map(Some)
585 }
586
587 fn from_sql_null(_: &Type) -> Result<Option<T>, Box<dyn Error + Sync + Send>> {
588 Ok(None)
589 }
590
591 fn accepts(ty: &Type) -> bool {
592 <T as FromSql>::accepts(ty)
593 }
594}
595
596impl<'a, T: FromSql<'a>> FromSql<'a> for Vec<T> {
597 fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Vec<T>, Box<dyn Error + Sync + Send>> {
598 let member_type = match *ty.kind() {
599 Kind::Array(ref member) => member,
600 _ => panic!("expected array type"),
601 };
602
603 let array = types::array_from_sql(raw)?;
604 if array.dimensions().count()? > 1 {
605 return Err("array contains too many dimensions".into());
606 }
607
608 array
609 .values()
610 .map(|v| T::from_sql_nullable(member_type, v))
611 .collect()
612 }
613
614 fn accepts(ty: &Type) -> bool {
615 match *ty.kind() {
616 Kind::Array(ref inner) => T::accepts(inner),
617 _ => false,
618 }
619 }
620}
621
622#[cfg(feature = "array-impls")]
623impl<'a, T: FromSql<'a>, const N: usize> FromSql<'a> for [T; N] {
624 fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Self, Box<dyn Error + Sync + Send>> {
625 let member_type = match *ty.kind() {
626 Kind::Array(ref member) => member,
627 _ => panic!("expected array type"),
628 };
629
630 let array = types::array_from_sql(raw)?;
631 if array.dimensions().count()? > 1 {
632 return Err("array contains too many dimensions".into());
633 }
634
635 let mut values = array.values();
636 let out = array_init::try_array_init(|i| {
637 let v = values
638 .next()?
639 .ok_or_else(|| -> Box<dyn Error + Sync + Send> {
640 format!("too few elements in array (expected {N}, got {i})").into()
641 })?;
642 T::from_sql_nullable(member_type, v)
643 })?;
644 if values.next()?.is_some() {
645 return Err(
646 format!("excess elements in array (expected {N}, got more than that)",).into(),
647 );
648 }
649
650 Ok(out)
651 }
652
653 fn accepts(ty: &Type) -> bool {
654 match *ty.kind() {
655 Kind::Array(ref inner) => T::accepts(inner),
656 _ => false,
657 }
658 }
659}
660
661impl<'a, T: FromSql<'a>> FromSql<'a> for Box<T> {
662 fn from_sql(ty: &Type, row: &'a [u8]) -> Result<Self, Box<dyn Error + Sync + Send>> {
663 T::from_sql(ty, row).map(Box::new)
664 }
665
666 fn accepts(ty: &Type) -> bool {
667 T::accepts(ty)
668 }
669}
670
671impl<'a, T: FromSql<'a>> FromSql<'a> for Box<[T]> {
672 fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Self, Box<dyn Error + Sync + Send>> {
673 Vec::<T>::from_sql(ty, raw).map(Vec::into_boxed_slice)
674 }
675
676 fn accepts(ty: &Type) -> bool {
677 Vec::<T>::accepts(ty)
678 }
679}
680
681impl<'a> FromSql<'a> for Vec<u8> {
682 fn from_sql(_: &Type, raw: &'a [u8]) -> Result<Vec<u8>, Box<dyn Error + Sync + Send>> {
683 Ok(types::bytea_from_sql(raw).to_owned())
684 }
685
686 accepts!(BYTEA);
687}
688
689impl<'a> FromSql<'a> for &'a [u8] {
690 fn from_sql(_: &Type, raw: &'a [u8]) -> Result<&'a [u8], Box<dyn Error + Sync + Send>> {
691 Ok(types::bytea_from_sql(raw))
692 }
693
694 accepts!(BYTEA);
695}
696
697impl<'a> FromSql<'a> for String {
698 fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<String, Box<dyn Error + Sync + Send>> {
699 <&str as FromSql>::from_sql(ty, raw).map(ToString::to_string)
700 }
701
702 fn accepts(ty: &Type) -> bool {
703 <&str as FromSql>::accepts(ty)
704 }
705}
706
707impl<'a> FromSql<'a> for Box<str> {
708 fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Box<str>, Box<dyn Error + Sync + Send>> {
709 <&str as FromSql>::from_sql(ty, raw)
710 .map(ToString::to_string)
711 .map(String::into_boxed_str)
712 }
713
714 fn accepts(ty: &Type) -> bool {
715 <&str as FromSql>::accepts(ty)
716 }
717}
718
719impl<'a> FromSql<'a> for &'a str {
720 fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<&'a str, Box<dyn Error + Sync + Send>> {
721 match *ty {
722 ref ty if ty.name() == "ltree" => types::ltree_from_sql(raw),
723 ref ty if ty.name() == "lquery" => types::lquery_from_sql(raw),
724 ref ty if ty.name() == "ltxtquery" => types::ltxtquery_from_sql(raw),
725 _ => types::text_from_sql(raw),
726 }
727 }
728
729 fn accepts(ty: &Type) -> bool {
730 match *ty {
731 Type::VARCHAR | Type::TEXT | Type::BPCHAR | Type::NAME | Type::UNKNOWN => true,
732 ref ty
733 if (ty.name() == "citext"
734 || ty.name() == "ltree"
735 || ty.name() == "lquery"
736 || ty.name() == "ltxtquery") =>
737 {
738 true
739 }
740 _ => false,
741 }
742 }
743}
744
745impl<'a> FromSql<'a> for Cow<'a, str> {
746 fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Cow<'a, str>, Box<dyn Error + Sync + Send>> {
747 <&str as FromSql>::from_sql(ty, raw).map(Cow::Borrowed)
748 }
749
750 fn accepts(ty: &Type) -> bool {
751 <&str as FromSql>::accepts(ty)
752 }
753}
754
755macro_rules! simple_from {
756 ($t:ty, $f:ident, $($expected:ident),+) => {
757 impl<'a> FromSql<'a> for $t {
758 fn from_sql(_: &Type, raw: &'a [u8]) -> Result<$t, Box<dyn Error + Sync + Send>> {
759 types::$f(raw)
760 }
761
762 accepts!($($expected),+);
763 }
764 }
765}
766
767simple_from!(bool, bool_from_sql, BOOL);
768simple_from!(i8, char_from_sql, CHAR);
769simple_from!(i16, int2_from_sql, INT2);
770simple_from!(i32, int4_from_sql, INT4);
771simple_from!(u32, oid_from_sql, OID);
772simple_from!(i64, int8_from_sql, INT8);
773simple_from!(f32, float4_from_sql, FLOAT4);
774simple_from!(f64, float8_from_sql, FLOAT8);
775
776impl<'a, S> FromSql<'a> for HashMap<String, Option<String>, S>
777where
778 S: Default + BuildHasher,
779{
780 fn from_sql(
781 _: &Type,
782 raw: &'a [u8],
783 ) -> Result<HashMap<String, Option<String>, S>, Box<dyn Error + Sync + Send>> {
784 types::hstore_from_sql(raw)?
785 .map(|(k, v)| Ok((k.to_owned(), v.map(str::to_owned))))
786 .collect()
787 }
788
789 fn accepts(ty: &Type) -> bool {
790 ty.name() == "hstore"
791 }
792}
793
794impl<'a> FromSql<'a> for SystemTime {
795 fn from_sql(_: &Type, raw: &'a [u8]) -> Result<SystemTime, Box<dyn Error + Sync + Send>> {
796 let time = types::timestamp_from_sql(raw)?;
797 let epoch = UNIX_EPOCH + Duration::from_secs(TIME_SEC_CONVERSION);
798
799 let negative = time < 0;
800 let time = time.unsigned_abs();
801
802 let secs = time / USEC_PER_SEC;
803 let nsec = (time % USEC_PER_SEC) * NSEC_PER_USEC;
804 let offset = Duration::new(secs, nsec as u32);
805
806 let time = if negative {
807 epoch - offset
808 } else {
809 epoch + offset
810 };
811
812 Ok(time)
813 }
814
815 accepts!(TIMESTAMP, TIMESTAMPTZ);
816}
817
818impl<'a> FromSql<'a> for IpAddr {
819 fn from_sql(_: &Type, raw: &'a [u8]) -> Result<IpAddr, Box<dyn Error + Sync + Send>> {
820 let inet = types::inet_from_sql(raw)?;
821 Ok(inet.addr())
822 }
823
824 accepts!(INET);
825}
826
827pub enum IsNull {
829 Yes,
831 No,
833}
834
835pub trait ToSql: fmt::Debug {
906 fn to_sql(&self, ty: &Type, out: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>>
916 where
917 Self: Sized;
918
919 fn accepts(ty: &Type) -> bool
922 where
923 Self: Sized;
924
925 fn to_sql_checked(
930 &self,
931 ty: &Type,
932 out: &mut BytesMut,
933 ) -> Result<IsNull, Box<dyn Error + Sync + Send>>;
934
935 fn encode_format(&self, _ty: &Type) -> Format {
937 Format::Binary
938 }
939}
940
941#[derive(Clone, Copy, Debug)]
945pub enum Format {
946 Text,
948 Binary,
950}
951
952impl<T> ToSql for &T
953where
954 T: ToSql,
955{
956 fn to_sql(
957 &self,
958 ty: &Type,
959 out: &mut BytesMut,
960 ) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
961 (*self).to_sql(ty, out)
962 }
963
964 fn accepts(ty: &Type) -> bool {
965 T::accepts(ty)
966 }
967
968 fn encode_format(&self, ty: &Type) -> Format {
969 (*self).encode_format(ty)
970 }
971
972 to_sql_checked!();
973}
974
975impl<T: ToSql> ToSql for Option<T> {
976 fn to_sql(
977 &self,
978 ty: &Type,
979 out: &mut BytesMut,
980 ) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
981 match *self {
982 Some(ref val) => val.to_sql(ty, out),
983 None => Ok(IsNull::Yes),
984 }
985 }
986
987 fn accepts(ty: &Type) -> bool {
988 <T as ToSql>::accepts(ty)
989 }
990
991 fn encode_format(&self, ty: &Type) -> Format {
992 match self {
993 Some(val) => val.encode_format(ty),
994 None => Format::Binary,
995 }
996 }
997
998 to_sql_checked!();
999}
1000
1001impl<T: ToSql> ToSql for &[T] {
1002 fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1003 let member_type = match *ty.kind() {
1004 Kind::Array(ref member) => member,
1005 _ => panic!("expected array type"),
1006 };
1007
1008 let lower_bound = match *ty {
1010 Type::OID_VECTOR | Type::INT2_VECTOR => 0,
1011 _ => 1,
1012 };
1013
1014 let dimension = ArrayDimension {
1015 len: downcast(self.len())?,
1016 lower_bound,
1017 };
1018
1019 types::array_to_sql(
1020 Some(dimension),
1021 member_type.oid(),
1022 self.iter(),
1023 |e, w| match e.to_sql(member_type, w)? {
1024 IsNull::No => Ok(postgres_protocol::IsNull::No),
1025 IsNull::Yes => Ok(postgres_protocol::IsNull::Yes),
1026 },
1027 w,
1028 )?;
1029 Ok(IsNull::No)
1030 }
1031
1032 fn accepts(ty: &Type) -> bool {
1033 match *ty.kind() {
1034 Kind::Array(ref member) => T::accepts(member),
1035 _ => false,
1036 }
1037 }
1038
1039 to_sql_checked!();
1040}
1041
1042impl ToSql for &[u8] {
1043 fn to_sql(&self, _: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1044 types::bytea_to_sql(self, w);
1045 Ok(IsNull::No)
1046 }
1047
1048 accepts!(BYTEA);
1049
1050 to_sql_checked!();
1051}
1052
1053#[cfg(feature = "array-impls")]
1054impl<const N: usize> ToSql for [u8; N] {
1055 fn to_sql(&self, _: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1056 types::bytea_to_sql(&self[..], w);
1057 Ok(IsNull::No)
1058 }
1059
1060 accepts!(BYTEA);
1061
1062 to_sql_checked!();
1063}
1064
1065#[cfg(feature = "array-impls")]
1066impl<T: ToSql, const N: usize> ToSql for [T; N] {
1067 fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1068 <&[T] as ToSql>::to_sql(&&self[..], ty, w)
1069 }
1070
1071 fn accepts(ty: &Type) -> bool {
1072 <&[T] as ToSql>::accepts(ty)
1073 }
1074
1075 to_sql_checked!();
1076}
1077
1078impl<T: ToSql> ToSql for Vec<T> {
1079 fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1080 <&[T] as ToSql>::to_sql(&&**self, ty, w)
1081 }
1082
1083 fn accepts(ty: &Type) -> bool {
1084 <&[T] as ToSql>::accepts(ty)
1085 }
1086
1087 to_sql_checked!();
1088}
1089
1090impl<T: ToSql> ToSql for Box<T> {
1091 fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1092 <&T as ToSql>::to_sql(&&**self, ty, w)
1093 }
1094
1095 fn accepts(ty: &Type) -> bool {
1096 <&T as ToSql>::accepts(ty)
1097 }
1098
1099 to_sql_checked!();
1100}
1101
1102impl<T: ToSql> ToSql for Box<[T]> {
1103 fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1104 <&[T] as ToSql>::to_sql(&&**self, ty, w)
1105 }
1106
1107 fn accepts(ty: &Type) -> bool {
1108 <&[T] as ToSql>::accepts(ty)
1109 }
1110
1111 to_sql_checked!();
1112}
1113
1114impl ToSql for Cow<'_, [u8]> {
1115 fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1116 <&[u8] as ToSql>::to_sql(&self.as_ref(), ty, w)
1117 }
1118
1119 fn accepts(ty: &Type) -> bool {
1120 <&[u8] as ToSql>::accepts(ty)
1121 }
1122
1123 to_sql_checked!();
1124}
1125
1126impl ToSql for Vec<u8> {
1127 fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1128 <&[u8] as ToSql>::to_sql(&&**self, ty, w)
1129 }
1130
1131 fn accepts(ty: &Type) -> bool {
1132 <&[u8] as ToSql>::accepts(ty)
1133 }
1134
1135 to_sql_checked!();
1136}
1137
1138impl ToSql for &str {
1139 fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1140 match ty.name() {
1141 "ltree" => types::ltree_to_sql(self, w),
1142 "lquery" => types::lquery_to_sql(self, w),
1143 "ltxtquery" => types::ltxtquery_to_sql(self, w),
1144 _ => types::text_to_sql(self, w),
1145 }
1146 Ok(IsNull::No)
1147 }
1148
1149 fn accepts(ty: &Type) -> bool {
1150 matches!(
1151 *ty,
1152 Type::VARCHAR | Type::TEXT | Type::BPCHAR | Type::NAME | Type::UNKNOWN
1153 ) || matches!(ty.name(), "citext" | "ltree" | "lquery" | "ltxtquery")
1154 }
1155
1156 to_sql_checked!();
1157}
1158
1159impl ToSql for Cow<'_, str> {
1160 fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1161 <&str as ToSql>::to_sql(&self.as_ref(), ty, w)
1162 }
1163
1164 fn accepts(ty: &Type) -> bool {
1165 <&str as ToSql>::accepts(ty)
1166 }
1167
1168 to_sql_checked!();
1169}
1170
1171impl ToSql for String {
1172 fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1173 <&str as ToSql>::to_sql(&&**self, ty, w)
1174 }
1175
1176 fn accepts(ty: &Type) -> bool {
1177 <&str as ToSql>::accepts(ty)
1178 }
1179
1180 to_sql_checked!();
1181}
1182
1183impl ToSql for Box<str> {
1184 fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1185 <&str as ToSql>::to_sql(&&**self, ty, w)
1186 }
1187
1188 fn accepts(ty: &Type) -> bool {
1189 <&str as ToSql>::accepts(ty)
1190 }
1191
1192 to_sql_checked!();
1193}
1194
1195macro_rules! simple_to {
1196 ($t:ty, $f:ident, $($expected:ident),+) => {
1197 impl ToSql for $t {
1198 fn to_sql(&self,
1199 _: &Type,
1200 w: &mut BytesMut)
1201 -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1202 types::$f(*self, w);
1203 Ok(IsNull::No)
1204 }
1205
1206 accepts!($($expected),+);
1207
1208 to_sql_checked!();
1209 }
1210 }
1211}
1212
1213simple_to!(bool, bool_to_sql, BOOL);
1214simple_to!(i8, char_to_sql, CHAR);
1215simple_to!(i16, int2_to_sql, INT2);
1216simple_to!(i32, int4_to_sql, INT4);
1217simple_to!(u32, oid_to_sql, OID);
1218simple_to!(i64, int8_to_sql, INT8);
1219simple_to!(f32, float4_to_sql, FLOAT4);
1220simple_to!(f64, float8_to_sql, FLOAT8);
1221
1222impl<H> ToSql for HashMap<String, Option<String>, H>
1223where
1224 H: BuildHasher,
1225{
1226 fn to_sql(&self, _: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1227 types::hstore_to_sql(
1228 self.iter().map(|(k, v)| (&**k, v.as_ref().map(|v| &**v))),
1229 w,
1230 )?;
1231 Ok(IsNull::No)
1232 }
1233
1234 fn accepts(ty: &Type) -> bool {
1235 ty.name() == "hstore"
1236 }
1237
1238 to_sql_checked!();
1239}
1240
1241impl ToSql for SystemTime {
1242 fn to_sql(&self, _: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1243 let epoch = UNIX_EPOCH + Duration::from_secs(TIME_SEC_CONVERSION);
1244
1245 let to_usec =
1246 |d: Duration| d.as_secs() * USEC_PER_SEC + u64::from(d.subsec_nanos()) / NSEC_PER_USEC;
1247
1248 let time = match self.duration_since(epoch) {
1249 Ok(duration) => to_usec(duration) as i64,
1250 Err(e) => -(to_usec(e.duration()) as i64),
1251 };
1252
1253 types::timestamp_to_sql(time, w);
1254 Ok(IsNull::No)
1255 }
1256
1257 accepts!(TIMESTAMP, TIMESTAMPTZ);
1258
1259 to_sql_checked!();
1260}
1261
1262impl ToSql for IpAddr {
1263 fn to_sql(&self, _: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1264 let netmask = match self {
1265 IpAddr::V4(_) => 32,
1266 IpAddr::V6(_) => 128,
1267 };
1268 types::inet_to_sql(*self, netmask, w);
1269 Ok(IsNull::No)
1270 }
1271
1272 accepts!(INET);
1273
1274 to_sql_checked!();
1275}
1276
1277fn downcast(len: usize) -> Result<i32, Box<dyn Error + Sync + Send>> {
1278 if len > i32::MAX as usize {
1279 Err("value too large to transmit".into())
1280 } else {
1281 Ok(len as i32)
1282 }
1283}
1284
1285mod sealed {
1286 pub trait Sealed {}
1287}
1288
1289pub trait BorrowToSql: sealed::Sealed {
1293 fn borrow_to_sql(&self) -> &dyn ToSql;
1295}
1296
1297impl sealed::Sealed for &dyn ToSql {}
1298
1299impl BorrowToSql for &dyn ToSql {
1300 #[inline]
1301 fn borrow_to_sql(&self) -> &dyn ToSql {
1302 *self
1303 }
1304}
1305
1306impl sealed::Sealed for Box<dyn ToSql + Sync + '_> {}
1307
1308impl BorrowToSql for Box<dyn ToSql + Sync + '_> {
1309 #[inline]
1310 fn borrow_to_sql(&self) -> &dyn ToSql {
1311 self.as_ref()
1312 }
1313}
1314
1315impl sealed::Sealed for Box<dyn ToSql + Sync + Send + '_> {}
1316impl BorrowToSql for Box<dyn ToSql + Sync + Send + '_> {
1317 #[inline]
1318 fn borrow_to_sql(&self) -> &dyn ToSql {
1319 self.as_ref()
1320 }
1321}
1322
1323impl sealed::Sealed for &(dyn ToSql + Sync) {}
1324
1325impl BorrowToSql for &(dyn ToSql + Sync) {
1330 #[inline]
1331 fn borrow_to_sql(&self) -> &dyn ToSql {
1332 *self
1333 }
1334}
1335
1336impl<T> sealed::Sealed for T where T: ToSql {}
1337
1338impl<T> BorrowToSql for T
1339where
1340 T: ToSql,
1341{
1342 #[inline]
1343 fn borrow_to_sql(&self) -> &dyn ToSql {
1344 self
1345 }
1346}