Skip to content

GH-41011: [C++][Compute] Fix the issue that comparison function could not handle decimal arguments with different scales#47459

Merged
zanmato1984 merged 4 commits intoapache:mainfrom
zanmato1984:fix/gh-41011
Sep 4, 2025
Merged

GH-41011: [C++][Compute] Fix the issue that comparison function could not handle decimal arguments with different scales#47459
zanmato1984 merged 4 commits intoapache:mainfrom
zanmato1984:fix/gh-41011

Conversation

@zanmato1984
Copy link
Contributor

@zanmato1984 zanmato1984 commented Aug 29, 2025

Rationale for this change

We used to be not able to suppress the exact matching for decimal arguments with different scales, when a decimal comparison kernel who actually requires the scales to be the same. This caused issue like #41011.

The "match constraint" introduced in #47297 is exactly for fixing issues like this, by simply adding a proper constraint.

What changes are included in this PR?

Added match constraint that requires all decimal inputs have the same scale (like for decimal addition and subtract).

Are these changes tested?

Yes.

Are there any user-facing changes?

None.

auto exec = GenerateDecimal<applicator::ScalarBinaryEqualTypes, BooleanType, Op>(id);
DCHECK_OK(
func->AddKernel({InputType(id), InputType(id)}, boolean(), std::move(exec)));
DCHECK_OK(func->AddKernel({InputType(id), InputType(id)}, boolean(), std::move(exec),
Copy link
Contributor Author

@zanmato1984 zanmato1984 Aug 29, 2025

Choose a reason for hiding this comment

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

Yep, the fix is as simple as this. Thanks to #47297.

Comment on lines 716 to 740
// decimal int
ExpectBindsTo(cmp(field_ref("dec128_3_2"), field_ref("i64")),
cmp(field_ref("dec128_3_2"), cast(field_ref("i64"), decimal128(21, 2))),
/*bound_out=*/nullptr, *exciting_schema);
ExpectBindsTo(cmp(field_ref("i64"), field_ref("dec128_3_2")),
cmp(cast(field_ref("i64"), decimal128(21, 2)), field_ref("dec128_3_2")),
/*bound_out=*/nullptr, *exciting_schema);

// decimal128 decimal256 with different scales
ExpectBindsTo(
cmp(field_ref("dec128_3_2"), field_ref("dec256_5_3")),
cmp(cast(field_ref("dec128_3_2"), decimal256(4, 3)), field_ref("dec256_5_3")),
/*bound_out=*/nullptr, *exciting_schema);
ExpectBindsTo(
cmp(field_ref("dec256_5_3"), field_ref("dec128_3_2")),
cmp(field_ref("dec256_5_3"), cast(field_ref("dec128_3_2"), decimal256(4, 3))),
/*bound_out=*/nullptr, *exciting_schema);
ExpectBindsTo(cmp(field_ref("dec128_5_3"), field_ref("dec256_3_2")),
cmp(cast(field_ref("dec128_5_3"), decimal256(5, 3)),
cast(field_ref("dec256_3_2"), decimal256(4, 3))),
/*bound_out=*/nullptr, *exciting_schema);
ExpectBindsTo(cmp(field_ref("dec256_3_2"), field_ref("dec128_5_3")),
cmp(cast(field_ref("dec256_3_2"), decimal256(4, 3)),
cast(field_ref("dec128_5_3"), decimal256(5, 3))),
/*bound_out=*/nullptr, *exciting_schema);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

These cases will actually pass w/o this fix. Just added them for intact coverage of all decimal casting paths.

Comment on lines 742 to 750
// decimal decimal with different scales
ExpectBindsTo(
cmp(field_ref("dec128_3_2"), field_ref("dec128_5_3")),
cmp(cast(field_ref("dec128_3_2"), decimal128(4, 3)), field_ref("dec128_5_3")),
/*bound_out=*/nullptr, *exciting_schema);
ExpectBindsTo(
cmp(field_ref("dec128_5_3"), field_ref("dec128_3_2")),
cmp(field_ref("dec128_5_3"), cast(field_ref("dec128_3_2"), decimal128(4, 3))),
/*bound_out=*/nullptr, *exciting_schema);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

These two will fail w/o the fix.

@github-actions github-actions bot added awaiting committer review Awaiting committer review and removed awaiting review Awaiting review labels Aug 29, 2025
@zanmato1984
Copy link
Contributor Author

@pitrou pretty easy fix (thanks to #47297), mind to take a look? Thanks.

}

TEST(Expression, BindWithImplicitCasts) {
auto exciting_schema = schema(
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Get excited one more time! @pitrou

Copy link
Member

Choose a reason for hiding this comment

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

My head spins.

cmp(cast(field_ref("i64"), decimal128(21, 2)), field_ref("dec128_3_2")),
/*bound_out=*/nullptr, *exciting_schema);

// decimal128 decimal256 with different scales
Copy link
Member

Choose a reason for hiding this comment

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

What happens with the same scale and different precisions, btw? Ideally no cast would occur since the raw values can be compared directly, but regardless we might add tests for that situation as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You are right, no casts applied for different precisions but same scale.

Added the cases. Thank you!

Copy link
Member

@pitrou pitrou left a comment

Choose a reason for hiding this comment

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

LGTM on the principle, some small suggestions

@zanmato1984
Copy link
Contributor Author

I'll merge. Thanks for reviewing @pitrou !

@zanmato1984 zanmato1984 merged commit 2987165 into apache:main Sep 4, 2025
39 checks passed
@zanmato1984 zanmato1984 removed the awaiting committer review Awaiting committer review label Sep 4, 2025
@conbench-apache-arrow
Copy link

After merging your PR, Conbench analyzed the 4 benchmarking runs that have been run so far on merge-commit 2987165.

There weren't enough matching historic benchmark results to make a call on whether there were regressions.

The full Conbench report has more details.

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.

2 participants