Skip to content

[C++] Why arrow decimal divide precision and scale is not correct? #39875

@godliness

Description

@godliness

Describe the usage question you have. Please include as many useful details as possible.

select 1.00/id from test;

id is decimal(15,2) which is  16906.24
1.00 is decimal(3,2)
but the result is decimal(3, 0);

code is that


expr: 1727_2arrowfunc_divide(1.00, 0)

ARROW_ASSIGN_OR_RAISE(auto res, arrow::compute::ExecuteScalarExpression(
                                            expr, arrow::compute::ExecBatch(*batch), &exec_context));

before we execute the scalar, we will bind the expr, it always go to the DispatchExct step not DispatchBest

image

and this

#0  arrow::compute::internal::(anonymous namespace)::ResolveDecimalDivisionOutput (types=std::vector of length -3918358451798, capacity 157086 = {...}) at /home/gpadmin/Projects/arrow/cpp/src/arrow/compute/kernels/scalar_arithmetic.cc:528
#1  0x00007f6374e52f29 in arrow::compute::OutputType::Resolve (this=0x558788ba0d58, ctx=0x7fffed4eb580, types=std::vector of length 2, capacity 2 = {...}) at /home/gpadmin/Projects/arrow/cpp/src/arrow/compute/kernel.cc:447
#2  0x00007f6374e1067d in arrow::compute::(anonymous namespace)::BindNonRecursive (call=..., insert_implicit_casts=true, exec_context=0x7fffed4eba70) at /home/gpadmin/Projects/arrow/cpp/src/arrow/compute/expression.cc:587
#3  0x00007f6374e1e0ba in arrow::compute::(anonymous namespace)::BindImpl<arrow::Schema> (expr=..., in=..., exec_context=0x7fffed4eba70) at /home/gpadmin/Projects/arrow/cpp/src/arrow/compute/expression.cc:619
#4  0x00007f6374e1db20 in arrow::compute::(anonymous namespace)::BindImpl<arrow::Schema> (expr=..., in=..., exec_context=0x0) at /home/gpadmin/Projects/arrow/cpp/src/arrow/compute/expression.cc:598
#5  0x00007f6374e10b6b in arrow::compute::Expression::Bind (this=0x558788f60570, in_schema=..., exec_context=0x0) at /home/gpadmin/Projects/arrow/cpp/src/arrow/compute/expression.cc:631

looks like it's follow the rule that is
rule1

Result<TypeHolder> ResolveDecimalDivisionOutput(KernelContext*,
                                                const std::vector<TypeHolder>& types) {
  return ResolveDecimalBinaryOperationOutput(
      types, [](int32_t p1, int32_t s1, int32_t p2, int32_t s2) {
        DCHECK_GE(s1, s2);
        const int32_t scale = s1 - s2;
        const int32_t precision = p1;
        return std::make_pair(precision, scale);
      });
}

but the document is show that
rule 2:

scale = max(4, s1 + p2 - s2 + 1)
precision = p1 - s1 + s2 + scale

How could i use the second rule?

Component(s)

C++

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions