Skip to content

Commit de443e1

Browse files
committed
wip: range to str decoding
1 parent 5f57b85 commit de443e1

File tree

3 files changed

+34
-0
lines changed

3 files changed

+34
-0
lines changed

sqlx-core/src/postgres/types/range.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,13 @@ where
474474
}
475475
}
476476

477+
pub fn decode_as_string<T: Display>(value: PgValueRef<'_>) -> Result<String, BoxDynError>
478+
where
479+
T: Type<Postgres> + for<'a> Decode<'a, Postgres>,
480+
{
481+
Ok(<PgRange<T> as Decode<'_, Postgres>>::decode(value)?.to_string())
482+
}
483+
477484
fn parse_bound<T>(ch: char, value: Option<T>) -> Result<Bound<T>, BoxDynError> {
478485
Ok(if let Some(value) = value {
479486
match ch {

sqlx-core/src/postgres/types/str.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ impl Type<Postgres> for str {
1919
PgTypeInfo::BPCHAR,
2020
PgTypeInfo::VARCHAR,
2121
PgTypeInfo::INTERVAL,
22+
PgTypeInfo::INT4_RANGE,
23+
PgTypeInfo::NUM_RANGE,
24+
PgTypeInfo::TS_RANGE,
25+
PgTypeInfo::TSTZ_RANGE,
26+
PgTypeInfo::DATE_RANGE,
27+
PgTypeInfo::INT8_RANGE,
2228
PgTypeInfo::MONEY,
2329
PgTypeInfo::UNKNOWN,
2430
]
@@ -115,6 +121,18 @@ impl Decode<'_, Postgres> for String {
115121
fn decode(value: PgValueRef<'_>) -> Result<Self, BoxDynError> {
116122
match *value.type_info {
117123
PgType::Interval => super::interval::decode_as_string(value),
124+
PgType::Int4Range => super::range::decode_as_string::<i32>(value),
125+
#[cfg(feature = "bigdecimal")]
126+
PgType::NumRange => super::range::decode_as_string::<bigdecimal::BigDecimal>(value),
127+
#[cfg(feature = "chrono")]
128+
PgType::TsRange => super::range::decode_as_string::<chrono::NaiveDateTime>(value),
129+
#[cfg(feature = "chrono")]
130+
PgType::TstzRange => {
131+
super::range::decode_as_string::<chrono::DateTime<chrono::Utc>>(value)
132+
}
133+
#[cfg(feature = "chrono")]
134+
PgType::DateRange => super::range::decode_as_string::<chrono::NaiveDate>(value),
135+
PgType::Int8Range => super::range::decode_as_string::<i64>(value),
118136
_ => Ok(value.as_str()?.to_owned()),
119137
}
120138
}

tests/postgres/types.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,15 @@ test_decode_type!(interval_string<String>(Postgres,
561561
"'00:01:00'::INTERVAL * 60" == "01:00:00"
562562
));
563563

564+
#[cfg(feature = "bigdecimal")]
565+
#[cfg(feature = "chrono")]
566+
test_decode_type!(range_string<String>(Postgres,
567+
"'(1,2)'::int4range" == "(1,2)",
568+
"'(1,2)'::numrange" == "(1,2)",
569+
"'[\"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\")",
570+
"'(1,2)'::int8range" == "(1,2)",
571+
));
572+
564573
test_prepared_type!(money<PgMoney>(Postgres, "123.45::money" == PgMoney(12345)));
565574

566575
test_prepared_type!(money_vec<Vec<PgMoney>>(Postgres,

0 commit comments

Comments
 (0)