Skip to content

GH-50692: [C++][Parquet] treat negative null_count and distinct_count values as missing - #50694

Closed
HuaHuaY wants to merge 1 commit into
apache:mainfrom
HuaHuaY:negative_count
Closed

GH-50692: [C++][Parquet] treat negative null_count and distinct_count values as missing#50694
HuaHuaY wants to merge 1 commit into
apache:mainfrom
HuaHuaY:negative_count

Conversation

@HuaHuaY

@HuaHuaY HuaHuaY commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Rationale for this change

To prevent negative null_count and distinct_count values ​​from leading to incorrect statistics-based pruning, we had better to check for negative values.

What changes are included in this PR?

Modify ColumnIndex::Makeat cpp/src/parquet/page_index.cc and MakeTypedColumnStats at cpp/src/parquet/metadata.cc. When reading null_count and distinct_count from a file, we no longer silently assume that the values ​​are natural numbers.

Are these changes tested?

Yes.

Are there any user-facing changes?

No.

@HuaHuaY
HuaHuaY requested review from pitrou and wgtmac as code owners July 28, 2026 17:48
@github-actions

Copy link
Copy Markdown

⚠️ GitHub issue #50692 has been automatically assigned in GitHub to PR creator.

const ColumnDescriptor* descr,
::arrow::MemoryPool* pool) {
const auto& statistics = metadata.statistics;
const int64_t null_count = encoded_stats.has_null_count ? encoded_stats.null_count : 0;

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.

Why can't we directly use metadata.statistics?

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.

Because the values which metadata.statistics contains are the negative values. I want to use the values ​​modified in FromThrift.

}
}
if (stats.__isset.null_count) {
if (stats.__isset.null_count && stats.null_count >= 0) {

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 silently changes the public behavior that corrupted values are no longer visible to users from reading a file. I think we have a few options w.r.t. values in the stats and page indexes:

  1. Reject any corrupted values by throwing an exception (@etseidl has proposed this in another thread)
  2. Regard corrupted values as unset (this PR does).
  3. Preserve corrupted values but provide a Validate function or a function to fix the corrupted values.
  4. Do nothing so it is users' responsibility to check corrupted values and take action (ignore them or error out).

My understanding is that users have to validate these values before consumption anyway. In that case, an unset or corrupted value does not make too much difference. Users may still want to read the file even when there are corrupted stats (or even columns/row groups), e.g. recover corrupted/legacy files. So I think we shouldn't error out on invalid stats. Preserving corrupted values still bring some values like help inspecting the files so here might be the best place to fix this issue?

WDYT? @pitrou @mapleFU @emkornfield

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.

FYI:

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.

I see this was closed, but would just like to say that the situation here is a little different from arrow-rs. It seems arrow-cpp keeps the sign for null_count and nan_count, so returning the actual encoded value is probably the best thing to do. Let users decide what to make of that. arrow-rs, for unknown historical reasons, changes these fields to unsigned, so when a conversion to unsigned is not possible, the IMO most reasonable thing to do is return an error to let the user know something is wrong with the metadata. I don't think silently ignoring the error in that case is an option.

@github-actions github-actions Bot added awaiting committer review Awaiting committer review and removed awaiting review Awaiting review labels Jul 29, 2026
@pitrou

pitrou commented Jul 29, 2026

Copy link
Copy Markdown
Member

Why do we care about this? The null_count could be incorrect in other ways (for example larger than num_values or inconsistent with the actual def levels). Writing a negative value is quite unlikely compared to the subtler ways of writing an incorrect value.

The bottom line is that an incorrect statistic should not lead to a crash or UB, but it could lead to incorrect results when reading. There's nothing that we can reasonably do against that (the whole point of a statistic is to avoid reading all values, but verifying that a statistic is correct would require reading all values, defeating the point of a statistic).

@HuaHuaY

HuaHuaY commented Jul 29, 2026

Copy link
Copy Markdown
Contributor Author

Why do we care about this?

When I implement nan_count, I had to decide how to handle negative numbers. I checked the arrow-rs implementation and saw that they include error handling for negative numbers, which prompted this PR. I just wanted to clarify the expected behavior for negative numbers; I'm also fine with doing nothing about them.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants