Skip to content

Commit

Permalink
ARROW-7631: return zero if there is an overflow while downscaling a d… (
Browse files Browse the repository at this point in the history
apache#13)

* ARROW-7631: return zero if there is an overflow while downscaling a decimal

  - also add castDecimalNullOnOverflow function

* inline helper function
  • Loading branch information
pprudhvi authored Jan 21, 2020
1 parent 92f2900 commit 6608e91
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 4 deletions.
4 changes: 4 additions & 0 deletions cpp/src/gandiva/function_registry_arithmetic.cc
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ std::vector<NativeFunction> GetArithmeticFunctionRegistry() {
UNARY_SAFE_NULL_IF_NULL(castDECIMAL, {}, decimal128, decimal128),
UNARY_UNSAFE_NULL_IF_NULL(castDECIMAL, {}, utf8, decimal128),

NativeFunction("castDECIMALNullOnOverflow", {}, DataTypeVector{decimal128()},
decimal128(), kResultNullInternal,
"castDECIMALNullOnOverflow_decimal128"),

UNARY_SAFE_NULL_IF_NULL(castDATE, {}, int64, date64),

// add/sub/multiply/divide/mod
Expand Down
5 changes: 4 additions & 1 deletion cpp/src/gandiva/precompiled/decimal_ops.cc
Original file line number Diff line number Diff line change
Expand Up @@ -544,7 +544,10 @@ static BasicDecimal128 ModifyScaleAndPrecision(const BasicDecimalScalar128& x,
return x.value().IncreaseScaleBy(delta_scale);
} else {
// Do not do any rounding, that is handled by the caller.
return x.value().ReduceScaleBy(-delta_scale, false);
auto result = x.value().ReduceScaleBy(-delta_scale, false);
DECIMAL_OVERFLOW_IF(BasicDecimal128::Abs(result) > GetMaxValue(out_precision),
overflow);
return result;
}
}

Expand Down
35 changes: 32 additions & 3 deletions cpp/src/gandiva/precompiled/decimal_wrapper.cc
Original file line number Diff line number Diff line change
Expand Up @@ -229,14 +229,43 @@ void castDECIMAL_float32(float in, int32_t x_precision, int32_t x_scale,
}

FORCE_INLINE
void castDECIMAL_decimal128(int64_t x_high, uint64_t x_low, int32_t x_precision,
int32_t x_scale, int32_t out_precision, int32_t out_scale,
int64_t* out_high, int64_t* out_low) {
boolean castDecimal_return_overflow(int64_t x_high, uint64_t x_low, int32_t x_precision,
int32_t x_scale, int32_t out_precision,
int32_t out_scale, int64_t* out_high,
int64_t* out_low) {
gandiva::BasicDecimalScalar128 x({x_high, x_low}, x_precision, x_scale);
bool overflow = false;
auto out = gandiva::decimalops::Convert(x, out_precision, out_scale, &overflow);
*out_high = out.high_bits();
*out_low = out.low_bits();
return overflow;
}

FORCE_INLINE
void castDECIMAL_decimal128(int64_t x_high, uint64_t x_low, int32_t x_precision,
int32_t x_scale, int32_t out_precision, int32_t out_scale,
int64_t* out_high, int64_t* out_low) {
castDecimal_return_overflow(x_high, x_low, x_precision, x_scale, out_precision,
out_scale, out_high, out_low);
}

FORCE_INLINE
void castDECIMALNullOnOverflow_decimal128(int64_t x_high, uint64_t x_low,
int32_t x_precision, int32_t x_scale,
boolean x_isvalid, bool* out_valid,
int32_t out_precision, int32_t out_scale,
int64_t* out_high, int64_t* out_low) {
*out_valid = true;

if (!x_isvalid) {
*out_valid = false;
return;
}

if (castDecimal_return_overflow(x_high, x_low, x_precision, x_scale, out_precision,
out_scale, out_high, out_low)) {
*out_valid = false;
}
}

FORCE_INLINE
Expand Down

0 comments on commit 6608e91

Please sign in to comment.