Skip to content

GH-559: [Java] Add FixedSizeBinary support to ComplexCopier - #1253

Open
Maria-Berta wants to merge 3 commits into
apache:mainfrom
Maria-Berta:GH-559-complex-copier-fixed-size-binary
Open

Maria-Berta wants to merge 3 commits into
apache:mainfrom
Maria-Berta:GH-559-complex-copier-fixed-size-binary

Conversation

@Maria-Berta

@Maria-Berta Maria-Berta commented Aug 3, 2026 •

Copy link
Copy Markdown

Rationale for this change

ComplexCopier did not support copying FixedSizeBinary columns nested in List, Map, Struct, or top-level contexts, throwing UnsupportedOperationException.

What changes are included in this PR?

Adds FIXEDSIZEBINARY cases to:

  • getListWriterForReader
  • getStructWriterForReader
  • getMapWriterForReader
  • the main copy() switch

Are these changes tested?

Yes:

  • testCopyListOfFixedSizeBinary — copying a List
  • testCopyStructOfFixedSizeBinary — copying a Struct field of type FixedSizeBinary

Full TestComplexCopier suite (22 tests) passes with no regressions.

Note: I attempted to add equivalent coverage for Map values of type FixedSizeBinary, but ran into a pre-existing limitation unrelated to this fix — MapWriter/ListWriter's no-arg fixedSizeBinary() delegates to NullableStructWriter.fixedSizeBinary(String), which only looks up an existing child writer and never creates one. The byteWidth-aware overload that does create the vector isn't reachable through the public MapWriter/ListWriter interface. This appears to be a gap in the writer codegen itself rather than something ComplexCopier can work around, so I've left it untested here — happy to open a follow-up issue if that's useful, or take a stab at it if maintainers think it's in scope for this PR.

Closes #559

@github-actions

This comment has been minimized.

@Maria-Berta

Copy link
Copy Markdown
Author

Hi @jbonofre @laurentgo @lidavidm @wgtmac — checking in on this PR.
I don't have permission to add labels myself as an external
contributor. Could someone add bug-fix (or whichever fits best)
when you have a chance so the "Ensure PR is labeled" check can pass?
Happy to make any other changes needed too. Thanks!

@lidavidm lidavidm added the bug-fix PRs that fix a big. label Aug 10, 2026
@github-actions github-actions Bot added this to the 20.0.0 milestone Aug 10, 2026
@jbonofre

jbonofre commented Sep 3, 2026 •

Copy link
Copy Markdown
Member

@Maria-Berta I'm doing the review. Thanks!

writer.writeNull();
}
break;
case FIXEDSIZEBINARY:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

writeFixedSizeBinary(fixedSizeBinaryHolder.buffer) is the deprecated overload that carries no byteWidth. When the target writer isn't already typed (a fresh ListVector.empty(...), a union, or an untyped struct field), PromotableWriter falls back to MinorType.FIXEDSIZEBINARY.getType() and the copy throws.

The new test don't catch this because they pre-seed the target child with addOrGetVector(FieldType.nullable(new ArrowType.FixedSizeBinary(byteWidth))).

Could we set byteWidth on the holder and call writer.write(fixedSizeBinaryHolder) instead? reader.read already populates the holder, and AbstractPromotableFieldWriter.write(FixedSizeBinaryHolder) builds the ArrowType from it. A test that copies into an untyped target would be good too.

return (FieldWriter) writer.<#if name == "Int">integer<#else>${uncappedName}</#if>();
</#if>
</#list></#list>
case FIXEDSIZEBINARY:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getListWriterForReader and getMapWriterForReader call writer.fixedSizeBinary() without a width, while the struct path passes fixedSizeBinary(name, byteWidth).

For maps, UnionMapWriter.fixedSizeBinary() delegates to entryWriter.fixedSizeBinary(KEY_NAME) with no width. So copying a MapVector with FixedSizeBinary keys or values into an empty target throws, even once the issue at line 120 is fixed. The list path only works if the target child is already typed.

Could we pass the width from the reader's ArrowType.FixedSizeBinary here as well? There are no tests for the map path, so one would help.

</#if>

</#list></#list>
case FIXEDSIZEBINARY:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the else branch, writer.fixedSizeBinary(name) is called without a width. This is reached when the reader's field type is not ArrowType.FixedSizeBinary (for example a union-backed reader), and it then throws an unhelpful error.

Could we throw an explicit exception with a clear message, or derive the width from the holder?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug-fix PRs that fix a big.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ComplexCopier missing support for FixedSizeBinary columns

3 participants