diff --git a/sqlx-core/src/postgres/types/range.rs b/sqlx-core/src/postgres/types/range.rs index 5290fd55df..66ad305bfc 100644 --- a/sqlx-core/src/postgres/types/range.rs +++ b/sqlx-core/src/postgres/types/range.rs @@ -474,6 +474,13 @@ where } } +pub fn decode_as_string(value: PgValueRef<'_>) -> Result +where + T: Type + for<'a> Decode<'a, Postgres>, +{ + Ok( as Decode<'_, Postgres>>::decode(value)?.to_string()) +} + fn parse_bound(ch: char, value: Option) -> Result, BoxDynError> { Ok(if let Some(value) = value { match ch { diff --git a/sqlx-core/src/postgres/types/str.rs b/sqlx-core/src/postgres/types/str.rs index d6a36ecb7b..689a7fecd6 100644 --- a/sqlx-core/src/postgres/types/str.rs +++ b/sqlx-core/src/postgres/types/str.rs @@ -19,6 +19,12 @@ impl Type for str { PgTypeInfo::BPCHAR, PgTypeInfo::VARCHAR, PgTypeInfo::INTERVAL, + PgTypeInfo::INT4_RANGE, + PgTypeInfo::NUM_RANGE, + PgTypeInfo::TS_RANGE, + PgTypeInfo::TSTZ_RANGE, + PgTypeInfo::DATE_RANGE, + PgTypeInfo::INT8_RANGE, PgTypeInfo::MONEY, PgTypeInfo::UNKNOWN, ] @@ -115,6 +121,18 @@ impl Decode<'_, Postgres> for String { fn decode(value: PgValueRef<'_>) -> Result { match *value.type_info { PgType::Interval => super::interval::decode_as_string(value), + PgType::Int4Range => super::range::decode_as_string::(value), + #[cfg(feature = "bigdecimal")] + PgType::NumRange => super::range::decode_as_string::(value), + #[cfg(feature = "chrono")] + PgType::TsRange => super::range::decode_as_string::(value), + #[cfg(feature = "chrono")] + PgType::TstzRange => { + super::range::decode_as_string::>(value) + } + #[cfg(feature = "chrono")] + PgType::DateRange => super::range::decode_as_string::(value), + PgType::Int8Range => super::range::decode_as_string::(value), _ => Ok(value.as_str()?.to_owned()), } } diff --git a/tests/postgres/types.rs b/tests/postgres/types.rs index bbc66b969d..33a0c5d4a5 100644 --- a/tests/postgres/types.rs +++ b/tests/postgres/types.rs @@ -561,6 +561,15 @@ test_decode_type!(interval_string(Postgres, "'00:01:00'::INTERVAL * 60" == "01:00:00" )); +#[cfg(feature = "bigdecimal")] +#[cfg(feature = "chrono")] +test_decode_type!(range_string(Postgres, + "'(1,2)'::int4range" == "(1,2)", + "'(1,2)'::numrange" == "(1,2)", + "'[\"2025-01-01T00:00:00+01:00\", \"2025-01-02T00:00:00+00:00\")'::tstzrange" == "[\"2025-01-01T00:00:00+01:00\", \"2025-01-02T00:00:00+00:00\")", + "'(1,2)'::int8range" == "(1,2)", +)); + test_prepared_type!(money(Postgres, "123.45::money" == PgMoney(12345))); test_prepared_type!(money_vec>(Postgres,