Merge numeric types based on options. Returns nullptr for non-numeric types.
| 472 | |
| 473 | // Merge numeric types based on options. Returns nullptr for non-numeric types. |
| 474 | Result<std::shared_ptr<DataType>> MaybeMergeNumericTypes( |
| 475 | std::shared_ptr<DataType> promoted_type, std::shared_ptr<DataType> other_type, |
| 476 | const Field::MergeOptions& options) { |
| 477 | bool promoted = false; |
| 478 | if (options.promote_decimal_to_float) { |
| 479 | if (is_decimal(promoted_type->id()) && is_floating(other_type->id())) { |
| 480 | promoted_type = other_type; |
| 481 | promoted = true; |
| 482 | } else if (is_floating(promoted_type->id()) && is_decimal(other_type->id())) { |
| 483 | other_type = promoted_type; |
| 484 | promoted = true; |
| 485 | } |
| 486 | } |
| 487 | |
| 488 | if (options.promote_integer_to_decimal && |
| 489 | ((is_decimal(promoted_type->id()) && is_integer(other_type->id())) || |
| 490 | (is_decimal(other_type->id()) && is_integer(promoted_type->id())))) { |
| 491 | if (is_integer(promoted_type->id()) && is_decimal(other_type->id())) { |
| 492 | // Other type is always the int |
| 493 | promoted_type.swap(other_type); |
| 494 | } |
| 495 | ARROW_ASSIGN_OR_RAISE(const int32_t precision, |
| 496 | MaxDecimalDigitsForInteger(other_type->id())); |
| 497 | ARROW_ASSIGN_OR_RAISE(const auto promoted_decimal, |
| 498 | DecimalType::Make(promoted_type->id(), precision - 1, 0)); |
| 499 | ARROW_ASSIGN_OR_RAISE(promoted_type, |
| 500 | WidenDecimals(promoted_type, promoted_decimal, options)); |
| 501 | return promoted_type; |
| 502 | } |
| 503 | |
| 504 | if (options.promote_decimal && is_decimal(promoted_type->id()) && |
| 505 | is_decimal(other_type->id())) { |
| 506 | ARROW_ASSIGN_OR_RAISE(promoted_type, |
| 507 | WidenDecimals(promoted_type, other_type, options)); |
| 508 | return promoted_type; |
| 509 | } |
| 510 | |
| 511 | if (options.promote_integer_sign && ((is_unsigned_integer(promoted_type->id()) && |
| 512 | is_signed_integer(other_type->id())) || |
| 513 | (is_signed_integer(promoted_type->id()) && |
| 514 | is_unsigned_integer(other_type->id())))) { |
| 515 | if (is_signed_integer(promoted_type->id()) && is_unsigned_integer(other_type->id())) { |
| 516 | // Other type is always the signed int |
| 517 | promoted_type.swap(other_type); |
| 518 | } |
| 519 | |
| 520 | if (!options.promote_numeric_width && |
| 521 | bit_width(promoted_type->id()) < bit_width(other_type->id())) { |
| 522 | return Status::TypeError( |
| 523 | "Cannot widen signed integers without promote_numeric_width=true"); |
| 524 | } |
| 525 | int max_width = |
| 526 | std::max<int>(bit_width(promoted_type->id()), bit_width(other_type->id())); |
| 527 | |
| 528 | // If the unsigned one is bigger or equal to the signed one, we need another bit |
| 529 | if (bit_width(promoted_type->id()) >= bit_width(other_type->id())) { |
| 530 | ++max_width; |
| 531 | } |
no test coverage detected