Skip to content

MINOR: [C++] Fix is_null nan_is_null for dictionary-encoded float arrays - #51000

Draft
shoemoney wants to merge 2 commits into
apache:mainfrom
shoemoney:fix/arrow-isnull-dict
Draft

MINOR: [C++] Fix is_null nan_is_null for dictionary-encoded float arrays#51000
shoemoney wants to merge 2 commits into
apache:mainfrom
shoemoney:fix/arrow-isnull-dict

Conversation

@shoemoney

@shoemoney shoemoney commented Aug 25, 2026

Copy link
Copy Markdown

Rationale for this change

is_null(..., nan_is_null=true) did not detect NaN values in dictionary-encoded floating-point arrays. IsNullExec only checked the top-level type id for floating point, so dictionary-encoded arrays (type id DICTIONARY) skipped the NaN path entirely and NaN values in the dictionary were never marked null.

What changes are included in this PR?

  • Added SetNanBitsDictionary, a templated helper that iterates dictionary indices and checks the referenced dictionary entry for NaN, for float, double, and half-float value types.
  • Added DispatchIndexType to dispatch over all standard integer dictionary index types (int8/16/32/64, uint8/16/32/64), failing fast on an unrecognized index type instead of assuming int32.
  • Extended IsNullExec to detect a DICTIONARY type with floating-point values and nan_is_null=true, and dispatch to the new NaN detection path.
  • SetNanBitsDictionary skips null index slots before dereferencing the dictionary, since the indices buffer is not guaranteed initialized at null positions.

Are these changes tested?

Yes, with a test that fails against the prior behavior and passes with this fix.

Are there any user-facing changes?

Yes. is_null(..., nan_is_null=true) now correctly treats NaN values in dictionary-encoded float arrays as null.

Fix verified RED->GREEN. is_null with nan_is_null=True ignores NaN in dictionary-encoded float arrays at scalar_validity.cc:124
@shoemoney
shoemoney requested a review from pitrou as a code owner August 25, 2026 20:53
Copilot AI lite review requested due to automatic review settings August 25, 2026 20:53
@github-actions

Copy link
Copy Markdown

Thanks for opening a pull request!

This pull request has been automatically converted to a draft because its title doesn't match Arrow's required format.

If this is not a minor PR. Could you open an issue for this pull request on GitHub? https://github.com/apache/arrow/issues/new/choose

Opening GitHub issues ahead of time contributes to the Openness of the Apache Arrow project.

Then could you also rename the pull request title in the following format?

GH-${GITHUB_ISSUE_ID}: [${COMPONENT}] ${SUMMARY}

or

MINOR: [${COMPONENT}] ${SUMMARY}

After updating the title, you can mark the pull request as ready for review.

See also:

@github-actions
github-actions Bot marked this pull request as draft August 25, 2026 20:54

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.

Pull request overview

This PR fixes is_null(..., nan_is_null=true) for dictionary-encoded floating-point arrays by detecting NaN values in the dictionary and marking corresponding slots as null in the output.

Changes:

  • Added dictionary-aware NaN detection for is_null when nan_is_null is enabled.
  • Implemented templated helpers to dispatch over dictionary index integer types and float value types (float/double/half-float).
  • Added includes needed for dictionary type inspection and safe casting.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +154 to +156
default:
SetNanBitsDictionary<int32_t, ValueType>(arr, dict_span, out_bitmap, out_offset);
break;
Comment on lines +109 to +118
const IndexType* indices = arr.GetValues<IndexType>(1);
const ValueType* dict_values = dict_span.GetValues<ValueType>(1);
for (int64_t i = 0; i < arr.length; ++i) {
auto dict_index = indices[i];
bool is_nan;
if constexpr (std::is_same_v<ValueType, uint16_t>) {
is_nan = Float16::FromBits(dict_values[dict_index]).is_nan();
} else {
is_nan = std::isnan(dict_values[dict_index]);
}

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

Could you use the Arrow PR title template:-
GH-<Issue Number>: [<Component>] <Title>

If there isn't an existed issue, you can create a new one.

And could you use Arrow PR template for description

  • Rationale for this change
  • What changes are included in this PR?
  • Are these changes tested?
  • Are there any user-facing changes?

…index types

Skip null index slots in SetNanBitsDictionary before dereferencing the
dictionary to avoid out-of-bounds reads on arrays with nulls. Make the
default case in DispatchIndexType fail fast instead of silently
treating unknown index types as int32.
@shoemoney shoemoney changed the title fix(arrow): handle nan_is_null for dictionary-encoded floats MINOR: [C++] Fix is_null nan_is_null for dictionary-encoded float arrays Aug 27, 2026
@shoemoney

Copy link
Copy Markdown
Author

Updated the title and description to match the template, and fixed both issues from the review: null index slots are now skipped before dereferencing the dictionary, and the default case in the index-type dispatch fails fast instead of assuming int32.

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.

3 participants