1use vortex_array::ArrayRef;
5use vortex_array::IntoArray;
6use vortex_array::dtype::DType;
7use vortex_array::scalar_fn::fns::cast::CastReduce;
8use vortex_error::VortexResult;
9
10use crate::PcoArray;
11use crate::PcoVTable;
12
13impl CastReduce for PcoVTable {
14 fn cast(array: &PcoArray, dtype: &DType) -> VortexResult<Option<ArrayRef>> {
15 if !dtype.is_nullable() || !array.all_valid()? {
16 return Ok(None);
20 }
21 if array.dtype().eq_ignore_nullability(dtype) {
26 let new_validity = array
28 .unsliced_validity
29 .clone()
30 .cast_nullability(dtype.nullability(), array.len())?;
31
32 return Ok(Some(
33 PcoArray::new(
34 array.chunk_metas.clone(),
35 array.pages.clone(),
36 dtype.clone(),
37 array.metadata.clone(),
38 array.unsliced_n_rows(),
39 new_validity,
40 )
41 ._slice(array.slice_start(), array.slice_stop())
42 .into_array(),
43 ));
44 }
45
46 Ok(None)
48 }
49}
50
51#[cfg(test)]
52mod tests {
53 use rstest::rstest;
54 use vortex_array::IntoArray;
55 use vortex_array::arrays::PrimitiveArray;
56 use vortex_array::assert_arrays_eq;
57 use vortex_array::builtins::ArrayBuiltins;
58 use vortex_array::compute::conformance::cast::test_cast_conformance;
59 use vortex_array::dtype::DType;
60 use vortex_array::dtype::Nullability;
61 use vortex_array::dtype::PType;
62 use vortex_array::validity::Validity;
63 use vortex_buffer::buffer;
64
65 use crate::PcoArray;
66
67 #[test]
68 fn test_cast_pco_f32_to_f64() {
69 let values = PrimitiveArray::from_iter([1.0f32, 2.0, 3.0, 4.0, 5.0]);
70 let pco = PcoArray::from_primitive(&values, 0, 128).unwrap();
71
72 let casted = pco
73 .into_array()
74 .cast(DType::Primitive(PType::F64, Nullability::NonNullable))
75 .unwrap();
76 assert_eq!(
77 casted.dtype(),
78 &DType::Primitive(PType::F64, Nullability::NonNullable)
79 );
80
81 assert_arrays_eq!(
82 casted,
83 PrimitiveArray::from_iter([1.0f64, 2.0, 3.0, 4.0, 5.0])
84 );
85 }
86
87 #[test]
88 fn test_cast_pco_nullability_change() {
89 let values = PrimitiveArray::from_iter([10u32, 20, 30, 40]);
91 let pco = PcoArray::from_primitive(&values, 0, 128).unwrap();
92
93 let casted = pco
94 .into_array()
95 .cast(DType::Primitive(PType::U32, Nullability::Nullable))
96 .unwrap();
97 assert_arrays_eq!(
98 casted,
99 PrimitiveArray::new(buffer![10u32, 20, 30, 40], Validity::AllValid,)
100 );
101 }
102
103 #[test]
104 fn test_cast_sliced_pco_nullable_to_nonnullable() {
105 let values = PrimitiveArray::new(
106 buffer![10u32, 20, 30, 40, 50, 60],
107 Validity::from_iter([true, true, true, true, true, true]),
108 );
109 let pco = PcoArray::from_primitive(&values, 0, 128).unwrap();
110 let sliced = pco.slice(1..5).unwrap();
111 let casted = sliced
112 .cast(DType::Primitive(PType::U32, Nullability::NonNullable))
113 .unwrap();
114 assert_eq!(
115 casted.dtype(),
116 &DType::Primitive(PType::U32, Nullability::NonNullable)
117 );
118 assert_arrays_eq!(casted, PrimitiveArray::from_iter([20u32, 30, 40, 50]));
120 }
121
122 #[test]
123 fn test_cast_sliced_pco_part_valid_to_nonnullable() {
124 let values = PrimitiveArray::from_option_iter([
125 None,
126 Some(20u32),
127 Some(30),
128 Some(40),
129 Some(50),
130 Some(60),
131 ]);
132 let pco = PcoArray::from_primitive(&values, 0, 128).unwrap();
133 let sliced = pco.slice(1..5).unwrap();
134 let casted = sliced
135 .cast(DType::Primitive(PType::U32, Nullability::NonNullable))
136 .unwrap();
137 assert_eq!(
138 casted.dtype(),
139 &DType::Primitive(PType::U32, Nullability::NonNullable)
140 );
141 assert_arrays_eq!(casted, PrimitiveArray::from_iter([20u32, 30, 40, 50]));
142 }
143
144 #[rstest]
145 #[case::f32(PrimitiveArray::new(
146 buffer![1.23f32, 4.56, 7.89, 10.11, 12.13],
147 Validity::NonNullable,
148 ))]
149 #[case::f64(PrimitiveArray::new(
150 buffer![100.1f64, 200.2, 300.3, 400.4, 500.5],
151 Validity::NonNullable,
152 ))]
153 #[case::i32(PrimitiveArray::new(
154 buffer![100i32, 200, 300, 400, 500],
155 Validity::NonNullable,
156 ))]
157 #[case::u64(PrimitiveArray::new(
158 buffer![1000u64, 2000, 3000, 4000],
159 Validity::NonNullable,
160 ))]
161 #[case::single(PrimitiveArray::new(
162 buffer![42.42f64],
163 Validity::NonNullable,
164 ))]
165 fn test_cast_pco_conformance(#[case] values: PrimitiveArray) {
166 let pco = PcoArray::from_primitive(&values, 0, 128).unwrap();
167 test_cast_conformance(&pco.into_array());
168 }
169}