Skip to content

GH-50338: [C++] Add ComputeLogicalNullCount to Datum#50347

Open
goel-skd wants to merge 2 commits into
apache:mainfrom
goel-skd:gh-50338-datum-compute-logical-null-count
Open

GH-50338: [C++] Add ComputeLogicalNullCount to Datum#50347
goel-skd wants to merge 2 commits into
apache:mainfrom
goel-skd:gh-50338-datum-compute-logical-null-count

Conversation

@goel-skd

@goel-skd goel-skd commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Rationale for this change

Datum::null_count() works on arrays, chunked arrays and scalars but ignores types whose logical nulls aren't in the top-level validity bitmap (union, run-end encoded, dictionary). ArrayData, ArraySpan, Array and ChunkedArray already expose ComputeLogicalNullCount(); Datum was the missing piece.

What changes are included in this PR?

Add Datum::ComputeLogicalNullCount(), delegating to ArrayData/ChunkedArray::ComputeLogicalNullCount() for array-like data and to a new Scalar::IsLogicalNull() for scalars.

Scalar::IsLogicalNull() returns !is_valid for most types (union and run-end encoded scalars already derive is_valid from their child). DictionaryScalar overrides it so a valid index pointing at a null dictionary value counts as null, matching dict_util::LogicalNullCount(); it reads the dictionary's validity directly (no encoded-scalar allocation) and falls back to !is_valid for ill-formed scalars. Like the array path, it does not recurse into nested (union/REE/extension-wrapped) values.

Are these changes tested?

Yes. Datum.ComputeLogicalNullCount covers scalars, null()-typed array/scalar, a bitmap array, sparse union, chunked union, run-end encoded and dictionary arrays, plus scalars extracted via Array::GetScalar(). Scalar::IsLogicalNull() is also tested directly across all dictionary index types, including the out-of-bounds fallback.

Are there any user-facing changes?

Adds Datum::ComputeLogicalNullCount() and Scalar::IsLogicalNull(); purely additive. The new virtual on Scalar is a C++ ABI change (do not backport to a patch release).

@goel-skd goel-skd requested a review from pitrou as a code owner July 2, 2026 22:09
@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown

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

@goel-skd goel-skd force-pushed the gh-50338-datum-compute-logical-null-count branch from 2e82f92 to 30f92df Compare July 2, 2026 22:35
Comment thread cpp/src/arrow/datum.cc Outdated
Comment thread cpp/src/arrow/datum.h
Comment thread cpp/src/arrow/datum_test.cc Outdated
Comment thread cpp/src/arrow/datum_test.cc
@github-actions github-actions Bot added awaiting committer review Awaiting committer review and removed awaiting review Awaiting review labels Jul 7, 2026
Comment thread cpp/src/arrow/scalar.cc
Comment on lines -781 to -817
switch (dict_type.index_type()->id()) {
case Type::UINT8:
index_value =
static_cast<int64_t>(checked_cast<const UInt8Scalar&>(*value.index).value);
break;
case Type::INT8:
index_value =
static_cast<int64_t>(checked_cast<const Int8Scalar&>(*value.index).value);
break;
case Type::UINT16:
index_value =
static_cast<int64_t>(checked_cast<const UInt16Scalar&>(*value.index).value);
break;
case Type::INT16:
index_value =
static_cast<int64_t>(checked_cast<const Int16Scalar&>(*value.index).value);
break;
case Type::UINT32:
index_value =
static_cast<int64_t>(checked_cast<const UInt32Scalar&>(*value.index).value);
break;
case Type::INT32:
index_value =
static_cast<int64_t>(checked_cast<const Int32Scalar&>(*value.index).value);
break;
case Type::UINT64:
index_value =
static_cast<int64_t>(checked_cast<const UInt64Scalar&>(*value.index).value);
break;
case Type::INT64:
index_value =
static_cast<int64_t>(checked_cast<const Int64Scalar&>(*value.index).value);
break;
default:
return Status::TypeError("Not implemented dictionary index type");
break;
}

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.

Did a small refactor while I was here!

goel-skd added 2 commits July 8, 2026 10:45
Datum::null_count() does not account for types that carry logical
nulls without a validity bitmap (union, dictionary and run-end
encoded types). Add Datum::ComputeLogicalNullCount(), delegating to
ArrayData::ComputeLogicalNullCount() and
ChunkedArray::ComputeLogicalNullCount() for array-like data; for
scalars, is_valid already reflects logical validity.
@goel-skd goel-skd force-pushed the gh-50338-datum-compute-logical-null-count branch from f6dbdc7 to ecb27c9 Compare July 8, 2026 14:47
@goel-skd

goel-skd commented Jul 9, 2026

Copy link
Copy Markdown
Contributor Author

@pitrou - the s3fs test times out. Seems unrelated to this change and an CI infra red herring!

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