[SPARK-58382][SQL] binaryFile archive support via wholeFile option - #57578
Open
akshatshenoi-db wants to merge 2 commits into
Open
[SPARK-58382][SQL] binaryFile archive support via wholeFile option#57578akshatshenoi-db wants to merge 2 commits into
akshatshenoi-db wants to merge 2 commits into
Conversation
Let format("binaryFile") read tar/zip/7z archives, gated by a new `wholeFile`
option (default true) and the existing spark.sql.files.archive.reader.enabled
flag. Extends the archive-reader series (SPARK-57135 CSV, SPARK-57419 JSON,
SPARK-57478 text, SPARK-57479 XML, SPARK-57481 Avro).
- wholeFile=true (default): the whole archive is one record -- unchanged
non-archive behavior.
- wholeFile=false: one row per inner entry; `content` is the entry's unpacked
bytes, `path` is `<archive>!/<entryName>`, `length` is the entry's size, and
`modificationTime` is the parent archive's (entry timestamps are optional).
BinaryFileFormat mixes in SupportsArchiveFormat and, on the wholeFile=false
archive path, reads each entry via readArchiveEntries, building one row per
entry from a synthetic per-entry FileStatus through the shared `parse`. The
readArchiveEntries callback now receives the ArchiveEntry (not just its name)
so consumers can read the entry's size; the CSV and localizeEntries callers are
updated accordingly.
New BinaryFileArchiveReadBase with BinaryFileTarArchiveReadSuite /
BinaryFileZipArchiveReadSuite / BinaryFileSevenZArchiveReadSuite. The per-entry
`length` tests are skipped for zip: streaming ZipArchiveInputStream reports an
entry sized by a trailing data descriptor as -1, so they are gated on
`entrySizeKnown` and re-enable when zip reads move to ZipFile.
Generated-by: Claude Code
Contributor
Author
|
This PR's |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changes were proposed in this pull request?
This PR lets
format("binaryFile")read tar/zip/7z archives, extending the archive-readerseries (SPARK-57135 CSV, SPARK-57419 JSON, SPARK-57478 text, SPARK-57479 XML, SPARK-57481 Avro).
It is gated by a new binaryFile option
wholeFile(defaulttrue) and the existingspark.sql.files.archive.reader.enabledflag (defaultfalse).wholeFile=true(default): the archive is read as a single record (its raw bytes) -- unchangedfrom today's non-archive behavior.
wholeFile=false: one row is emitted per inner entry.contentholds the entry's unpackedbytes,
pathis<archive>!/<entryName>,lengthis the entry's size, andmodificationTimeis the parent archive's (archive entry timestamps are optional, so the parent's is used).
BinaryFileFormatmixes inSupportsArchiveFormat. On thewholeFile=falsearchive path itstreams each entry via
SupportsArchiveFormat.readArchiveEntriesand builds one row per entry froma synthetic per-entry
FileStatus, reusing the same row-builder (BinaryFileFormat.parse) as thenon-archive path so length/modtime filter pushdown applies per entry.
To expose the entry's size to consumers, the
readArchiveEntriesparseEntrycallback nowreceives the
ArchiveEntryinstead of just the entry name; the existing CSV andlocalizeEntriescallers are updated to read
entry.getName.Known limitation (zip, until
ZipFile): the streamingZipArchiveInputStreamreports an entry'sgetSizeas-1when the size is only in a trailing data descriptor, so for such entries theper-entry
lengthcolumn is-1and thespark.sql.sources.binaryFile.maxLengthguard(
status.getLen > maxLength) is skipped, i.e. the entry is read unbounded. tar and 7z report realsizes and are unaffected. This closes when zip reads move to
ZipFile, which exposes entry sizesfrom the central directory up front.
Why are the changes needed?
binaryFile is the natural way to ingest opaque/blob files, and archives (tar/zip/7z) are a common
packaging for large numbers of such files. This lets an archive be read as a directory of its
entries without unpacking it to disk first, completing the archive-reader feature across the
file-based formats.
Does this PR introduce any user-facing change?
Yes, gated behind
spark.sql.files.archive.reader.enabled(defaultfalse). When enabled,spark.read.format("binaryFile").option("wholeFile", "false").load(<archive>)returns one row perinner entry. With the flag off, or with
wholeFile=true(the default), behavior is unchanged.How was this patch tested?
New
BinaryFileArchiveReadBasewithBinaryFileTarArchiveReadSuite,BinaryFileZipArchiveReadSuite, andBinaryFileSevenZArchiveReadSuite, covering: whole-file vsper-entry reads, per-entry content/path/length, empty archives, hidden-entry skipping,
spark.sql.sources.binaryFile.maxLengthenforcement, length filter pushdown, single-partitionscans, and corrupt-archive handling under
ignoreCorruptFiles. The per-entrylengthassertionsare skipped for zip because the streaming
ZipArchiveInputStreamreports a data-descriptor entry'ssize as
-1; they re-enable when zip reads move toZipFile.Was this patch authored or co-authored using generative AI tooling?
Generated-by: Claude Code