Skip to content

Commit 21a9a2a

Browse files
Implement cast and other operations on decimal32 and decimal64 (#7815)
# Which issue does this PR close? Part of addressing #6661 but does not close it; there is at least one more PR for CSV/Parquet/JSON support. # What changes are included in this PR? This change adds cast operations for the recently-added `decimal32` and `decimal64` types. It also adds tests to verify that sort and comparison work correctly, and includes these types in benchmarks. # Are these changes tested? Yes. # Are there any user-facing changes? Casting to and from `decimal32` and `decimal64` is now supported.
1 parent cf0c089 commit 21a9a2a

File tree

14 files changed

+1158
-43
lines changed

14 files changed

+1158
-43
lines changed

arrow-array/src/cast.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1132,6 +1132,18 @@ mod tests {
11321132
assert!(!as_string_array(&array).is_empty())
11331133
}
11341134

1135+
#[test]
1136+
fn test_decimal32array() {
1137+
let a = Decimal32Array::from_iter_values([1, 2, 4, 5]);
1138+
assert!(!as_primitive_array::<Decimal32Type>(&a).is_empty());
1139+
}
1140+
1141+
#[test]
1142+
fn test_decimal64array() {
1143+
let a = Decimal64Array::from_iter_values([1, 2, 4, 5]);
1144+
assert!(!as_primitive_array::<Decimal64Type>(&a).is_empty());
1145+
}
1146+
11351147
#[test]
11361148
fn test_decimal128array() {
11371149
let a = Decimal128Array::from_iter_values([1, 2, 4, 5]);

arrow-array/src/types.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1820,6 +1820,8 @@ mod tests {
18201820
test_layout::<Float16Type>();
18211821
test_layout::<Float32Type>();
18221822
test_layout::<Float64Type>();
1823+
test_layout::<Decimal32Type>();
1824+
test_layout::<Decimal64Type>();
18231825
test_layout::<Decimal128Type>();
18241826
test_layout::<Decimal256Type>();
18251827
test_layout::<TimestampNanosecondType>();

arrow-cast/src/cast/decimal.rs

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ use crate::cast::*;
2020
/// A utility trait that provides checked conversions between
2121
/// decimal types inspired by [`NumCast`]
2222
pub(crate) trait DecimalCast: Sized {
23+
fn to_i32(self) -> Option<i32>;
24+
25+
fn to_i64(self) -> Option<i64>;
26+
2327
fn to_i128(self) -> Option<i128>;
2428

2529
fn to_i256(self) -> Option<i256>;
@@ -29,7 +33,67 @@ pub(crate) trait DecimalCast: Sized {
2933
fn from_f64(n: f64) -> Option<Self>;
3034
}
3135

36+
impl DecimalCast for i32 {
37+
fn to_i32(self) -> Option<i32> {
38+
Some(self)
39+
}
40+
41+
fn to_i64(self) -> Option<i64> {
42+
Some(self as i64)
43+
}
44+
45+
fn to_i128(self) -> Option<i128> {
46+
Some(self as i128)
47+
}
48+
49+
fn to_i256(self) -> Option<i256> {
50+
Some(i256::from_i128(self as i128))
51+
}
52+
53+
fn from_decimal<T: DecimalCast>(n: T) -> Option<Self> {
54+
n.to_i32()
55+
}
56+
57+
fn from_f64(n: f64) -> Option<Self> {
58+
n.to_i32()
59+
}
60+
}
61+
62+
impl DecimalCast for i64 {
63+
fn to_i32(self) -> Option<i32> {
64+
i32::try_from(self).ok()
65+
}
66+
67+
fn to_i64(self) -> Option<i64> {
68+
Some(self)
69+
}
70+
71+
fn to_i128(self) -> Option<i128> {
72+
Some(self as i128)
73+
}
74+
75+
fn to_i256(self) -> Option<i256> {
76+
Some(i256::from_i128(self as i128))
77+
}
78+
79+
fn from_decimal<T: DecimalCast>(n: T) -> Option<Self> {
80+
n.to_i64()
81+
}
82+
83+
fn from_f64(n: f64) -> Option<Self> {
84+
n.to_i64()
85+
}
86+
}
87+
3288
impl DecimalCast for i128 {
89+
fn to_i32(self) -> Option<i32> {
90+
i32::try_from(self).ok()
91+
}
92+
93+
fn to_i64(self) -> Option<i64> {
94+
i64::try_from(self).ok()
95+
}
96+
3397
fn to_i128(self) -> Option<i128> {
3498
Some(self)
3599
}
@@ -48,6 +112,14 @@ impl DecimalCast for i128 {
48112
}
49113

50114
impl DecimalCast for i256 {
115+
fn to_i32(self) -> Option<i32> {
116+
self.to_i128().map(|x| i32::try_from(x).ok())?
117+
}
118+
119+
fn to_i64(self) -> Option<i64> {
120+
self.to_i128().map(|x| i64::try_from(x).ok())?
121+
}
122+
51123
fn to_i128(self) -> Option<i128> {
52124
self.to_i128()
53125
}

0 commit comments

Comments
 (0)