| 398 | } |
| 399 | |
| 400 | Status CastBinaryDecimalArgs(DecimalPromotion promotion, std::vector<TypeHolder>* types) { |
| 401 | const DataType& left_type = *(*types)[0]; |
| 402 | const DataType& right_type = *(*types)[1]; |
| 403 | DCHECK(is_decimal(left_type.id()) || is_decimal(right_type.id())); |
| 404 | |
| 405 | if ((is_decimal(left_type.id()) && !CastableToDecimal(right_type)) || |
| 406 | (is_decimal(right_type.id()) && !CastableToDecimal(left_type))) { |
| 407 | // If the other type is not castable to decimal, do not cast. The dispatch will |
| 408 | // gracefully fail by kernel selection. |
| 409 | return Status::OK(); |
| 410 | } |
| 411 | |
| 412 | // decimal + float64 = float64 |
| 413 | // decimal + float32 is roughly float64 + float32 so we choose float64 |
| 414 | if (is_floating(left_type.id()) || is_floating(right_type.id())) { |
| 415 | (*types)[0] = float64(); |
| 416 | (*types)[1] = float64(); |
| 417 | return Status::OK(); |
| 418 | } |
| 419 | |
| 420 | // precision, scale of left and right args |
| 421 | int32_t p1, s1, p2, s2; |
| 422 | |
| 423 | // decimal + integer = decimal |
| 424 | if (is_decimal(left_type.id())) { |
| 425 | const auto& decimal = checked_cast<const DecimalType&>(left_type); |
| 426 | p1 = decimal.precision(); |
| 427 | s1 = decimal.scale(); |
| 428 | } else { |
| 429 | DCHECK(is_integer(left_type.id())); |
| 430 | ARROW_ASSIGN_OR_RAISE(p1, MaxDecimalDigitsForInteger(left_type.id())); |
| 431 | s1 = 0; |
| 432 | } |
| 433 | if (is_decimal(right_type.id())) { |
| 434 | const auto& decimal = checked_cast<const DecimalType&>(right_type); |
| 435 | p2 = decimal.precision(); |
| 436 | s2 = decimal.scale(); |
| 437 | } else { |
| 438 | DCHECK(is_integer(right_type.id())); |
| 439 | ARROW_ASSIGN_OR_RAISE(p2, MaxDecimalDigitsForInteger(right_type.id())); |
| 440 | s2 = 0; |
| 441 | } |
| 442 | if (s1 < 0 || s2 < 0) { |
| 443 | return Status::NotImplemented("Decimals with negative scales not supported"); |
| 444 | } |
| 445 | |
| 446 | // decimal128 + decimal256 = decimal256 |
| 447 | Type::type casted_type_id = Type::DECIMAL128; |
| 448 | if (left_type.id() == Type::DECIMAL256 || right_type.id() == Type::DECIMAL256) { |
| 449 | casted_type_id = Type::DECIMAL256; |
| 450 | } |
| 451 | |
| 452 | // decimal promotion rules compatible with amazon redshift |
| 453 | // https://docs.aws.amazon.com/redshift/latest/dg/r_numeric_computations201.html |
| 454 | int32_t left_scaleup = 0; |
| 455 | int32_t right_scaleup = 0; |
| 456 | |
| 457 | switch (promotion) { |