-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Convert list array and non-list array to scalars #7862
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 5 commits
3472b51
d704c83
aee4eff
b92d535
3b6b53e
c69f874
f7b6ac0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -2039,7 +2039,11 @@ impl ScalarValue { | |||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| /// Retrieve ScalarValue for each row in `array` | ||||||||||||||||||||||||||
| /// Retrieve `ScalarValue` for each row in `array` | ||||||||||||||||||||||||||
| /// | ||||||||||||||||||||||||||
| /// Convert `ListArray` to `Vec<Vec<ScalarValue>>`, first `Vec` is for rows, second `Vec` is for elements in the list | ||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 It might also help to explain why we need two different signatures. It took me a while to grok things too
Suggested change
|
||||||||||||||||||||||||||
| /// | ||||||||||||||||||||||||||
| /// Return `Err` if `array` is not `ListArray` | ||||||||||||||||||||||||||
| /// | ||||||||||||||||||||||||||
| /// Example | ||||||||||||||||||||||||||
| /// ``` | ||||||||||||||||||||||||||
|
|
@@ -2053,7 +2057,7 @@ impl ScalarValue { | |||||||||||||||||||||||||
| /// Some(vec![Some(4), Some(5)]) | ||||||||||||||||||||||||||
| /// ]); | ||||||||||||||||||||||||||
| /// | ||||||||||||||||||||||||||
| /// let scalar_vec = ScalarValue::convert_array_to_scalar_vec(&list_arr).unwrap(); | ||||||||||||||||||||||||||
| /// let scalar_vec = ScalarValue::convert_list_array_to_scalar_vec::<i32>(&list_arr).unwrap(); | ||||||||||||||||||||||||||
| /// | ||||||||||||||||||||||||||
| /// let expected = vec![ | ||||||||||||||||||||||||||
| /// vec![ | ||||||||||||||||||||||||||
|
|
@@ -2067,30 +2071,78 @@ impl ScalarValue { | |||||||||||||||||||||||||
| /// | ||||||||||||||||||||||||||
| /// assert_eq!(scalar_vec, expected); | ||||||||||||||||||||||||||
| /// ``` | ||||||||||||||||||||||||||
| pub fn convert_array_to_scalar_vec(array: &dyn Array) -> Result<Vec<Vec<Self>>> { | ||||||||||||||||||||||||||
| let mut scalars = Vec::with_capacity(array.len()); | ||||||||||||||||||||||||||
| pub fn convert_list_array_to_scalar_vec<O: OffsetSizeTrait>( | ||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this would be easier to use if it didn't mix generic and non generic code Maybe something like
Suggested change
And then internally pass in the cast Array by changing to |
||||||||||||||||||||||||||
| array: &dyn Array, | ||||||||||||||||||||||||||
| ) -> Result<Vec<Vec<Self>>> { | ||||||||||||||||||||||||||
| if array.as_list_opt::<O>().is_some() { | ||||||||||||||||||||||||||
| Self::convert_list_array_to_scalar_vec_internal::<O>(array) | ||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||
| _internal_err!("Expected GenericListArray but found: {array:?}") | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| for index in 0..array.len() { | ||||||||||||||||||||||||||
| let scalar_values = match array.data_type() { | ||||||||||||||||||||||||||
| DataType::List(_) => { | ||||||||||||||||||||||||||
| let list_array = as_list_array(array); | ||||||||||||||||||||||||||
| match list_array.is_null(index) { | ||||||||||||||||||||||||||
| true => Vec::new(), | ||||||||||||||||||||||||||
| false => { | ||||||||||||||||||||||||||
| let nested_array = list_array.value(index); | ||||||||||||||||||||||||||
| ScalarValue::convert_array_to_scalar_vec(&nested_array)? | ||||||||||||||||||||||||||
| .into_iter() | ||||||||||||||||||||||||||
| .flatten() | ||||||||||||||||||||||||||
| .collect() | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| fn convert_list_array_to_scalar_vec_internal<O: OffsetSizeTrait>( | ||||||||||||||||||||||||||
| array: &dyn Array, | ||||||||||||||||||||||||||
| ) -> Result<Vec<Vec<Self>>> { | ||||||||||||||||||||||||||
| let mut scalars_vec = Vec::with_capacity(array.len()); | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| if let Some(list_arr) = array.as_list_opt::<O>() { | ||||||||||||||||||||||||||
| for index in 0..list_arr.len() { | ||||||||||||||||||||||||||
| let scalars = match list_arr.is_null(index) { | ||||||||||||||||||||||||||
| true => Vec::new(), | ||||||||||||||||||||||||||
| false => { | ||||||||||||||||||||||||||
| let nested_array = list_arr.value(index); | ||||||||||||||||||||||||||
| Self::convert_list_array_to_scalar_vec_internal::<O>( | ||||||||||||||||||||||||||
| &nested_array, | ||||||||||||||||||||||||||
| )? | ||||||||||||||||||||||||||
| .into_iter() | ||||||||||||||||||||||||||
| .flatten() | ||||||||||||||||||||||||||
| .collect() | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| _ => { | ||||||||||||||||||||||||||
| let scalar = ScalarValue::try_from_array(array, index)?; | ||||||||||||||||||||||||||
| vec![scalar] | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||
| scalars.push(scalar_values); | ||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||
| scalars_vec.push(scalars); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||
| let scalars = ScalarValue::convert_non_list_array_to_scalars(array)?; | ||||||||||||||||||||||||||
|
jayzhan211 marked this conversation as resolved.
|
||||||||||||||||||||||||||
| scalars_vec.push(scalars); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| Ok(scalars_vec) | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| /// Convert non-ListArray to `Vec<ScalarValue>` | ||||||||||||||||||||||||||
| /// | ||||||||||||||||||||||||||
| /// Return Err if `array` is ListArray | ||||||||||||||||||||||||||
| /// | ||||||||||||||||||||||||||
| /// Example | ||||||||||||||||||||||||||
| /// ``` | ||||||||||||||||||||||||||
| /// use datafusion_common::ScalarValue; | ||||||||||||||||||||||||||
| /// use arrow::array::Int32Array; | ||||||||||||||||||||||||||
| /// | ||||||||||||||||||||||||||
| /// let list_arr = Int32Array::from(vec![Some(1), Some(2), Some(3), None, Some(4), Some(5)]); | ||||||||||||||||||||||||||
| /// | ||||||||||||||||||||||||||
| /// let scalar_vec = ScalarValue::convert_non_list_array_to_scalars(&list_arr).unwrap(); | ||||||||||||||||||||||||||
| /// | ||||||||||||||||||||||||||
| /// let expected = vec![ | ||||||||||||||||||||||||||
| /// ScalarValue::Int32(Some(1)), | ||||||||||||||||||||||||||
| /// ScalarValue::Int32(Some(2)), | ||||||||||||||||||||||||||
| /// ScalarValue::Int32(Some(3)), | ||||||||||||||||||||||||||
| /// ScalarValue::Int32(None), | ||||||||||||||||||||||||||
| /// ScalarValue::Int32(Some(4)), | ||||||||||||||||||||||||||
| /// ScalarValue::Int32(Some(5)), | ||||||||||||||||||||||||||
| /// ]; | ||||||||||||||||||||||||||
| /// | ||||||||||||||||||||||||||
| /// assert_eq!(scalar_vec, expected); | ||||||||||||||||||||||||||
| /// ``` | ||||||||||||||||||||||||||
| pub fn convert_non_list_array_to_scalars(array: &dyn Array) -> Result<Vec<Self>> { | ||||||||||||||||||||||||||
| if array.as_list_opt::<i32>().is_some() || array.as_list_opt::<i64>().is_some() { | ||||||||||||||||||||||||||
| return _internal_err!("Expected non ListArray but found: {array:?}"); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| let mut scalars = Vec::with_capacity(array.len()); | ||||||||||||||||||||||||||
| for index in 0..array.len() { | ||||||||||||||||||||||||||
| let scalar = ScalarValue::try_from_array(array, index)?; | ||||||||||||||||||||||||||
| scalars.push(scalar); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| Ok(scalars) | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
@@ -3129,6 +3181,44 @@ mod tests { | |||||||||||||||||||||||||
| use arrow_array::ArrowNumericType; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| use crate::cast::{as_string_array, as_uint32_array, as_uint64_array}; | ||||||||||||||||||||||||||
| use crate::utils::arrays_into_list_array; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| #[test] | ||||||||||||||||||||||||||
| fn convert_list_array_to_scalar_vec_nested() { | ||||||||||||||||||||||||||
| let l1 = ListArray::from_iter_primitive::<Int32Type, _, _>(vec![ | ||||||||||||||||||||||||||
| Some(vec![Some(1), Some(2), Some(3)]), | ||||||||||||||||||||||||||
| Some(vec![Some(4), Some(5)]), | ||||||||||||||||||||||||||
| ]); | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| let l2 = ListArray::from_iter_primitive::<Int32Type, _, _>(vec![Some(vec![ | ||||||||||||||||||||||||||
| Some(6), | ||||||||||||||||||||||||||
| Some(7), | ||||||||||||||||||||||||||
| Some(8), | ||||||||||||||||||||||||||
| ])]); | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| let l1 = Arc::new(l1) as ArrayRef; | ||||||||||||||||||||||||||
| let l2 = Arc::new(l2) as ArrayRef; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| let l12 = arrays_into_list_array([l1, l2]).unwrap(); | ||||||||||||||||||||||||||
| let arr = Arc::new(l12) as ArrayRef; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| let actual = ScalarValue::convert_list_array_to_scalar_vec::<i32>(&arr).unwrap(); | ||||||||||||||||||||||||||
| let expected = vec![ | ||||||||||||||||||||||||||
| vec![ | ||||||||||||||||||||||||||
| ScalarValue::Int32(Some(1)), | ||||||||||||||||||||||||||
| ScalarValue::Int32(Some(2)), | ||||||||||||||||||||||||||
| ScalarValue::Int32(Some(3)), | ||||||||||||||||||||||||||
| ScalarValue::Int32(Some(4)), | ||||||||||||||||||||||||||
| ScalarValue::Int32(Some(5)), | ||||||||||||||||||||||||||
| ], | ||||||||||||||||||||||||||
| vec![ | ||||||||||||||||||||||||||
| ScalarValue::Int32(Some(6)), | ||||||||||||||||||||||||||
| ScalarValue::Int32(Some(7)), | ||||||||||||||||||||||||||
| ScalarValue::Int32(Some(8)), | ||||||||||||||||||||||||||
| ], | ||||||||||||||||||||||||||
| ]; | ||||||||||||||||||||||||||
| assert_eq!(actual, expected); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| #[test] | ||||||||||||||||||||||||||
| fn test_to_array_of_size_for_list() { | ||||||||||||||||||||||||||
|
|
@@ -3188,6 +3278,7 @@ mod tests { | |||||||||||||||||||||||||
| "arrow", | ||||||||||||||||||||||||||
| "data-fusion", | ||||||||||||||||||||||||||
| ]))); | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| let result = as_list_array(&array); | ||||||||||||||||||||||||||
| assert_eq!(result, &expected); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems left over