Commits


Adam Reeve authored and GitHub committed 83dc0a91d2f
GH-40790: [C#] Account for offset and length when getting fields of a StructArray (#40805) ### Rationale for this change See #40790. The `StructArray.Fields` property currently returns the child arrays without accounting for the array offset and length. This meant that consumers would need to know to account for the offset and length themselves when accessing the child arrays, and this is inconsistent with the behaviour of Arrow APIs in other languages. ### What changes are included in this PR? Changes the behaviour of the `StructArray.Fields` property, so that the returned arrays are sliced if required. This behaviour is consistent with the C++ Arrow API, eg. see: https://github.com/apache/arrow/blob/f710ac52b049806515a14445b242c3ec819fb99d/cpp/src/arrow/array/array_nested.cc#L1019-L1020 I also checked that pyarrow behaves like this too: ```python import pyarrow as pa a = pa.array([0, 1, 2, 3, 4], type=pa.int32()) b = pa.array([0.0, 0.1, 0.2, 0.3, 0.4], type=pa.float32()) xs = pa.StructArray.from_arrays([a, b], names=["a", "b"]) slice = xs.slice(2, 3) assert len(slice) == 3 assert len(slice.field(0)) == 3 assert len(slice.field(1)) == 3 ``` ### Are these changes tested? Yes, I've added new unit tests. ### Are there any user-facing changes? Yes, this is a user-facing bug fix and behaviour change. **This PR includes breaking changes to public APIs.** The behaviour of `StructArray.Fields` has changed. If users were previously accounting for the array offset and length themselves, this will break existing code. I first tried to make this non-breaking, by introducing a new property to replace `Fields`, and marking that property as obsolete. But `StructArray` implements `IArrowRecord`, so the behaviour of the `IArrowRecord.Column` would either need to be kept as broken, or fixed with a breaking change. It seems simplest and most consistent to fix the behaviour for all methods. If users need to maintain compatibility across different Arrow versions, I'd suggest using a pattern like: ```c# var field = structArray.Fields[0]; if (field.Length != structArray.Length) { field = ArrowArrayFactory.Slice(field, structArray.Offset, structArray.Length); } ``` * GitHub Issue: #40790 Authored-by: Adam Reeve <adreeve@gmail.com> Signed-off-by: Curt Hagenlocher <curt@hagenlocher.org>