clickhouse_arrow/arrow/
utils.rs

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
10/// Splits a `RecordBatch` into multiple `RecordBatch`es, each containing at most `max` rows.
11///
12/// # Arguments
13///
14/// * `batch` - A reference to the input `RecordBatch` to split.
15/// * `max` - The maximum number of rows per output `RecordBatch`. Must be non-zero to avoid an
16///   empty result.
17///
18/// # Returns
19///
20/// A `Result` containing:
21/// * `Vec<RecordBatch>` - A vector of `RecordBatch`es, each with at most `max_rows` rows.
22///
23/// # Edge Cases
24///
25/// * If `max` is 0, returns an empty `Vec`.
26/// * If the input `batch` has 0 rows, returns an the original `RecordBatch`.
27/// * If the number of rows is not evenly divisible by `max`, the last `RecordBatch` will contain
28///   the remaining rows.
29///
30/// # Performance Notes
31///
32/// * **Zero-copy**: Uses `RecordBatch::slice` for zero-copy access to the underlying data buffers,
33///   avoiding deep copies of row data.
34/// * **Single allocation**: Allocates a single `Vec` with pre-computed capacity to store the output
35///   `RecordBatch`es, avoiding reallocations.
36///
37/// # Example
38///
39/// ```rust,ignore
40/// use arrow::record_batch::RecordBatch;
41/// use arrow::error::ArrowError;
42///
43/// let max_rows = 3;
44/// let chunks = split_record_batch_by_rows(batch, max_rows)?;
45/// for (i, chunk) in chunks.iter().enumerate() {
46///     println!("Chunk {}: {} rows", i, chunk.num_rows());
47/// }
48/// ```
49pub 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    // Calculate number of chunks using ceiling division
60    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
72/// Converts a [`RecordBatch`] to an iterator of rows, where each row is a Vec of Values.
73///
74/// # Arguments
75/// - `batch`: The [`RecordBatch`] to convert.
76/// - `type_hints`: Optional mapping of column names to `ClickHouse` types for disambiguation.
77///
78/// # Returns
79/// A Result containing an iterator of rows, where each row is a [`Vec<Value>`].
80///
81/// # Errors
82/// Returns an error if downcasting fails or the arrow data type is not supported
83pub 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    // Convert columns to Vec<Vec<Value>> once
93    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/// Converts a [`ArrayRef`]s to clickhouse values
113///
114/// # Errors
115///
116/// Returns an error is downcasting fails or the arrow data type is not supported
117#[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        // Integer types
132        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        // Unsigned integer types
138        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        // Floating point types
144        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        // Binary-like types (converted to String)
148        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        // UUID type
156        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        // String-like types (converted to String)
170        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        // Boolean (convert to UInt8)
176        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        // Decimal types
182        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        // Date types
212        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        // Timestamp/DateTime types
227        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        // List type
251        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        // Struct type (map to Tuple)
266        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        // Map type
295        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        // Dictionary type - need to unpack it first
317        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        // Null type
355        DataType::Null => vec![Value::Null; column.len()],
356
357        // For all other types, return an error
358        _ => {
359            return Err(Error::ArrowUnsupportedType(format!(
360                "Unsupported Arrow data type: {data_type:?}"
361            )));
362        }
363    })
364}
365
366/// Modify the items for list-like arrays
367///
368/// # Errors
369/// Errors if the array cannot be downcast
370pub 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
406/// Converts any array that can be cast to a string array into an iterator of [`Option<String>`]
407///
408/// # Errors
409/// Returns an error if the array cannot be cast to a string array.
410pub fn array_to_string_iter(array: &dyn Array) -> Result<impl Iterator<Item = Option<String>>> {
411    // First, cast the array to Utf8 (String) type
412    let string_array = if let Ok(array) = cast(array, &DataType::Utf8) {
413        array
414
415    // Then try Binary
416    } 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    // Return an iterator that yields Option<String> for each element
428    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
435/// Converts any array that can be cast to a binary array into an iterator of [`Option<Vec<u8>>`]
436///
437/// # Errors
438/// Returns an error if the array cannot be cast to a binary array.
439pub fn array_to_binary_iter(array: &dyn Array) -> Result<impl Iterator<Item = Option<Vec<u8>>>> {
440    // First, cast the array to Binary type
441    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    // Return an iterator that yields Option<String> for each element
451    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
458/// Converts any array that can be cast to a boolean array into an iterator of [`Option<bool>`]
459///
460/// # Errors
461/// Returns an error if the array cannot be cast to a bool array.
462pub fn array_to_bool_iter(array: &dyn Array) -> Result<impl Iterator<Item = Option<bool>>> {
463    // First, cast the array to Boolean type
464    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    // Return an iterator that yields Option<bool> for each element
474    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
480/// Directly converts an arrow [`PrimitiveArray`] to a rust primitive type
481///
482/// # Errors
483/// Returns an error if the array cannot be cast to the target arrow type.
484pub 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
507/// Converts any array to an iterator of [`Option<i8>`]
508///
509/// # Errors
510/// Returns an error if the array cannot be cast
511pub fn array_to_i8_iter(array: &dyn Array) -> Result<impl Iterator<Item = Option<i8>>> {
512    array_to_native_iter::<Int8Type, _>(array)
513}
514
515/// Converts any array to an iterator of [`Option<i16>`]
516///
517/// # Errors
518/// Returns an error if the array cannot be cast
519pub fn array_to_i16_iter(array: &dyn Array) -> Result<impl Iterator<Item = Option<i16>>> {
520    array_to_native_iter::<Int16Type, _>(array)
521}
522
523/// Converts any array to an iterator of [`Option<i32>`]
524///
525/// # Errors
526/// Returns an error if the array cannot be cast
527pub fn array_to_i32_iter(array: &dyn Array) -> Result<impl Iterator<Item = Option<i32>>> {
528    array_to_native_iter::<Int32Type, _>(array)
529}
530
531/// Converts any array to an iterator of [`Option<i64>`]
532///
533/// # Errors
534/// Returns an error if the array cannot be cast
535pub fn array_to_i64_iter(array: &dyn Array) -> Result<impl Iterator<Item = Option<i64>>> {
536    array_to_native_iter::<Int64Type, _>(array)
537}
538
539/// Converts any array to an iterator of [`Option<u8>`]
540///
541/// # Errors
542/// Returns an error if the array cannot be cast
543pub fn array_to_u8_iter(array: &dyn Array) -> Result<impl Iterator<Item = Option<u8>>> {
544    array_to_native_iter::<UInt8Type, _>(array)
545}
546
547/// Converts any array to an iterator of [`Option<u16>`]
548///
549/// # Errors
550/// Returns an error if the array cannot be cast
551pub fn array_to_u16_iter(array: &dyn Array) -> Result<impl Iterator<Item = Option<u16>>> {
552    array_to_native_iter::<UInt16Type, _>(array)
553}
554
555/// Converts any array to an iterator of [`Option<u32>`]
556///
557/// # Errors
558/// Returns an error if the array cannot be cast
559pub fn array_to_u32_iter(array: &dyn Array) -> Result<impl Iterator<Item = Option<u32>>> {
560    array_to_native_iter::<UInt32Type, _>(array)
561}
562
563/// Converts any array to an iterator of [`Option<u64>`]
564///
565/// # Errors
566/// Returns an error if the array cannot be cast
567pub fn array_to_u64_iter(array: &dyn Array) -> Result<impl Iterator<Item = Option<u64>>> {
568    array_to_native_iter::<UInt64Type, _>(array)
569}
570
571/// Converts any array to an iterator of [`Option<f32>`]
572///
573/// # Errors
574/// Returns an error if the array cannot be cast
575pub fn array_to_f32_iter(array: &dyn Array) -> Result<impl Iterator<Item = Option<f32>>> {
576    array_to_native_iter::<Float32Type, _>(array)
577}
578
579/// Converts any array to an iterator of [`Option<f64>`]
580///
581/// # Errors
582/// Returns an error if the array cannot be cast
583pub 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    // Helper function to collect iterator to a Vec for easier testing
602    fn collect_string_iter<I: Iterator<Item = Option<String>>>(iter: I) -> Vec<Option<String>> {
603        iter.collect()
604    }
605
606    // Helper function to collect binary iterator to a Vec for easier testing
607    fn collect_binary_iter<I: Iterator<Item = Option<Vec<u8>>>>(iter: I) -> Vec<Option<Vec<u8>>> {
608        iter.collect()
609    }
610
611    // Helper function to collect boolean iterator to a Vec for easier testing
612    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        // Create a fixed size binary array with 5-byte elements
664        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        // Create a dictionary array with string values
675        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    // Tests for the numeric conversion functions
700    #[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]); // Explicit i64
824        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    // Cross-type conversion tests
970    #[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); // Raw value, represents 123.45 with scale 2
1035            }
1036            _ => panic!("Expected Decimal128"),
1037        }
1038        match &result[1] {
1039            Value::Decimal128(p, v) => {
1040                assert_eq!(*p, 10);
1041                assert_eq!(*v, -67890); // Raw value, represents -678.90 with scale 2
1042            }
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.to_string().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.to_string().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        // With timezone
1111        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        // With timezone default
1120        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.to_string().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    // Failure tests
1417    #[test]
1418    fn test_invalid_string_conversion() {
1419        // Create an array with invalid UTF-8 data
1420        let invalid_utf8 = vec![0xFF, 0xFE, 0xFD]; // Invalid UTF-8 bytes
1421        let array = BinaryArray::from_iter_values(vec![&invalid_utf8]);
1422
1423        // This should still technically work but the strings might be corrupted
1424        // as the system will substitute replacement characters
1425        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        // Try to convert a number that's too large for i8
1432        let array = Int32Array::from(vec![Some(1000)]); // Too large for i8
1433        let result = array_to_i8_iter(&array);
1434
1435        // The conversion should succeed, but the value will be None because it's out of range
1436        let collected: Vec<_> = result.unwrap().collect();
1437        assert_eq!(collected, vec![None]);
1438    }
1439}