Skip to content

Core, Parquet: Fix null counting for parquet that doesn't have null_count stats - #17557

Merged
RussellSpitzer merged 6 commits into
apache:mainfrom
xndai:fix-parquet-missing-null-count
Sep 11, 2026
Merged

Core, Parquet: Fix null counting for parquet that doesn't have null_count stats#17557
RussellSpitzer merged 6 commits into
apache:mainfrom
xndai:fix-parquet-missing-null-count

Conversation

@xndai

@xndai xndai commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Parquet's Statistics#getNumNulls returns -1 when null_count is missing from the stats. But our current metrics logic doesn't handle this -1 value specifically, instead it just adds to the existing count.

For a single row group the -1 total was dropped because Metrics only keeps non-negative counts. But say we have row group 0 that has one null value and row group 1 doesn't have null_count stats and return -1, we end up counting total null count as 0, which is wrong. A query engine that relays on total null count being 0, can skip the file completely when evaluating predicate like WHERE c IS NULL causing wrong results.

Fix by checking the -1 when sum the nulls. Add corresponding tests.

@xndai

xndai commented Aug 8, 2026

Copy link
Copy Markdown
Contributor Author

Issue #17558

@anoopj anoopj left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The core code change looks good to me. This is an important correctness fix - thanks for catching this!

I have a couple of comments on tests.

Comment thread parquet/src/test/java/org/apache/iceberg/parquet/TestParquetMissingNullCount.java Outdated
@singhpk234 singhpk234 added this to the Iceberg 1.12.0 milestone Aug 11, 2026

@singhpk234 singhpk234 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.

Thanks for fix @xndai, I added this to 1.12 milestone too keep track of it

Comment thread parquet/src/test/java/org/apache/iceberg/parquet/TestParquetMissingNullCount.java Outdated
// without accounting for the -1 sentinel, this sums to an incorrect null count of 0
Metrics metrics = metrics(block(statsWithoutNullCount(1, 10), 10), block(stats(20, 30, 1), 10));

assertThat(metrics.nullValueCounts()).doesNotContainKey(1);

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.

should we instead assert what the val returned is ? -1 right ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The -1 is returned from Statistics.getNumNulls() as an internal sentinel to represent unknown state. But when the null count is stored into Metrics, -1 is dropped so here we assert the null value count is unavailable in the map.

@xndai

xndai commented Aug 11, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for fix @xndai, I added this to 1.12 milestone too keep track of it

No problem. please also track #17560 - another correctness issue regarding null count.

@xndai

xndai commented Aug 25, 2026

Copy link
Copy Markdown
Contributor Author

@singhpk234 can you please review again?

@nssalian
nssalian requested review from anoopj and singhpk234 August 26, 2026 15:50
Comment thread parquet/src/test/java/org/apache/iceberg/parquet/TestParquetMissingNullCount.java Outdated
Comment thread parquet/src/test/java/org/apache/iceberg/parquet/TestParquetMissingNullCount.java Outdated
Comment thread parquet/src/test/java/org/apache/iceberg/parquet/TestParquetMissingNullCount.java Outdated

@RussellSpitzer RussellSpitzer left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This looks good to me but I have a few blockers on the test layout. Let's fix that up and we can merge this in

@uros-b uros-b left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

PR title still seems cut-off @xndai

Core, Parquet: Fix null counting for parquet that doesn't have null_c…

@nssalian

nssalian commented Sep 8, 2026

Copy link
Copy Markdown
Collaborator

@xndai do you have some time to address the pending comments. It would be great to get this in the release.

Comment thread parquet/src/test/java/org/apache/iceberg/parquet/TestParquetMissingNullCount.java Outdated
…ount stats

Parquet's Statistics#getNumNulls returns -1 when null_count is missing
from the stats. But our current metrics logic doesn't handle this -1
value specifically, instead it just adds to the existing count.

For a single row group the -1 total was dropped because Metrics only
keeps non-negative counts. But say we have row group 0 that has one null
value and row group 1 doesn't have null_count stats and return -1, we end up
counting total null count as 0, which is wrong. A query engine that
relys on total null count being 0, can skip the file completely when
evaluating predicate like `WHERE c IS NULL` causing wrong results.

Fix by checking the -1 when sum the nulls. Add corresponding tests.
Address review feedback: the manifest round-trip test does not need the
filesystem. Use InMemoryOutputFile and InMemoryFileIO instead of a temp
directory, following TestVariantMetrics.
Address review feedback: the variant metrics paths handle a missing
null_count too, but had no test for it. Add cases that build a two row
group footer where one row group omits the variant column's null_count,
covering both the footer null count path and the all-null-variant path
that uses the value count instead.
Address review feedback: follow the convention of omitting the redundant
"test" prefix on test method names.
Address review feedback: relocate the missing null_count tests into
TestParquet, alongside testMetricsMissingColumnStatisticsInRowGroups
which has the same shape. Drop knownNullCountsAreSummed and
missingNullCountIsNotWrittenToManifest, which duplicate coverage in
TestMetrics and TestManifestWriterVersions, and remove the now-empty
TestParquetMissingNullCount class.
@xndai
xndai force-pushed the fix-parquet-missing-null-count branch from 111d68b to 4c7433d Compare September 9, 2026 17:54
@xndai xndai changed the title Core, Parquet: Fix null counting for parquet that doesn't have null_c… Core, Parquet: Fix null counting for parquet that doesn't have null_count stats Sep 9, 2026
@xndai

xndai commented Sep 9, 2026

Copy link
Copy Markdown
Contributor Author

PR title still seems cut-off @xndai

Core, Parquet: Fix null counting for parquet that doesn't have null_c…

fixed.

Comment thread parquet/src/test/java/org/apache/iceberg/parquet/TestVariantMetrics.java Outdated

@uros-b uros-b left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thank you @xndai for working on this and addressing all comments so far!

@xndai

xndai commented Sep 10, 2026

Copy link
Copy Markdown
Contributor Author

@xndai do you have some time to address the pending comments. It would be great to get this in the release.

thanks for review. I see this PR is approved. I will send out a small follow up PR to address your comments.

@RussellSpitzer

Copy link
Copy Markdown
Member

Please address @nssalian's comments if they are valid. We try to get consensus before merging especially for folks who have been reviewing the PR since the beginning. If you think they aren't worth addressing we can close them, but if they are then let's just patch them right now.

@nssalian nssalian left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Should have mentioned those are non-blocking mostly cleanup related. Everything else does look good. @xndai if you want to clean it up here that works just want to make sure we are not leaving the tests with a lot of duplication. In the past I've cleaned up a bunch of the variant related tests as we go.

Address review feedback: extract a shared writeVariants helper so the
variant write helpers no longer repeat the Parquet.write build and record
loop, and tighten a comment on the shredded null-count test.
@RussellSpitzer
RussellSpitzer merged commit 53d0e73 into apache:main Sep 11, 2026
42 checks passed
@RussellSpitzer

Copy link
Copy Markdown
Member

Merged, Thanks @xndai for the PR and @anoopj , @nssalian , @uros-b , @nandorKollar for reviewing!

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.

7 participants