Skip to content

[C++] DCHECK_EQ failed in ResolveDecimalAdditionOrSubtractionOutput function when execute two different decimal scale arrays' add  #40126

Description

@ZhangHuiGui

Describe the bug, including details regarding any error messages, version, and platform.

How to reproduce

Add two different precision and scale decimal arrays through expression.

 auto expr=arrow::compute::call("add", {arrow::compute::field_ref("l1"),
arrow::compute::field_ref("r1")});
auto s1=arrow::schema({arrow::field("l1", arrow::decimal128(30, 3)),
arrow::field("r1", arrow::decimal128(20, 9))});
ASSERT_OK_AND_ASSIGN(expr, expr.Bind(*s1)); // crash
auto b=arrow::RecordBatchFromJSON(s1, R"([
["1.000", "-1.000000000"],
["-123456789012345678901234567.890", "12345678901.234567890"]
])");ASSERT_OK_AND_ASSIGN(autoinput, arrow::compute::MakeExecBatch(*s1, b));
ASSERT_OK_AND_ASSIGN(autores_dat,
arrow::compute::ExecuteScalarExpression(expr, input));

The test will crash at below function's DCHECK_EQ because the input types' scale is different during arrow::compute::Expression::Bind.

Result<TypeHolder>ResolveDecimalAdditionOrSubtractionOutput(
KernelContext*, conststd::vector<TypeHolder>&types) {
returnResolveDecimalBinaryOperationOutput(
types, [](int32_tp1, int32_ts1, int32_tp2, int32_ts2) {
DCHECK_EQ(s1, s2);
constint32_tscale=s1;
constint32_tprecision=std::max(p1-s1, p2-s2) +scale+1;
returnstd::make_pair(precision, scale);
});
}

The CallFunction is correct.

Reason

The expression's bind function will skip DispatchBest in BindNonRecursive. Because DispatchExact will return ok and skip the DispatchBest which overrided by ArithmeticFunction.

// First try and bind exactlyResult<constKernel*>maybe_exact_match=call.function->DispatchExact(types);
if (maybe_exact_match.ok()) {
call.kernel=*maybe_exact_match;
}

So the implicit cast in ArithmeticFunction::DispatchBest for decimal will be skipped.

But the logic is correct in CallFunction which will call DispatchBest first.
If we want to let user do cast by theirselves in expression call, we should return an error if we checked current situation? Or return not-ok in DispatchExact for decimal special case?

Component(s)

C++

Activity

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

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions