Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion be/src/exprs/math_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ const double log_10[] = {

#define ARRAY_ELEMENTS(A) ((uint64_t) (sizeof(A)/sizeof(A[0])))

static double my_double_round(double value, int64_t dec, bool dec_unsigned, bool truncate) {
double MathFunctions::my_double_round(double value, int64_t dec, bool dec_unsigned, bool truncate) {
bool dec_negative = (dec < 0) && !dec_unsigned;
uint64_t abs_dec = dec_negative ? -dec : dec;
/*
Expand Down
3 changes: 3 additions & 0 deletions be/src/exprs/math_functions.h
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,9 @@ class MathFunctions {
doris_udf::FunctionContext* ctx, int num_args, const doris_udf::DecimalV2Val* val);
static doris_udf::DecimalV2Val greatest(
doris_udf::FunctionContext* ctx, int num_args, const doris_udf::DecimalV2Val* val);

static double my_double_round(double value, int64_t dec, bool dec_unsigned, bool truncate);

private:
static const int32_t MIN_BASE = 2;
static const int32_t MAX_BASE = 36;
Expand Down
54 changes: 54 additions & 0 deletions be/src/exprs/string_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "runtime/string_value.hpp"
#include "runtime/tuple_row.h"
#include "util/url_parser.h"
#include "math_functions.h"

// NOTE: be careful not to use string::append. It is not performant.
namespace doris {
Expand Down Expand Up @@ -707,4 +708,57 @@ StringVal StringFunctions::parse_url_key(
return result_sv;
}

StringVal StringFunctions::money_format(FunctionContext* context, const DoubleVal& v) {
if (v.is_null) {
return StringVal::null();
}

double v_cent= MathFunctions::my_double_round(v.val, 2, false, false) * 100;
return do_money_format(context, std::to_string(v_cent));
}

StringVal StringFunctions::money_format(FunctionContext *context, const DecimalVal &v) {
if (v.is_null) {
return StringVal::null();
}

DecimalValue rounded;
DecimalValue::from_decimal_val(v).round(&rounded, 2, HALF_UP);
DecimalValue tmp(std::string("100"));
DecimalValue result = rounded * tmp;
return do_money_format(context, result.to_string());
}

StringVal StringFunctions::money_format(FunctionContext *context, const DecimalV2Val &v) {
if (v.is_null) {
return StringVal::null();
}

DecimalV2Value rounded;
DecimalV2Value::from_decimal_val(v).round(&rounded, 2, HALF_UP);
DecimalV2Value tmp(std::string("100"));
DecimalV2Value result = rounded * tmp;
return do_money_format(context, result.to_string());
}


StringVal StringFunctions::money_format(FunctionContext *context, const BigIntVal &v) {
if (v.is_null) {
return StringVal::null();
}

std::string cent_money = std::to_string(v.val) + std::string("00");
return do_money_format(context, cent_money);
}

StringVal StringFunctions::money_format(FunctionContext *context, const LargeIntVal &v) {
if (v.is_null) {
return StringVal::null();
}

std::stringstream ss;
ss << v.val << "00";
return do_money_format(context, ss.str());
}

}
38 changes: 37 additions & 1 deletion be/src/exprs/string_functions.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@

#include "runtime/string_value.h"
#include "runtime/string_search.hpp"
#include "anyval_util.h"
#include <locale>
#include <sstream>
#include <iomanip>

namespace doris {

Expand Down Expand Up @@ -137,8 +141,40 @@ class StringFunctions {
static void parse_url_close(
doris_udf::FunctionContext*,
doris_udf::FunctionContext::FunctionStateScope);
};


static doris_udf::StringVal money_format(doris_udf::FunctionContext* context,
const doris_udf::DoubleVal& v);

static doris_udf::StringVal money_format(doris_udf::FunctionContext* context,
const doris_udf::DecimalVal& v);

static doris_udf::StringVal money_format(doris_udf::FunctionContext* context,
const doris_udf::DecimalV2Val& v);

static doris_udf::StringVal money_format(doris_udf::FunctionContext* context,
const doris_udf::BigIntVal& v);

static doris_udf::StringVal money_format(doris_udf::FunctionContext* context,
const doris_udf::LargeIntVal& v);

struct CommaMoneypunct : std::moneypunct<char> {
pattern do_pos_format() const override { return {{none, sign, none, value}}; }
pattern do_neg_format() const override { return {{none, sign, none, value}}; }
int do_frac_digits() const override { return 2; }
char_type do_thousands_sep() const override { return ','; }
string_type do_grouping() const override { return "\003"; }
string_type do_negative_sign() const override { return "-"; }
};

static StringVal do_money_format(FunctionContext *context, const std::string& v) {
std::locale comma_locale(std::locale(), new CommaMoneypunct ());
std::stringstream ss;
ss.imbue(comma_locale);
ss << std::put_money(v);
return AnyValUtil::from_string_temp(context, ss.str());
};
};
}

#endif
1 change: 1 addition & 0 deletions be/test/exprs/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,5 @@ ADD_BE_TEST(json_function_test)
#ADD_BE_TEST(in_predicate_test)
#ADD_BE_TEST(expr-test)
ADD_BE_TEST(hybird_set_test)
ADD_BE_TEST(string_functions_test)
#ADD_BE_TEST(in-predicate-test)
132 changes: 132 additions & 0 deletions be/test/exprs/string_functions_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
// 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 "exprs/string_functions.h"
#include "util/logging.h"
#include "exprs/anyval_util.h"
#include <iostream>
#include <string>

#include <gtest/gtest.h>

namespace doris {

class StringFunctionsTest : public testing::Test {
public:
StringFunctionsTest() {
}
};

TEST_F(StringFunctionsTest, money_format_bigint) {
doris_udf::FunctionContext* context = new doris_udf::FunctionContext();

StringVal result = StringFunctions::money_format(context, doris_udf::BigIntVal(123456));
StringVal expected = AnyValUtil::from_string_temp(context, std::string("123,456.00"));
ASSERT_EQ(expected, result);

result = StringFunctions::money_format(context, doris_udf::BigIntVal(-123456));
expected = AnyValUtil::from_string_temp(context, std::string("-123,456.00"));
ASSERT_EQ(expected, result);

result = StringFunctions::money_format(context, doris_udf::BigIntVal(9223372036854775807));
expected = AnyValUtil::from_string_temp(context, std::string("9,223,372,036,854,775,807.00"));
ASSERT_EQ(expected, result);
}

TEST_F(StringFunctionsTest, money_format_large_int) {
doris_udf::FunctionContext* context = new doris_udf::FunctionContext();

std::string str("170141183460469231731687303715884105727");
std::stringstream ss;
ss << str;
__int128 value;
ss >> value;

std::cout << "value: " << value << std::endl;

StringVal result = StringFunctions::money_format(context, doris_udf::LargeIntVal(value));
StringVal expected = AnyValUtil::from_string_temp(context, std::string("170,141,183,460,469,231,731,687,303,715,884,105,727.00"));
ASSERT_EQ(expected, result);
}

TEST_F(StringFunctionsTest, money_format_double) {
doris_udf::FunctionContext* context = new doris_udf::FunctionContext();

StringVal result = StringFunctions::money_format(context, doris_udf::DoubleVal(1234.456));
StringVal expected = AnyValUtil::from_string_temp(context, std::string("1,234.46"));
ASSERT_EQ(expected, result);

result = StringFunctions::money_format(context, doris_udf::DoubleVal(1234.45));
expected = AnyValUtil::from_string_temp(context, std::string("1,234.45"));
ASSERT_EQ(expected, result);

result = StringFunctions::money_format(context, doris_udf::DoubleVal(1234.4));
expected = AnyValUtil::from_string_temp(context, std::string("1,234.40"));
ASSERT_EQ(expected, result);

result = StringFunctions::money_format(context, doris_udf::DoubleVal(1234.454));
expected = AnyValUtil::from_string_temp(context, std::string("1,234.45"));
ASSERT_EQ(expected, result);
}

TEST_F(StringFunctionsTest, money_format_decimal) {
doris_udf::FunctionContext* context = new doris_udf::FunctionContext();

DecimalValue dv1(std::string("3333333333.2222222222"));
DecimalVal value1;
dv1.to_decimal_val(&value1);

StringVal result = StringFunctions::money_format(context, value1);
StringVal expected = AnyValUtil::from_string_temp(context, std::string("3,333,333,333.22"));
ASSERT_EQ(expected, result);

DecimalValue dv2(std::string("-7407407406790123456.71604938271975308642"));
DecimalVal value2;
dv2.to_decimal_val(&value2);

result = StringFunctions::money_format(context, value2);
expected = AnyValUtil::from_string_temp(context, std::string("-7,407,407,406,790,123,456.72"));
ASSERT_EQ(expected, result);
}

TEST_F(StringFunctionsTest, money_format_decimal_v2) {
doris_udf::FunctionContext* context = new doris_udf::FunctionContext();

DecimalV2Value dv1(std::string("3333333333.2222222222"));
DecimalV2Val value1;
dv1.to_decimal_val(&value1);

StringVal result = StringFunctions::money_format(context, value1);
StringVal expected = AnyValUtil::from_string_temp(context, std::string("3,333,333,333.22"));
ASSERT_EQ(expected, result);

DecimalV2Value dv2(std::string("-740740740.71604938271975308642"));
DecimalV2Val value2;
dv2.to_decimal_val(&value2);

result = StringFunctions::money_format(context, value2);
expected = AnyValUtil::from_string_temp(context, std::string("-740,740,740.72"));
ASSERT_EQ(expected, result);
}

}

int main(int argc, char** argv) {
doris::init_glog("be-test");
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# money_format

## Syntax

VARCHAR money_format(Number)

## Description

将数字按照货币格式输出,整数部分每隔3位用逗号分隔,小数部分保留2位

## Examples

```
mysql> select money_format(17014116);
+------------------------+
| money_format(17014116) |
+------------------------+
| 17,014,116.00 |
+------------------------+

mysql> select money_format(1123.456);
+------------------------+
| money_format(1123.456) |
+------------------------+
| 1,123.46 |
+------------------------+

mysql> select money_format(1123.4);
+----------------------+
| money_format(1123.4) |
+----------------------+
| 1,123.40 |
+----------------------+
```
Loading