Skip to content

fix: DH-23629: Make an empty key-value partitioned write a no-op - #9060

Draft
lbooker42 wants to merge 2 commits into
deephaven:mainfrom
lbooker42:nightly/dh-23629-empty-partitioned-write
Draft

lbooker42 wants to merge 2 commits into
deephaven:mainfrom
lbooker42:nightly/dh-23629-empty-partitioned-write

Conversation

@lbooker42

Copy link
Copy Markdown
Contributor

ParquetTools.writeKeyValuePartitionedTable threw an ArrayIndexOutOfBoundsException with no useful message when the source table had no rows, or the partitioned table had no constituents. writeKeyValuePartitionedTableImpl builds one destination per constituent, an empty table yields no constituents, and writeTablesImpl picks its channels provider from destinations[0]. The pushdown fuzzer (DH-23557, finding 4) found the crash.

Changes

  • writeKeyValuePartitionedTableImpl returns before calling writeTablesImpl when there are no destinations. Nothing is written, not even the metadata files requested by generateMetadataFiles, and the destination directory is not created.
  • writeTablesImpl now requires at least one destination (Require.gtZero), so a zero-length destination array can no longer reach destinations[0] through any caller.
  • The Javadoc on both writeKeyValuePartitionedTable overloads documents the empty case, and the "Non-existing directories are created" promise now reads "when there is data to write".

Why a no-op rather than an exception

An empty table is a normal state: a day with no rows in a pipeline that partitions by day, or a PartitionedTable after an upstream filter. Throwing would force every caller to add an emptiness check, and a caller that forgets would fail on the first quiet day. An empty write over a populated directory leaves the existing data intact.

Not in this PR

Reading the empty result back still needs a TableDefinition in the read instructions, because the key-value layout records the schema only in the data files. DH-23638 follows up for the metadata-files case by writing schema-only _metadata and _common_metadata files.

@semanticdiff-com

semanticdiff-com Bot commented Oct 30, 2026 •

Copy link
Copy Markdown

Copilot AI 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.

Warning

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

Copilot review overview

3 open issues
What changed in this PR

Fixes writeKeyValuePartitionedTable crashing on empty inputs by making empty key-value partitioned writes a no-op and tightening internal preconditions.

Changes:

  • Add early return in writeKeyValuePartitionedTableImpl when there are no destinations/partitions to write.
  • Add Require.gtZero(destinations.length) in writeTablesImpl to prevent destinations[0] access on empty arrays.
  • Add/extend tests and Javadocs documenting the empty-write behavior and directory-creation semantics.
File Description
extensions/​parquet/​table/​src/​test/​java/​io/​deephaven/​parquet/​table/​ParquetTableReadWriteTest.java Adds regression tests covering empty key-value partitioned writes, metadata-file behavior, and overwriting semantics.
extensions/​parquet/​table/​src/​main/​java/​io/​deephaven/​parquet/​table/​ParquetTools.java Implements no-op behavior for empty destination sets, documents empty-write contract, and adds a defensive precondition in writeTablesImpl.

Review effort: Lite

Copilot AI 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.

🟢 Approval recommended

No active review issues remain for the changes to empty partitioned Parquet writes.

No open issues 🎉

3 resolved since last review

Review effort: Balanced

@github-actions

Copy link
Copy Markdown
Contributor

No docs changes detected for 67f6a43

@lbooker42

Copy link
Copy Markdown
Contributor Author

Test coverage of changes vs upstream/main

Files changed

File Lines Branches Changed lines
mod ParquetTools 422/445 (94%) 174/193 (90%) 3/3 (100%)

All new and modified files

0 new, 1 modified — lines 422/445 (94%), branches 174/193 (90%)

All new and modified lines

3 executable lines added or changed — 3/3 (100%) covered

Gaps

Every executable line the branch changed runs under the existing tests: the early return for a partitioned table with no constituents, with and without metadata files and over an existing directory, and the new Require.gtZero precondition in writeTablesImpl. The only path not taken is the precondition's failure branch, a defensive guard that no public entry point can reach: the key-value write now returns before calling writeTablesImpl with zero destinations, and the public writeTables already rejects an empty array up front.

Measured at 67f6a43e3 against main, over test and testOutOfBand in :extensions-parquet-table.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants