Skip to content

AVRO-4355: [Java] Allow field name swaps by aliases in SchemaCompatibility - #4019

Closed
rayokota wants to merge 1 commit into
apache:mainfrom
rayokota:AVRO-4355
Closed

rayokota wants to merge 1 commit into
apache:mainfrom
rayokota:AVRO-4355

Conversation

@rayokota

@rayokota rayokota commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

What is the purpose of the change

When a reader swaps or rotates field names using aliases (for example b aliased a, and a aliased b), SchemaCompatibility throws AvroRuntimeException ("Reader record field b ... matches multiple fields in writer record schema"). The decoder reads the same schemas correctly. This fixes AVRO-4355.

lookupWriterField collects the writer field with the reader field's own name, plus each writer field named by one of its aliases, and throws when it finds more than one. The decoder instead goes through Schema.applyAliases, which renames the writer's a to b and its b to a, so each reader field reads the writer field its alias names. Record name swaps already work in both, because the checker compares type names at each location.

The record-fields check now uses a new package-private lookupWriterField(writer, reader, readerField), which can see the whole reader record. If the writer field with the reader field's own name is claimed by another reader field's alias, the reader field takes the writer field its own alias names. That is exactly when applyAliases renames that writer field away.

Every other case falls through to the existing lookupWriterField(Schema, Field), whose behavior is unchanged:

  • A reader field aliasing a writer field that no other alias frees still throws. The decoder fails there too, with "Duplicate field".
  • Renaming a field and reusing its old name for a new field is checked as before.

Verifying this change

This change added tests to TestSchemaCompatibility:

  • A two-field swap is compatible, and decoding with GenericDatumReader gives the same pairing.
  • A three-field rotation is compatible.
  • A swap inside a nested record is compatible.
  • Swapped fields are compared against the writer fields their aliases name, so a type swapped as well is reported as TYPE_MISMATCH.
  • A reader field aliasing a writer field that no other alias frees still throws.

The swap and rotation tests fail without the change. All TestSchemaCompatibility* tests pass (82).

Documentation

  • Does this pull request introduce a new feature? no
  • If yes, how is the feature documented? not applicable

@github-actions github-actions Bot added the Java Pull Requests for Java binding label Oct 1, 2026
@rayokota rayokota changed the title AVRO-4355: [Java] Allow field name swaps by aliases in SchemaCompatib… AVRO-4355: [Java] Allow field name swaps by aliases in SchemaCompatibity Oct 1, 2026
@rayokota rayokota changed the title AVRO-4355: [Java] Allow field name swaps by aliases in SchemaCompatibity AVRO-4355: [Java] Allow field name swaps by aliases in SchemaCompatibility Oct 1, 2026
@rayokota

rayokota commented Oct 1, 2026

Copy link
Copy Markdown
Contributor Author

Closing for now. The checker change is correct for an exact renamed reader. But the decoder applies aliases twice (FastReaderBuilder/GenericDatumReader, then Resolver.resolve), so a swapped schema read by any other reader, e.g. one that adds a field, silently reverses the swap. Making the checker accept swaps would let those schemas register. The decoder would need additional fixing.

@rayokota rayokota closed this Oct 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Java Pull Requests for Java binding

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant