[fix](function) money format (#34680)

This commit is contained in:
zhiqiang
2024-05-17 10:44:31 +08:00
committed by yiguolei
parent 6f5abfd23f
commit eb7eaee386
5 changed files with 452 additions and 55 deletions

View File

@ -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);
}

View File

@ -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

View File

@ -189,10 +189,10 @@ ab d
1.12
-- !sql_float64 --
1.12
1.13
-- !sql_float64 --
1.12
1.13
-- !sql --
true

View File

@ -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

View File

@ -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));"""
}