From f071d5a3075d1172db36b497cf935733b82d732f Mon Sep 17 00:00:00 2001 From: frwrdt <38685812+frwrdt@users.noreply.github.com> Date: Tue, 14 Jan 2020 22:37:20 +0800 Subject: [PATCH] Support ends_with function (#2746) --- be/src/exprs/string_functions.cpp | 10 ++++ be/src/exprs/string_functions.h | 3 ++ be/test/exprs/string_functions_test.cpp | 33 +++++++++++++ .../string-functions/ends_with.md | 46 ++++++++++++++++++ .../string-functions/ends_with_EN.md | 47 +++++++++++++++++++ gensrc/script/doris_builtins_functions.py | 2 + gensrc/script/doris_functions.py | 1 + 7 files changed, 142 insertions(+) create mode 100644 docs/documentation/cn/sql-reference/sql-functions/string-functions/ends_with.md create mode 100644 docs/documentation/en/sql-reference/sql-functions/string-functions/ends_with_EN.md diff --git a/be/src/exprs/string_functions.cpp b/be/src/exprs/string_functions.cpp index d2af736250..48d045a54c 100644 --- a/be/src/exprs/string_functions.cpp +++ b/be/src/exprs/string_functions.cpp @@ -79,6 +79,16 @@ StringVal StringFunctions::right( return substring(context, str, IntVal(pos), len); } +BooleanVal StringFunctions::ends_with( + FunctionContext* context, const StringVal& str, const StringVal& suffix) { + if (str.is_null || suffix.is_null) { + return BooleanVal::null(); + } + re2::StringPiece str_sp(reinterpret_cast(str.ptr), str.len); + re2::StringPiece suffix_sp(reinterpret_cast(suffix.ptr), suffix.len); + return BooleanVal(str_sp.ends_with(suffix_sp)); +} + StringVal StringFunctions::space(FunctionContext* context, const IntVal& len) { if (len.is_null){ return StringVal::null(); diff --git a/be/src/exprs/string_functions.h b/be/src/exprs/string_functions.h index fc7087d6af..92967e9d6e 100644 --- a/be/src/exprs/string_functions.h +++ b/be/src/exprs/string_functions.h @@ -49,6 +49,9 @@ public: static doris_udf::StringVal right( doris_udf::FunctionContext* context, const doris_udf::StringVal& str, const doris_udf::IntVal& len); + static doris_udf::BooleanVal ends_with( + doris_udf::FunctionContext* context, const doris_udf::StringVal& str, + const doris_udf::StringVal& suffix); static doris_udf::StringVal space( doris_udf::FunctionContext* context, const doris_udf::IntVal& len); static doris_udf::StringVal repeat( diff --git a/be/test/exprs/string_functions_test.cpp b/be/test/exprs/string_functions_test.cpp index bd7e9ae9f8..fbb6576146 100644 --- a/be/test/exprs/string_functions_test.cpp +++ b/be/test/exprs/string_functions_test.cpp @@ -157,6 +157,39 @@ TEST_F(StringFunctionsTest, split_part) { StringFunctions::split_part(context, StringVal("abcdabda"), StringVal("a"), 4)); } +TEST_F(StringFunctionsTest, ends_with) { + doris_udf::FunctionContext* context = new doris_udf::FunctionContext(); + doris_udf::BooleanVal falseRet = doris_udf::BooleanVal(false); + doris_udf::BooleanVal trueRet = doris_udf::BooleanVal(true); + doris_udf::BooleanVal nullRet = doris_udf::BooleanVal::null(); + + ASSERT_EQ(trueRet, StringFunctions::ends_with(context, StringVal(""), StringVal(""))); + + ASSERT_EQ(trueRet, StringFunctions::ends_with(context, StringVal("hello"), StringVal(""))); + + ASSERT_EQ(falseRet, StringFunctions::ends_with(context, StringVal(""), StringVal("hello"))); + + ASSERT_EQ(trueRet, StringFunctions::ends_with(context, StringVal("hello"), StringVal("hello"))); + + ASSERT_EQ(trueRet, StringFunctions::ends_with(context, StringVal(" "), StringVal(" "))); + + ASSERT_EQ(falseRet, StringFunctions::ends_with(context, StringVal("hello"), StringVal(" "))); + + ASSERT_EQ(falseRet, StringFunctions::ends_with(context, StringVal(" "), StringVal("hello"))); + + ASSERT_EQ(falseRet, StringFunctions::ends_with(context, StringVal("hello doris"), StringVal("hello"))); + + ASSERT_EQ(trueRet, StringFunctions::ends_with(context, StringVal("hello doris"), StringVal("doris"))); + + ASSERT_EQ(trueRet, StringFunctions::ends_with(context, StringVal("hello doris"), StringVal("hello doris"))); + + ASSERT_EQ(nullRet, StringFunctions::ends_with(context, StringVal("hello"), StringVal::null())); + + ASSERT_EQ(nullRet, StringFunctions::ends_with(context, StringVal::null(), StringVal("hello"))); + + ASSERT_EQ(nullRet, StringFunctions::ends_with(context, StringVal::null(), StringVal::null())); +} + } int main(int argc, char** argv) { diff --git a/docs/documentation/cn/sql-reference/sql-functions/string-functions/ends_with.md b/docs/documentation/cn/sql-reference/sql-functions/string-functions/ends_with.md new file mode 100644 index 0000000000..c2eecca684 --- /dev/null +++ b/docs/documentation/cn/sql-reference/sql-functions/string-functions/ends_with.md @@ -0,0 +1,46 @@ + + +# ends_with +## description +### Syntax + +`BOOLEAN ENDS_WITH (VARCHAR str, VARCHAR suffix)` + +如果字符串以指定后缀结尾,返回true。否则,返回false。任意参数为NULL,返回NULL。 + +## example + +``` +mysql> select ends_with("Hello doris", "doris"); ++-----------------------------------+ +| ends_with('Hello doris', 'doris') | ++-----------------------------------+ +| 1 | ++-----------------------------------+ + +mysql> select ends_with("Hello doris", "Hello"); ++-----------------------------------+ +| ends_with('Hello doris', 'Hello') | ++-----------------------------------+ +| 0 | ++-----------------------------------+ +``` +##keyword +ENDS_WITH diff --git a/docs/documentation/en/sql-reference/sql-functions/string-functions/ends_with_EN.md b/docs/documentation/en/sql-reference/sql-functions/string-functions/ends_with_EN.md new file mode 100644 index 0000000000..7da9bd5c2f --- /dev/null +++ b/docs/documentation/en/sql-reference/sql-functions/string-functions/ends_with_EN.md @@ -0,0 +1,47 @@ + + +# ends_with +## Description +### Syntax + +`BOOLEAN ENDS_WITH (VARCHAR str, VARCHAR suffix)` + +It returns true if the string ends with the specified suffix, otherwise it returns false. +If any parameter is NULL, it returns NULL. + +## example + +``` +mysql> select ends_with("Hello doris", "doris"); ++-----------------------------------+ +| ends_with('Hello doris', 'doris') | ++-----------------------------------+ +| 1 | ++-----------------------------------+ + +mysql> select ends_with("Hello doris", "Hello"); ++-----------------------------------+ +| ends_with('Hello doris', 'Hello') | ++-----------------------------------+ +| 0 | ++-----------------------------------+ +``` +##keyword +ENDS_WITH diff --git a/gensrc/script/doris_builtins_functions.py b/gensrc/script/doris_builtins_functions.py index 83b0eccee0..25a6462267 100755 --- a/gensrc/script/doris_builtins_functions.py +++ b/gensrc/script/doris_builtins_functions.py @@ -489,6 +489,8 @@ visible_functions = [ [['strright', 'right'], 'VARCHAR', ['VARCHAR', 'INT'], '_ZN5doris15StringFunctions5rightEPN9doris_udf' '15FunctionContextERKNS1_9StringValERKNS1_6IntValE'], + [['ends_with'], 'BOOLEAN', ['VARCHAR', 'VARCHAR'], + '_ZN5doris15StringFunctions9ends_withEPN9doris_udf15FunctionContextERKNS1_9StringValES6_'], [['space'], 'VARCHAR', ['INT'], '_ZN5doris15StringFunctions5spaceEPN9doris_udf15FunctionContextERKNS1_6IntValE'], [['repeat'], 'VARCHAR', ['VARCHAR', 'INT'], diff --git a/gensrc/script/doris_functions.py b/gensrc/script/doris_functions.py index e6e7742ec5..842560381a 100755 --- a/gensrc/script/doris_functions.py +++ b/gensrc/script/doris_functions.py @@ -106,6 +106,7 @@ functions = [ # left and right are key words, leave them out for now. ['String_Left', 'VARCHAR', ['VARCHAR', 'INT'], 'StringFunctions::left', ['strleft', 'left']], ['String_Right', 'VARCHAR', ['VARCHAR', 'INT'], 'StringFunctions::right', ['strright', 'right']], + ['String_Ends_With', 'BOOLEAN', ['VARCHAR', 'VARCHAR'], 'StringFunctions::ends_with', ['ends_with']], ['String_Length', 'INT', ['VARCHAR'], 'StringFunctions::length', ['length']], ['String_Lower', 'VARCHAR', ['VARCHAR'], 'StringFunctions::lower', ['lower', 'lcase']], ['String_Upper', 'VARCHAR', ['VARCHAR'], 'StringFunctions::upper', ['upper', 'ucase']],