diff --git a/sqlx-core/src/postgres/mod.rs b/sqlx-core/src/postgres/mod.rs index cac6c004b7..85f8d2457b 100644 --- a/sqlx-core/src/postgres/mod.rs +++ b/sqlx-core/src/postgres/mod.rs @@ -37,6 +37,7 @@ pub use row::PgRow; pub use statement::PgStatement; pub use transaction::PgTransactionManager; pub use type_info::{PgTypeInfo, PgTypeKind}; +pub use types::PgHasArrayType; pub use value::{PgValue, PgValueFormat, PgValueRef}; /// An alias for [`Pool`][crate::pool::Pool], specialized for Postgres. diff --git a/sqlx-core/src/postgres/types/array.rs b/sqlx-core/src/postgres/types/array.rs index cf2baea40a..a478e11d05 100644 --- a/sqlx-core/src/postgres/types/array.rs +++ b/sqlx-core/src/postgres/types/array.rs @@ -7,29 +7,49 @@ use crate::postgres::type_info::PgType; use crate::postgres::{PgArgumentBuffer, PgTypeInfo, PgValueFormat, PgValueRef, Postgres}; use crate::types::Type; -impl Type for [Option] +pub trait PgHasArrayType { + fn array_type_info() -> PgTypeInfo; + fn array_compatible(ty: &PgTypeInfo) -> bool { + *ty == Self::array_type_info() + } +} + +impl PgHasArrayType for Option +where + T: PgHasArrayType, +{ + fn array_type_info() -> PgTypeInfo { + T::array_type_info() + } + + fn array_compatible(ty: &PgTypeInfo) -> bool { + T::array_compatible(ty) + } +} + +impl Type for [T] where - [T]: Type, + T: PgHasArrayType, { fn type_info() -> PgTypeInfo { - <[T] as Type>::type_info() + T::array_type_info() } fn compatible(ty: &PgTypeInfo) -> bool { - <[T] as Type>::compatible(ty) + T::array_compatible(ty) } } -impl Type for Vec> +impl Type for Vec where - Vec: Type, + T: PgHasArrayType, { fn type_info() -> PgTypeInfo { - as Type>::type_info() + T::array_type_info() } fn compatible(ty: &PgTypeInfo) -> bool { - as Type>::compatible(ty) + T::array_compatible(ty) } } diff --git a/sqlx-core/src/postgres/types/bigdecimal.rs b/sqlx-core/src/postgres/types/bigdecimal.rs index 2a2479a740..54cbf9e320 100644 --- a/sqlx-core/src/postgres/types/bigdecimal.rs +++ b/sqlx-core/src/postgres/types/bigdecimal.rs @@ -8,7 +8,9 @@ use crate::decode::Decode; use crate::encode::{Encode, IsNull}; use crate::error::BoxDynError; use crate::postgres::types::numeric::{PgNumeric, PgNumericSign}; -use crate::postgres::{PgArgumentBuffer, PgTypeInfo, PgValueFormat, PgValueRef, Postgres}; +use crate::postgres::{ + PgArgumentBuffer, PgHasArrayType, PgTypeInfo, PgValueFormat, PgValueRef, Postgres, +}; use crate::types::Type; impl Type for BigDecimal { @@ -17,18 +19,12 @@ impl Type for BigDecimal { } } -impl Type for [BigDecimal] { - fn type_info() -> PgTypeInfo { +impl PgHasArrayType for BigDecimal { + fn array_type_info() -> PgTypeInfo { PgTypeInfo::NUMERIC_ARRAY } } -impl Type for Vec { - fn type_info() -> PgTypeInfo { - <[BigDecimal] as Type>::type_info() - } -} - impl TryFrom for BigDecimal { type Error = BoxDynError; diff --git a/sqlx-core/src/postgres/types/bit_vec.rs b/sqlx-core/src/postgres/types/bit_vec.rs index ea01367809..902ab12674 100644 --- a/sqlx-core/src/postgres/types/bit_vec.rs +++ b/sqlx-core/src/postgres/types/bit_vec.rs @@ -2,7 +2,7 @@ use crate::{ decode::Decode, encode::{Encode, IsNull}, error::BoxDynError, - postgres::{PgArgumentBuffer, PgTypeInfo, PgValueFormat, PgValueRef, Postgres}, + postgres::{PgArgumentBuffer, PgHasArrayType, PgTypeInfo, PgValueFormat, PgValueRef, Postgres}, types::Type, }; use bit_vec::BitVec; @@ -19,26 +19,16 @@ impl Type for BitVec { } } -impl Type for [BitVec] { - fn type_info() -> PgTypeInfo { +impl PgHasArrayType for BitVec { + fn array_type_info() -> PgTypeInfo { PgTypeInfo::VARBIT_ARRAY } - fn compatible(ty: &PgTypeInfo) -> bool { + fn array_compatible(ty: &PgTypeInfo) -> bool { *ty == PgTypeInfo::BIT_ARRAY || *ty == PgTypeInfo::VARBIT_ARRAY } } -impl Type for Vec { - fn type_info() -> PgTypeInfo { - <[BitVec] as Type>::type_info() - } - - fn compatible(ty: &PgTypeInfo) -> bool { - <[BitVec] as Type>::compatible(ty) - } -} - impl Encode<'_, Postgres> for BitVec { fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull { buf.extend(&(self.len() as i32).to_be_bytes()); diff --git a/sqlx-core/src/postgres/types/bool.rs b/sqlx-core/src/postgres/types/bool.rs index 457d07cecf..30a7297b54 100644 --- a/sqlx-core/src/postgres/types/bool.rs +++ b/sqlx-core/src/postgres/types/bool.rs @@ -1,7 +1,9 @@ use crate::decode::Decode; use crate::encode::{Encode, IsNull}; use crate::error::BoxDynError; -use crate::postgres::{PgArgumentBuffer, PgTypeInfo, PgValueFormat, PgValueRef, Postgres}; +use crate::postgres::{ + PgArgumentBuffer, PgHasArrayType, PgTypeInfo, PgValueFormat, PgValueRef, Postgres, +}; use crate::types::Type; impl Type for bool { @@ -10,18 +12,12 @@ impl Type for bool { } } -impl Type for [bool] { - fn type_info() -> PgTypeInfo { +impl PgHasArrayType for bool { + fn array_type_info() -> PgTypeInfo { PgTypeInfo::BOOL_ARRAY } } -impl Type for Vec { - fn type_info() -> PgTypeInfo { - <[bool] as Type>::type_info() - } -} - impl Encode<'_, Postgres> for bool { fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull { buf.push(*self as u8); diff --git a/sqlx-core/src/postgres/types/bytes.rs b/sqlx-core/src/postgres/types/bytes.rs index 37d158add9..2a3433e52b 100644 --- a/sqlx-core/src/postgres/types/bytes.rs +++ b/sqlx-core/src/postgres/types/bytes.rs @@ -1,41 +1,25 @@ use crate::decode::Decode; use crate::encode::{Encode, IsNull}; use crate::error::BoxDynError; -use crate::postgres::{PgArgumentBuffer, PgTypeInfo, PgValueFormat, PgValueRef, Postgres}; +use crate::postgres::{ + PgArgumentBuffer, PgHasArrayType, PgTypeInfo, PgValueFormat, PgValueRef, Postgres, +}; use crate::types::Type; -impl Type for [u8] { - fn type_info() -> PgTypeInfo { +impl PgHasArrayType for u8 { + fn array_type_info() -> PgTypeInfo { PgTypeInfo::BYTEA } } -impl Type for Vec { - fn type_info() -> PgTypeInfo { - <[u8] as Type>::type_info() - } -} - -impl Type for [&'_ [u8]] { - fn type_info() -> PgTypeInfo { +impl PgHasArrayType for &'_ [u8] { + fn array_type_info() -> PgTypeInfo { PgTypeInfo::BYTEA_ARRAY } } -impl Type for [Vec] { - fn type_info() -> PgTypeInfo { - <[&[u8]] as Type>::type_info() - } -} - -impl Type for Vec<&'_ [u8]> { - fn type_info() -> PgTypeInfo { - <[&[u8]] as Type>::type_info() - } -} - -impl Type for Vec> { - fn type_info() -> PgTypeInfo { +impl PgHasArrayType for Vec { + fn array_type_info() -> PgTypeInfo { <[&[u8]] as Type>::type_info() } } diff --git a/sqlx-core/src/postgres/types/chrono/date.rs b/sqlx-core/src/postgres/types/chrono/date.rs index 185f46c761..68ee1d48dc 100644 --- a/sqlx-core/src/postgres/types/chrono/date.rs +++ b/sqlx-core/src/postgres/types/chrono/date.rs @@ -1,7 +1,9 @@ use crate::decode::Decode; use crate::encode::{Encode, IsNull}; use crate::error::BoxDynError; -use crate::postgres::{PgArgumentBuffer, PgTypeInfo, PgValueFormat, PgValueRef, Postgres}; +use crate::postgres::{ + PgArgumentBuffer, PgHasArrayType, PgTypeInfo, PgValueFormat, PgValueRef, Postgres, +}; use crate::types::Type; use chrono::{Duration, NaiveDate}; use std::mem; @@ -12,18 +14,12 @@ impl Type for NaiveDate { } } -impl Type for [NaiveDate] { - fn type_info() -> PgTypeInfo { +impl PgHasArrayType for NaiveDate { + fn array_type_info() -> PgTypeInfo { PgTypeInfo::DATE_ARRAY } } -impl Type for Vec { - fn type_info() -> PgTypeInfo { - <[NaiveDate] as Type>::type_info() - } -} - impl Encode<'_, Postgres> for NaiveDate { fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull { // DATE is encoded as the days since epoch diff --git a/sqlx-core/src/postgres/types/chrono/datetime.rs b/sqlx-core/src/postgres/types/chrono/datetime.rs index a8712e7b1e..ff0fdff4c2 100644 --- a/sqlx-core/src/postgres/types/chrono/datetime.rs +++ b/sqlx-core/src/postgres/types/chrono/datetime.rs @@ -1,7 +1,9 @@ use crate::decode::Decode; use crate::encode::{Encode, IsNull}; use crate::error::BoxDynError; -use crate::postgres::{PgArgumentBuffer, PgTypeInfo, PgValueFormat, PgValueRef, Postgres}; +use crate::postgres::{ + PgArgumentBuffer, PgHasArrayType, PgTypeInfo, PgValueFormat, PgValueRef, Postgres, +}; use crate::types::Type; use chrono::{ DateTime, Duration, FixedOffset, Local, NaiveDate, NaiveDateTime, Offset, TimeZone, Utc, @@ -20,30 +22,18 @@ impl Type for DateTime { } } -impl Type for [NaiveDateTime] { - fn type_info() -> PgTypeInfo { +impl PgHasArrayType for NaiveDateTime { + fn array_type_info() -> PgTypeInfo { PgTypeInfo::TIMESTAMP_ARRAY } } -impl Type for [DateTime] { - fn type_info() -> PgTypeInfo { +impl PgHasArrayType for DateTime { + fn array_type_info() -> PgTypeInfo { PgTypeInfo::TIMESTAMPTZ_ARRAY } } -impl Type for Vec { - fn type_info() -> PgTypeInfo { - <[NaiveDateTime] as Type>::type_info() - } -} - -impl Type for Vec> { - fn type_info() -> PgTypeInfo { - <[DateTime] as Type>::type_info() - } -} - impl Encode<'_, Postgres> for NaiveDateTime { fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull { // FIXME: We should *really* be returning an error, Encode needs to be fallible diff --git a/sqlx-core/src/postgres/types/chrono/time.rs b/sqlx-core/src/postgres/types/chrono/time.rs index e0a5ceb6ed..e21550033a 100644 --- a/sqlx-core/src/postgres/types/chrono/time.rs +++ b/sqlx-core/src/postgres/types/chrono/time.rs @@ -1,7 +1,9 @@ use crate::decode::Decode; use crate::encode::{Encode, IsNull}; use crate::error::BoxDynError; -use crate::postgres::{PgArgumentBuffer, PgTypeInfo, PgValueFormat, PgValueRef, Postgres}; +use crate::postgres::{ + PgArgumentBuffer, PgHasArrayType, PgTypeInfo, PgValueFormat, PgValueRef, Postgres, +}; use crate::types::Type; use chrono::{Duration, NaiveTime}; use std::mem; @@ -12,18 +14,12 @@ impl Type for NaiveTime { } } -impl Type for [NaiveTime] { - fn type_info() -> PgTypeInfo { +impl PgHasArrayType for NaiveTime { + fn array_type_info() -> PgTypeInfo { PgTypeInfo::TIME_ARRAY } } -impl Type for Vec { - fn type_info() -> PgTypeInfo { - <[NaiveTime] as Type>::type_info() - } -} - impl Encode<'_, Postgres> for NaiveTime { fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull { // TIME is encoded as the microseconds since midnight diff --git a/sqlx-core/src/postgres/types/decimal.rs b/sqlx-core/src/postgres/types/decimal.rs index 61ca06fcb7..8502a636cc 100644 --- a/sqlx-core/src/postgres/types/decimal.rs +++ b/sqlx-core/src/postgres/types/decimal.rs @@ -9,7 +9,9 @@ use crate::decode::Decode; use crate::encode::{Encode, IsNull}; use crate::error::BoxDynError; use crate::postgres::types::numeric::{PgNumeric, PgNumericSign}; -use crate::postgres::{PgArgumentBuffer, PgTypeInfo, PgValueFormat, PgValueRef, Postgres}; +use crate::postgres::{ + PgArgumentBuffer, PgHasArrayType, PgTypeInfo, PgValueFormat, PgValueRef, Postgres, +}; use crate::types::Type; impl Type for Decimal { @@ -18,18 +20,12 @@ impl Type for Decimal { } } -impl Type for [Decimal] { - fn type_info() -> PgTypeInfo { +impl PgHasArrayType for Decimal { + fn array_type_info() -> PgTypeInfo { PgTypeInfo::NUMERIC_ARRAY } } -impl Type for Vec { - fn type_info() -> PgTypeInfo { - <[Decimal] as Type>::type_info() - } -} - impl TryFrom for Decimal { type Error = BoxDynError; diff --git a/sqlx-core/src/postgres/types/float.rs b/sqlx-core/src/postgres/types/float.rs index 76cb41073d..ca5789ebce 100644 --- a/sqlx-core/src/postgres/types/float.rs +++ b/sqlx-core/src/postgres/types/float.rs @@ -3,7 +3,9 @@ use byteorder::{BigEndian, ByteOrder}; use crate::decode::Decode; use crate::encode::{Encode, IsNull}; use crate::error::BoxDynError; -use crate::postgres::{PgArgumentBuffer, PgTypeInfo, PgValueFormat, PgValueRef, Postgres}; +use crate::postgres::{ + PgArgumentBuffer, PgHasArrayType, PgTypeInfo, PgValueFormat, PgValueRef, Postgres, +}; use crate::types::Type; impl Type for f32 { @@ -12,18 +14,12 @@ impl Type for f32 { } } -impl Type for [f32] { - fn type_info() -> PgTypeInfo { +impl PgHasArrayType for f32 { + fn array_type_info() -> PgTypeInfo { PgTypeInfo::FLOAT4_ARRAY } } -impl Type for Vec { - fn type_info() -> PgTypeInfo { - <[f32] as Type>::type_info() - } -} - impl Encode<'_, Postgres> for f32 { fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull { buf.extend(&self.to_be_bytes()); @@ -47,18 +43,12 @@ impl Type for f64 { } } -impl Type for [f64] { - fn type_info() -> PgTypeInfo { +impl PgHasArrayType for f64 { + fn array_type_info() -> PgTypeInfo { PgTypeInfo::FLOAT8_ARRAY } } -impl Type for Vec { - fn type_info() -> PgTypeInfo { - <[f64] as Type>::type_info() - } -} - impl Encode<'_, Postgres> for f64 { fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull { buf.extend(&self.to_be_bytes()); diff --git a/sqlx-core/src/postgres/types/int.rs b/sqlx-core/src/postgres/types/int.rs index 4fc2bf3917..63b7d3dfee 100644 --- a/sqlx-core/src/postgres/types/int.rs +++ b/sqlx-core/src/postgres/types/int.rs @@ -3,7 +3,9 @@ use byteorder::{BigEndian, ByteOrder}; use crate::decode::Decode; use crate::encode::{Encode, IsNull}; use crate::error::BoxDynError; -use crate::postgres::{PgArgumentBuffer, PgTypeInfo, PgValueFormat, PgValueRef, Postgres}; +use crate::postgres::{ + PgArgumentBuffer, PgHasArrayType, PgTypeInfo, PgValueFormat, PgValueRef, Postgres, +}; use crate::types::Type; impl Type for i8 { @@ -12,18 +14,12 @@ impl Type for i8 { } } -impl Type for [i8] { - fn type_info() -> PgTypeInfo { +impl PgHasArrayType for i8 { + fn array_type_info() -> PgTypeInfo { PgTypeInfo::CHAR_ARRAY } } -impl Type for Vec { - fn type_info() -> PgTypeInfo { - <[i8] as Type>::type_info() - } -} - impl Encode<'_, Postgres> for i8 { fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull { buf.extend(&self.to_be_bytes()); @@ -45,18 +41,12 @@ impl Type for i16 { } } -impl Type for [i16] { - fn type_info() -> PgTypeInfo { +impl PgHasArrayType for i16 { + fn array_type_info() -> PgTypeInfo { PgTypeInfo::INT2_ARRAY } } -impl Type for Vec { - fn type_info() -> PgTypeInfo { - <[i16] as Type>::type_info() - } -} - impl Encode<'_, Postgres> for i16 { fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull { buf.extend(&self.to_be_bytes()); @@ -80,18 +70,12 @@ impl Type for u32 { } } -impl Type for [u32] { - fn type_info() -> PgTypeInfo { +impl PgHasArrayType for u32 { + fn array_type_info() -> PgTypeInfo { PgTypeInfo::OID_ARRAY } } -impl Type for Vec { - fn type_info() -> PgTypeInfo { - <[u32] as Type>::type_info() - } -} - impl Encode<'_, Postgres> for u32 { fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull { buf.extend(&self.to_be_bytes()); @@ -115,18 +99,12 @@ impl Type for i32 { } } -impl Type for [i32] { - fn type_info() -> PgTypeInfo { +impl PgHasArrayType for i32 { + fn array_type_info() -> PgTypeInfo { PgTypeInfo::INT4_ARRAY } } -impl Type for Vec { - fn type_info() -> PgTypeInfo { - <[i32] as Type>::type_info() - } -} - impl Encode<'_, Postgres> for i32 { fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull { buf.extend(&self.to_be_bytes()); @@ -150,18 +128,12 @@ impl Type for i64 { } } -impl Type for [i64] { - fn type_info() -> PgTypeInfo { +impl PgHasArrayType for i64 { + fn array_type_info() -> PgTypeInfo { PgTypeInfo::INT8_ARRAY } } -impl Type for Vec { - fn type_info() -> PgTypeInfo { - <[i64] as Type>::type_info() - } -} - impl Encode<'_, Postgres> for i64 { fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull { buf.extend(&self.to_be_bytes()); diff --git a/sqlx-core/src/postgres/types/interval.rs b/sqlx-core/src/postgres/types/interval.rs index 42805a56b5..05f8089f0b 100644 --- a/sqlx-core/src/postgres/types/interval.rs +++ b/sqlx-core/src/postgres/types/interval.rs @@ -6,7 +6,9 @@ use byteorder::{NetworkEndian, ReadBytesExt}; use crate::decode::Decode; use crate::encode::{Encode, IsNull}; use crate::error::BoxDynError; -use crate::postgres::{PgArgumentBuffer, PgTypeInfo, PgValueFormat, PgValueRef, Postgres}; +use crate::postgres::{ + PgArgumentBuffer, PgHasArrayType, PgTypeInfo, PgValueFormat, PgValueRef, Postgres, +}; use crate::types::Type; // `PgInterval` is available for direct access to the INTERVAL type @@ -24,8 +26,8 @@ impl Type for PgInterval { } } -impl Type for [PgInterval] { - fn type_info() -> PgTypeInfo { +impl PgHasArrayType for PgInterval { + fn array_type_info() -> PgTypeInfo { PgTypeInfo::INTERVAL_ARRAY } } @@ -77,8 +79,8 @@ impl Type for std::time::Duration { } } -impl Type for [std::time::Duration] { - fn type_info() -> PgTypeInfo { +impl PgHasArrayType for std::time::Duration { + fn array_type_info() -> PgTypeInfo { PgTypeInfo::INTERVAL_ARRAY } } @@ -123,8 +125,8 @@ impl Type for chrono::Duration { } #[cfg(feature = "chrono")] -impl Type for [chrono::Duration] { - fn type_info() -> PgTypeInfo { +impl PgHasArrayType for chrono::Duration { + fn array_type_info() -> PgTypeInfo { PgTypeInfo::INTERVAL_ARRAY } } @@ -185,8 +187,8 @@ impl Type for time::Duration { } #[cfg(feature = "time")] -impl Type for [time::Duration] { - fn type_info() -> PgTypeInfo { +impl PgHasArrayType for time::Duration { + fn array_type_info() -> PgTypeInfo { PgTypeInfo::INTERVAL_ARRAY } } diff --git a/sqlx-core/src/postgres/types/ipnetwork.rs b/sqlx-core/src/postgres/types/ipnetwork.rs index 84611814b2..73c776bc60 100644 --- a/sqlx-core/src/postgres/types/ipnetwork.rs +++ b/sqlx-core/src/postgres/types/ipnetwork.rs @@ -5,7 +5,9 @@ use ipnetwork::{IpNetwork, Ipv4Network, Ipv6Network}; use crate::decode::Decode; use crate::encode::{Encode, IsNull}; use crate::error::BoxDynError; -use crate::postgres::{PgArgumentBuffer, PgTypeInfo, PgValueFormat, PgValueRef, Postgres}; +use crate::postgres::{ + PgArgumentBuffer, PgHasArrayType, PgTypeInfo, PgValueFormat, PgValueRef, Postgres, +}; use crate::types::Type; // https://github.com/rust-lang/rust/search?q=AF_INET&unscoped_q=AF_INET @@ -34,26 +36,16 @@ impl Type for IpNetwork { } } -impl Type for [IpNetwork] { - fn type_info() -> PgTypeInfo { +impl PgHasArrayType for IpNetwork { + fn array_type_info() -> PgTypeInfo { PgTypeInfo::INET_ARRAY } - fn compatible(ty: &PgTypeInfo) -> bool { + fn array_compatible(ty: &PgTypeInfo) -> bool { *ty == PgTypeInfo::CIDR_ARRAY || *ty == PgTypeInfo::INET_ARRAY } } -impl Type for Vec { - fn type_info() -> PgTypeInfo { - <[IpNetwork] as Type>::type_info() - } - - fn compatible(ty: &PgTypeInfo) -> bool { - <[IpNetwork] as Type>::compatible(ty) - } -} - impl Encode<'_, Postgres> for IpNetwork { fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull { // https://github.com/postgres/postgres/blob/574925bfd0a8175f6e161936ea11d9695677ba09/src/backend/utils/adt/network.c#L293 diff --git a/sqlx-core/src/postgres/types/json.rs b/sqlx-core/src/postgres/types/json.rs index 212cc0a883..d72281699b 100644 --- a/sqlx-core/src/postgres/types/json.rs +++ b/sqlx-core/src/postgres/types/json.rs @@ -2,7 +2,9 @@ use crate::decode::Decode; use crate::encode::{Encode, IsNull}; use crate::error::BoxDynError; use crate::postgres::types::array_compatible; -use crate::postgres::{PgArgumentBuffer, PgTypeInfo, PgValueFormat, PgValueRef, Postgres}; +use crate::postgres::{ + PgArgumentBuffer, PgHasArrayType, PgTypeInfo, PgValueFormat, PgValueRef, Postgres, +}; use crate::types::{Json, Type}; use serde::{Deserialize, Serialize}; @@ -22,26 +24,16 @@ impl Type for Json { } } -impl Type for [Json] { - fn type_info() -> PgTypeInfo { +impl PgHasArrayType for Json { + fn array_type_info() -> PgTypeInfo { PgTypeInfo::JSONB_ARRAY } - fn compatible(ty: &PgTypeInfo) -> bool { + fn array_compatible(ty: &PgTypeInfo) -> bool { array_compatible::>(ty) } } -impl Type for Vec> { - fn type_info() -> PgTypeInfo { - <[Json] as Type>::type_info() - } - - fn compatible(ty: &PgTypeInfo) -> bool { - <[Json] as Type>::compatible(ty) - } -} - impl<'q, T> Encode<'q, Postgres> for Json where T: Serialize, diff --git a/sqlx-core/src/postgres/types/mac_address.rs b/sqlx-core/src/postgres/types/mac_address.rs index 37bd543217..33f4132681 100644 --- a/sqlx-core/src/postgres/types/mac_address.rs +++ b/sqlx-core/src/postgres/types/mac_address.rs @@ -5,7 +5,9 @@ use std::convert::TryInto; use crate::decode::Decode; use crate::encode::{Encode, IsNull}; use crate::error::BoxDynError; -use crate::postgres::{PgArgumentBuffer, PgTypeInfo, PgValueFormat, PgValueRef, Postgres}; +use crate::postgres::{ + PgArgumentBuffer, PgHasArrayType, PgTypeInfo, PgValueFormat, PgValueRef, Postgres, +}; use crate::types::Type; impl Type for MacAddress { @@ -18,22 +20,12 @@ impl Type for MacAddress { } } -impl Type for [MacAddress] { - fn type_info() -> PgTypeInfo { +impl PgHasArrayType for MacAddress { + fn array_type_info() -> PgTypeInfo { PgTypeInfo::MACADDR_ARRAY } } -impl Type for Vec { - fn type_info() -> PgTypeInfo { - <[MacAddress] as Type>::type_info() - } - - fn compatible(ty: &PgTypeInfo) -> bool { - <[MacAddress] as Type>::compatible(ty) - } -} - impl Encode<'_, Postgres> for MacAddress { fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull { buf.extend_from_slice(&self.bytes()); // write just the address diff --git a/sqlx-core/src/postgres/types/mod.rs b/sqlx-core/src/postgres/types/mod.rs index 066a8c2309..eaf11f1093 100644 --- a/sqlx-core/src/postgres/types/mod.rs +++ b/sqlx-core/src/postgres/types/mod.rs @@ -208,6 +208,7 @@ mod mac_address; #[cfg(feature = "bit-vec")] mod bit_vec; +pub use array::PgHasArrayType; pub use interval::PgInterval; pub use money::PgMoney; pub use range::PgRange; diff --git a/sqlx-core/src/postgres/types/money.rs b/sqlx-core/src/postgres/types/money.rs index f327726710..1deacd74c7 100644 --- a/sqlx-core/src/postgres/types/money.rs +++ b/sqlx-core/src/postgres/types/money.rs @@ -2,7 +2,7 @@ use crate::{ decode::Decode, encode::{Encode, IsNull}, error::BoxDynError, - postgres::{PgArgumentBuffer, PgTypeInfo, PgValueFormat, PgValueRef, Postgres}, + postgres::{PgArgumentBuffer, PgHasArrayType, PgTypeInfo, PgValueFormat, PgValueRef, Postgres}, types::Type, }; use byteorder::{BigEndian, ByteOrder}; @@ -151,18 +151,12 @@ impl Type for PgMoney { } } -impl Type for [PgMoney] { - fn type_info() -> PgTypeInfo { +impl PgHasArrayType for PgMoney { + fn array_type_info() -> PgTypeInfo { PgTypeInfo::MONEY_ARRAY } } -impl Type for Vec { - fn type_info() -> PgTypeInfo { - <[PgMoney] as Type>::type_info() - } -} - impl From for PgMoney where T: Into, diff --git a/sqlx-core/src/postgres/types/range.rs b/sqlx-core/src/postgres/types/range.rs index 59f689d9c0..fab2ddfc84 100644 --- a/sqlx-core/src/postgres/types/range.rs +++ b/sqlx-core/src/postgres/types/range.rs @@ -8,7 +8,9 @@ use crate::decode::Decode; use crate::encode::{Encode, IsNull}; use crate::error::BoxDynError; use crate::postgres::type_info::PgTypeKind; -use crate::postgres::{PgArgumentBuffer, PgTypeInfo, PgValueFormat, PgValueRef, Postgres}; +use crate::postgres::{ + PgArgumentBuffer, PgHasArrayType, PgTypeInfo, PgValueFormat, PgValueRef, Postgres, +}; use crate::types::Type; // https://github.com/postgres/postgres/blob/2f48ede080f42b97b594fb14102c82ca1001b80c/src/include/utils/rangetypes.h#L35-L44 @@ -219,138 +221,70 @@ impl Type for PgRange { } } -impl Type for [PgRange] { - fn type_info() -> PgTypeInfo { - PgTypeInfo::INT4_RANGE_ARRAY - } -} - -impl Type for [PgRange] { - fn type_info() -> PgTypeInfo { - PgTypeInfo::INT8_RANGE_ARRAY - } -} - -#[cfg(feature = "bigdecimal")] -impl Type for [PgRange] { - fn type_info() -> PgTypeInfo { - PgTypeInfo::NUM_RANGE_ARRAY - } -} - -#[cfg(feature = "decimal")] -impl Type for [PgRange] { - fn type_info() -> PgTypeInfo { - PgTypeInfo::NUM_RANGE_ARRAY - } -} - -#[cfg(feature = "chrono")] -impl Type for [PgRange] { - fn type_info() -> PgTypeInfo { - PgTypeInfo::DATE_RANGE_ARRAY - } -} - -#[cfg(feature = "chrono")] -impl Type for [PgRange] { - fn type_info() -> PgTypeInfo { - PgTypeInfo::TS_RANGE_ARRAY - } -} - -#[cfg(feature = "chrono")] -impl Type for [PgRange>] { - fn type_info() -> PgTypeInfo { - PgTypeInfo::TSTZ_RANGE_ARRAY - } -} - -#[cfg(feature = "time")] -impl Type for [PgRange] { - fn type_info() -> PgTypeInfo { - PgTypeInfo::DATE_RANGE_ARRAY - } -} - -#[cfg(feature = "time")] -impl Type for [PgRange] { - fn type_info() -> PgTypeInfo { - PgTypeInfo::TS_RANGE_ARRAY - } -} - -#[cfg(feature = "time")] -impl Type for [PgRange] { - fn type_info() -> PgTypeInfo { - PgTypeInfo::TSTZ_RANGE_ARRAY - } -} - -impl Type for Vec> { - fn type_info() -> PgTypeInfo { +impl PgHasArrayType for PgRange { + fn array_type_info() -> PgTypeInfo { PgTypeInfo::INT4_RANGE_ARRAY } } -impl Type for Vec> { - fn type_info() -> PgTypeInfo { +impl PgHasArrayType for PgRange { + fn array_type_info() -> PgTypeInfo { PgTypeInfo::INT8_RANGE_ARRAY } } #[cfg(feature = "bigdecimal")] -impl Type for Vec> { - fn type_info() -> PgTypeInfo { +impl PgHasArrayType for PgRange { + fn array_type_info() -> PgTypeInfo { PgTypeInfo::NUM_RANGE_ARRAY } } #[cfg(feature = "decimal")] -impl Type for Vec> { - fn type_info() -> PgTypeInfo { +impl PgHasArrayType for PgRange { + fn array_type_info() -> PgTypeInfo { PgTypeInfo::NUM_RANGE_ARRAY } } #[cfg(feature = "chrono")] -impl Type for Vec> { - fn type_info() -> PgTypeInfo { +impl PgHasArrayType for PgRange { + fn array_type_info() -> PgTypeInfo { PgTypeInfo::DATE_RANGE_ARRAY } } #[cfg(feature = "chrono")] -impl Type for Vec> { - fn type_info() -> PgTypeInfo { +impl PgHasArrayType for PgRange { + fn array_type_info() -> PgTypeInfo { PgTypeInfo::TS_RANGE_ARRAY } } #[cfg(feature = "chrono")] -impl Type for Vec>> { - fn type_info() -> PgTypeInfo { +impl PgHasArrayType for PgRange> { + fn array_type_info() -> PgTypeInfo { PgTypeInfo::TSTZ_RANGE_ARRAY } } #[cfg(feature = "time")] -impl Type for Vec> { - fn type_info() -> PgTypeInfo { +impl PgHasArrayType for PgRange { + fn array_type_info() -> PgTypeInfo { PgTypeInfo::DATE_RANGE_ARRAY } } #[cfg(feature = "time")] -impl Type for Vec> { - fn type_info() -> PgTypeInfo { +impl PgHasArrayType for PgRange { + fn array_type_info() -> PgTypeInfo { PgTypeInfo::TS_RANGE_ARRAY } } #[cfg(feature = "time")] -impl Type for Vec> { - fn type_info() -> PgTypeInfo { +impl PgHasArrayType for PgRange { + fn array_type_info() -> PgTypeInfo { PgTypeInfo::TSTZ_RANGE_ARRAY } } diff --git a/sqlx-core/src/postgres/types/str.rs b/sqlx-core/src/postgres/types/str.rs index 7a721569d6..76e4a71a67 100644 --- a/sqlx-core/src/postgres/types/str.rs +++ b/sqlx-core/src/postgres/types/str.rs @@ -2,7 +2,7 @@ use crate::decode::Decode; use crate::encode::{Encode, IsNull}; use crate::error::BoxDynError; use crate::postgres::types::array_compatible; -use crate::postgres::{PgArgumentBuffer, PgTypeInfo, PgValueRef, Postgres}; +use crate::postgres::{PgArgumentBuffer, PgHasArrayType, PgTypeInfo, PgValueRef, Postgres}; use crate::types::Type; use std::borrow::Cow; @@ -33,23 +33,43 @@ impl Type for Cow<'_, str> { } } -impl Type for [&'_ str] { +impl Type for String { fn type_info() -> PgTypeInfo { - PgTypeInfo::TEXT_ARRAY + <&str as Type>::type_info() } fn compatible(ty: &PgTypeInfo) -> bool { + <&str as Type>::compatible(ty) + } +} + +impl PgHasArrayType for &'_ str { + fn array_type_info() -> PgTypeInfo { + PgTypeInfo::TEXT_ARRAY + } + + fn array_compatible(ty: &PgTypeInfo) -> bool { array_compatible::<&str>(ty) } } -impl Type for Vec<&'_ str> { - fn type_info() -> PgTypeInfo { - <[&str] as Type>::type_info() +impl PgHasArrayType for Cow<'_, str> { + fn array_type_info() -> PgTypeInfo { + <&str as PgHasArrayType>::array_type_info() } - fn compatible(ty: &PgTypeInfo) -> bool { - <[&str] as Type>::compatible(ty) + fn array_compatible(ty: &PgTypeInfo) -> bool { + <&str as PgHasArrayType>::array_compatible(ty) + } +} + +impl PgHasArrayType for String { + fn array_type_info() -> PgTypeInfo { + <&str as PgHasArrayType>::array_type_info() + } + + fn array_compatible(ty: &PgTypeInfo) -> bool { + <&str as PgHasArrayType>::array_compatible(ty) } } @@ -88,36 +108,6 @@ impl<'r> Decode<'r, Postgres> for Cow<'r, str> { } } -impl Type for String { - fn type_info() -> PgTypeInfo { - <&str as Type>::type_info() - } - - fn compatible(ty: &PgTypeInfo) -> bool { - <&str as Type>::compatible(ty) - } -} - -impl Type for [String] { - fn type_info() -> PgTypeInfo { - <[&str] as Type>::type_info() - } - - fn compatible(ty: &PgTypeInfo) -> bool { - <[&str] as Type>::compatible(ty) - } -} - -impl Type for Vec { - fn type_info() -> PgTypeInfo { - <[String] as Type>::type_info() - } - - fn compatible(ty: &PgTypeInfo) -> bool { - <[String] as Type>::compatible(ty) - } -} - impl Decode<'_, Postgres> for String { fn decode(value: PgValueRef<'_>) -> Result { Ok(value.as_str()?.to_owned()) diff --git a/sqlx-core/src/postgres/types/time/date.rs b/sqlx-core/src/postgres/types/time/date.rs index e2c74b8ce5..3864826c98 100644 --- a/sqlx-core/src/postgres/types/time/date.rs +++ b/sqlx-core/src/postgres/types/time/date.rs @@ -2,7 +2,9 @@ use crate::decode::Decode; use crate::encode::{Encode, IsNull}; use crate::error::BoxDynError; use crate::postgres::types::time::PG_EPOCH; -use crate::postgres::{PgArgumentBuffer, PgTypeInfo, PgValueFormat, PgValueRef, Postgres}; +use crate::postgres::{ + PgArgumentBuffer, PgHasArrayType, PgTypeInfo, PgValueFormat, PgValueRef, Postgres, +}; use crate::types::Type; use std::mem; use time::{Date, Duration}; @@ -13,18 +15,12 @@ impl Type for Date { } } -impl Type for [Date] { - fn type_info() -> PgTypeInfo { +impl PgHasArrayType for Date { + fn array_type_info() -> PgTypeInfo { PgTypeInfo::DATE_ARRAY } } -impl Type for Vec { - fn type_info() -> PgTypeInfo { - <[Date] as Type>::type_info() - } -} - impl Encode<'_, Postgres> for Date { fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull { // DATE is encoded as the days since epoch diff --git a/sqlx-core/src/postgres/types/time/datetime.rs b/sqlx-core/src/postgres/types/time/datetime.rs index 19d543a3e2..5950c58206 100644 --- a/sqlx-core/src/postgres/types/time/datetime.rs +++ b/sqlx-core/src/postgres/types/time/datetime.rs @@ -2,7 +2,9 @@ use crate::decode::Decode; use crate::encode::{Encode, IsNull}; use crate::error::BoxDynError; use crate::postgres::types::time::PG_EPOCH; -use crate::postgres::{PgArgumentBuffer, PgTypeInfo, PgValueFormat, PgValueRef, Postgres}; +use crate::postgres::{ + PgArgumentBuffer, PgHasArrayType, PgTypeInfo, PgValueFormat, PgValueRef, Postgres, +}; use crate::types::Type; use std::borrow::Cow; use std::mem; @@ -20,30 +22,18 @@ impl Type for OffsetDateTime { } } -impl Type for [PrimitiveDateTime] { - fn type_info() -> PgTypeInfo { +impl PgHasArrayType for PrimitiveDateTime { + fn array_type_info() -> PgTypeInfo { PgTypeInfo::TIMESTAMP_ARRAY } } -impl Type for [OffsetDateTime] { - fn type_info() -> PgTypeInfo { +impl PgHasArrayType for OffsetDateTime { + fn array_type_info() -> PgTypeInfo { PgTypeInfo::TIMESTAMPTZ_ARRAY } } -impl Type for Vec { - fn type_info() -> PgTypeInfo { - <[PrimitiveDateTime] as Type>::type_info() - } -} - -impl Type for Vec { - fn type_info() -> PgTypeInfo { - <[OffsetDateTime] as Type>::type_info() - } -} - impl Encode<'_, Postgres> for PrimitiveDateTime { fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull { // TIMESTAMP is encoded as the microseconds since the epoch diff --git a/sqlx-core/src/postgres/types/time/time.rs b/sqlx-core/src/postgres/types/time/time.rs index ee88e4d084..46c209b491 100644 --- a/sqlx-core/src/postgres/types/time/time.rs +++ b/sqlx-core/src/postgres/types/time/time.rs @@ -1,7 +1,9 @@ use crate::decode::Decode; use crate::encode::{Encode, IsNull}; use crate::error::BoxDynError; -use crate::postgres::{PgArgumentBuffer, PgTypeInfo, PgValueFormat, PgValueRef, Postgres}; +use crate::postgres::{ + PgArgumentBuffer, PgHasArrayType, PgTypeInfo, PgValueFormat, PgValueRef, Postgres, +}; use crate::types::Type; use std::borrow::Cow; use std::mem; @@ -13,18 +15,12 @@ impl Type for Time { } } -impl Type for [Time] { - fn type_info() -> PgTypeInfo { +impl PgHasArrayType for Time { + fn array_type_info() -> PgTypeInfo { PgTypeInfo::TIME_ARRAY } } -impl Type for Vec