arrow-row: Fix decode_fixed_size_list to apply the corrected_type step for dictionary children - #10414
Merged
Merged
Conversation
…onary children (apache#10413) Closes apache#10413. `RowConverter::convert_rows` used to fail with a schema-mismatch InvalidArgumentError on any target type that contained a `FixedSizeList<Dictionary<K, V>>`: InvalidArgumentError("FixedSizeListArray expected data type Dictionary(Int32, Utf8) got Utf8 for \"item\"") `decode_fixed_size_list` was building the returned array with the declared `element_field` (which still carried `Dictionary<...>`) while its children came from `converter.convert_raw`, which returns the flattened (non-dictionary) type. `try_new_with_length` validates the child type against `element_field` and returned Err. The other list-like decoders — `List`, `LargeList`, `ListView`, `LargeListView`, `Map` — already reconcile declared-vs-actual via a `corrected_type` step (see `list::decode<L>` at list.rs:~260), and `Codec::Struct` in `lib.rs` does the same via `corrected_fields`. `decode_fixed_size_list` is the only list-like decoder that skipped this pattern. This commit adopts it, matching the shape of every other list-like decode path in the file. Test: `test_fixed_size_list_of_dictionaries_round_trips` reproduces the original failure on one row `["a", "b"]` of `FixedSizeList<Dictionary<Int32, Utf8>, 2>`. Pre-fix it panicked at the first `convert_rows(...).unwrap()` (matching the report in apache#10413); post-fix it returns a `FixedSizeList<Utf8>` (same flattened shape produced for `List<Dictionary<...>>` today) whose values are `"a"`, `"b"`. Downstream context: DataFusion hit this in apache/datafusion#23523 where a `GROUP BY fsl_col` on a `FixedSizeList<Dictionary<Int32, Utf8>>` would panic on emit. The DataFusion PR is landing a defensive blacklist in the meantime; this fix lets that blacklist be lifted in a follow-up.
Contributor
There was a problem hiding this comment.
Pull request overview
Fixes arrow-row decoding for FixedSizeList<Dictionary<..>> by ensuring decode_fixed_size_list uses the actual decoded child data type (post-dictionary-flattening) when constructing the returned FixedSizeListArray, matching the existing “corrected type” behavior of other list-like decoders.
Changes:
- Update
decode_fixed_size_listto rebuild the elementFieldwith the decoded child’s (possibly flattened)DataTypebefore callingFixedSizeListArray::try_new_with_length - Add a regression test covering round-tripping
FixedSizeList<Dictionary<Int32, Utf8>, 2>throughRowConverter::{convert_columns, convert_rows}
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| arrow-row/src/list.rs | Applies “corrected type” logic to FixedSizeList decoding to avoid schema mismatch when dictionary children are flattened |
| arrow-row/src/lib.rs | Adds regression test ensuring convert_rows succeeds and returns a self-consistent flattened child type for FixedSizeList<Dictionary<..>> |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Jefffrey
reviewed
Jul 23, 2026
Jefffrey
left a comment
Contributor
There was a problem hiding this comment.
the comments seem overly verbose
Co-authored-by: Jeffrey Vo <jeffrey.vo.australia@gmail.com>
Co-authored-by: Jeffrey Vo <jeffrey.vo.australia@gmail.com>
Contributor
Author
Thanks @Jefffrey for good suggestion, applied now. |
Jefffrey
approved these changes
Jul 23, 2026
Contributor
|
thanks @zhuqi-lucas |
zhuqi-lucas
added a commit
to zhuqi-lucas/arrow-datafusion
that referenced
this pull request
Jul 24, 2026
…rgeListView in RowsGroupColumn Address kosiew's review on apache#23523: `RowsGroupColumn::supports_type` accepts `ListView<Dictionary<..>>` and `LargeListView<Dictionary<..>>`, but `encode_array_if_necessary` had no reconstruction arm for either container. arrow-row's `decode_list_view` applies the dictionary-flatten `corrected_type` step to the child, so the emitted array came back as e.g. `ListView<Utf8>` and no longer matched `output_type`: SELECT arrow_cast(a, 'ListView(Dictionary(Int32, Utf8))') AS k, COUNT(*) FROM (VALUES (['a','b']), (['a','b']), (['c'])) AS t(a) GROUP BY k; -- expected ListView(Dictionary(Int32, Utf8)) but found ListView(Utf8) Changes: - `encode_array_if_necessary`: add `ListView` / `LargeListView` arms mirroring the `List` / `LargeList` ones, additionally carrying the `sizes` buffer that view-lists have. - `contains_fsl_with_dictionary`: add the TODO kosiew requested — the guard works around apache/arrow-rs#10413, fixed upstream by apache/arrow-rs#10414 (merged 2026-07-24, not yet released as of arrow 59.1.0); remove the guard when DataFusion upgrades past that. - `supports_type` doc: replace the now-inaccurate "round-trip cleanly" wording — the correction means these containers decode without panicking but with a *flattened* child type that `build` / `take_n` must re-encode. Tests (all red without the fix, green with it): - `build_preserves_list_view_of_dictionary_schema` — the reproducer shape, `build` path. - `take_n_preserves_list_view_of_dictionary_schema` — `take_n` path, plus type of the remainder emitted by a subsequent `build`. - `build_and_take_n_preserve_large_list_view_of_dictionary_schema` — same coverage for `LargeListView`. - `list_view_of_dict_groups_by_logical_value` — group identity across distinct dictionary key mappings (3 input rows → 2 groups), matching the reproducer's GROUP BY semantics.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Which issue does this PR close?
Closes #10413.
Rationale for this change
RowConverter::convert_rowsused to fail with a schema-mismatchInvalidArgumentErroron any target type that contained aFixedSizeList<Dictionary<K, V>>:decode_fixed_size_listwas building the returned array with the declaredelement_field(which still carriedDictionary<...>) while the children came fromconverter.convert_raw, which returns the flattened (non-dictionary) type.try_new_with_lengthvalidates the child type againstelement_fieldand returnedErr.The other list-like decoders —
List,LargeList,ListView,LargeListView,Map— already reconcile declared-vs-actual via acorrected_typestep (seelist::decode<L>at list.rs:~260 on main), andCodec::Structinlib.rsdoes the same viacorrected_fields.decode_fixed_size_listwas the only list-like decoder that skipped this pattern.What changes are included in this PR?
arrow-row/src/list.rs::decode_fixed_size_list: adopt thecorrected_typestep, mirroring the shape of every other list-like decoder in the file.arrow-row/src/lib.rs::tests::test_fixed_size_list_of_dictionaries_round_trips: regression test that reproduces the original failure on one row["a", "b"]ofFixedSizeList<Dictionary<Int32, Utf8>, 2>.Diff on the decoder is ~10 lines:
Are these changes tested?
Yes:
test_fixed_size_list_of_dictionaries_round_trips— regression test inarrow-row/src/lib.rs. Pre-fix it panics at the firstconvert_rows(...).unwrap()(matching the report in arrow-row:decode_fixed_size_listpanics onFixedSizeList<Dictionary>(missing corrected_type) #10413); post-fix it returns aFixedSizeList<Utf8>(same flattened shape produced today forList<Dictionary<...>>) whose values are"a","b".arrow-rowtests continue to pass (cargo test -p arrow-row).cargo clippy -p arrow-row --all-targets -- -D warningsclean.Are there any user-facing changes?
Behaviour change (bug fix):
RowConverter::convert_rowsnow succeeds where it previously returned anInvalidArgumentErrorforFixedSizeList<Dictionary<...>>(and any type containing one, e.g.FSL<Struct<Dict>>,List<FSL<Dict>>). The returned array flattens the dictionary child to its native representation — same behaviour today'sList<Dict>/LargeList<Dict>/Map<Dict>decoders exhibit. Callers that need the declared dictionary type back can re-encode afterconvert_rows(that's the documented contract).No public API surface changes.
Downstream context
DataFusion hit this in apache/datafusion#23523 (nested-type support in
GroupValuesColumn) where aGROUP BY fsl_colonFixedSizeList<Dictionary<Int32, Utf8>>would panic on emit. The DataFusion PR is landing a defensive blacklist in the meantime; this fix will let that blacklist be lifted in a follow-up.