This is an automated email from the ASF dual-hosted git repository. yiguolei pushed a commit to branch branch-2.1 in repository https://gitbox.apache.org/repos/asf/doris.git
commit eb7eaee386280e9854863eb03258126d70d99f48 Author: zhiqiang <seuhezhiqi...@163.com> AuthorDate: Fri May 17 10:44:31 2024 +0800 [fix](function) money format (#34680) --- be/src/vec/functions/function_string.h | 180 +++++++++++++++------ .../vec/function/function_money_format_test.cpp | 92 +++++++++++ .../string_functions/test_string_function.out | 4 +- .../string_functions/test_money_format.out | 154 ++++++++++++++++++ .../string_functions/test_money_format.groovy | 77 +++++++++ 5 files changed, 452 insertions(+), 55 deletions(-) diff --git a/be/src/vec/functions/function_string.h b/be/src/vec/functions/function_string.h index 61339bbd9cf..6dbd2704187 100644 --- a/be/src/vec/functions/function_string.h +++ b/be/src/vec/functions/function_string.h @@ -25,15 +25,18 @@ #include <algorithm> #include <array> #include <boost/iterator/iterator_facade.hpp> +#include <cmath> #include <cstddef> #include <cstdlib> #include <iomanip> +#include <limits> #include <memory> #include <ostream> #include <random> #include <sstream> #include <stdexcept> #include <tuple> +#include <type_traits> #include <utility> #include <vector> @@ -65,6 +68,7 @@ #include "vec/core/field.h" #include "vec/core/types.h" #include "vec/data_types/data_type.h" +#include "vec/functions/round.h" #include "vec/io/io_helper.h" #ifndef USE_LIBCPP @@ -2959,18 +2963,97 @@ public: namespace MoneyFormat { +constexpr size_t MAX_FORMAT_LEN_DEC32() { + // Decimal(9, 0) + // Double the size to avoid some unexpected bug. + return 2 * (1 + 9 + (9 / 3) + 3); +} + +constexpr size_t MAX_FORMAT_LEN_DEC64() { + // Decimal(18, 0) + // Double the size to avoid some unexpected bug. + return 2 * (1 + 18 + (18 / 3) + 3); +} + +constexpr size_t MAX_FORMAT_LEN_DEC128V2() { + // DecimalV2 has at most 27 digits + // Double the size to avoid some unexpected bug. + return 2 * (1 + 27 + (27 / 3) + 3); +} + +constexpr size_t MAX_FORMAT_LEN_DEC128V3() { + // Decimal(38, 0) + // Double the size to avoid some unexpected bug. + return 2 * (1 + 39 + (39 / 3) + 3); +} + +constexpr size_t MAX_FORMAT_LEN_INT64() { + // INT_MIN = -9223372036854775807 + // Double the size to avoid some unexpected bug. + return 2 * (1 + 20 + (20 / 3) + 3); +} + +constexpr size_t MAX_FORMAT_LEN_INT128() { + // INT128_MIN = -170141183460469231731687303715884105728 + return 2 * (1 + 39 + (39 / 3) + 3); +} + template <typename T, size_t N> -StringRef do_money_format(FunctionContext* context, const T int_value, - const int32_t frac_value = 0) { +StringRef do_money_format(FunctionContext* context, UInt32 scale, T int_value, T frac_value) { + static_assert(std::is_integral<T>::value); + const bool is_negative = int_value < 0 || frac_value < 0; + + // do round to frac_part + // magic number 2: since we need to round frac_part to 2 digits + if (scale > 2) { + DCHECK(scale <= 38); + // do rounding, so we need to reserve 3 digits. + auto multiplier = common::exp10_i128(std::abs(static_cast<int>(scale - 3))); + // do devide first to avoid overflow + // after round frac_value will be positive by design. + frac_value = std::abs(frac_value / multiplier) + 5; + frac_value /= 10; + } else if (scale < 2) { + DCHECK(frac_value < 100); + // since scale <= 2, overflow is impossiable + frac_value = frac_value * common::exp10_i32(2 - scale); + } + + if (frac_value == 100) { + if (is_negative) { + int_value -= 1; + } else { + int_value += 1; + } + frac_value = 0; + } + + bool append_sign_manually = false; + if (is_negative && int_value == 0) { + // when int_value is 0, result of SimpleItoaWithCommas will contains just zero + // for Decimal like -0.1234, this will leads to problem, because negative sign is discarded. + // this is why we introduce argument append_sing_manually. + append_sign_manually = true; + } + char local[N]; char* p = SimpleItoaWithCommas(int_value, local, sizeof(local)); - int32_t string_val_len = local + sizeof(local) - p + 3; - StringRef result = context->create_temp_string_val(string_val_len); + const Int32 integer_str_len = N - (p - local); + const Int32 frac_str_len = 2; + const Int32 whole_decimal_str_len = + (append_sign_manually ? 1 : 0) + integer_str_len + 1 + frac_str_len; + + StringRef result = context->create_temp_string_val(whole_decimal_str_len); char* result_data = const_cast<char*>(result.data); - memcpy(result_data, p, string_val_len - 3); - *(result_data + string_val_len - 3) = '.'; - *(result_data + string_val_len - 2) = '0' + (frac_value / 10); - *(result_data + string_val_len - 1) = '0' + (frac_value % 10); + + if (append_sign_manually) { + memset(result_data, '-', 1); + } + + memcpy(result_data + (append_sign_manually ? 1 : 0), p, integer_str_len); + *(result_data + whole_decimal_str_len - 3) = '.'; + *(result_data + whole_decimal_str_len - 2) = '0' + std::abs(frac_value / 10); + *(result_data + whole_decimal_str_len - 1) = '0' + std::abs(frac_value % 10); return result; }; @@ -3010,9 +3093,9 @@ struct MoneyFormatDoubleImpl { const auto* data_column = assert_cast<const ColumnVector<Float64>*>(col_ptr.get()); // when scale is above 38, we will go here for (size_t i = 0; i < input_rows_count; i++) { - // truncate to 2 decimal places, keep same with mysql + // round to 2 decimal places double value = - MathFunctions::my_double_round(data_column->get_element(i), 2, false, true); + MathFunctions::my_double_round(data_column->get_element(i), 2, false, false); StringRef str = MoneyFormat::do_money_format(context, fmt::format("{:.2f}", value)); result_column->insert_data(str.data, str.size); } @@ -3027,7 +3110,9 @@ struct MoneyFormatInt64Impl { const auto* data_column = assert_cast<const ColumnVector<Int64>*>(col_ptr.get()); for (size_t i = 0; i < input_rows_count; i++) { Int64 value = data_column->get_element(i); - StringRef str = MoneyFormat::do_money_format<Int64, 26>(context, value); + StringRef str = + MoneyFormat::do_money_format<Int64, MoneyFormat::MAX_FORMAT_LEN_INT64()>( + context, 0, value, 0); result_column->insert_data(str.data, str.size); } } @@ -3039,9 +3124,14 @@ struct MoneyFormatInt128Impl { static void execute(FunctionContext* context, ColumnString* result_column, const ColumnPtr col_ptr, size_t input_rows_count) { const auto* data_column = assert_cast<const ColumnVector<Int128>*>(col_ptr.get()); + // SELECT money_format(170141183460469231731687303715884105728/*INT128_MAX + 1*/) will + // get "170,141,183,460,469,231,731,687,303,715,884,105,727.00" in doris, + // see https://github.com/apache/doris/blob/788abf2d7c3c7c2d57487a9608e889e7662d5fb2/be/src/vec/data_types/data_type_number_base.cpp#L124 for (size_t i = 0; i < input_rows_count; i++) { Int128 value = data_column->get_element(i); - StringRef str = MoneyFormat::do_money_format<Int128, 52>(context, value); + StringRef str = + MoneyFormat::do_money_format<Int128, MoneyFormat::MAX_FORMAT_LEN_INT128()>( + context, 0, value, 0); result_column->insert_data(str.data, str.size); } } @@ -3056,70 +3146,54 @@ struct MoneyFormatDecimalImpl { size_t input_rows_count) { if (auto* decimalv2_column = check_and_get_column<ColumnDecimal<Decimal128V2>>(*col_ptr)) { for (size_t i = 0; i < input_rows_count; i++) { - DecimalV2Value value = DecimalV2Value(decimalv2_column->get_element(i)); - - DecimalV2Value rounded(0); - value.round(&rounded, 2, HALF_UP); - - StringRef str = MoneyFormat::do_money_format<int64_t, 26>( - context, rounded.int_value(), abs(rounded.frac_value() / 10000000)); + const Decimal128V2& dec128 = decimalv2_column->get_element(i); + DecimalV2Value value = DecimalV2Value(dec128.value); + // unified_frac_value has 3 digits + auto unified_frac_value = value.frac_value() / 1000000; + StringRef str = + MoneyFormat::do_money_format<Int128, + MoneyFormat::MAX_FORMAT_LEN_DEC128V2()>( + context, 3, value.int_value(), unified_frac_value); result_column->insert_data(str.data, str.size); } } else if (auto* decimal32_column = check_and_get_column<ColumnDecimal<Decimal32>>(*col_ptr)) { const UInt32 scale = decimal32_column->get_scale(); - // scale is up to 9, so exp10_i32 is enough - const auto multiplier = common::exp10_i32(std::abs(static_cast<int>(scale - 2))); for (size_t i = 0; i < input_rows_count; i++) { - Decimal32 frac_part = decimal32_column->get_fractional_part(i); - if (scale > 2) { - int delta = ((frac_part % multiplier) << 1) > multiplier; - frac_part = frac_part / multiplier + delta; - } else if (scale < 2) { - frac_part = frac_part * multiplier; - } - - StringRef str = MoneyFormat::do_money_format<int64_t, 26>( - context, decimal32_column->get_whole_part(i), frac_part); + const Decimal32& frac_part = decimal32_column->get_fractional_part(i); + const Decimal32& whole_part = decimal32_column->get_whole_part(i); + StringRef str = + MoneyFormat::do_money_format<Int64, MoneyFormat::MAX_FORMAT_LEN_DEC32()>( + context, scale, static_cast<Int64>(whole_part.value), + static_cast<Int64>(frac_part.value)); result_column->insert_data(str.data, str.size); } } else if (auto* decimal64_column = check_and_get_column<ColumnDecimal<Decimal64>>(*col_ptr)) { const UInt32 scale = decimal64_column->get_scale(); - // 9 < scale <= 18 - const auto multiplier = common::exp10_i64(std::abs(static_cast<int>(scale - 2))); for (size_t i = 0; i < input_rows_count; i++) { - Decimal64 frac_part = decimal64_column->get_fractional_part(i); - if (scale > 2) { - int delta = ((frac_part % multiplier) << 1) > multiplier; - frac_part = frac_part / multiplier + delta; - } else if (scale < 2) { - frac_part = frac_part * multiplier; - } + const Decimal64& frac_part = decimal64_column->get_fractional_part(i); + const Decimal64& whole_part = decimal64_column->get_whole_part(i); - StringRef str = MoneyFormat::do_money_format<int64_t, 26>( - context, decimal64_column->get_whole_part(i), frac_part); + StringRef str = + MoneyFormat::do_money_format<Int64, MoneyFormat::MAX_FORMAT_LEN_DEC64()>( + context, scale, whole_part.value, frac_part.value); result_column->insert_data(str.data, str.size); } } else if (auto* decimal128_column = check_and_get_column<ColumnDecimal<Decimal128V3>>(*col_ptr)) { const UInt32 scale = decimal128_column->get_scale(); - // 18 < scale <= 38 - const auto multiplier = common::exp10_i128(std::abs(static_cast<int>(scale - 2))); for (size_t i = 0; i < input_rows_count; i++) { - Decimal128V3 frac_part = decimal128_column->get_fractional_part(i); - if (scale > 2) { - int delta = ((frac_part % multiplier) << 1) > multiplier; - frac_part = frac_part / multiplier + delta; - } else if (scale < 2) { - frac_part = frac_part * multiplier; - } + const Decimal128V3& frac_part = decimal128_column->get_fractional_part(i); + const Decimal128V3& whole_part = decimal128_column->get_whole_part(i); - StringRef str = MoneyFormat::do_money_format<__int128, 53>( - context, decimal128_column->get_whole_part(i), frac_part); + StringRef str = + MoneyFormat::do_money_format<Int128, + MoneyFormat::MAX_FORMAT_LEN_DEC128V3()>( + context, scale, whole_part.value, frac_part.value); result_column->insert_data(str.data, str.size); } diff --git a/be/test/vec/function/function_money_format_test.cpp b/be/test/vec/function/function_money_format_test.cpp new file mode 100644 index 00000000000..6a17caab3b3 --- /dev/null +++ b/be/test/vec/function/function_money_format_test.cpp @@ -0,0 +1,92 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +#include <gtest/gtest.h> + +#include <cassert> +#include <memory> + +#include "function_test_util.h" +#include "runtime/decimalv2_value.h" +#include "runtime/define_primitive_type.h" +#include "runtime/runtime_state.h" +#include "runtime/types.h" +#include "vec/columns/column_decimal.h" +#include "vec/columns/column_string.h" +#include "vec/core/block.h" +#include "vec/core/types.h" +#include "vec/data_types/data_type_decimal.h" +#include "vec/functions/function_string.h" + +namespace doris::vectorized { +TEST(function_money_format_test, money_format_with_decimalV2) { + // why not using + std::multimap<std::string, std::string> input_dec_str_and_expected_str = { + {std::string("123.12"), std::string("123.12")}, + {std::string("-123.12"), std::string("-123.12")}, + {std::string("-0.12434"), std::string("-0.12")}, + {std::string("-0.12534"), std::string("-0.13")}, + {std::string("-123456789.12434"), std::string("-123,456,789.12")}, + {std::string("-123456789.12534"), std::string("-123,456,789.13")}, + {std::string("0.999999999"), std::string("1.00")}, + {std::string("-0.999999999"), std::string("-1.00")}, + {std::string("999999999999999999.994999999"), + std::string("999,999,999,999,999,999.99")}, + {std::string("-999999999999999999.994999999"), + std::string("-999,999,999,999,999,999.99")}, + {std::string("-999999999999999999.995999999"), + std::string("-1,000,000,000,000,000,000.00")}}; + + auto money_format = FunctionMoneyFormat<MoneyFormatDecimalImpl>::create(); + std::unique_ptr<RuntimeState> runtime_state = std::make_unique<RuntimeState>(); + TypeDescriptor return_type = {PrimitiveType::TYPE_VARCHAR}; + TypeDescriptor arg_type = {PrimitiveType::TYPE_DECIMALV2}; + std::vector<TypeDescriptor> arg_types = {arg_type}; + + auto context = FunctionContext::create_context(runtime_state.get(), return_type, arg_types); + + Block block; + ColumnNumbers arguments = {0}; + size_t result_idx = 1; + auto col_dec_v2 = ColumnDecimal<Decimal128V2>::create(0, 9); + auto col_res_expected = ColumnString::create(); + for (const auto& input_and_expected : input_dec_str_and_expected_str) { + DecimalV2Value dec_v2_value(input_and_expected.first); + col_dec_v2->insert_value(Decimal128V2(dec_v2_value.value())); + col_res_expected->insert_data(input_and_expected.second.c_str(), + input_and_expected.second.size()); + } + + block.insert({std::move(col_dec_v2), std::make_shared<DataTypeDecimal<Decimal128V2>>(10, 1), + "col_dec_v2"}); + block.insert({nullptr, std::make_shared<DataTypeString>(), "col_res"}); + + Status exec_status = money_format->execute_impl(context.get(), block, arguments, result_idx, + block.get_by_position(0).column->size()); + + // Check result + auto col_res = block.get_by_position(result_idx).column; + for (size_t i = 0; i < col_res->size(); ++i) { + auto res = col_res->get_data_at(i); + auto res_expected = col_res_expected->get_data_at(i); + EXPECT_EQ(res.debug_string(), res_expected.debug_string()) + << "res " << res.debug_string() << ' ' << "res_expected " + << res_expected.debug_string(); + } +} + +}; // namespace doris::vectorized \ No newline at end of file diff --git a/regression-test/data/nereids_p0/sql_functions/string_functions/test_string_function.out b/regression-test/data/nereids_p0/sql_functions/string_functions/test_string_function.out index 090ec198a7b..e8305c284ff 100644 --- a/regression-test/data/nereids_p0/sql_functions/string_functions/test_string_function.out +++ b/regression-test/data/nereids_p0/sql_functions/string_functions/test_string_function.out @@ -189,10 +189,10 @@ ab d 1.12 -- !sql_float64 -- -1.12 +1.13 -- !sql_float64 -- -1.12 +1.13 -- !sql -- true diff --git a/regression-test/data/query_p0/sql_functions/string_functions/test_money_format.out b/regression-test/data/query_p0/sql_functions/string_functions/test_money_format.out new file mode 100644 index 00000000000..55a3609aa91 --- /dev/null +++ b/regression-test/data/query_p0/sql_functions/string_functions/test_money_format.out @@ -0,0 +1,154 @@ +-- This file is automatically generated. You should know what you did if you want to edit this +-- !money_format -- +\N + +-- !money_format -- +0.00 + +-- !money_format -- +0.00 + +-- !money_format -- +-123.13 + +-- !money_format -- +-17,014,116.00 + +-- !money_format -- +1,123.46 + +-- !money_format -- +1,123.40 + +-- !money_format -- +1.12 + +-- !money_format_dec32_2_1 -- +-0.10 + +-- !money_format_dec32_3_2 -- +-0.11 + +-- !money_format_dec32_4_3 -- +-0.11 + +-- !money_format_dec32_4_3 -- +-0.12 + +-- !money_format_dec32_9_0 -- +999,999,999.00 + +-- !money_format_dec32_9_0_negative -- +-999,999,999.00 + +-- !money_format_dec32_9_1 -- +99,999,999.90 + +-- !money_format_dec32_9_1_negative -- +-9,999,999.90 + +-- !money_format_dec32_9_2 -- +9,999,999.99 + +-- !money_format_dec32_9_2_negative -- +-9,999,999.99 + +-- !money_format_dec32_9_9 -- +1.00 + +-- !money_format_dec32_9_9_negative -- +-1.00 + +-- !money_format_dec64_18_0 -- +999,999,999,999,999,999.00 + +-- !money_format_dec64_18_0_negative -- +-999,999,999,999,999,999.00 + +-- !money_format_dec64_18_1 -- +99,999,999,999,999,999.90 + +-- !money_format_dec64_18_1_negative -- +-99,999,999,999,999,999.90 + +-- !money_format_dec64_18_2 -- +999,999,999,999,999.99 + +-- !money_format_dec64_18_2_negative -- +-999,999,999,999,999.99 + +-- !money_format_dec64_18_17 -- +10.00 + +-- !money_format_dec64_18_17_negative -- +-10.00 + +-- !money_format_dec64_18_18 -- +1.00 + +-- !money_format_dec64_18_18_negative -- +-1.00 + +-- !money_format_dec128_38_0 -- +99,999,999,999,999,999,999,999,999,999,999,999,999.00 + +-- !money_format_dec128_38_0_negative -- +-99,999,999,999,999,999,999,999,999,999,999,999,999.00 + +-- !money_format_dec128_38_1 -- +9,999,999,999,999,999,999,999,999,999,999,999,999.90 + +-- !money_format_dec128_38_1_negative -- +-9,999,999,999,999,999,999,999,999,999,999,999,999.90 + +-- !money_format_dec128_38_2 -- +999,999,999,999,999,999,999,999,999,999,999,999.99 + +-- !money_format_dec128_38_2_negative -- +-999,999,999,999,999,999,999,999,999,999,999,999.99 + +-- !money_format_dec128_38_38 -- +1.00 + +-- !money_format_dec128_38_38_negative -- +-1.00 + +-- !money_format_interger -- +1.00 + +-- !money_format_interger -- +-1.00 + +-- !money_format_interger -- +1,233,456,789.00 + +-- !money_format_interger -- +-1,233,456,789.00 + +-- !money_format_interger -- +9,223,372,036,854,775,807.00 + +-- !money_format_interger -- +-9,223,372,036,854,775,808.00 + +-- !money_format_interger_int128_min -- +-170,141,183,460,469,231,731,687,303,715,884,105,728.00 + +-- !money_format_interger_int128_max -- +170,141,183,460,469,231,731,687,303,715,884,105,727.00 + +-- !money_format_double -- +1.2323 1.23 + +-- !money_format_double -- +1.2353 1.24 + +-- !money_format_double -- +-1.2353 -1.24 + +-- !money_format_double -- +-1.234567892353E8 -123,456,789.24 + +-- !money_format_double -- +-0.2353 -0.24 + diff --git a/regression-test/suites/query_p0/sql_functions/string_functions/test_money_format.groovy b/regression-test/suites/query_p0/sql_functions/string_functions/test_money_format.groovy new file mode 100644 index 00000000000..b30062d3052 --- /dev/null +++ b/regression-test/suites/query_p0/sql_functions/string_functions/test_money_format.groovy @@ -0,0 +1,77 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +suite("test_money_format") { + qt_money_format "SELECT money_format(NULL);" + qt_money_format "SELECT money_format(0);" + qt_money_format "SELECT money_format(0.000);" + qt_money_format "select money_format(-123.125);" + qt_money_format "select money_format(-17014116);" + qt_money_format "select money_format(1123.456);" + qt_money_format "select money_format(1123.4);" + qt_money_format "select money_format(1.1249);" + + qt_money_format_dec32_2_1 "select money_format(-0.1);" + qt_money_format_dec32_3_2 "select money_format(-0.11);" + qt_money_format_dec32_4_3 "select money_format(-0.114);" + qt_money_format_dec32_4_3 "select money_format(-0.115);" + + qt_money_format_dec32_9_0 """select money_format(cast(concat(repeat('9', 9)) as DECIMALV3(9, 0)));""" + qt_money_format_dec32_9_0_negative """select money_format(cast(concat('-', repeat('9', 9)) as DECIMALV3(9, 0)));""" + qt_money_format_dec32_9_1 """select money_format(cast(concat(repeat('9', 8), '.', repeat('9', 1)) as DECIMALV3(9, 1)));""" + qt_money_format_dec32_9_1_negative """select money_format(cast(concat('-',repeat('9', 7), '.', repeat('9', 1)) as DECIMALV3(9, 1)));""" + qt_money_format_dec32_9_2 """select money_format(cast(concat(repeat('9', 7), '.', repeat('9', 2)) as DECIMALV3(9, 2)));""" + qt_money_format_dec32_9_2_negative """select money_format(cast(concat('-', repeat('9', 7), '.', repeat('9', 2)) as DECIMALV3(9, 2)));""" + qt_money_format_dec32_9_9 """select money_format(cast(concat('0.', repeat('9', 9)) as DECIMALV3(9, 9)));""" + qt_money_format_dec32_9_9_negative """select money_format(cast(concat('-', '0.', repeat('9', 9)) as DECIMALV3(9, 9)));""" + + qt_money_format_dec64_18_0 """select money_format(cast(concat(repeat('9', 18)) as DECIMALV3(18, 0)));""" + qt_money_format_dec64_18_0_negative """select money_format(cast(concat('-', repeat('9', 18)) as DECIMALV3(18, 0)));""" + qt_money_format_dec64_18_1 """select money_format(cast(concat(repeat('9', 17), '.', repeat('9', 1)) as DECIMALV3(18, 1)));""" + qt_money_format_dec64_18_1_negative """select money_format(cast(concat('-',repeat('9', 17), '.', repeat('9', 1)) as DECIMALV3(18, 1)));""" + qt_money_format_dec64_18_2 """select money_format(cast(concat(repeat('9', 15), '.', repeat('9', 2)) as DECIMALV3(18, 2)));""" + qt_money_format_dec64_18_2_negative """select money_format(cast(concat('-', repeat('9', 15), '.', repeat('9', 2)) as DECIMALV3(18, 2)));""" + qt_money_format_dec64_18_17 """select money_format(cast(concat('9.', repeat('9', 17)) as DECIMALV3(18, 17)))""" + qt_money_format_dec64_18_17_negative """select money_format(cast(concat('-', '9.', repeat('9', 17)) as DECIMALV3(18, 17)))""" + qt_money_format_dec64_18_18 """select money_format(cast(concat('0.', repeat('9', 18)) as DECIMALV3(18, 18)));""" + qt_money_format_dec64_18_18_negative """select money_format(cast(concat('-', '0.', repeat('9', 18)) as DECIMALV3(18, 18)));""" + + qt_money_format_dec128_38_0 """select money_format(cast(concat(repeat('9', 38)) as DECIMALV3(38, 0)));""" + qt_money_format_dec128_38_0_negative """select money_format(cast(concat('-', repeat('9', 38)) as DECIMALV3(38, 0)));""" + qt_money_format_dec128_38_1 """select money_format(cast(concat(repeat('9', 37), '.', repeat('9', 1)) as DECIMALV3(38, 1)));""" + qt_money_format_dec128_38_1_negative """select money_format(cast(concat('-',repeat('9', 37), '.', repeat('9', 1)) as DECIMALV3(38, 1)));""" + qt_money_format_dec128_38_2 """select money_format(cast(concat(repeat('9', 36), '.', repeat('9', 2)) as DECIMALV3(38, 2)));""" + qt_money_format_dec128_38_2_negative """select money_format(cast(concat('-', repeat('9', 36), '.', repeat('9', 2)) as DECIMALV3(38, 2)));""" + qt_money_format_dec128_38_38 """select money_format(cast(concat('0.', repeat('9', 38)) as DECIMALV3(38, 38)));""" + qt_money_format_dec128_38_38_negative """select money_format(cast(concat('-', '0.', repeat('9', 38)) as DECIMALV3(38, 38)));""" + + qt_money_format_interger "select money_format(1);" + qt_money_format_interger "select money_format(-1);" + qt_money_format_interger "select money_format(1233456789);" + qt_money_format_interger "select money_format(-1233456789);" + qt_money_format_interger """select money_format(cast("9223372036854775807" as BigInt))""" + qt_money_format_interger """select money_format(cast("-9223372036854775808" as BigInt))""" + qt_money_format_interger_int128_min """select money_format(-170141183460469231731687303715884105728);""" + qt_money_format_interger_int128_max """select money_format(170141183460469231731687303715884105727);""" + + qt_money_format_double """select cast("1.2323" as Double), money_format(cast("1.2323" as Double));""" + qt_money_format_double """select cast("1.2353" as Double), money_format(cast("1.2353" as Double));""" + qt_money_format_double """select cast("-1.2353" as Double), money_format(cast("-1.2353" as Double));""" + qt_money_format_double """select cast("-123456789.2353" as Double), money_format(cast("-123456789.2353" as Double));""" + qt_money_format_double """select cast("-0.2353" as Double), money_format(cast("-0.2353" as Double));""" +} + --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org