Skip to content

Read manifests with V3 projection - #3690

Merged
Fokko merged 4 commits into
apache:mainfrom
KaiqiJinWow:fix-v3-manifest-read-projection
Aug 31, 2026
Merged

Read manifests with V3 projection#3690
Fokko merged 4 commits into
apache:mainfrom
KaiqiJinWow:fix-v3-manifest-read-projection

Conversation

@KaiqiJinWow

@KaiqiJinWow KaiqiJinWow commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Rationale for this change

V3 manifest schemas are defined, but manifest entries and manifest lists are still read with the V2 projection. Avro schema resolution therefore drops V3-only fields such as first_row_id, referenced_data_file, content_offset, and content_size_in_bytes before they reach DataFile and ManifestFile.

Use V3 as the default read and in-memory projection. V1 and V2 writers continue to use their version-specific file schemas, and older manifests remain compatible because missing V3 fields resolve to null.

This isolates the read-side concern raised in #3624 from its V3 writer work and is a prerequisite for #3478 to consume deletion-vector content ranges from catalog manifests.

Are these changes tested?

Yes.

  • Added V3 manifest-entry round trips covering all four V3 data-file fields.
  • Added a V3 manifest-list round trip covering first_row_id.
  • Extended the V1 and V2 compatibility tests to verify V3 fields resolve to null and are not written into older manifest formats.
  • Ran pytest tests/avro/test_file.py tests/utils/test_manifest.py: 50 passed.
  • Ran the available table test suite: 293 passed; tests requiring unavailable optional datafusion and pyiceberg-core extras were excluded.
  • Ran Ruff format and lint checks for the changed files.
  • Manually validated the read path against an Iceberg 1.10 V3 manifest containing a deletion-vector content range.

Are there any user-facing changes?

No. This fixes internal manifest deserialization and prepares V3 read support without changing behavior for currently supported V1 and V2 tables.

Read manifest entries and manifest lists with the latest supported schema so V3-only fields are retained while older manifests resolve missing fields to null.
Exclude V3-only properties from V1 and V2 fastavro comparisons and clarify the latest read-version constant name.
Exclude V3-only properties from the reflected V2 manifest dictionary used by the REST integration test.

@Fokko Fokko left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think the right approach would be to bump DEFAULT_READ_VERSION instead of introducing _LATEST_MANIFEST_READ_VERSION. Having the two introduces complexity that we want to avoid. When we have the versions aligned, then the projection should populate all the fields (and fill in None for ≤V2).

Comment thread pyiceberg/manifest.py Outdated
@kevinjqliu
kevinjqliu self-requested a review August 4, 2026 16:25
@KaiqiJinWow
KaiqiJinWow requested a review from Fokko August 6, 2026 21:30
@KaiqiJinWow

Copy link
Copy Markdown
Contributor Author

Hi @Fokko @kevinjqliu would you mind taking another look when you have time? Thanks!

winding-lines added a commit to magmalake/magmalake.org that referenced this pull request Aug 31, 2026
The correctness section claimed this work "surfaced upstream bugs in
PyIceberg, pyarrow and iceberg-rust" without saying which, or where.

Each disagreement has now been reduced to a standalone reproducer with no
magmalake code in it. Two turned out to be unreported and were filed:

- apache/arrow#51097 — the Parquet writer undercounts nulls for a
  fixed-width leaf under list<struct> when some lists are null or empty,
  while the BYTE_ARRAY leaf beside it is correct.
- apache/iceberg-rust#3118 — an In predicate whose literals straddle a
  file's bounds is never pruned, because each bound is tested against the
  whole literal set rather than narrowing it.

Three were already open upstream and are linked rather than duplicated:
apache/iceberg-python#3690, #3620 and #3833.

Two earlier candidates are dropped from the list. pyarrow reporting
LZ4_RAW as "LZ4" and deriving no ConvertedType for a non-UTC timestamp
are both deliberate API behaviour, not defects.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015or6oTZmb7EQTXTbALbBXY

@Fokko Fokko left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Clean and crisp, I love it! Thanks @KaiqiJinWow 🙌

@Fokko
Fokko merged commit 2dd080e into apache:main Aug 31, 2026
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.

2 participants