wjones127 opened a new issue, #10975:
URL: https://github.com/apache/arrow-rs/issues/10975

   ### Describe the bug
   
   Casting a sliced `ListArray` (or `LargeListArray`) to a `FixedSizeList` 
silently returns the wrong values: the result is taken from the start of the 
child array rather than from where the slice's offsets point. No error is 
raised — the data is just shifted.
   
   `cast_list_to_fixed_size_list` reads the values as `array.values().slice(0, 
cap)` on the "all slices were the correct length" fast path, and starts 
`last_pos` at `0` on the padding path, neither of which accounts for 
`array.offsets()[0]` being non-zero after a slice.
   
   https://github.com/apache/arrow-rs/blob/main/arrow-cast/src/cast/list.rs (in 
`cast_list_to_fixed_size_list`):
   
   ```rust
   let values = match last_pos {
       0 if !is_prev_empty => array.values().slice(0, cap), // All slices were 
the correct length
       ...
   ```
   
   Still present on `main` as of today.
   
   ### To Reproduce
   
   ```rust
   use std::sync::Arc;
   
   use arrow::array::{ListArray, types::Int32Type};
   use arrow::compute::cast;
   use arrow::datatypes::{DataType, Field};
   
   fn main() {
       let list = ListArray::from_iter_primitive::<Int32Type, _, _>(vec![
           Some(vec![Some(1), Some(2)]),
           Some(vec![Some(3), Some(4)]),
           Some(vec![Some(5), Some(6)]),
       ]);
   
       let to = DataType::FixedSizeList(Arc::new(Field::new("item", 
DataType::Int32, true)), 2);
   
       println!("unsliced: {:?}", cast(&list, &to).unwrap());
   
       let sliced = list.slice(1, 2);
       println!("sliced:   {:?}", cast(&sliced, &to).unwrap());
   }
   ```
   
   The unsliced cast is correct. The sliced cast prints rows `[1, 2]` and `[3, 
4]`, i.e. the first two rows of the original array rather than the two rows the 
slice covers.
   
   ### Expected behavior
   
   The sliced cast should produce rows `[3, 4]` and `[5, 6]`, matching 
`cast(&list, &to).unwrap().slice(1, 2)`.
   
   For comparison, `cast_list_values` (list → list of another item type) keeps 
the sliced offsets and casts the whole child array, so it handles a slice 
correctly. `cast_list_view_to_fixed_size_list` also looks correct, since it 
reads each element through `value_offset(idx)`.
   
   ### Additional context
   
   Reproduced with `arrow` 58.4.0 and read on `main`. Slicing is easy to hit 
without doing it explicitly — a record batch sliced by the caller, or a list 
column coming out of a re-chunked stream — and because the cast succeeds, the 
wrong values are written or returned with nothing to indicate it. Found while 
writing a fixed-size-list column in LanceDB, where rows landed one position out 
of step.
   
   I'm happy to open a PR if the fix — rebasing off `array.offsets()[0]` in 
both paths — looks right to you.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to