Skip to content

Commit 8b5a6c9

Browse files
committed
fix decimal divide problem
Co-authored-by ZhangHuiGui <2689496754@qq.com> Co-authored-by laotan332 <qinpengxiang@outlook.com>
1 parent 41a989c commit 8b5a6c9

File tree

3 files changed

+39
-13
lines changed

3 files changed

+39
-13
lines changed

cpp/src/arrow/compute/expression_test.cc

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -944,6 +944,41 @@ TEST(Expression, ExecuteDictionaryTransparent) {
944944
])"));
945945
}
946946

947+
TEST(Expression, ExecuteDecimalDivide) {
948+
// GH-40911 Decimal divide promotion rule output wrong precision and scale
949+
// in expression Bind when scale1 >= scale2
950+
//
951+
// scale1 < scale2
952+
ExpectExecute(
953+
call("divide", {field_ref("a"), field_ref("b")}),
954+
ArrayFromJSON(struct_({field("a", decimal128(6, 1)), field("b", decimal128(7, 2))}),
955+
R"([
956+
{"a": "0.7", "b": "-2.17"},
957+
{"a": "2.9", "b": "9.11"},
958+
{"a": "3.1", "b" : "12.31"}
959+
])"));
960+
961+
// scale1 == scale2
962+
ExpectExecute(
963+
call("divide", {field_ref("a"), field_ref("b")}),
964+
ArrayFromJSON(struct_({field("a", decimal128(6, 1)), field("b", decimal128(6, 1))}),
965+
R"([
966+
{"a": "0.7", "b": "-2.1"},
967+
{"a": "2.9", "b": "9.1"},
968+
{"a": "3.1", "b" : "12.3"}
969+
])"));
970+
971+
// scale1 > scale2
972+
ExpectExecute(
973+
call("divide", {field_ref("a"), field_ref("b")}),
974+
ArrayFromJSON(struct_({field("a", decimal128(6, 2)), field("b", decimal128(6, 1))}),
975+
R"([
976+
{"a": "0.71", "b": "-2.1"},
977+
{"a": "2.92", "b": "9.1"},
978+
{"a": "3.17", "b" : "12.3"}
979+
])"));
980+
}
981+
947982
void ExpectIdenticalIfUnchanged(Expression modified, Expression original) {
948983
if (modified == original) {
949984
// no change -> must be identical

cpp/src/arrow/compute/kernels/codegen_internal.cc

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -428,13 +428,9 @@ Status CastBinaryDecimalArgs(DecimalPromotion promotion, std::vector<TypeHolder>
428428
right_scaleup = std::max(s1, s2) - s2;
429429
break;
430430
}
431-
case DecimalPromotion::kMultiply: {
432-
left_scaleup = right_scaleup = 0;
433-
break;
434-
}
431+
case DecimalPromotion::kMultiply:
435432
case DecimalPromotion::kDivide: {
436-
left_scaleup = std::max(4, s1 + p2 - s2 + 1) + s2 - s1;
437-
right_scaleup = 0;
433+
left_scaleup = right_scaleup = 0;
438434
break;
439435
}
440436
default:

cpp/src/arrow/compute/kernels/scalar_arithmetic.cc

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -541,13 +541,8 @@ Result<TypeHolder> ResolveDecimalDivisionOutput(KernelContext*,
541541
types,
542542
[](int32_t p1, int32_t s1, int32_t p2,
543543
int32_t s2) -> Result<std::pair<int32_t, int32_t>> {
544-
if (s1 < s2) {
545-
return Status::Invalid("Division of two decimal types scale1 < scale2. ", "(",
546-
s1, s2, ").");
547-
}
548-
DCHECK_GE(s1, s2);
549-
const int32_t scale = s1 - s2;
550-
const int32_t precision = p1;
544+
const int32_t scale = std::max(4, s1 + p2 - s2 + 1);
545+
const int32_t precision = p1 - s1 + s2 + scale;
551546
return std::make_pair(precision, scale);
552547
});
553548
}

0 commit comments

Comments
 (0)