1use arrow::array::{ArrayRef, AsArray};
16use arrow::datatypes::{
17 DataType, DurationMicrosecondType, DurationMillisecondType, DurationNanosecondType,
18 DurationSecondType, Int8Type, Int16Type, Int32Type, Int64Type, Time32MillisecondType,
19 Time32SecondType, Time64MicrosecondType, Time64NanosecondType, TimeUnit,
20 TimestampMicrosecondType, TimestampMillisecondType, TimestampNanosecondType,
21 TimestampSecondType, UInt8Type, UInt16Type, UInt32Type, UInt64Type,
22};
23use arrow::downcast_dictionary_array;
24use arrow_array::Array;
25use common_time::time::Time;
26use common_time::{Duration, Timestamp};
27
28pub type BinaryArray = arrow::array::BinaryArray;
29pub type LargeBinaryArray = arrow::array::LargeBinaryArray;
30pub type MutableBinaryArray = arrow::array::BinaryBuilder;
31pub type BinaryViewArray = arrow::array::BinaryViewArray;
32pub type MutableBinaryViewArray = arrow::array::BinaryViewBuilder;
33pub type StringArray = arrow::array::StringArray;
34pub type MutableStringArray = arrow::array::StringBuilder;
35pub type LargeStringArray = arrow::array::LargeStringArray;
36pub type MutableLargeStringArray = arrow::array::LargeStringBuilder;
37pub type StringViewArray = arrow::array::StringViewArray;
38pub type MutableStringViewArray = arrow::array::StringViewBuilder;
39
40pub fn timestamp_array_value(array: &ArrayRef, i: usize) -> Timestamp {
49 let DataType::Timestamp(time_unit, _) = &array.data_type() else {
50 unreachable!()
51 };
52 let v = match time_unit {
53 TimeUnit::Second => {
54 let array = array.as_primitive::<TimestampSecondType>();
55 array.value(i)
56 }
57 TimeUnit::Millisecond => {
58 let array = array.as_primitive::<TimestampMillisecondType>();
59 array.value(i)
60 }
61 TimeUnit::Microsecond => {
62 let array = array.as_primitive::<TimestampMicrosecondType>();
63 array.value(i)
64 }
65 TimeUnit::Nanosecond => {
66 let array = array.as_primitive::<TimestampNanosecondType>();
67 array.value(i)
68 }
69 };
70 Timestamp::new(v, time_unit.into())
71}
72
73pub fn time_array_value(array: &ArrayRef, i: usize) -> Time {
82 match array.data_type() {
83 DataType::Time32(time_unit) | DataType::Time64(time_unit) => match time_unit {
84 TimeUnit::Second => {
85 let array = array.as_primitive::<Time32SecondType>();
86 Time::new_second(array.value(i) as i64)
87 }
88 TimeUnit::Millisecond => {
89 let array = array.as_primitive::<Time32MillisecondType>();
90 Time::new_millisecond(array.value(i) as i64)
91 }
92 TimeUnit::Microsecond => {
93 let array = array.as_primitive::<Time64MicrosecondType>();
94 Time::new_microsecond(array.value(i))
95 }
96 TimeUnit::Nanosecond => {
97 let array = array.as_primitive::<Time64NanosecondType>();
98 Time::new_nanosecond(array.value(i))
99 }
100 },
101 _ => unreachable!(),
102 }
103}
104
105pub fn duration_array_value(array: &ArrayRef, i: usize) -> Duration {
114 let DataType::Duration(time_unit) = array.data_type() else {
115 unreachable!();
116 };
117 let v = match time_unit {
118 TimeUnit::Second => {
119 let array = array.as_primitive::<DurationSecondType>();
120 array.value(i)
121 }
122 TimeUnit::Millisecond => {
123 let array = array.as_primitive::<DurationMillisecondType>();
124 array.value(i)
125 }
126 TimeUnit::Microsecond => {
127 let array = array.as_primitive::<DurationMicrosecondType>();
128 array.value(i)
129 }
130 TimeUnit::Nanosecond => {
131 let array = array.as_primitive::<DurationNanosecondType>();
132 array.value(i)
133 }
134 };
135 Duration::new(v, time_unit.into())
136}
137
138pub fn string_array_value_at_index(array: &ArrayRef, i: usize) -> Option<&str> {
146 match array.data_type() {
147 DataType::Utf8 => {
148 let array = array.as_string::<i32>();
149 array.is_valid(i).then(|| array.value(i))
150 }
151 DataType::LargeUtf8 => {
152 let array = array.as_string::<i64>();
153 array.is_valid(i).then(|| array.value(i))
154 }
155 DataType::Utf8View => {
156 let array = array.as_string_view();
157 array.is_valid(i).then(|| array.value(i))
158 }
159 DataType::Dictionary(key_type, value_type)
160 if key_type.is_integer() && value_type.is_string() =>
161 {
162 downcast_dictionary_array! {
163 array => string_array_value_at_index(array.values(), array.key(i)?),
164 _ => None,
165 }
166 }
167 _ => None,
168 }
169}
170
171pub fn is_string_null_at(array: &ArrayRef, i: usize) -> bool {
181 match array.data_type() {
182 DataType::Utf8 => {
183 let array = array.as_string::<i32>();
184 !array.is_valid(i)
185 }
186 DataType::LargeUtf8 => {
187 let array = array.as_string::<i64>();
188 !array.is_valid(i)
189 }
190 DataType::Utf8View => {
191 let array = array.as_string_view();
192 !array.is_valid(i)
193 }
194 DataType::Dictionary(key_type, value_type)
195 if key_type.is_integer() && value_type.is_string() =>
196 {
197 downcast_dictionary_array! {
198 array => array
199 .key(i)
200 .is_none_or(|key| is_string_null_at(array.values(), key)),
201 _ => true,
202 }
203 }
204 _ => true,
205 }
206}
207
208pub fn string_array_value(array: &ArrayRef, i: usize) -> &str {
217 match array.data_type() {
218 DataType::Utf8 => array.as_string::<i32>().value(i),
219 DataType::LargeUtf8 => array.as_string::<i64>().value(i),
220 DataType::Utf8View => array.as_string_view().value(i),
221 _ => unreachable!(),
222 }
223}
224
225pub fn binary_array_value(array: &ArrayRef, i: usize) -> &[u8] {
234 match array.data_type() {
235 DataType::Binary => array.as_binary::<i32>().value(i),
236 DataType::LargeBinary => array.as_binary::<i64>().value(i),
237 DataType::BinaryView => array.as_binary_view().value(i),
238 _ => unreachable!(),
239 }
240}
241
242pub fn int_array_value_at_index(array: &ArrayRef, i: usize) -> Option<i64> {
254 match array.data_type() {
255 DataType::Int8 => {
256 let array = array.as_primitive::<Int8Type>();
257 array.is_valid(i).then(|| array.value(i) as i64)
258 }
259 DataType::Int16 => {
260 let array = array.as_primitive::<Int16Type>();
261 array.is_valid(i).then(|| array.value(i) as i64)
262 }
263 DataType::Int32 => {
264 let array = array.as_primitive::<Int32Type>();
265 array.is_valid(i).then(|| array.value(i) as i64)
266 }
267 DataType::Int64 => {
268 let array = array.as_primitive::<Int64Type>();
269 array.is_valid(i).then(|| array.value(i))
270 }
271 DataType::UInt8 => {
272 let array = array.as_primitive::<UInt8Type>();
273 array.is_valid(i).then(|| array.value(i) as i64)
274 }
275 DataType::UInt16 => {
276 let array = array.as_primitive::<UInt16Type>();
277 array.is_valid(i).then(|| array.value(i) as i64)
278 }
279 DataType::UInt32 => {
280 let array = array.as_primitive::<UInt32Type>();
281 array.is_valid(i).then(|| array.value(i) as i64)
282 }
283 DataType::UInt64 => {
284 let array = array.as_primitive::<UInt64Type>();
285 array
286 .is_valid(i)
287 .then(|| {
288 let i = array.value(i);
289 if i <= i64::MAX as u64 {
290 Some(i as i64)
291 } else {
292 None
293 }
294 })
295 .flatten()
296 }
297 _ => None,
298 }
299}
300
301#[cfg(test)]
302mod tests {
303 use std::sync::Arc;
304
305 use arrow::array::StringDictionaryBuilder;
306 use arrow::datatypes::ArrowDictionaryKeyType;
307
308 use super::*;
309
310 fn assert_dictionary_key_type<K: ArrowDictionaryKeyType>() {
311 let mut builder = StringDictionaryBuilder::<K>::new();
312 builder.append("foo").unwrap();
313 builder.append("bar").unwrap();
314 builder.append("foo").unwrap();
315 builder.append_null();
316 let array: ArrayRef = Arc::new(builder.finish());
317
318 assert_eq!(Some("foo"), string_array_value_at_index(&array, 0));
319 assert_eq!(Some("bar"), string_array_value_at_index(&array, 1));
320 assert_eq!(Some("foo"), string_array_value_at_index(&array, 2));
321 assert_eq!(None, string_array_value_at_index(&array, 3));
322 }
323
324 #[test]
325 fn reads_dictionary_encoded_strings_with_all_key_types() {
326 assert_dictionary_key_type::<Int8Type>();
327 assert_dictionary_key_type::<Int16Type>();
328 assert_dictionary_key_type::<Int32Type>();
329 assert_dictionary_key_type::<Int64Type>();
330 assert_dictionary_key_type::<UInt8Type>();
331 assert_dictionary_key_type::<UInt16Type>();
332 assert_dictionary_key_type::<UInt32Type>();
333 assert_dictionary_key_type::<UInt64Type>();
334 }
335}