Skip to content

Commit 2e05648

Browse files
authored
Preserve field name when casting List (#13468)
* Add option to pass in field name to create array to support retaining field name during cast * add unit tests for list casting round trip * Documentation example was missing parameter * Rather than deprecate an existing function or change pub signature add in a parallel function for the small cases where we want to explicitly set the field name
1 parent bd47d4f commit 2e05648

File tree

2 files changed

+105
-8
lines changed

2 files changed

+105
-8
lines changed

datafusion/common/src/scalar/mod.rs

Lines changed: 64 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,9 @@ use crate::cast::{
4040
use crate::error::{DataFusionError, Result, _exec_err, _internal_err, _not_impl_err};
4141
use crate::hash_utils::create_hashes;
4242
use crate::utils::{
43-
array_into_fixed_size_list_array, array_into_large_list_array, array_into_list_array,
43+
array_into_fixed_size_list_array_with_field_name, array_into_large_list_array,
44+
array_into_large_list_array_with_field_name, array_into_list_array,
45+
array_into_list_array_with_field_name,
4446
};
4547
use arrow::compute::kernels::numeric::*;
4648
use arrow::util::display::{array_value_to_string, ArrayFormatter, FormatOptions};
@@ -2663,27 +2665,36 @@ impl ScalarValue {
26632665
let list_array = array.as_list::<i32>();
26642666
let nested_array = list_array.value(index);
26652667
// Produces a single element `ListArray` with the value at `index`.
2666-
let arr =
2667-
Arc::new(array_into_list_array(nested_array, field.is_nullable()));
2668+
let arr = Arc::new(array_into_list_array_with_field_name(
2669+
nested_array,
2670+
field.is_nullable(),
2671+
field.name(),
2672+
));
26682673

26692674
ScalarValue::List(arr)
26702675
}
2671-
DataType::LargeList(_) => {
2676+
DataType::LargeList(field) => {
26722677
let list_array = as_large_list_array(array);
26732678
let nested_array = list_array.value(index);
26742679
// Produces a single element `LargeListArray` with the value at `index`.
2675-
let arr = Arc::new(array_into_large_list_array(nested_array));
2680+
let arr = Arc::new(array_into_large_list_array_with_field_name(
2681+
nested_array,
2682+
field.name(),
2683+
));
26762684

26772685
ScalarValue::LargeList(arr)
26782686
}
26792687
// TODO: There is no test for FixedSizeList now, add it later
2680-
DataType::FixedSizeList(_, _) => {
2688+
DataType::FixedSizeList(field, _) => {
26812689
let list_array = as_fixed_size_list_array(array)?;
26822690
let nested_array = list_array.value(index);
26832691
// Produces a single element `ListArray` with the value at `index`.
26842692
let list_size = nested_array.len();
2685-
let arr =
2686-
Arc::new(array_into_fixed_size_list_array(nested_array, list_size));
2693+
let arr = Arc::new(array_into_fixed_size_list_array_with_field_name(
2694+
nested_array,
2695+
list_size,
2696+
field.name(),
2697+
));
26872698

26882699
ScalarValue::FixedSizeList(arr)
26892700
}
@@ -5970,6 +5981,51 @@ mod tests {
59705981
ScalarValue::from("larger than 12 bytes string"),
59715982
DataType::Utf8View,
59725983
);
5984+
check_scalar_cast(
5985+
{
5986+
let element_field =
5987+
Arc::new(Field::new("element", DataType::Int32, true));
5988+
5989+
let mut builder =
5990+
ListBuilder::new(Int32Builder::new()).with_field(element_field);
5991+
builder.append_value([Some(1)]);
5992+
builder.append(true);
5993+
5994+
ScalarValue::List(Arc::new(builder.finish()))
5995+
},
5996+
DataType::List(Arc::new(Field::new("element", DataType::Int64, true))),
5997+
);
5998+
check_scalar_cast(
5999+
{
6000+
let element_field =
6001+
Arc::new(Field::new("element", DataType::Int32, true));
6002+
6003+
let mut builder = FixedSizeListBuilder::new(Int32Builder::new(), 1)
6004+
.with_field(element_field);
6005+
builder.values().append_value(1);
6006+
builder.append(true);
6007+
6008+
ScalarValue::FixedSizeList(Arc::new(builder.finish()))
6009+
},
6010+
DataType::FixedSizeList(
6011+
Arc::new(Field::new("element", DataType::Int64, true)),
6012+
1,
6013+
),
6014+
);
6015+
check_scalar_cast(
6016+
{
6017+
let element_field =
6018+
Arc::new(Field::new("element", DataType::Int32, true));
6019+
6020+
let mut builder =
6021+
LargeListBuilder::new(Int32Builder::new()).with_field(element_field);
6022+
builder.append_value([Some(1)]);
6023+
builder.append(true);
6024+
6025+
ScalarValue::LargeList(Arc::new(builder.finish()))
6026+
},
6027+
DataType::LargeList(Arc::new(Field::new("element", DataType::Int64, true))),
6028+
);
59736029
}
59746030

59756031
// mimics how casting work on scalar values by `casting` `scalar` to `desired_type`

datafusion/common/src/utils/mod.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,20 @@ pub fn array_into_list_array(arr: ArrayRef, nullable: bool) -> ListArray {
342342
)
343343
}
344344

345+
pub fn array_into_list_array_with_field_name(
346+
arr: ArrayRef,
347+
nullable: bool,
348+
field_name: &str,
349+
) -> ListArray {
350+
let offsets = OffsetBuffer::from_lengths([arr.len()]);
351+
ListArray::new(
352+
Arc::new(Field::new(field_name, arr.data_type().to_owned(), nullable)),
353+
offsets,
354+
arr,
355+
None,
356+
)
357+
}
358+
345359
/// Wrap an array into a single element `LargeListArray`.
346360
/// For example `[1, 2, 3]` would be converted into `[[1, 2, 3]]`
347361
pub fn array_into_large_list_array(arr: ArrayRef) -> LargeListArray {
@@ -354,6 +368,19 @@ pub fn array_into_large_list_array(arr: ArrayRef) -> LargeListArray {
354368
)
355369
}
356370

371+
pub fn array_into_large_list_array_with_field_name(
372+
arr: ArrayRef,
373+
field_name: &str,
374+
) -> LargeListArray {
375+
let offsets = OffsetBuffer::from_lengths([arr.len()]);
376+
LargeListArray::new(
377+
Arc::new(Field::new(field_name, arr.data_type().to_owned(), true)),
378+
offsets,
379+
arr,
380+
None,
381+
)
382+
}
383+
357384
pub fn array_into_fixed_size_list_array(
358385
arr: ArrayRef,
359386
list_size: usize,
@@ -367,6 +394,20 @@ pub fn array_into_fixed_size_list_array(
367394
)
368395
}
369396

397+
pub fn array_into_fixed_size_list_array_with_field_name(
398+
arr: ArrayRef,
399+
list_size: usize,
400+
field_name: &str,
401+
) -> FixedSizeListArray {
402+
let list_size = list_size as i32;
403+
FixedSizeListArray::new(
404+
Arc::new(Field::new(field_name, arr.data_type().to_owned(), true)),
405+
list_size,
406+
arr,
407+
None,
408+
)
409+
}
410+
370411
/// Wrap arrays into a single element `ListArray`.
371412
///
372413
/// Example:

0 commit comments

Comments
 (0)