1use std::sync::Arc;
2
3use arrow::array::*;
4use arrow::compute::cast;
5use arrow::datatypes::*;
6use arrow::record_batch::RecordBatch;
7
8use crate::{Date, DateTime, DynDateTime64, Error, Result, Type, Value};
9
10pub fn split_record_batch(batch: RecordBatch, max: usize) -> Vec<RecordBatch> {
50 if max == 0 {
51 return vec![];
52 }
53
54 let rows = batch.num_rows();
55 if rows == 0 || rows < max {
56 return vec![batch];
57 }
58
59 let mut chunks = Vec::with_capacity(rows.div_ceil(max));
61 let mut offset = 0;
62 while offset < rows {
63 let remaining_rows = rows - offset;
64 let chunk_rows = remaining_rows.min(max);
65 chunks.push(batch.slice(offset, chunk_rows));
66 offset += chunk_rows;
67 }
68
69 chunks
70}
71
72pub fn batch_to_rows(
84 batch: &RecordBatch,
85 type_hints: Option<&[(String, Type)]>,
86) -> Result<impl Iterator<Item = Result<Vec<Value>, Error>> + use<>> {
87 let row_len = batch.num_rows();
88 let col_len = batch.num_columns();
89 let columns = batch.columns();
90 let schema = batch.schema();
91
92 let values = columns
94 .iter()
95 .enumerate()
96 .map(|(i, column)| {
97 let name = schema.field(i).name();
98 let type_hint =
99 type_hints.as_ref().and_then(|hints| hints.iter().find(|(n, _)| n == name));
100 array_to_values(column, column.data_type(), type_hint.map(|(_, t)| t))
101 })
102 .collect::<Result<Vec<_>>>()?;
103
104 let row_iter = (0..row_len).map(move |i| {
105 let row = (0..col_len).map(|j| values[j][i].clone()).collect::<Vec<_>>();
106 Ok(row)
107 });
108
109 Ok(row_iter)
110}
111
112#[expect(clippy::too_many_lines)]
118pub fn array_to_values(
119 column: &dyn Array,
120 data_type: &DataType,
121 type_hint: Option<&Type>,
122) -> Result<Vec<Value>> {
123 fn map_or_null<T>(
124 iter: impl Iterator<Item = Option<T>>,
125 conv: impl Fn(T) -> Value,
126 ) -> Vec<Value> {
127 iter.map(|v| v.map_or(Value::Null, &conv)).collect::<Vec<Value>>()
128 }
129
130 Ok(match data_type {
131 DataType::Int8 => map_or_null(array_to_i8_iter(column)?, Value::Int8),
133 DataType::Int16 => map_or_null(array_to_i16_iter(column)?, Value::Int16),
134 DataType::Int32 => map_or_null(array_to_i32_iter(column)?, Value::Int32),
135 DataType::Int64 => map_or_null(array_to_i64_iter(column)?, Value::Int64),
136
137 DataType::UInt8 => map_or_null(array_to_u8_iter(column)?, Value::UInt8),
139 DataType::UInt16 => map_or_null(array_to_u16_iter(column)?, Value::UInt16),
140 DataType::UInt32 => map_or_null(array_to_u32_iter(column)?, Value::UInt32),
141 DataType::UInt64 => map_or_null(array_to_u64_iter(column)?, Value::UInt64),
142
143 DataType::Float32 => map_or_null(array_to_f32_iter(column)?, Value::Float32),
145 DataType::Float64 => map_or_null(array_to_f64_iter(column)?, Value::Float64),
146
147 DataType::Binary | DataType::LargeBinary | DataType::BinaryView => {
149 map_or_null(array_to_binary_iter(column)?, Value::String)
150 }
151 DataType::FixedSizeBinary(_) if !matches!(type_hint, Some(Type::Uuid)) => {
152 map_or_null(array_to_binary_iter(column)?, Value::String)
153 }
154
155 DataType::FixedSizeBinary(16) if matches!(type_hint, Some(Type::Uuid)) => {
157 let iter = array_to_binary_iter(column)?.map(|opt| {
158 opt.and_then(|bytes| {
159 (bytes.len() == 16).then(|| {
160 let mut uuid_bytes = [0u8; 16];
161 uuid_bytes.copy_from_slice(&bytes);
162 uuid::Uuid::from_bytes(uuid_bytes)
163 })
164 })
165 });
166 map_or_null(iter, Value::Uuid)
167 }
168
169 DataType::Utf8 | DataType::LargeUtf8 | DataType::Utf8View => {
171 let iter = array_to_string_iter(column)?.map(|opt| opt.map(String::into_bytes));
172 map_or_null(iter, Value::String)
173 }
174
175 DataType::Boolean => {
177 let iter = array_to_bool_iter(column)?.map(|opt| opt.map(u8::from));
178 map_or_null(iter, Value::UInt8)
179 }
180
181 DataType::Decimal128(precision, _) => {
183 let arr = column
184 .as_any()
185 .downcast_ref::<Decimal128Array>()
186 .ok_or_else(|| Error::ArrowDeserialize("Expected Decimal128Array".to_string()))?;
187 map_or_null(
188 (0..arr.len()).map(|i| {
189 if arr.is_null(i) { None } else { Some((*precision as usize, arr.value(i))) }
190 }),
191 |(p, v)| Value::Decimal128(p, v),
192 )
193 }
194 DataType::Decimal256(precision, _) => {
195 let arr = column
196 .as_any()
197 .downcast_ref::<Decimal256Array>()
198 .ok_or_else(|| Error::ArrowDeserialize("Expected Decimal256Array".to_string()))?;
199 map_or_null(
200 (0..arr.len()).map(|i| {
201 if arr.is_null(i) {
202 None
203 } else {
204 Some((*precision as usize, arr.value(i).into()))
205 }
206 }),
207 |(p, v)| Value::Decimal256(p, v),
208 )
209 }
210
211 DataType::Date32 => {
213 map_or_null(array_to_i32_iter(column)?, |d| Value::Date(Date::from_days(d)))
214 }
215 DataType::Date64 => {
216 let tz = type_hint.and_then(|t| match t {
217 Type::DateTime64(_, tz) => Some(Arc::from(tz.clone().to_string().as_str())),
218 Type::Date | Type::Date32 => Some(Arc::from("UTC")),
219 _ => None,
220 });
221 map_or_null(array_to_i64_iter(column)?, |ms| {
222 Value::DateTime64(DynDateTime64::from_millis(ms, tz.clone()))
223 })
224 }
225
226 DataType::Timestamp(unit, tz) => match unit {
228 TimeUnit::Second => map_or_null(
229 array_to_i64_iter(column)?
230 .map(|opt| opt.map(|s| DateTime::from_seconds(s, tz.clone()))),
231 Value::DateTime,
232 ),
233 TimeUnit::Millisecond => map_or_null(
234 array_to_i64_iter(column)?
235 .map(|opt| opt.map(|ms| DynDateTime64::from_millis(ms, tz.clone()))),
236 Value::DateTime64,
237 ),
238 TimeUnit::Microsecond => map_or_null(
239 array_to_i64_iter(column)?
240 .map(|opt| opt.map(|us| DynDateTime64::from_micros(us, tz.clone()))),
241 Value::DateTime64,
242 ),
243 TimeUnit::Nanosecond => map_or_null(
244 array_to_i64_iter(column)?
245 .map(|opt| opt.map(|ns| DynDateTime64::from_nanos(ns, tz.clone()))),
246 Value::DateTime64,
247 ),
248 },
249
250 DataType::List(f) | DataType::LargeList(f) | DataType::FixedSizeList(f, _) => {
252 let data_type = f.data_type();
253 let inner_type_hint = type_hint.and_then(|t| match t {
254 Type::Array(inner) => Some(&(**inner)),
255 _ => None,
256 });
257 let mut caster = |a: Option<ArrayRef>| {
258 a.map_or(Ok(Value::Null), |arr| {
259 array_to_values(&arr, data_type, inner_type_hint).map(Value::Array)
260 })
261 };
262 array_to_list_vec(column, &mut caster)?
263 }
264
265 DataType::Struct(fields) => {
267 let struct_array = column.as_any().downcast_ref::<StructArray>().ok_or_else(|| {
268 Error::ArrowDeserialize("Could not downcast struct array".to_string())
269 })?;
270 (0..struct_array.len())
271 .map(|i| {
272 if struct_array.is_null(i) {
273 Ok(Value::Null)
274 } else {
275 let field_values = fields
276 .iter()
277 .enumerate()
278 .map(|(j, field)| {
279 let field_array = struct_array.column(j);
280 let single_value = array_to_values(
281 &field_array.slice(i, 1),
282 field.data_type(),
283 None,
284 )?;
285 Ok(single_value[0].clone())
286 })
287 .collect::<Result<Vec<Value>>>()?;
288 Ok(Value::Tuple(field_values))
289 }
290 })
291 .collect::<Result<Vec<Value>>>()?
292 }
293
294 DataType::Map(_, _) => {
296 let map_array = column.as_any().downcast_ref::<MapArray>().ok_or_else(|| {
297 Error::ArrowDeserialize("Could not downcast map array".to_string())
298 })?;
299 (0..map_array.len())
300 .map(|i| {
301 if map_array.is_null(i) {
302 Ok(Value::Null)
303 } else {
304 let entry = map_array.value(i);
305 let keys_type = map_array.keys().data_type();
306 let values_type = map_array.values().data_type();
307 Ok(Value::Map(
308 array_to_values(&entry.column(0), keys_type, None)?,
309 array_to_values(&entry.column(1), values_type, None)?,
310 ))
311 }
312 })
313 .collect::<Result<Vec<Value>>>()?
314 }
315
316 DataType::Dictionary(key_type, value_type) => {
318 match (key_type.as_ref(), type_hint) {
319 (DataType::Int8, Some(Type::Enum8(pairs))) => {
320 return Ok(array_to_string_iter(column)?
321 .map(|v| {
322 if let Some(v) = v {
323 pairs
324 .iter()
325 .find(|(value, _)| &v == value)
326 .map_or(Value::Null, |(_, i)| Value::Enum8(v, *i))
327 } else {
328 Value::Null
329 }
330 })
331 .collect::<Vec<_>>());
332 }
333 (DataType::Int16, Some(Type::Enum16(pairs))) => {
334 return Ok(array_to_string_iter(column)?
335 .map(|v| {
336 if let Some(v) = v {
337 pairs
338 .iter()
339 .find(|(value, _)| &v == value)
340 .map_or(Value::Null, |(_, i)| Value::Enum16(v, *i))
341 } else {
342 Value::Null
343 }
344 })
345 .collect::<Vec<_>>());
346 }
347 _ => {}
348 }
349
350 let unpacked = cast(column, value_type).map_err(Error::Arrow)?;
351 array_to_values(&unpacked, value_type, type_hint)?
352 }
353
354 DataType::Null => vec![Value::Null; column.len()],
356
357 _ => {
359 return Err(Error::ArrowUnsupportedType(format!(
360 "Unsupported Arrow data type: {data_type:?}"
361 )));
362 }
363 })
364}
365
366pub fn array_to_list_vec<T>(
371 array: &dyn Array,
372 caster: &mut impl FnMut(Option<ArrayRef>) -> Result<T>,
373) -> Result<Vec<T>> {
374 match array.data_type() {
375 DataType::List(_) => {
376 let array = array.as_any().downcast_ref::<ListArray>().ok_or_else(|| {
377 Error::ArrowDeserialize("Failed to downcast to ListArray".to_string())
378 })?;
379 Ok(array.iter().map(caster).collect::<Result<Vec<_>>>()?)
380 }
381 DataType::LargeList(_) => {
382 let array = array.as_any().downcast_ref::<LargeListArray>().ok_or_else(|| {
383 Error::ArrowDeserialize("Failed to downcast to LargeListArray".to_string())
384 })?;
385 Ok(array.iter().map(caster).collect::<Result<Vec<_>>>()?)
386 }
387 DataType::ListView(_) => {
388 let array = array.as_any().downcast_ref::<ListViewArray>().ok_or_else(|| {
389 Error::ArrowDeserialize("Failed to downcast to ListView".to_string())
390 })?;
391 Ok(array.iter().map(caster).collect::<Result<Vec<_>>>()?)
392 }
393 DataType::FixedSizeList(..) => {
394 let array = array.as_any().downcast_ref::<FixedSizeListArray>().ok_or_else(|| {
395 Error::ArrowDeserialize("Failed to downcast to FixedSizeListArray".to_string())
396 })?;
397 Ok(array.iter().map(caster).collect::<Result<Vec<_>>>()?)
398 }
399 _ => Err(Error::ArrowUnsupportedType(format!(
400 "Could not cast array to list type: {:?}",
401 array.data_type()
402 ))),
403 }
404}
405
406pub fn array_to_string_iter(array: &dyn Array) -> Result<impl Iterator<Item = Option<String>>> {
411 let string_array = if let Ok(array) = cast(array, &DataType::Utf8) {
413 array
414
415 } else {
417 let binary_array = cast(array, &DataType::Binary).map_err(Error::Arrow)?;
418 cast(&binary_array, &DataType::Utf8).map_err(Error::Arrow)?
419 }
420 .as_string_opt::<i32>()
421 .ok_or(Error::ArrowUnsupportedType(format!(
422 "Unable to downcast array to string: type hint={:?}",
423 array.data_type(),
424 )))?
425 .clone();
426
427 let iter = (0..string_array.len()).map(move |i| {
429 if string_array.is_null(i) { None } else { Some(string_array.value(i).to_string()) }
430 });
431
432 Ok(iter)
433}
434
435pub fn array_to_binary_iter(array: &dyn Array) -> Result<impl Iterator<Item = Option<Vec<u8>>>> {
440 let binary_array = cast(array, &DataType::Binary)
442 .map_err(Error::Arrow)?
443 .as_binary_opt::<i32>()
444 .ok_or(Error::ArrowUnsupportedType(format!(
445 "Unable to downcast array to binary: type hint={:?}",
446 array.data_type(),
447 )))?
448 .clone();
449
450 let iter = (0..binary_array.len()).map(move |i| {
452 if binary_array.is_null(i) { None } else { Some(binary_array.value(i).to_vec()) }
453 });
454
455 Ok(iter)
456}
457
458pub fn array_to_bool_iter(array: &dyn Array) -> Result<impl Iterator<Item = Option<bool>>> {
463 let bool_array = cast(array, &DataType::Boolean)
465 .map_err(Error::Arrow)?
466 .as_boolean_opt()
467 .ok_or(Error::ArrowUnsupportedType(format!(
468 "Unable to downcast array boolean: type hint={:?}",
469 array.data_type(),
470 )))?
471 .clone();
472
473 let iter = (0..bool_array.len())
475 .map(move |i| if bool_array.is_null(i) { None } else { Some(bool_array.value(i)) });
476
477 Ok(iter)
478}
479
480pub fn array_to_native_iter<A, T>(array: &dyn Array) -> Result<impl Iterator<Item = Option<T>>>
485where
486 A: ArrowPrimitiveType,
487 A::Native: Into<T>,
488 T: Clone,
489{
490 let cast_array = cast(array, &A::DATA_TYPE).map_err(Error::Arrow)?;
491 let primitive_array = cast_array
492 .as_primitive_opt::<A>()
493 .ok_or(Error::ArrowUnsupportedType(format!(
494 "Unable to downcast array {}: type hint={:?}",
495 A::DATA_TYPE,
496 array.data_type(),
497 )))?
498 .clone();
499
500 let iter = (0..primitive_array.len()).map(move |i| {
501 if primitive_array.is_null(i) { None } else { Some(primitive_array.value(i).into()) }
502 });
503
504 Ok(iter)
505}
506
507pub fn array_to_i8_iter(array: &dyn Array) -> Result<impl Iterator<Item = Option<i8>>> {
512 array_to_native_iter::<Int8Type, _>(array)
513}
514
515pub fn array_to_i16_iter(array: &dyn Array) -> Result<impl Iterator<Item = Option<i16>>> {
520 array_to_native_iter::<Int16Type, _>(array)
521}
522
523pub fn array_to_i32_iter(array: &dyn Array) -> Result<impl Iterator<Item = Option<i32>>> {
528 array_to_native_iter::<Int32Type, _>(array)
529}
530
531pub fn array_to_i64_iter(array: &dyn Array) -> Result<impl Iterator<Item = Option<i64>>> {
536 array_to_native_iter::<Int64Type, _>(array)
537}
538
539pub fn array_to_u8_iter(array: &dyn Array) -> Result<impl Iterator<Item = Option<u8>>> {
544 array_to_native_iter::<UInt8Type, _>(array)
545}
546
547pub fn array_to_u16_iter(array: &dyn Array) -> Result<impl Iterator<Item = Option<u16>>> {
552 array_to_native_iter::<UInt16Type, _>(array)
553}
554
555pub fn array_to_u32_iter(array: &dyn Array) -> Result<impl Iterator<Item = Option<u32>>> {
560 array_to_native_iter::<UInt32Type, _>(array)
561}
562
563pub fn array_to_u64_iter(array: &dyn Array) -> Result<impl Iterator<Item = Option<u64>>> {
568 array_to_native_iter::<UInt64Type, _>(array)
569}
570
571pub fn array_to_f32_iter(array: &dyn Array) -> Result<impl Iterator<Item = Option<f32>>> {
576 array_to_native_iter::<Float32Type, _>(array)
577}
578
579pub fn array_to_f64_iter(array: &dyn Array) -> Result<impl Iterator<Item = Option<f64>>> {
584 array_to_native_iter::<Float64Type, _>(array)
585}
586
587#[cfg(test)]
588mod tests {
589 use std::sync::Arc;
590
591 use arrow::array::*;
592 use arrow::buffer::{Buffer, OffsetBuffer};
593 use arrow::datatypes::*;
594 use chrono_tz::Tz;
595
596 use super::*;
597 use crate::arrow::types::{
598 LIST_ITEM_FIELD_NAME, MAP_FIELD_NAME, STRUCT_KEY_FIELD_NAME, STRUCT_VALUE_FIELD_NAME,
599 };
600
601 fn collect_string_iter<I: Iterator<Item = Option<String>>>(iter: I) -> Vec<Option<String>> {
603 iter.collect()
604 }
605
606 fn collect_binary_iter<I: Iterator<Item = Option<Vec<u8>>>>(iter: I) -> Vec<Option<Vec<u8>>> {
608 iter.collect()
609 }
610
611 fn collect_bool_iter<I: Iterator<Item = Option<bool>>>(iter: I) -> Vec<Option<bool>> {
613 iter.collect()
614 }
615
616 #[test]
617 fn test_string_array() {
618 let array = StringArray::from(vec![Some("hello"), None, Some("world")]);
619 let result = collect_string_iter(array_to_string_iter(&array).unwrap());
620 assert_eq!(result, vec![Some("hello".to_string()), None, Some("world".to_string())]);
621 }
622
623 #[test]
624 fn test_large_string_array() {
625 let array = LargeStringArray::from(vec![Some("hello"), None, Some("world")]);
626 let result = collect_string_iter(array_to_string_iter(&array).unwrap());
627 assert_eq!(result, vec![Some("hello".to_string()), None, Some("world".to_string())]);
628 }
629
630 #[test]
631 fn test_string_view_array() {
632 let array = StringViewArray::from(vec![Some("hello"), None, Some("world")]);
633 let result = collect_string_iter(array_to_string_iter(&array).unwrap());
634 assert_eq!(result, vec![Some("hello".to_string()), None, Some("world".to_string())]);
635 }
636
637 #[test]
638 fn test_binary_array() {
639 let array =
640 BinaryArray::from(vec![Some("hello".as_bytes()), None, Some("world".as_bytes())]);
641 let result = collect_string_iter(array_to_string_iter(&array).unwrap());
642 assert_eq!(result, vec![Some("hello".to_string()), None, Some("world".to_string())]);
643 }
644
645 #[test]
646 fn test_large_binary_array() {
647 let array =
648 LargeBinaryArray::from(vec![Some("hello".as_bytes()), None, Some("world".as_bytes())]);
649 let result = collect_string_iter(array_to_string_iter(&array).unwrap());
650 assert_eq!(result, vec![Some("hello".to_string()), None, Some("world".to_string())]);
651 }
652
653 #[test]
654 fn test_binary_view_array() {
655 let array =
656 BinaryViewArray::from(vec![Some("hello".as_bytes()), None, Some("world".as_bytes())]);
657 let result = collect_string_iter(array_to_string_iter(&array).unwrap());
658 assert_eq!(result, vec![Some("hello".to_string()), None, Some("world".to_string())]);
659 }
660
661 #[test]
662 fn test_fixed_size_binary_array() {
663 let array = FixedSizeBinaryArray::try_from_iter(
665 vec!["hello".as_bytes(), "world".as_bytes()].into_iter(),
666 )
667 .unwrap();
668 let result = array_to_string_iter(&array).unwrap().collect::<Vec<_>>();
669 assert_eq!(result, vec![Some("hello".to_string()), Some("world".to_string())]);
670 }
671
672 #[test]
673 fn test_dictionary_array() {
674 let mut builder = StringDictionaryBuilder::<Int8Type>::new();
676 let _ = builder.append("hello").unwrap();
677 builder.append_null();
678 let _ = builder.append("world").unwrap();
679 let array = builder.finish();
680
681 let result = collect_string_iter(array_to_string_iter(&array).unwrap());
682 assert_eq!(result, vec![Some("hello".to_string()), None, Some("world".to_string())]);
683 }
684
685 #[test]
686 fn test_boolean_to_string() {
687 let array = BooleanArray::from(vec![Some(true), None, Some(false)]);
688 let result = collect_string_iter(array_to_string_iter(&array).unwrap());
689 assert_eq!(result, vec![Some("true".to_string()), None, Some("false".to_string())]);
690 }
691
692 #[test]
693 fn test_numeric_to_string() {
694 let array = Int32Array::from(vec![Some(42), None, Some(-123)]);
695 let result = collect_string_iter(array_to_string_iter(&array).unwrap());
696 assert_eq!(result, vec![Some("42".to_string()), None, Some("-123".to_string())]);
697 }
698
699 #[test]
701 fn test_i32_array() {
702 let array = Int32Array::from(vec![Some(1), None, Some(3)]);
703 let result: Vec<_> = array_to_i32_iter(&array).unwrap().collect();
704 assert_eq!(result, vec![Some(1), None, Some(3)]);
705 }
706
707 #[test]
708 fn test_i64_array() {
709 let array = Int64Array::from(vec![Some(1), None, Some(3)]);
710 let result: Vec<_> = array_to_i64_iter(&array).unwrap().collect();
711 assert_eq!(result, vec![Some(1), None, Some(3)]);
712 }
713
714 #[test]
715 fn test_f64_array() {
716 let array = Float64Array::from(vec![Some(1.5), None, Some(3.7)]);
717 let result: Vec<_> = array_to_f64_iter(&array).unwrap().collect();
718 assert_eq!(result, vec![Some(1.5), None, Some(3.7)]);
719 }
720
721 #[test]
722 fn test_i8_array() {
723 let array = Int8Array::from(vec![Some(1), None, Some(3)]);
724 let result: Vec<_> = array_to_i8_iter(&array).unwrap().collect();
725 assert_eq!(result, vec![Some(1), None, Some(3)]);
726 }
727
728 #[test]
729 fn test_i16_array() {
730 let array = Int16Array::from(vec![Some(1), None, Some(3)]);
731 let result: Vec<_> = array_to_i16_iter(&array).unwrap().collect();
732 assert_eq!(result, vec![Some(1), None, Some(3)]);
733 }
734
735 #[test]
736 fn test_u8_array() {
737 let array = UInt8Array::from(vec![Some(1), None, Some(3)]);
738 let result: Vec<_> = array_to_u8_iter(&array).unwrap().collect();
739 assert_eq!(result, vec![Some(1), None, Some(3)]);
740 }
741
742 #[test]
743 fn test_u16_array() {
744 let array = UInt16Array::from(vec![Some(1), None, Some(3)]);
745 let result: Vec<_> = array_to_u16_iter(&array).unwrap().collect();
746 assert_eq!(result, vec![Some(1), None, Some(3)]);
747 }
748
749 #[test]
750 fn test_u32_array() {
751 let array = UInt32Array::from(vec![Some(1), None, Some(3)]);
752 let result: Vec<_> = array_to_u32_iter(&array).unwrap().collect();
753 assert_eq!(result, vec![Some(1), None, Some(3)]);
754 }
755
756 #[test]
757 fn test_u64_array() {
758 let array = UInt64Array::from(vec![Some(1), None, Some(3)]);
759 let result: Vec<_> = array_to_u64_iter(&array).unwrap().collect();
760 assert_eq!(result, vec![Some(1), None, Some(3)]);
761 }
762
763 #[test]
764 fn test_f32_array() {
765 let array = Float32Array::from(vec![Some(1.5), None, Some(3.7)]);
766 let result: Vec<_> = array_to_f32_iter(&array).unwrap().collect();
767 assert_eq!(result, vec![Some(1.5), None, Some(3.7)]);
768 }
769
770 #[test]
771 fn test_int32_array() {
772 let array = Int32Array::from(vec![Some(42), None, Some(-123)]);
773 let result = array_to_values(&array, &DataType::Int32, None).unwrap();
774 assert_eq!(result, vec![Value::Int32(42), Value::Null, Value::Int32(-123)]);
775 }
776
777 #[test]
778 fn test_float64_array() {
779 let array = Float64Array::from(vec![Some(3.15), None, Some(-2.719)]);
780 let result = array_to_values(&array, &DataType::Float64, None).unwrap();
781 assert_eq!(result, vec![Value::Float64(3.15), Value::Null, Value::Float64(-2.719)]);
782 }
783
784 #[test]
785 fn test_utf8_array() {
786 let array = StringArray::from(vec![Some("hello"), None, Some("world")]);
787 let result = array_to_values(&array, &DataType::Utf8, None).unwrap();
788 assert_eq!(result, vec![
789 Value::String(b"hello".to_vec()),
790 Value::Null,
791 Value::String(b"world".to_vec()),
792 ]);
793 }
794
795 #[test]
796 fn test_binary_array_values() {
797 let array = BinaryArray::from(vec![Some(b"abc".as_ref()), None, Some(b"def".as_ref())]);
798 let result = array_to_values(&array, &DataType::Binary, None).unwrap();
799 assert_eq!(result, vec![
800 Value::String(b"abc".to_vec()),
801 Value::Null,
802 Value::String(b"def".to_vec()),
803 ]);
804 }
805
806 #[test]
807 fn test_binary_array_direct() {
808 let array = BinaryArray::from(vec![Some(b"abc".as_ref()), None, Some(b"def".as_ref())]);
809 let result = collect_binary_iter(array_to_binary_iter(&array).unwrap());
810 assert_eq!(result, vec![Some(b"abc".to_vec()), None, Some(b"def".to_vec()),]);
811 }
812
813 #[test]
814 fn test_bool_array_direct() {
815 let array = BooleanArray::from(vec![Some(true), None, Some(false)]);
816 let result = collect_bool_iter(array_to_bool_iter(&array).unwrap());
817 assert_eq!(result, vec![Some(true), None, Some(false)]);
818 }
819
820 #[test]
821 fn test_large_list_array() {
822 let values = Int32Array::from(vec![1, 2, 3, 4]);
823 let offsets_buffer = Buffer::from_vec(vec![0_i64, 2_i64, 4_i64]); let offsets = OffsetBuffer::new(offsets_buffer.into());
825 let large_list_array = LargeListArray::new(
826 Arc::new(Field::new(LIST_ITEM_FIELD_NAME, DataType::Int32, false)),
827 offsets,
828 Arc::new(values),
829 None,
830 );
831 let result = array_to_values(
832 &large_list_array,
833 &DataType::LargeList(Arc::new(Field::new(
834 LIST_ITEM_FIELD_NAME,
835 DataType::Int32,
836 false,
837 ))),
838 None,
839 )
840 .unwrap();
841 assert_eq!(result, vec![
842 Value::Array(vec![Value::Int32(1), Value::Int32(2)]),
843 Value::Array(vec![Value::Int32(3), Value::Int32(4)]),
844 ]);
845 }
846
847 #[test]
848 fn test_fixed_size_list_array() {
849 let values = Int32Array::from(vec![1, 2, 3, 4]);
850 let fixed_size_list_array = FixedSizeListArray::new(
851 Arc::new(Field::new(LIST_ITEM_FIELD_NAME, DataType::Int32, false)),
852 2,
853 Arc::new(values),
854 None,
855 );
856 let result = array_to_values(
857 &fixed_size_list_array,
858 &DataType::FixedSizeList(
859 Arc::new(Field::new(LIST_ITEM_FIELD_NAME, DataType::Int32, false)),
860 2,
861 ),
862 None,
863 )
864 .unwrap();
865 assert_eq!(result, vec![
866 Value::Array(vec![Value::Int32(1), Value::Int32(2)]),
867 Value::Array(vec![Value::Int32(3), Value::Int32(4)]),
868 ]);
869 }
870
871 #[test]
872 fn test_empty_list_array() {
873 let values = Int32Array::from(Vec::<i32>::new());
874 let offsets_buffer = Buffer::from_vec(vec![0, 0, 0]);
875 let offsets = OffsetBuffer::new(offsets_buffer.into());
876 let list_array = ListArray::new(
877 Arc::new(Field::new(LIST_ITEM_FIELD_NAME, DataType::Int32, false)),
878 offsets,
879 Arc::new(values),
880 None,
881 );
882 let result = array_to_values(
883 &list_array,
884 &DataType::List(Arc::new(Field::new(LIST_ITEM_FIELD_NAME, DataType::Int32, false))),
885 None,
886 )
887 .unwrap();
888 assert_eq!(result, vec![Value::Array(vec![]), Value::Array(vec![])]);
889 }
890
891 #[test]
892 fn test_enum8_dictionary() {
893 let pairs = vec![("a".to_string(), 1_i8), ("b".to_string(), 2_i8)];
894 let mut builder = StringDictionaryBuilder::<Int8Type>::new();
895 let _ = builder.append("a").unwrap();
896 builder.append_null();
897 let _ = builder.append("b").unwrap();
898 let array = builder.finish();
899 let result = array_to_values(
900 &array,
901 &DataType::Dictionary(Box::new(DataType::Int8), Box::new(DataType::Utf8)),
902 Some(&Type::Enum8(pairs.clone())),
903 )
904 .unwrap();
905 assert_eq!(result, vec![
906 Value::Enum8("a".to_string(), 1),
907 Value::Null,
908 Value::Enum8("b".to_string(), 2),
909 ]);
910 }
911
912 #[test]
913 fn test_enum16_dictionary() {
914 let pairs = vec![("x".to_string(), 10_i16), ("y".to_string(), 20_i16)];
915 let mut builder = StringDictionaryBuilder::<Int16Type>::new();
916 let _ = builder.append("x").unwrap();
917 builder.append_null();
918 let _ = builder.append("y").unwrap();
919 let array = builder.finish();
920 let result = array_to_values(
921 &array,
922 &DataType::Dictionary(Box::new(DataType::Int16), Box::new(DataType::Utf8)),
923 Some(&Type::Enum16(pairs.clone())),
924 )
925 .unwrap();
926 assert_eq!(result, vec![
927 Value::Enum16("x".to_string(), 10),
928 Value::Null,
929 Value::Enum16("y".to_string(), 20),
930 ]);
931 }
932
933 #[test]
934 fn test_nested_struct_array() {
935 let inner_field = Arc::new(Field::new("inner", DataType::Int32, false));
936 let inner_struct_array = StructArray::from(vec![(
937 Arc::clone(&inner_field),
938 Arc::new(Int32Array::from(vec![1, 2])) as ArrayRef,
939 )]);
940 let outer_field =
941 Arc::new(Field::new("outer", inner_struct_array.data_type().clone(), false));
942 let outer_struct_array = StructArray::from(vec![(
943 Arc::clone(&outer_field),
944 Arc::new(inner_struct_array) as ArrayRef,
945 )]);
946 let fields = Fields::from_iter(vec![outer_field]);
947 let result = array_to_values(&outer_struct_array, &DataType::Struct(fields), None).unwrap();
948 assert_eq!(result, vec![
949 Value::Tuple(vec![Value::Tuple(vec![Value::Int32(1)])]),
950 Value::Tuple(vec![Value::Tuple(vec![Value::Int32(2)])]),
951 ]);
952 }
953
954 #[test]
955 fn test_timestamp_non_utc() {
956 let tz: Arc<str> = Arc::from("America/New_York");
957 let array =
958 TimestampSecondArray::from(vec![Some(1_625_097_600), None, Some(1_625_184_000)]);
959 let result =
960 array_to_values(&array, &DataType::Timestamp(TimeUnit::Second, Some(tz)), None)
961 .unwrap();
962 assert_eq!(result, vec![
963 Value::DateTime(DateTime(Tz::America__New_York, 1_625_097_600)),
964 Value::Null,
965 Value::DateTime(DateTime(Tz::America__New_York, 1_625_184_000)),
966 ]);
967 }
968
969 #[test]
971 fn test_string_to_i32() {
972 let array = StringArray::from(vec![Some("42"), None, Some("-123")]);
973 let result: Vec<_> = array_to_i32_iter(&array).unwrap().collect();
974 assert_eq!(result, vec![Some(42), None, Some(-123)]);
975 }
976
977 #[test]
978 fn test_i32_to_f64() {
979 let array = Int32Array::from(vec![Some(42), None, Some(-123)]);
980 let result: Vec<_> = array_to_f64_iter(&array).unwrap().collect();
981 assert_eq!(result, vec![Some(42.0), None, Some(-123.0)]);
982 }
983
984 #[test]
985 fn test_bool_to_i32() {
986 let array = BooleanArray::from(vec![Some(true), None, Some(false)]);
987 let result: Vec<_> = array_to_i32_iter(&array).unwrap().collect();
988 assert_eq!(result, vec![Some(1), None, Some(0)]);
989 }
990
991 #[test]
992 fn test_fixed_size_binary_as_string() {
993 let array = FixedSizeBinaryArray::try_from_iter(
994 vec![b"abcde".as_ref(), b"fghij".as_ref()].into_iter(),
995 )
996 .unwrap();
997 let result = array_to_values(&array, &DataType::FixedSizeBinary(5), None).unwrap();
998 assert_eq!(result, vec![
999 Value::String(b"abcde".to_vec()),
1000 Value::String(b"fghij".to_vec()),
1001 ]);
1002 }
1003
1004 #[test]
1005 fn test_fixed_size_binary_as_uuid() {
1006 let uuid1 = uuid::Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000").unwrap();
1007 let uuid2 = uuid::Uuid::parse_str("550e8400-e29b-41d4-a716-446655440001").unwrap();
1008 let array = FixedSizeBinaryArray::try_from_iter(
1009 vec![uuid1.as_bytes(), uuid2.as_bytes()].into_iter(),
1010 )
1011 .unwrap();
1012 let result =
1013 array_to_values(&array, &DataType::FixedSizeBinary(16), Some(&Type::Uuid)).unwrap();
1014 assert_eq!(result, vec![Value::Uuid(uuid1), Value::Uuid(uuid2)]);
1015 }
1016
1017 #[test]
1018 fn test_boolean_array() {
1019 let array = BooleanArray::from(vec![Some(true), None, Some(false)]);
1020 let result = array_to_values(&array, &DataType::Boolean, None).unwrap();
1021 assert_eq!(result, vec![Value::UInt8(1), Value::Null, Value::UInt8(0)]);
1022 }
1023
1024 #[test]
1025 fn test_decimal128_array() {
1026 let array = Decimal128Array::from_iter_values([12345, -67890])
1027 .with_precision_and_scale(10, 2)
1028 .unwrap();
1029 let result = array_to_values(&array, &DataType::Decimal128(10, 2), None).unwrap();
1030 assert_eq!(result.len(), 2);
1031 match &result[0] {
1032 Value::Decimal128(p, v) => {
1033 assert_eq!(*p, 10);
1034 assert_eq!(*v, 12345); }
1036 _ => panic!("Expected Decimal128"),
1037 }
1038 match &result[1] {
1039 Value::Decimal128(p, v) => {
1040 assert_eq!(*p, 10);
1041 assert_eq!(*v, -67890); }
1043 _ => panic!("Expected Decimal128"),
1044 }
1045 }
1046
1047 #[test]
1048 fn test_decimal128_array_error() {
1049 let array = StringArray::from(vec![""]);
1050 let result = array_to_values(&array, &DataType::Decimal128(10, 2), None);
1051 assert!(matches!(
1052 result.unwrap_err(),
1053 Error::ArrowDeserialize(err)
1054 if err.clone().contains("Expected Decimal128Array")
1055 ));
1056 }
1057
1058 #[test]
1059 fn test_decimal256_array() {
1060 let array =
1061 Decimal256Array::from_iter_values([i256::from_i128(12345), i256::from_i128(-67890)])
1062 .with_precision_and_scale(20, 2)
1063 .unwrap();
1064 let result = array_to_values(&array, &DataType::Decimal256(20, 2), None).unwrap();
1065 assert_eq!(result.len(), 2);
1066 match &result[0] {
1067 Value::Decimal256(p, v) => {
1068 assert_eq!(*p, 20);
1069 assert_eq!(*v, crate::i256(i256::from_i128(12345).to_be_bytes()));
1070 }
1071 _ => panic!("Expected Decimal256"),
1072 }
1073 match &result[1] {
1074 Value::Decimal256(p, v) => {
1075 assert_eq!(*p, 20);
1076 assert_eq!(*v, crate::i256(i256::from_i128(-67890).to_be_bytes()));
1077 }
1078 _ => panic!("Expected Decimal256"),
1079 }
1080 }
1081
1082 #[test]
1083 fn test_decimal256_array_error() {
1084 let array = StringArray::from(vec![""]);
1085 let result = array_to_values(&array, &DataType::Decimal256(20, 2), None);
1086 assert!(matches!(
1087 result.unwrap_err(),
1088 Error::ArrowDeserialize(err)
1089 if err.clone().contains("Expected Decimal256Array")
1090 ));
1091 }
1092
1093 #[test]
1094 fn test_date32_array() {
1095 let array = Date32Array::from(vec![Some(0), None, Some(1)]);
1096 let result = array_to_values(&array, &DataType::Date32, None).unwrap();
1097 assert_eq!(result, vec![Value::Date(Date(0)), Value::Null, Value::Date(Date(1))]);
1098 }
1099
1100 #[test]
1101 fn test_date64_array() {
1102 let array = Date64Array::from(vec![Some(0), None, Some(1)]);
1103 let result = array_to_values(&array, &DataType::Date64, None).unwrap();
1104 assert_eq!(result, vec![
1105 Value::DateTime64(DynDateTime64(Tz::UTC, 0, 3)),
1106 Value::Null,
1107 Value::DateTime64(DynDateTime64(Tz::UTC, 1, 3)),
1108 ]);
1109
1110 let typ = Type::DateTime64(3, Tz::America__New_York);
1112 let result = array_to_values(&array, &DataType::Date64, Some(&typ)).unwrap();
1113 assert_eq!(result, vec![
1114 Value::DateTime64(DynDateTime64(Tz::America__New_York, 0, 3)),
1115 Value::Null,
1116 Value::DateTime64(DynDateTime64(Tz::America__New_York, 1, 3)),
1117 ]);
1118
1119 let typ = Type::Date;
1121 let result = array_to_values(&array, &DataType::Date64, Some(&typ)).unwrap();
1122 assert_eq!(result, vec![
1123 Value::DateTime64(DynDateTime64(Tz::UTC, 0, 3)),
1124 Value::Null,
1125 Value::DateTime64(DynDateTime64(Tz::UTC, 1, 3)),
1126 ]);
1127 }
1128
1129 #[test]
1130 fn test_timestamp_second_array() {
1131 let array =
1132 TimestampSecondArray::from(vec![Some(1_625_097_600), None, Some(1_625_184_000)]);
1133 let result =
1134 array_to_values(&array, &DataType::Timestamp(TimeUnit::Second, None), None).unwrap();
1135 assert_eq!(result, vec![
1136 Value::DateTime(DateTime(chrono_tz::UTC, 1_625_097_600)),
1137 Value::Null,
1138 Value::DateTime(DateTime(chrono_tz::UTC, 1_625_184_000)),
1139 ]);
1140 }
1141
1142 #[test]
1143 fn test_list_array() {
1144 let values = Int32Array::from(vec![1, 2, 3, 4]);
1145 let offsets_buffer = Buffer::from_vec(vec![0, 2, 4]);
1146 let offsets = OffsetBuffer::new(offsets_buffer.into());
1147 let list_array = ListArray::new(
1148 Arc::new(Field::new(LIST_ITEM_FIELD_NAME, DataType::Int32, false)),
1149 offsets,
1150 Arc::new(values),
1151 None,
1152 );
1153 let result = array_to_values(
1154 &list_array,
1155 &DataType::List(Arc::new(Field::new(LIST_ITEM_FIELD_NAME, DataType::Int32, false))),
1156 None,
1157 )
1158 .unwrap();
1159 assert_eq!(result, vec![
1160 Value::Array(vec![Value::Int32(1), Value::Int32(2)]),
1161 Value::Array(vec![Value::Int32(3), Value::Int32(4)]),
1162 ]);
1163 }
1164
1165 #[test]
1166 fn test_struct_array() {
1167 let int_field = Arc::new(Field::new("a", DataType::Int32, false));
1168 let str_field = Arc::new(Field::new("b", DataType::Utf8, false));
1169 let struct_array = StructArray::from(vec![
1170 (Arc::clone(&int_field), Arc::new(Int32Array::from(vec![1, 2])) as ArrayRef),
1171 (Arc::clone(&str_field), Arc::new(StringArray::from(vec!["x", "y"])) as ArrayRef),
1172 ]);
1173 let fields = Fields::from_iter(vec![int_field, str_field]);
1174 let result = array_to_values(&struct_array, &DataType::Struct(fields), None).unwrap();
1175 assert_eq!(result, vec![
1176 Value::Tuple(vec![Value::Int32(1), Value::String(b"x".to_vec())]),
1177 Value::Tuple(vec![Value::Int32(2), Value::String(b"y".to_vec())]),
1178 ]);
1179 }
1180
1181 #[test]
1182 fn test_struct_array_with_nulls() {
1183 let int_field = Arc::new(Field::new("a", DataType::Int32, false));
1184 let str_field = Arc::new(Field::new("b", DataType::Utf8, true));
1185 let struct_array = StructArray::from(vec![
1186 (Arc::clone(&int_field), Arc::new(Int32Array::from(vec![1, 2])) as ArrayRef),
1187 (
1188 Arc::clone(&str_field),
1189 Arc::new(StringArray::from(vec![Some("x"), None])) as ArrayRef,
1190 ),
1191 ]);
1192 let fields = Fields::from_iter(vec![int_field, str_field]);
1193 let result = array_to_values(&struct_array, &DataType::Struct(fields), None).unwrap();
1194 assert_eq!(result, vec![
1195 Value::Tuple(vec![Value::Int32(1), Value::String(b"x".to_vec())]),
1196 Value::Tuple(vec![Value::Int32(2), Value::Null]),
1197 ]);
1198 }
1199
1200 #[test]
1201 fn test_struct_array_err() {
1202 let int_field = Arc::new(Field::new("a", DataType::Int32, false));
1203 let str_field = Arc::new(Field::new("b", DataType::Utf8, false));
1204 let string_array = StringArray::from(vec![""]);
1205 let fields = Fields::from_iter(vec![int_field, str_field]);
1206 let result = array_to_values(&string_array, &DataType::Struct(fields), None);
1207 assert!(matches!(
1208 result,
1209 Err(Error::ArrowDeserialize(e))
1210 if e.clone().contains("Could not downcast struct array")
1211 ));
1212 }
1213
1214 #[test]
1215 fn test_map_array() {
1216 let keys = Arc::new(StringArray::from(vec!["k1", "k2"])) as ArrayRef;
1217 let values = Arc::new(Int32Array::from(vec![10, 20])) as ArrayRef;
1218 let struct_array = StructArray::from(vec![
1219 (Arc::new(Field::new(STRUCT_KEY_FIELD_NAME, DataType::Utf8, false)), keys),
1220 (Arc::new(Field::new(STRUCT_VALUE_FIELD_NAME, DataType::Int32, false)), values),
1221 ]);
1222 let map_array = MapArray::new(
1223 Arc::new(Field::new(MAP_FIELD_NAME, struct_array.data_type().clone(), false)),
1224 OffsetBuffer::new(Buffer::from_vec(vec![0, 1, 2]).into()),
1225 struct_array,
1226 None,
1227 false,
1228 );
1229 let result = array_to_values(
1230 &map_array,
1231 &DataType::Map(
1232 Arc::new(Field::new(
1233 MAP_FIELD_NAME,
1234 DataType::Struct(Fields::from_iter(vec![
1235 Field::new(STRUCT_KEY_FIELD_NAME, DataType::Utf8, false),
1236 Field::new(STRUCT_VALUE_FIELD_NAME, DataType::Int32, false),
1237 ])),
1238 false,
1239 )),
1240 false,
1241 ),
1242 None,
1243 )
1244 .unwrap();
1245 assert_eq!(result, vec![
1246 Value::Map(vec![Value::String(b"k1".to_vec())], vec![Value::Int32(10)]),
1247 Value::Map(vec![Value::String(b"k2".to_vec())], vec![Value::Int32(20)]),
1248 ]);
1249 }
1250
1251 #[test]
1252 fn test_dictionary_array_values() {
1253 use arrow::array::StringDictionaryBuilder;
1254 let mut builder = StringDictionaryBuilder::<Int32Type>::new();
1255 let _ = builder.append("hello").unwrap();
1256 builder.append_null();
1257 let _ = builder.append("world").unwrap();
1258 let array = builder.finish();
1259 let result = array_to_values(
1260 &array,
1261 &DataType::Dictionary(Box::new(DataType::Int32), Box::new(DataType::Utf8)),
1262 None,
1263 )
1264 .unwrap();
1265 assert_eq!(result, vec![
1266 Value::String(b"hello".to_vec()),
1267 Value::Null,
1268 Value::String(b"world".to_vec()),
1269 ]);
1270 }
1271
1272 #[test]
1273 fn test_null_array() {
1274 let array = NullArray::new(3);
1275 let result = array_to_values(&array, &DataType::Null, None).unwrap();
1276 assert_eq!(result, vec![Value::Null, Value::Null, Value::Null]);
1277 }
1278
1279 #[test]
1280 fn test_unhandled_array() {
1281 let array = StringArray::from(vec![""]);
1282 let result = array_to_values(&array, &DataType::Float16, None);
1283 assert!(matches!(result, Err(Error::ArrowUnsupportedType(_))));
1284 }
1285
1286 #[test]
1287 fn test_batch_to_rows_simple() {
1288 let schema = Arc::new(Schema::new(vec![
1289 Field::new("v_0", DataType::Int8, false),
1290 Field::new("v_1", DataType::Int16, false),
1291 Field::new("v_2", DataType::Int32, false),
1292 Field::new("v_3", DataType::Int64, false),
1293 Field::new("v_4", DataType::UInt8, false),
1294 Field::new("v_5", DataType::UInt16, false),
1295 Field::new("v_6", DataType::UInt32, false),
1296 Field::new("v_7", DataType::UInt64, false),
1297 Field::new("v_8", DataType::Float32, false),
1298 Field::new("v_9", DataType::Float64, false),
1299 Field::new("v_10", DataType::Timestamp(TimeUnit::Second, None), false),
1300 Field::new("v_11", DataType::Timestamp(TimeUnit::Millisecond, None), false),
1301 Field::new("v_12", DataType::Timestamp(TimeUnit::Microsecond, None), false),
1302 Field::new("v_13", DataType::Timestamp(TimeUnit::Nanosecond, None), false),
1303 Field::new("v_14", DataType::Utf8, false),
1304 ]));
1305 let str_vals = vec!["a", "b", "c"];
1306 let batch = RecordBatch::try_new(schema, vec![
1307 Arc::new(Int8Array::from(vec![1, 2, 3])),
1308 Arc::new(Int16Array::from(vec![1, 2, 3])),
1309 Arc::new(Int32Array::from(vec![1, 2, 3])),
1310 Arc::new(Int64Array::from(vec![1, 2, 3])),
1311 Arc::new(UInt8Array::from(vec![1, 2, 3])),
1312 Arc::new(UInt16Array::from(vec![1, 2, 3])),
1313 Arc::new(UInt32Array::from(vec![1, 2, 3])),
1314 Arc::new(UInt64Array::from(vec![1, 2, 3])),
1315 Arc::new(Float32Array::from(vec![1.0_f32, 2.0, 3.0])),
1316 Arc::new(Float64Array::from(vec![1.0_f64, 2.0, 3.0])),
1317 Arc::new(TimestampSecondArray::from(vec![1, 2, 3])),
1318 Arc::new(TimestampMillisecondArray::from(vec![1000, 2 * 1000, 3 * 1000])),
1319 Arc::new(TimestampMicrosecondArray::from(vec![
1320 1_000_000,
1321 2 * 1_000_000,
1322 3 * 1_000_000,
1323 ])),
1324 Arc::new(TimestampNanosecondArray::from(vec![
1325 1_000_000_000,
1326 2 * 1_000_000_000,
1327 3 * 1_000_000_000,
1328 ])),
1329 Arc::new(StringArray::from(str_vals.clone())),
1330 ])
1331 .unwrap();
1332
1333 let result = batch_to_rows(&batch, None).unwrap().collect::<Vec<_>>();
1334 assert_eq!(result.len(), 3);
1335
1336 #[expect(clippy::cast_precision_loss)]
1337 #[expect(clippy::cast_possible_truncation)]
1338 #[expect(clippy::cast_possible_wrap)]
1339 for (i, row) in result.into_iter().enumerate() {
1340 let row = row.unwrap();
1341 let seed = i + 1;
1342 assert_eq!(row, vec![
1343 Value::Int8(seed as i8),
1344 Value::Int16(seed as i16),
1345 Value::Int32(seed as i32),
1346 Value::Int64(seed as i64),
1347 Value::UInt8(seed as u8),
1348 Value::UInt16(seed as u16),
1349 Value::UInt32(seed as u32),
1350 Value::UInt64(seed as u64),
1351 Value::Float32(seed as f32),
1352 Value::Float64(seed as f64),
1353 Value::DateTime(DateTime(Tz::UTC, seed as u32)),
1354 Value::DateTime64(DynDateTime64(Tz::UTC, seed as u64 * 1000, 3)),
1355 Value::DateTime64(DynDateTime64(Tz::UTC, seed as u64 * 1_000_000, 6)),
1356 Value::DateTime64(DynDateTime64(Tz::UTC, seed as u64 * 1_000_000_000, 9)),
1357 Value::String(str_vals[i].as_bytes().to_vec())
1358 ]);
1359 }
1360 }
1361
1362 #[test]
1363 fn test_batch_to_rows_with_nulls() {
1364 let schema = Arc::new(Schema::new(vec![
1365 Field::new("id", DataType::Int32, true),
1366 Field::new("name", DataType::Utf8, true),
1367 ]));
1368 let batch = RecordBatch::try_new(schema, vec![
1369 Arc::new(Int32Array::from(vec![Some(1), None, Some(3)])),
1370 Arc::new(StringArray::from(vec![Some("a"), Some("b"), None])),
1371 ])
1372 .unwrap();
1373
1374 let mut result = batch_to_rows(&batch, None).unwrap().collect::<Vec<_>>();
1375 assert_eq!(result.len(), 3);
1376 assert_eq!(result.pop().unwrap().unwrap(), vec![Value::Int32(3), Value::Null]);
1377 assert_eq!(result.pop().unwrap().unwrap(), vec![Value::Null, Value::String(b"b".to_vec())]);
1378 assert_eq!(result.pop().unwrap().unwrap(), vec![
1379 Value::Int32(1),
1380 Value::String(b"a".to_vec())
1381 ]);
1382 }
1383
1384 #[test]
1385 fn test_batch_to_rows_with_type_hints() {
1386 let schema =
1387 Arc::new(Schema::new(vec![Field::new("uuid", DataType::FixedSizeBinary(16), false)]));
1388 let uuid1 = uuid::Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000").unwrap();
1389 let uuid2 = uuid::Uuid::parse_str("550e8400-e29b-41d4-a716-446655440001").unwrap();
1390 let batch = RecordBatch::try_new(schema, vec![Arc::new(
1391 FixedSizeBinaryArray::try_from_iter(
1392 vec![uuid1.as_bytes(), uuid2.as_bytes()].into_iter(),
1393 )
1394 .unwrap(),
1395 )])
1396 .unwrap();
1397
1398 let type_hints = vec![("uuid".to_string(), Type::Uuid)];
1399 let mut result = batch_to_rows(&batch, Some(&type_hints)).unwrap().collect::<Vec<_>>();
1400 assert_eq!(result.len(), 2);
1401 assert_eq!(result.pop().unwrap().unwrap(), vec![Value::Uuid(uuid2)]);
1402 assert_eq!(result.pop().unwrap().unwrap(), vec![Value::Uuid(uuid1)]);
1403 }
1404
1405 #[test]
1406 fn test_batch_to_rows_empty() {
1407 let schema = Arc::new(Schema::new(vec![Field::new("id", DataType::Int32, false)]));
1408 let batch =
1409 RecordBatch::try_new(schema, vec![Arc::new(Int32Array::from(Vec::<i32>::new()))])
1410 .unwrap();
1411
1412 let result = batch_to_rows(&batch, None).unwrap().collect::<Vec<_>>();
1413 assert_eq!(result.len(), 0);
1414 }
1415
1416 #[test]
1418 fn test_invalid_string_conversion() {
1419 let invalid_utf8 = vec![0xFF, 0xFE, 0xFD]; let array = BinaryArray::from_iter_values(vec![&invalid_utf8]);
1422
1423 let result = array_to_string_iter(&array);
1426 assert!(result.is_ok(), "Should convert even with replacement chars");
1427 }
1428
1429 #[test]
1430 fn test_out_of_range_conversion() {
1431 let array = Int32Array::from(vec![Some(1000)]); let result = array_to_i8_iter(&array);
1434
1435 let collected: Vec<_> = result.unwrap().collect();
1437 assert_eq!(collected, vec![None]);
1438 }
1439}