datatypes/vectors/operations/
cast.rs

1// Copyright 2023 Greptime Team
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15macro_rules! cast_non_constant {
16    ($vector: expr, $to_type: expr) => {{
17        use arrow::compute;
18        use snafu::ResultExt;
19
20        use crate::data_type::DataType;
21        use crate::vectors::helper::Helper;
22
23        let arrow_array = $vector.to_arrow_array();
24        let casted = compute::cast(&arrow_array, &$to_type.as_arrow_type())
25            .context(crate::error::ArrowComputeSnafu)?;
26        Helper::try_into_vector(casted)
27    }};
28}
29
30pub(crate) use cast_non_constant;
31
32/// There are already many test cases in arrow:
33/// https://github.com/apache/arrow-rs/blob/59016e53e5cfa1d368009ed640d1f3dce326e7bb/arrow-cast/src/cast.rs#L3349-L7584
34/// So we don't(can't) want to copy these cases, just test some cases which are important for us.
35#[cfg(test)]
36mod tests {
37    use std::sync::Arc;
38
39    use common_time::date::Date;
40    use common_time::timestamp::{TimeUnit, Timestamp};
41
42    use crate::types::{LogicalPrimitiveType, *};
43    use crate::vectors::{ConcreteDataType, *};
44
45    fn get_cast_values<T>(vector: &VectorRef, dt: &ConcreteDataType) -> Vec<String>
46    where
47        T: LogicalPrimitiveType,
48    {
49        let c = vector.cast(dt).unwrap();
50        let a = c.as_any().downcast_ref::<PrimitiveVector<T>>().unwrap();
51        let mut v: Vec<String> = vec![];
52        for i in 0..vector.len() {
53            if a.is_null(i) {
54                v.push("null".to_string())
55            } else {
56                v.push(format!("{}", a.get(i)));
57            }
58        }
59        v
60    }
61
62    #[test]
63    fn test_cast_from_f64() {
64        let f64_values: Vec<f64> = vec![
65            i64::MIN as f64,
66            i32::MIN as f64,
67            i16::MIN as f64,
68            i8::MIN as f64,
69            0_f64,
70            u8::MAX as f64,
71            u16::MAX as f64,
72            u32::MAX as f64,
73            u64::MAX as f64,
74        ];
75        let f64_vector: VectorRef = Arc::new(Float64Vector::from_slice(f64_values));
76
77        let f64_expected = vec![
78            -9223372036854776000.0,
79            -2147483648.0,
80            -32768.0,
81            -128.0,
82            0.0,
83            255.0,
84            65535.0,
85            4294967295.0,
86            18446744073709552000.0,
87        ];
88        assert_eq!(
89            f64_expected,
90            get_cast_values::<Float64Type>(&f64_vector, &ConcreteDataType::float64_datatype())
91                .iter()
92                .map(|i| i.parse::<f64>().unwrap())
93                .collect::<Vec<f64>>()
94        );
95
96        let i64_expected = vec![
97            "-9223372036854775808",
98            "-2147483648",
99            "-32768",
100            "-128",
101            "0",
102            "255",
103            "65535",
104            "4294967295",
105            "null",
106        ];
107        assert_eq!(
108            i64_expected,
109            get_cast_values::<Int64Type>(&f64_vector, &ConcreteDataType::int64_datatype())
110        );
111
112        let u64_expected = vec![
113            "null",
114            "null",
115            "null",
116            "null",
117            "0",
118            "255",
119            "65535",
120            "4294967295",
121            "null",
122        ];
123        assert_eq!(
124            u64_expected,
125            get_cast_values::<UInt64Type>(&f64_vector, &ConcreteDataType::uint64_datatype())
126        );
127    }
128
129    #[test]
130    fn test_cast_from_date() {
131        let i32_values: Vec<i32> = vec![
132            i32::MIN,
133            i16::MIN as i32,
134            i8::MIN as i32,
135            0,
136            i8::MAX as i32,
137            i16::MAX as i32,
138            i32::MAX,
139        ];
140        let date32_vector: VectorRef = Arc::new(DateVector::from_slice(i32_values));
141
142        let i32_expected = vec![
143            "-2147483648",
144            "-32768",
145            "-128",
146            "0",
147            "127",
148            "32767",
149            "2147483647",
150        ];
151        assert_eq!(
152            i32_expected,
153            get_cast_values::<Int32Type>(&date32_vector, &ConcreteDataType::int32_datatype()),
154        );
155
156        let i64_expected = vec![
157            "-2147483648",
158            "-32768",
159            "-128",
160            "0",
161            "127",
162            "32767",
163            "2147483647",
164        ];
165        assert_eq!(
166            i64_expected,
167            get_cast_values::<Int64Type>(&date32_vector, &ConcreteDataType::int64_datatype()),
168        );
169    }
170
171    #[test]
172    fn test_cast_timestamp_to_date32() {
173        let vector =
174            TimestampMillisecondVector::from(vec![Some(864000000005), Some(1545696000001), None]);
175        let b = vector.cast(&ConcreteDataType::date_datatype()).unwrap();
176        let c = b.as_any().downcast_ref::<DateVector>().unwrap();
177        assert_eq!(Value::Date(Date::from(10000)), c.get(0));
178        assert_eq!(Value::Date(Date::from(17890)), c.get(1));
179        assert!(c.is_null(2));
180    }
181
182    #[test]
183    fn test_cast_string_to_timestamp() {
184        let a1 = Arc::new(StringVector::from(vec![
185            Some("2020-09-08T12:00:00+00:00"),
186            Some("Not a valid date"),
187            None,
188        ])) as VectorRef;
189        let a2 = Arc::new(StringVector::from(vec![
190            Some("2020-09-08T12:00:00+00:00"),
191            Some("Not a valid date"),
192            None,
193        ])) as VectorRef;
194
195        for array in &[a1, a2] {
196            let to_type = ConcreteDataType::timestamp_nanosecond_datatype();
197            let b = array.cast(&to_type).unwrap();
198            let c = b
199                .as_any()
200                .downcast_ref::<TimestampNanosecondVector>()
201                .unwrap();
202            assert_eq!(
203                Value::Timestamp(Timestamp::new(1599566400000000000, TimeUnit::Nanosecond)),
204                c.get(0)
205            );
206            assert!(c.is_null(1));
207            assert!(c.is_null(2));
208        }
209    }
210
211    #[test]
212    fn test_safe_cast_to_null() {
213        let string_vector = Arc::new(StringVector::from(vec![
214            Some("1"),
215            Some("hello"),
216            Some(&i64::MAX.to_string()),
217            None,
218        ])) as VectorRef;
219        let to_type = ConcreteDataType::int32_datatype();
220        let b = string_vector.cast(&to_type).unwrap();
221        let c = b.as_any().downcast_ref::<Int32Vector>().unwrap();
222        assert_eq!(Value::Int32(1), c.get(0));
223        assert_eq!(Value::Null, c.get(1));
224        assert_eq!(Value::Null, c.get(2));
225        assert_eq!(Value::Null, c.get(3));
226    }
227}