Skip to content

[SPARK-58394][SQL] Use ZipFile instead of ZipArchiveInputStream for zip archives - #57588

Open
akshatshenoi-db wants to merge 2 commits into
apache:masterfrom
akshatshenoi-db:archive-zipfile
Open

[SPARK-58394][SQL] Use ZipFile instead of ZipArchiveInputStream for zip archives#57588
akshatshenoi-db wants to merge 2 commits into
apache:masterfrom
akshatshenoi-db:archive-zipfile

Conversation

@akshatshenoi-db

Copy link
Copy Markdown
Contributor

What changes were proposed in this pull request?

commons-compress recommends preferring the random-access ZipFile over the streaming ZipArchiveInputStream: the streaming reader parses local file headers sequentially (so it can return entries absent from the central directory, duplicate names, and incomplete metadata) and cannot handle STORED entries sized only by a trailing data descriptor. ZipFile reads the central directory first, giving correct metadata and reliable extraction across all compression methods.

This reuses the seekable-channel abstraction already built for 7z (HadoopSeekableByteChannel): openArchiveStream now returns an Iterator[(ArchiveEntry, InputStream)], letting each container expose its natural shape -- tar/7z advance one forward cursor, while zip serves each entry's own getInputStream from the central directory. ZipFile#canReadEntryData flags encrypted / unsupported-method entries with a clear CANNOT_READ_ZIP_ENTRY error. The tar and 7z paths are unchanged behaviorally.

This is part of the archive-reader series (SPARK-57135 CSV, SPARK-57321 CSV-infer, SPARK-57419 JSON, SPARK-57478 text, SPARK-57479 XML, SPARK-57481 Avro, SPARK-57705 zip container).

Why are the changes needed?

The streaming reader rejects valid zips -- notably STORED entries whose size lives only in a trailing data descriptor -- and exposes incomplete/duplicated entry metadata. Reading the central directory fixes both, and the per-entry byte offsets it exposes are a prerequisite for future zip parallelization.

Does this PR introduce any user-facing change?

Yes, gated by spark.sql.files.archive.reader.enabled (default false): zip archives that previously failed to read (e.g. a STORED entry sized by a trailing data descriptor) now read successfully.

How was this patch tested?

Updated SupportsArchiveFormatSuite: the previously-non-streamable STORED+data-descriptor zip now reads successfully (assertion flipped); added duplicate-name, encrypted-entry (asserting CANNOT_READ_ZIP_ENTRY via checkError), and corrupt-archive cases. The existing tar and 7z cases are unchanged.

Was this patch authored or co-authored using generative AI tooling?

Generated-by: Claude Code

…ip archives

commons-compress recommends preferring the random-access `ZipFile` over the
streaming `ZipArchiveInputStream`: the streaming reader parses local file
headers sequentially (so it can return entries absent from the central
directory, duplicate names, and incomplete metadata) and cannot handle STORED
entries sized only by a trailing data descriptor. `ZipFile` reads the central
directory first, giving correct metadata and reliable extraction across all
compression methods.

This reuses the seekable-channel abstraction already built for 7z
(`HadoopSeekableByteChannel`): `openArchiveStream` now returns an
`Iterator[(ArchiveEntry, InputStream)]`, letting each container expose its
natural shape -- tar/7z advance one forward cursor; zip serves each entry's own
`getInputStream` from the central directory. `ZipFile#canReadEntryData` flags
encrypted / unsupported-method entries with a clear `CANNOT_READ_ZIP_ENTRY`
error. The tar and 7z paths are unchanged behaviorally.

### Why are the changes needed?
Correctly reads STORED-with-data-descriptor zips and other zips the streaming
reader rejects, and yields correct per-entry metadata (a prerequisite for future
zip parallelization via per-entry central-directory offsets).

### Does this PR introduce any user-facing change?
Yes, gated by `spark.sql.files.archive.reader.enabled` (default false): zip
archives that previously failed to read (e.g. STORED with a data descriptor) now
read successfully.

### How was this patch tested?
Updated `SupportsArchiveFormatSuite`: the previously-non-streamable
STORED+data-descriptor zip now reads successfully; added duplicate-name,
encrypted-entry (`CANNOT_READ_ZIP_ENTRY`), and corrupt-archive cases.

### Was this patch authored or co-authored using generative AI tooling?
Generated-by: Claude Code
…ding

Self-review fixes: TaskContextImpl takes cpuAmount (not the DBR-only cpus) in
OSS, and the ArchiveEntries scaladoc now says (entry, stream) to match the type.
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