Skip to content

fix(table): accept DataSplit version 9 and mirror _WRITE_COLS_SEQUENCES - #745

Open
JunRuiLee wants to merge 4 commits into
apache:mainfrom
JunRuiLee:datasplit-v9
Open

fix(table): accept DataSplit version 9 and mirror _WRITE_COLS_SEQUENCES#745
JunRuiLee wants to merge 4 commits into
apache:mainfrom
JunRuiLee:datasplit-v9

Conversation

@JunRuiLee

Copy link
Copy Markdown
Contributor

What

DataSplit::deserialize accepted wire version 8 only, so any DataSplit produced by
current Paimon Java is rejected with Unsupported.

Java bumped DataSplit#VERSION 8 → 9 in apache/paimon#9313 when it appended
_WRITE_COLS_SEQUENCES (per-column maximum sequence numbers) to DataFileMeta.SCHEMA.
The split body itself is unchanged — the only difference is that the per-file
DataFileMeta row grew by one nullable trailing field:

version per-file row Java serializer
8 20 fields, ends at _WRITE_COLS DataFileMetaWriteColsLegacySerializer
9 21 fields, _WRITE_COLS_SEQUENCES at slot 20 DataFileMetaSerializer

Changes

  • DataFileMeta carries column_max_sequence_numbers: Option<Vec<i64>>.
  • The row codec is layout-aware via DataFileMetaRowLayout. The two layouts share
    slots 0..=19 and differ only in arity, which the enclosing split's version selects.
    Only the current layout is written, mirroring Java keeping its legacy serializers
    deserialize-only.
  • DataSplit::deserialize accepts v8 and v9; serialize emits v9.
  • The field is decoded from manifest entries and declared in the manifest Avro schema,
    so a file read from a manifest and handed on inside a split no longer silently drops it.

Goldens

All taken from the Java compatibility fixtures rather than generated here:

  • goldens/datasplit_v9.bin is the raw body of compatibility/datasplit-v9 (the Java
    fixture is an object stream: TC_BLOCKDATALONG + declared length + body +
    TC_ENDBLOCKDATA). Extracting the same way from compatibility/datasplit-v8 reproduces
    the existing goldens/datasplit_v8.bin byte for byte, which is what validates the
    extraction.
  • goldens/split_v1_data.bin / split_v1_indexed.bin are refreshed from their Java
    counterparts, whose embedded DataSplit is now v9. They were still carrying a v8 body.

The v8 golden is kept as a legacy-decode test.

Note for reviewers

serialize now emits v9 rather than v8. That follows Java, which no longer writes v8, and
v8 stays readable — but it does mean bytes produced here can no longer be read by a Paimon
older than apache/paimon#9313. Happy to gate it behind an explicit version argument instead
if you would rather not move the write side in the same change.

Java bumped `DataSplit#VERSION` from 8 to 9 when it appended
`_WRITE_COLS_SEQUENCES` (per-column maximum sequence numbers) to
`DataFileMeta.SCHEMA`. The split body itself did not change -- only the
per-file `DataFileMeta` row grew by one nullable trailing field -- but
`DataSplit::deserialize` accepted version 8 exclusively, so every split
produced by current Java was rejected with `Unsupported`.

Carry the new field on `DataFileMeta` and make the row codec layout-aware:
the 20-field layout (Java `DataFileMetaWriteColsLegacySerializer`) and the
21-field layout (Java `DataFileMetaSerializer`) share slots 0..=19 and
differ only in arity, which the enclosing split's version selects. Only
the current layout is written, matching Java keeping its legacy
serializers deserialize-only.

The field is also decoded from manifest entries and declared in the
manifest Avro schema, so a file read from a manifest and handed on inside
a split no longer silently drops it.

Goldens come from the Java compatibility fixtures: `datasplit_v9.bin` is
the raw body of `compatibility/datasplit-v9`, and the two `split_v1_*.bin`
fixtures are refreshed from their Java counterparts, whose embedded
`DataSplit` is now version 9.
The three fixtures live behind the `fulltext` feature, so they were not
covered by a default-feature build.
@JunRuiLee
JunRuiLee marked this pull request as ready for review August 25, 2026 12:19
@JunRuiLee
JunRuiLee marked this pull request as draft August 25, 2026 12:26
The binding test pinned the emitted body version to 8.
Bound the array reservation by the remaining input: a declared element
count came straight from the manifest, so a corrupt one could ask for an
arbitrary allocation before the first element read failed.

Reject a union index other than 0 or 1 for the nullable array instead of
reading the following bytes as an array.

Reject a DataFileMeta row shorter than the fixed part of the layout it is
being read as, rather than letting the row constructor accept it.

Also correct a wrong claim in the row codec doc: Java's legacy
serializers do expose toRow, so they are not deserialize-only.
@JunRuiLee
JunRuiLee marked this pull request as ready for review August 25, 2026 13:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant