diff --git a/be/src/exprs/string_functions.cpp b/be/src/exprs/string_functions.cpp index 48d045a54c..92860d8959 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::starts_with( + FunctionContext* context, const StringVal& str, const StringVal& prefix) { + if (str.is_null || prefix.is_null) { + return BooleanVal::null(); + } + re2::StringPiece str_sp(reinterpret_cast(str.ptr), str.len); + re2::StringPiece prefix_sp(reinterpret_cast(prefix.ptr), prefix.len); + return BooleanVal(str_sp.starts_with(prefix_sp)); +} + BooleanVal StringFunctions::ends_with( FunctionContext* context, const StringVal& str, const StringVal& suffix) { if (str.is_null || suffix.is_null) { diff --git a/be/src/exprs/string_functions.h b/be/src/exprs/string_functions.h index 92967e9d6e..502d55520b 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 starts_with( + doris_udf::FunctionContext* context, const doris_udf::StringVal& str, + const doris_udf::StringVal& prefix); static doris_udf::BooleanVal ends_with( doris_udf::FunctionContext* context, const doris_udf::StringVal& str, const doris_udf::StringVal& suffix); diff --git a/be/test/exprs/string_functions_test.cpp b/be/test/exprs/string_functions_test.cpp index fbb6576146..8a2cd8108a 100644 --- a/be/test/exprs/string_functions_test.cpp +++ b/be/test/exprs/string_functions_test.cpp @@ -190,6 +190,39 @@ TEST_F(StringFunctionsTest, ends_with) { ASSERT_EQ(nullRet, StringFunctions::ends_with(context, StringVal::null(), StringVal::null())); } +TEST_F(StringFunctionsTest, starts_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::starts_with(context, StringVal(""), StringVal(""))); + + ASSERT_EQ(trueRet, StringFunctions::starts_with(context, StringVal(" "), StringVal(" "))); + + ASSERT_EQ(trueRet, StringFunctions::starts_with(context, StringVal("hello"), StringVal(""))); + + ASSERT_EQ(falseRet, StringFunctions::starts_with(context, StringVal(""), StringVal("hello"))); + + ASSERT_EQ(trueRet, StringFunctions::starts_with(context, StringVal("hello"), StringVal("hello"))); + + ASSERT_EQ(falseRet, StringFunctions::starts_with(context, StringVal("hello"), StringVal(" "))); + + ASSERT_EQ(falseRet, StringFunctions::starts_with(context, StringVal(" "), StringVal("world"))); + + ASSERT_EQ(trueRet, StringFunctions::starts_with(context, StringVal("hello world"), StringVal("hello"))); + + ASSERT_EQ(falseRet, StringFunctions::starts_with(context, StringVal("hello world"), StringVal("world"))); + + ASSERT_EQ(trueRet, StringFunctions::starts_with(context, StringVal("hello world"), StringVal("hello world"))); + + ASSERT_EQ(nullRet, StringFunctions::starts_with(context, StringVal("hello world"), StringVal::null())); + + ASSERT_EQ(nullRet, StringFunctions::starts_with(context, StringVal::null(), StringVal("hello world"))); + + ASSERT_EQ(nullRet, StringFunctions::starts_with(context, StringVal::null(), StringVal::null())); +} + } int main(int argc, char** argv) { diff --git a/docs/documentation/cn/sql-reference/sql-functions/string-functions/starts_with.md b/docs/documentation/cn/sql-reference/sql-functions/string-functions/starts_with.md new file mode 100644 index 0000000000..5997abd140 --- /dev/null +++ b/docs/documentation/cn/sql-reference/sql-functions/string-functions/starts_with.md @@ -0,0 +1,46 @@ + + +# starts_with +## description +### Syntax + +`BOOLEAN STARTS_WITH (VARCHAR str, VARCHAR prefix)` + +如果字符串以指定前缀开头,返回true。否则,返回false。任意参数为NULL,返回NULL。 + +## example + +``` +MySQL [(none)]> select starts_with("hello world","hello"); ++-------------------------------------+ +| starts_with('hello world', 'hello') | ++-------------------------------------+ +| 1 | ++-------------------------------------+ + +MySQL [(none)]> select starts_with("hello world","world"); ++-------------------------------------+ +| starts_with('hello world', 'world') | ++-------------------------------------+ +| 0 | ++-------------------------------------+ +``` +##keyword +STARTS_WITH \ No newline at end of file diff --git a/docs/documentation/en/sql-reference/sql-functions/string-functions/starts_with_EN.md b/docs/documentation/en/sql-reference/sql-functions/string-functions/starts_with_EN.md new file mode 100644 index 0000000000..81f1456c91 --- /dev/null +++ b/docs/documentation/en/sql-reference/sql-functions/string-functions/starts_with_EN.md @@ -0,0 +1,47 @@ + + +# starts_with +## Description +### Syntax + +`BOOLEAN STARTS_WITH (VARCHAR str, VARCHAR prefix)` + +It returns true if the string starts with the specified prefix, otherwise it returns false. +If any parameter is NULL, it returns NULL. + +## example + +``` +MySQL [(none)]> select starts_with("hello world","hello"); ++-------------------------------------+ +| starts_with('hello world', 'hello') | ++-------------------------------------+ +| 1 | ++-------------------------------------+ + +MySQL [(none)]> select starts_with("hello world","world"); ++-------------------------------------+ +| starts_with('hello world', 'world') | ++-------------------------------------+ +| 0 | ++-------------------------------------+ +``` +##keyword +STARTS_WITH \ No newline at end of file diff --git a/gensrc/script/doris_builtins_functions.py b/gensrc/script/doris_builtins_functions.py index 11f106a336..0b938a07c1 100755 --- a/gensrc/script/doris_builtins_functions.py +++ b/gensrc/script/doris_builtins_functions.py @@ -506,6 +506,8 @@ visible_functions = [ '15FunctionContextERKNS1_9StringValERKNS1_6IntValE'], [['ends_with'], 'BOOLEAN', ['VARCHAR', 'VARCHAR'], '_ZN5doris15StringFunctions9ends_withEPN9doris_udf15FunctionContextERKNS1_9StringValES6_'], + [['starts_with'], 'BOOLEAN', ['VARCHAR', 'VARCHAR'], + '_ZN5doris15StringFunctions11starts_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 842560381a..a651747bc4 100755 --- a/gensrc/script/doris_functions.py +++ b/gensrc/script/doris_functions.py @@ -107,6 +107,7 @@ functions = [ ['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_Starts_With', 'BOOLEAN', ['VARCHAR', 'VARCHAR'], 'StringFunctions::starts_with', ['starts_with']], ['String_Length', 'INT', ['VARCHAR'], 'StringFunctions::length', ['length']], ['String_Lower', 'VARCHAR', ['VARCHAR'], 'StringFunctions::lower', ['lower', 'lcase']], ['String_Upper', 'VARCHAR', ['VARCHAR'], 'StringFunctions::upper', ['upper', 'ucase']],