From 9d9dd6d6e0893a93c5019afb87ca7bb218c98903 Mon Sep 17 00:00:00 2001 From: Jin Chengcheng Date: Tue, 4 Apr 2023 14:39:15 +0800 Subject: [PATCH] [GLUTEN-1273] Support casting decimal as int (#177) --- velox/expression/tests/CastExprTest.cpp | 34 ++++++++++------ velox/type/Conversions.h | 54 +++++++++++++++++++------ 2 files changed, 63 insertions(+), 25 deletions(-) diff --git a/velox/expression/tests/CastExprTest.cpp b/velox/expression/tests/CastExprTest.cpp index 2a8fbd4a6aa0..a478aaf444f6 100644 --- a/velox/expression/tests/CastExprTest.cpp +++ b/velox/expression/tests/CastExprTest.cpp @@ -805,6 +805,12 @@ TEST_F(CastExprTest, toString) { ASSERT_EQ("cast((a) as ARRAY)", exprSet.exprs()[1]->toString()); } +TEST_F(CastExprTest, decimalToInt) { + // short to short, scale up. + auto longFlat = makeLongDecimalFlatVector({8976067200}, DECIMAL(21, 6)); + testComplexCast("c0", longFlat, makeFlatVector({8976})); +} + TEST_F(CastExprTest, decimalToDecimal) { // short to short, scale up. auto shortFlat = @@ -932,22 +938,24 @@ TEST_F(CastExprTest, integerToDecimal) { TEST_F(CastExprTest, varcharToDecimal) { // varchar to short decimal -// auto input = makeFlatVector({"-3", "177"}); -// testComplexCast( -// "c0", input, makeShortDecimalFlatVector({-300, 17700}, DECIMAL(6, 2))); - -// // varchar to long decimal -// auto input2 = makeFlatVector( -// {"-300000001234567891234.5", "1771234.5678912345678"}); -// testComplexCast( -// "c0", input2, makeLongDecimalFlatVector({-300, 17700}, DECIMAL(32, 7))); + // auto input = makeFlatVector({"-3", "177"}); + // testComplexCast( + // "c0", input, makeShortDecimalFlatVector({-300, 17700}, DECIMAL(6, + // 2))); + + // // varchar to long decimal + // auto input2 = makeFlatVector( + // {"-300000001234567891234.5", "1771234.5678912345678"}); + // testComplexCast( + // "c0", input2, makeLongDecimalFlatVector({-300, 17700}, DECIMAL(32, + // 7))); auto input3 = makeFlatVector({"9999999999.99", "9999999999.99"}); testComplexCast( - "c0", input3, makeLongDecimalFlatVector( - {-30'000'000'000, - -20'000'000'000}, - DECIMAL(12, 2))); + "c0", + input3, + makeLongDecimalFlatVector( + {-30'000'000'000, -20'000'000'000}, DECIMAL(12, 2))); } TEST_F(CastExprTest, castInTry) { diff --git a/velox/type/Conversions.h b/velox/type/Conversions.h index de5530b4e0a9..6aba356766b3 100644 --- a/velox/type/Conversions.h +++ b/velox/type/Conversions.h @@ -87,13 +87,11 @@ struct Converter { } static T cast(const UnscaledLongDecimal& d, bool& nullOutput) { - VELOX_UNSUPPORTED( - "Conversion of UnscaledLongDecimal to Boolean is not supported"); + return folly::to(d.unscaledValue()); } static T cast(const UnscaledShortDecimal& d, bool& nullOutput) { - VELOX_UNSUPPORTED( - "Conversion of UnscaledShortDecimal to Boolean is not supported"); + return folly::to(d.unscaledValue()); } }; @@ -113,6 +111,40 @@ struct Converter< VELOX_NYI(); } + static T cast( + const UnscaledLongDecimal& d, + bool& nullOutput, + const TypePtr& fromType) { + const auto& decimalType = fromType->asLongDecimal(); + auto scale0Decimal = DecimalUtil:: + rescaleWithRoundUp( + d, + decimalType.precision(), + decimalType.scale(), + decimalType.precision(), + 0, + false, + false); + return cast(scale0Decimal.value().unscaledValue(), nullOutput); + } + + static T cast( + const UnscaledShortDecimal& d, + bool& nullOutput, + const TypePtr& fromType) { + const auto& decimalType = fromType->asShortDecimal(); + auto scale0Decimal = DecimalUtil:: + rescaleWithRoundUp( + d, + decimalType.precision(), + decimalType.scale(), + decimalType.precision(), + 0, + false, + false); + return cast(scale0Decimal.value().unscaledValue(), nullOutput); + } + template static T cast(const From& v, bool& nullOutput) { VELOX_UNSUPPORTED( @@ -318,14 +350,12 @@ struct Converter< } } - static T cast(const UnscaledLongDecimal& d, bool& nullOutput) { - VELOX_UNSUPPORTED( - "Conversion of UnscaledLongDecimal to Boolean is not supported"); - } - - static T cast(const UnscaledShortDecimal& d, bool& nullOutput) { - VELOX_UNSUPPORTED( - "Conversion of UnscaledShortDecimal to Boolean is not supported"); + static T cast(const int128_t& v, bool& nullOutput) { + if constexpr (TRUNCATE) { + return T(v); + } else { + return static_cast(v); + } } };