This is an automated email from the ASF dual-hosted git repository. lihaopeng pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push: new 8a068c8c92 [function](string_function) add new string function 'not_null_or_empty' (#13418) 8a068c8c92 is described below commit 8a068c8c9278d9c44c4e724c6eb914178ed814f4 Author: zy-kkk <zhong...@qq.com> AuthorDate: Wed Oct 19 11:10:37 2022 +0800 [function](string_function) add new string function 'not_null_or_empty' (#13418) --- be/src/exprs/string_functions.cpp | 8 +++ be/src/exprs/string_functions.h | 2 + be/src/vec/functions/function_string.cpp | 1 + be/src/vec/functions/function_string.h | 64 +++++++++++++++++----- .../string-functions/not_null_or_empty.md | 60 ++++++++++++++++++++ docs/sidebars.json | 1 + .../string-functions/not_null_or_empty.md | 60 ++++++++++++++++++++ gensrc/script/doris_builtins_functions.py | 7 +++ .../string_functions/test_string_function.out | 9 +++ .../string_functions/test_string_function.groovy | 4 ++ 10 files changed, 202 insertions(+), 14 deletions(-) diff --git a/be/src/exprs/string_functions.cpp b/be/src/exprs/string_functions.cpp index 8c381f5d0c..bb033d0c04 100644 --- a/be/src/exprs/string_functions.cpp +++ b/be/src/exprs/string_functions.cpp @@ -143,6 +143,14 @@ BooleanVal StringFunctions::null_or_empty(FunctionContext* context, const String } } +BooleanVal StringFunctions::not_null_or_empty(FunctionContext* context, const StringVal& str) { + if (str.is_null || str.len == 0) { + return 0; + } else { + return 1; + } +} + 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 ac9cfee632..ad8cc356a5 100644 --- a/be/src/exprs/string_functions.h +++ b/be/src/exprs/string_functions.h @@ -60,6 +60,8 @@ public: const doris_udf::StringVal& suffix); static doris_udf::BooleanVal null_or_empty(doris_udf::FunctionContext* context, const doris_udf::StringVal& str); + static doris_udf::BooleanVal not_null_or_empty(doris_udf::FunctionContext* context, + const doris_udf::StringVal& str); static doris_udf::StringVal space(doris_udf::FunctionContext* context, const doris_udf::IntVal& len); static doris_udf::StringVal repeat(doris_udf::FunctionContext* context, diff --git a/be/src/vec/functions/function_string.cpp b/be/src/vec/functions/function_string.cpp index 8ab6066372..b8bf150249 100644 --- a/be/src/vec/functions/function_string.cpp +++ b/be/src/vec/functions/function_string.cpp @@ -666,6 +666,7 @@ void register_function_string(SimpleFunctionFactory& factory) { factory.register_function<FunctionLeft>(); factory.register_function<FunctionRight>(); factory.register_function<FunctionNullOrEmpty>(); + factory.register_function<FunctionNotNullOrEmpty>(); factory.register_function<FunctionStringConcat>(); factory.register_function<FunctionStringElt>(); factory.register_function<FunctionStringConcatWs>(); diff --git a/be/src/vec/functions/function_string.h b/be/src/vec/functions/function_string.h index c916cd17f5..9588e7a2c0 100644 --- a/be/src/vec/functions/function_string.h +++ b/be/src/vec/functions/function_string.h @@ -391,6 +391,37 @@ public: } }; +struct NullOrEmptyImpl { + static DataTypes get_variadic_argument_types() { return {std::make_shared<DataTypeUInt8>()}; } + + static Status execute(FunctionContext* context, Block& block, const ColumnNumbers& arguments, + size_t result, size_t input_rows_count, bool reverse) { + auto res_map = ColumnUInt8::create(input_rows_count, 0); + + auto column = block.get_by_position(arguments[0]).column; + if (auto* nullable = check_and_get_column<const ColumnNullable>(*column)) { + column = nullable->get_nested_column_ptr(); + VectorizedUtils::update_null_map(res_map->get_data(), nullable->get_null_map_data()); + } + auto str_col = assert_cast<const ColumnString*>(column.get()); + const auto& offsets = str_col->get_offsets(); + + auto& res_map_data = res_map->get_data(); + for (int i = 0; i < input_rows_count; ++i) { + int size = offsets[i] - offsets[i - 1]; + res_map_data[i] |= (size == 0); + } + if (reverse) { + for (int i = 0; i < input_rows_count; ++i) { + res_map_data[i] = !res_map_data[i]; + } + } + + block.replace_by_position(result, std::move(res_map)); + return Status::OK(); + } +}; + class FunctionNullOrEmpty : public IFunction { public: static constexpr auto name = "null_or_empty"; @@ -407,23 +438,28 @@ public: Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments, size_t result, size_t input_rows_count) override { - auto res_map = ColumnUInt8::create(input_rows_count, 0); + NullOrEmptyImpl::execute(context, block, arguments, result, input_rows_count, false); + return Status::OK(); + } +}; - auto column = block.get_by_position(arguments[0]).column; - if (auto* nullable = check_and_get_column<const ColumnNullable>(*column)) { - column = nullable->get_nested_column_ptr(); - VectorizedUtils::update_null_map(res_map->get_data(), nullable->get_null_map_data()); - } - auto str_col = assert_cast<const ColumnString*>(column.get()); - const auto& offsets = str_col->get_offsets(); +class FunctionNotNullOrEmpty : public IFunction { +public: + static constexpr auto name = "not_null_or_empty"; + static FunctionPtr create() { return std::make_shared<FunctionNotNullOrEmpty>(); } + String get_name() const override { return name; } + size_t get_number_of_arguments() const override { return 1; } - auto& res_map_data = res_map->get_data(); - for (int i = 0; i < input_rows_count; ++i) { - int size = offsets[i] - offsets[i - 1]; - res_map_data[i] |= (size == 0); - } + DataTypePtr get_return_type_impl(const DataTypes& arguments) const override { + return std::make_shared<DataTypeUInt8>(); + } - block.replace_by_position(result, std::move(res_map)); + bool use_default_implementation_for_nulls() const override { return false; } + bool use_default_implementation_for_constants() const override { return true; } + + Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments, + size_t result, size_t input_rows_count) override { + NullOrEmptyImpl::execute(context, block, arguments, result, input_rows_count, true); return Status::OK(); } }; diff --git a/docs/en/docs/sql-manual/sql-functions/string-functions/not_null_or_empty.md b/docs/en/docs/sql-manual/sql-functions/string-functions/not_null_or_empty.md new file mode 100644 index 0000000000..9d807e1107 --- /dev/null +++ b/docs/en/docs/sql-manual/sql-functions/string-functions/not_null_or_empty.md @@ -0,0 +1,60 @@ +--- +{ + "title": "not_null_or_empty", + "language": "en" +} +--- + +<!-- +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. +--> + +## not_null_or_empty +### description +#### Syntax + +`BOOLEAN NOT_NULL_OR_EMPTY (VARCHAR str)` + +It returns false if the string is an empty string or NULL. Otherwise it returns true. + +### example + +``` +MySQL [(none)]> select not_null_or_empty(null); ++-------------------------+ +| not_null_or_empty(NULL) | ++-------------------------+ +| 0 | ++-------------------------+ + +MySQL [(none)]> select not_null_or_empty(""); ++-----------------------+ +| not_null_or_empty('') | ++-----------------------+ +| 0 | ++-----------------------+ + +MySQL [(none)]> select not_null_or_empty("a"); ++------------------------+ +| not_null_or_empty('a') | ++------------------------+ +| 1 | ++------------------------+ +``` +### keywords + NOT_NULL_OR_EMPTY diff --git a/docs/sidebars.json b/docs/sidebars.json index 8c7cb3a277..8721e9b76f 100644 --- a/docs/sidebars.json +++ b/docs/sidebars.json @@ -371,6 +371,7 @@ "sql-manual/sql-functions/string-functions/ltrim", "sql-manual/sql-functions/string-functions/rtrim", "sql-manual/sql-functions/string-functions/null_or_empty", + "sql-manual/sql-functions/string-functions/not_null_or_empty", "sql-manual/sql-functions/string-functions/hex", "sql-manual/sql-functions/string-functions/unhex", "sql-manual/sql-functions/string-functions/elt", diff --git a/docs/zh-CN/docs/sql-manual/sql-functions/string-functions/not_null_or_empty.md b/docs/zh-CN/docs/sql-manual/sql-functions/string-functions/not_null_or_empty.md new file mode 100644 index 0000000000..89d0cb0b88 --- /dev/null +++ b/docs/zh-CN/docs/sql-manual/sql-functions/string-functions/not_null_or_empty.md @@ -0,0 +1,60 @@ +--- +{ + "title": "not_null_or_empty", + "language": "zh-CN" +} +--- + +<!-- +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. +--> + +## not_null_or_empty +### description +#### Syntax + +`BOOLEAN NOT_NULL_OR_EMPTY (VARCHAR str)` + +如果字符串为空字符串或者NULL,返回false。否则,返回true。 + +### example + +``` +MySQL [(none)]> select not_null_or_empty(null); ++-------------------------+ +| not_null_or_empty(NULL) | ++-------------------------+ +| 0 | ++-------------------------+ + +MySQL [(none)]> select not_null_or_empty(""); ++-----------------------+ +| not_null_or_empty('') | ++-----------------------+ +| 0 | ++-----------------------+ + +MySQL [(none)]> select not_null_or_empty("a"); ++------------------------+ +| not_null_or_empty('a') | ++------------------------+ +| 1 | ++------------------------+ +``` +### keywords + NOT_NULL_OR_EMPTY diff --git a/gensrc/script/doris_builtins_functions.py b/gensrc/script/doris_builtins_functions.py index f1bb4faf86..621bcb3764 100755 --- a/gensrc/script/doris_builtins_functions.py +++ b/gensrc/script/doris_builtins_functions.py @@ -2026,6 +2026,9 @@ visible_functions = [ [['null_or_empty'], 'BOOLEAN', ['VARCHAR'], '_ZN5doris15StringFunctions13null_or_emptyEPN9doris_udf15FunctionContextERKNS1_9StringValE', '', '', 'vec', 'ALWAYS_NOT_NULLABLE'], + [['not_null_or_empty'], 'BOOLEAN', ['VARCHAR'], + '_ZN5doris15StringFunctions17not_null_or_emptyEPN9doris_udf15FunctionContextERKNS1_9StringValE', + '', '', 'vec', 'ALWAYS_NOT_NULLABLE'], [['space'], 'VARCHAR', ['INT'], '_ZN5doris15StringFunctions5spaceEPN9doris_udf15FunctionContextERKNS1_6IntValE', '', '', 'vec', ''], [['repeat'], 'VARCHAR', ['VARCHAR', 'INT'], @@ -2157,6 +2160,9 @@ visible_functions = [ [['null_or_empty'], 'BOOLEAN', ['STRING'], '_ZN5doris15StringFunctions13null_or_emptyEPN9doris_udf15FunctionContextERKNS1_9StringValE', '', '', 'vec', 'ALWAYS_NOT_NULLABLE'], + [['not_null_or_empty'], 'BOOLEAN', ['STRING'], + '_ZN5doris15StringFunctions17not_null_or_emptyEPN9doris_udf15FunctionContextERKNS1_9StringValE', + '', '', 'vec', 'ALWAYS_NOT_NULLABLE'], [['space'], 'STRING', ['INT'], '_ZN5doris15StringFunctions5spaceEPN9doris_udf15FunctionContextERKNS1_6IntValE', '', '', 'vec', ''], [['repeat'], 'STRING', ['STRING', 'INT'], @@ -2714,6 +2720,7 @@ non_null_result_with_null_param_functions = [ 'nvl', 'nullif', 'null_or_empty', + 'not_null_or_empty' 'coalesce', 'array', 'json_array', diff --git a/regression-test/data/query_p0/sql_functions/string_functions/test_string_function.out b/regression-test/data/query_p0/sql_functions/string_functions/test_string_function.out index d0f2b8c71a..1eaf68bbca 100644 --- a/regression-test/data/query_p0/sql_functions/string_functions/test_string_function.out +++ b/regression-test/data/query_p0/sql_functions/string_functions/test_string_function.out @@ -185,6 +185,15 @@ true -- !sql -- false +-- !sql -- +false + +-- !sql -- +false + +-- !sql -- +true + -- !sql -- aaa diff --git a/regression-test/suites/query_p0/sql_functions/string_functions/test_string_function.groovy b/regression-test/suites/query_p0/sql_functions/string_functions/test_string_function.groovy index 80ef709bd3..2a107ef487 100644 --- a/regression-test/suites/query_p0/sql_functions/string_functions/test_string_function.groovy +++ b/regression-test/suites/query_p0/sql_functions/string_functions/test_string_function.groovy @@ -102,6 +102,10 @@ suite("test_string_function") { qt_sql "select null_or_empty(\"\");" qt_sql "select null_or_empty(\"a\");" + qt_sql "select not_null_or_empty(null);" + qt_sql "select not_null_or_empty(\"\");" + qt_sql "select not_null_or_empty(\"a\");" + qt_sql "SELECT repeat(\"a\", 3);" qt_sql "SELECT repeat(\"a\", -1);" qt_sql "SELECT repeat(\"a\", 0);" --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org