Propagate delete file replication factor for Hadoop ORC files - #254
Merged
cbb330 merged 1 commit intoJul 14, 2026
Merged
Conversation
ORC.newFileWriter hands ORC the raw Hadoop FileSystem for HadoopOutputFile, so ORC's PhysicalFsWriter opens the stream itself with the filesystem default replication and the replication factor carried by Iceberg's HadoopOutputFile never applies. Route Hadoop output files with a custom replication factor through FileIOFSUtil.OutputFileSystem so the stream is created by Iceberg's HadoopOutputFile with the configured replication. Verified end-to-end through SQL-only Spark 3.5 tests: CREATE TABLE with merge-on-read ORC, INSERT, DELETE, and the delete_files metadata table, with the catalog warehouse on a capturing filesystem that records the replication factor passed to FileSystem.create. Covers the write.delete-file-replication table property and the spark.sql.iceberg.delete-file-replication session conf set via SQL SET (whose hyphenated key must be backquoted), and verifies data files keep the filesystem default. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
cbb330
approved these changes
Jul 14, 2026
cbb330
left a comment
Collaborator
There was a problem hiding this comment.
please bump in linkedin/openhouse and set up an e2e test using sparkitest within linkedin/openhouse after this merges
shanthoosh
pushed a commit
to shanthoosh/openhouse
that referenced
this pull request
Jul 14, 2026
… e2e tests Picks up com.linkedin.iceberg v1.5.2.17 (linkedin/iceberg#254), which propagates the delete file replication factor to ORC delete files. Adds spark-3.5 sparkitest coverage exercising the configuration through the full OpenHouse stack via SQL: the write.delete-file-replication table property round-trips through the tables service, and merge-on-read DELETE on an ORC table produces ORC position delete files through the replication-aware write path, for both the table property and the spark.sql.iceberg.delete-file-replication session conf routes. Verification is metadata-based (delete_files manifests) because the itest classpath mixes shaded and unshaded iceberg, which breaks ORC position delete reads with a TypeDescription ClassCastException. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
shanthoosh
pushed a commit
to shanthoosh/openhouse
that referenced
this pull request
Jul 14, 2026
… e2e tests Picks up com.linkedin.iceberg v1.5.2.17 (linkedin/iceberg#254), which propagates the delete file replication factor to ORC delete files. Adds spark-3.5 sparkitest coverage exercising the configuration through the full OpenHouse stack via SQL: the write.delete-file-replication table property round-trips through the tables service, and merge-on-read DELETE on an ORC table produces ORC position delete files through the replication-aware write path, for both the table property and the spark.sql.iceberg.delete-file-replication session conf routes. Verification is metadata-based (delete_files manifests) because the itest classpath mixes shaded and unshaded iceberg, which breaks ORC position delete reads with a TypeDescription ClassCastException. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
17 tasks
cbb330
pushed a commit
to linkedin/openhouse
that referenced
this pull request
Jul 14, 2026
## Summary Picks up com.linkedin.iceberg v1.5.2.17 (linkedin/iceberg#254), which propagates the delete file replication factor to ORC delete files. Adds spark-3.5 sparkitest coverage exercising the configuration through the full OpenHouse stack via SQL: the write.delete-file-replication table property round-trips through the tables service, and merge-on-read DELETE on an ORC table produces ORC position delete files through the replication-aware write path, for both the table property and the spark.sql.iceberg.delete-file-replication session conf routes. Verification is metadata-based (delete_files manifests) because the itest classpath mixes shaded and unshaded iceberg, which breaks ORC position delete reads with a TypeDescription ClassCastException. ## Changes - [ ] Client-facing API Changes - [ ] Internal API Changes - [ ] Bug Fixes - [X] New Features - [ ] Performance Improvements - [ ] Code Style - [ ] Refactoring - [ ] Documentation - [ ] Tests For all the boxes checked, please include additional details of the changes made in this pull request. ## Testing Done <!--- Check any relevant boxes with "x" --> - [x] Manually Tested on local docker setup. Please include commands ran, and their output. - [x] Added new tests for the changes made. - [x] Updated existing tests to reflect the changes made. - [x] No tests added or updated. Please explain why. If unsure, please feel free to ask for help. - [ ] Some other form of testing like staging or soak time in production. Please explain. For all the boxes checked, include a detailed description of the testing done for the changes made in this pull request. # Additional Information - [ ] Breaking Changes - [ ] Deprecations - [ ] Large PR broken into smaller PRs, and PR plan linked in the description. For all the boxes checked, include additional details of the changes made in this pull request. --------- Co-authored-by: Shanthoosh Pazhanjur Venkataraman <pvs@Shanthooshs-MacBook-Air.local> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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.
Problem Summary
PRs #219 and #229 added support for configuring the replication factor of delete files
(
delete-file-replicationwrite option,spark.sql.iceberg.delete-file-replicationsessionconf,
write.delete-file-replicationtable property). The configured value is resolvedcorrectly by
SparkWriteConfand carried all the way into Iceberg'sHadoopOutputFile, butfor ORC delete files it never reaches HDFS.
Root cause:
ORC.newFileWritershort-circuits Hadoop-backed output files by handing ORC theraw Hadoop
FileSystem:ORC's PhysicalFsWriter then opens the output stream itself via
fs.create(path, overwrite, bufferSize, fs.getDefaultReplication(path), blockSize)— using the filesystem default replication and discarding the replication factor carried by the Iceberg HadoopOutputFile. Iceberg's HadoopOutputFile.create(), the only place the configured replication is applied, is never invoked. As a result, merge-on-read DELETE/UPDATE/MERGE on ORC tables always produces delete files with the cluster default replication regardless of configuration.Solution
fs.create(...).Behavior is unchanged when no replication is configured: the raw-filesystem shortcut is still
used and files inherit the filesystem default.
Testing Done
Unit tests — orc:TestOrcReplication (new): writes through the plain ORC FileAppender and the position-delete writer against a RawLocalFileSystem subclass that records the replication factor passed to every FileSystem.create(...) call:
Integration tests (SQL-only) — spark 3.5:TestOrcDeleteFileReplication (new): the catalog warehouse lives on a capturing filesystem, and the whole flow is driven through
CREATE TABLE (format-version 2, merge-on-read, ORC) → INSERT → DELETE →
SELECT file_path FROM t.delete_files:
replication 5; data files keep the filesystem default; SELECT after DELETE return
rows (deletes apply on read)
spark.sql.iceberg.delete-file-replication=7 session conf → delete files cwith replication 7 (note: the hyphenated key must be backquoted in Spark SQL SET)