[Function](ELT)Add elt function (#12321)

This commit is contained in:
yongjinhou
2022-09-07 15:21:08 +08:00
committed by GitHub
parent f2923f9180
commit 09b45f2b71
11 changed files with 256 additions and 0 deletions

View File

@ -682,6 +682,15 @@ StringVal StringFunctions::concat_ws(FunctionContext* context, const StringVal&
return result;
}
StringVal StringFunctions::elt(FunctionContext* context, const IntVal& pos, int num_children,
const StringVal* strs) {
if (pos.is_null || pos.val < 1 || num_children == 0 || pos.val > num_children) {
return StringVal::null();
}
return strs[pos.val - 1];
}
IntVal StringFunctions::find_in_set(FunctionContext* context, const StringVal& str,
const StringVal& str_set) {
if (str.is_null || str_set.is_null) {

View File

@ -115,6 +115,8 @@ public:
static StringVal concat(doris_udf::FunctionContext*, int num_children, const StringVal* strs);
static StringVal concat_ws(doris_udf::FunctionContext*, const doris_udf::StringVal& sep,
int num_children, const doris_udf::StringVal* strs);
static StringVal elt(doris_udf::FunctionContext*, const doris_udf::IntVal& pos,
int num_children, const StringVal* strs);
static IntVal find_in_set(doris_udf::FunctionContext*, const doris_udf::StringVal& str,
const doris_udf::StringVal& str_set);

View File

@ -629,6 +629,7 @@ void register_function_string(SimpleFunctionFactory& factory) {
factory.register_function<FunctionRight>();
factory.register_function<FunctionNullOrEmpty>();
factory.register_function<FunctionStringConcat>();
factory.register_function<FunctionStringElt>();
factory.register_function<FunctionStringConcatWs>();
factory.register_function<FunctionStringAppendTrailingCharIfAbsent>();
factory.register_function<FunctionStringRepeat>();

View File

@ -494,6 +494,51 @@ public:
}
};
class FunctionStringElt : public IFunction {
public:
static constexpr auto name = "elt";
static FunctionPtr create() { return std::make_shared<FunctionStringElt>(); }
String get_name() const override { return name; }
size_t get_number_of_arguments() const override { return 0; }
bool is_variadic() const override { return true; }
DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
return std::make_shared<DataTypeString>();
}
bool use_default_implementation_for_nulls() const override { return true; }
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 {
int arguent_size = arguments.size();
auto pos_col =
block.get_by_position(arguments[0]).column->convert_to_full_column_if_const();
if (auto* nullable = check_and_get_column<const ColumnNullable>(*pos_col)) {
pos_col = nullable->get_nested_column_ptr();
}
auto& pos_data = assert_cast<const ColumnInt32*>(pos_col.get())->get_data();
auto pos = pos_data[0];
int num_children = arguent_size - 1;
if (pos < 1 || num_children == 0 || pos > num_children) {
auto null_map = ColumnUInt8::create(input_rows_count, 1);
auto res = ColumnString::create();
auto& res_data = res->get_chars();
auto& res_offset = res->get_offsets();
res_offset.resize(input_rows_count);
for (size_t i = 0; i < input_rows_count; ++i) {
res_data.push_back('\0');
res_offset[i] = res_data.size();
}
block.get_by_position(result).column =
ColumnNullable::create(std::move(res), std::move(null_map));
return Status::OK();
}
block.get_by_position(result).column = block.get_by_position(arguments[pos]).column;
return Status::OK();
}
};
// concat_ws (string,string....) or (string, Array)
// TODO: avoid use fmtlib
class FunctionStringConcatWs : public IFunction {

View File

@ -669,6 +669,14 @@ TEST_F(StringFunctionsTest, lower) {
EXPECT_EQ(StringVal(""), StringFunctions::lower(ctx, StringVal("")));
}
TEST_F(StringFunctionsTest, elt) {
StringVal str[] = {"hello", "world"};
EXPECT_EQ(StringVal("hello"), StringFunctions::elt(ctx, 1, 2, str));
EXPECT_EQ(StringVal("world"), StringFunctions::elt(ctx, 2, 2, str));
EXPECT_EQ(StringVal::null(), StringFunctions::elt(ctx, 0, 2, str));
EXPECT_EQ(StringVal::null(), StringFunctions::elt(ctx, 3, 2, str));
}
TEST_F(StringFunctionsTest, upper) {
// function test
EXPECT_EQ(StringVal("HELLO"), StringFunctions::upper(ctx, StringVal("HELLO")));

View File

@ -343,6 +343,50 @@ TEST(function_string_test, function_concat_test) {
};
}
TEST(function_string_test, function_elt_test) {
std::string func_name = "elt";
{
InputTypeSet input_types = {TypeIndex::Int32, TypeIndex::String, TypeIndex::String};
DataSet data_set = {{{1, std::string("hello"), std::string("world")}, std::string("hello")},
{{1, std::string("你好"), std::string("百度")}, std::string("你好")},
{{1, std::string("hello"), std::string("")}, std::string("hello")}};
check_function<DataTypeString, true>(func_name, input_types, data_set);
};
{
InputTypeSet input_types = {TypeIndex::Int32, TypeIndex::String, TypeIndex::String};
DataSet data_set = {{{2, std::string("hello"), std::string("world")}, std::string("world")},
{{2, std::string("你好"), std::string("百度")}, std::string("百度")},
{{2, std::string("hello"), std::string("")}, std::string("")}};
check_function<DataTypeString, true>(func_name, input_types, data_set);
};
{
InputTypeSet input_types = {TypeIndex::Int32, TypeIndex::String, TypeIndex::String};
DataSet data_set = {{{0, std::string("hello"), std::string("world")}, Null()},
{{0, std::string("你好"), std::string("百度")}, Null()},
{{0, std::string("hello"), std::string("")}, Null()}};
check_function<DataTypeString, true>(func_name, input_types, data_set);
};
{
InputTypeSet input_types = {TypeIndex::Int32, TypeIndex::String, TypeIndex::String};
DataSet data_set = {{{3, std::string("hello"), std::string("world")}, Null()},
{{3, std::string("你好"), std::string("百度")}, Null()},
{{3, std::string("hello"), std::string("")}, Null()}};
check_function<DataTypeString, true>(func_name, input_types, data_set);
};
}
TEST(function_string_test, function_concat_ws_test) {
std::string func_name = "concat_ws";
{

View File

@ -0,0 +1,62 @@
---
{
"title": "elt",
"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.
-->
## elt
### Description
#### Syntax
`VARCHAR elt (INT,VARCHAR,...)`
Returns the string at specified index. Returns NULL if there is no string at specified index.
### example
```
mysql> select elt(1, 'aaa', 'bbb');
+----------------------+
| elt(1, 'aaa', 'bbb') |
+----------------------+
| aaa |
+----------------------+
mysql> select elt(2, 'aaa', 'bbb');
+-----------------------+
| elt(2, 'aaa', 'bbb') |
+-----------------------+
| bbb |
+-----------------------+
mysql> select elt(0, 'aaa', 'bbb');
+----------------------+
| elt(0, 'aaa', 'bbb') |
+----------------------+
| NULL |
+----------------------+
mysql> select elt(2, 'aaa', 'bbb');
+-----------------------+
| elt(3, 'aaa', 'bbb') |
+-----------------------+
| NULL |
+-----------------------+
```
### keywords
ELT

View File

@ -0,0 +1,62 @@
---
{
"title": "elt",
"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.
-->
## elt
### Description
#### Syntax
`VARCHAR elt (INT,VARCHAR,...)`
在指定的索引处返回一个字符串。如果指定的索引处没有字符串,则返回NULL。
### example
```
mysql> select elt(1, 'aaa', 'bbb');
+----------------------+
| elt(1, 'aaa', 'bbb') |
+----------------------+
| aaa |
+----------------------+
mysql> select elt(2, 'aaa', 'bbb');
+-----------------------+
| elt(2, 'aaa', 'bbb') |
+-----------------------+
| bbb |
+-----------------------+
mysql> select elt(0, 'aaa', 'bbb');
+----------------------+
| elt(0, 'aaa', 'bbb') |
+----------------------+
| NULL |
+----------------------+
mysql> select elt(2, 'aaa', 'bbb');
+-----------------------+
| elt(3, 'aaa', 'bbb') |
+-----------------------+
| NULL |
+-----------------------+
```
### keywords
ELT

View File

@ -2027,6 +2027,12 @@ visible_functions = [
[['concat'], 'VARCHAR', ['VARCHAR', '...'],
'_ZN5doris15StringFunctions6concatEPN9doris_udf15FunctionContextEiPKNS1_9StringValE',
'', '', 'vec', ''],
[['elt'], 'VARCHAR', ['INT', 'VARCHAR', '...'],
'_ZN5doris15StringFunctions3eltEPN9doris_udf15FunctionContextERKNS1_6IntValEiPKNS1_9StringValE',
'', '', 'vec', ''],
[['elt'], 'STRING', ['INT', 'STRING', '...'],
'_ZN5doris15StringFunctions3eltEPN9doris_udf15FunctionContextERKNS1_6IntValEiPKNS1_9StringValE',
'', '', 'vec', ''],
[['replace'], 'VARCHAR', ['VARCHAR', 'VARCHAR', 'VARCHAR'],
'_ZN5doris15StringFunctions7replaceEPN9doris_udf15FunctionContextERKNS1_9StringValES6_S6_',
'', '', 'vec', ''],

View File

@ -1,4 +1,16 @@
-- This file is automatically generated. You should know what you did if you want to edit this
-- !sql --
\N
-- !sql --
hello
-- !sql --
doris
-- !sql --
\N
-- !sql --
ac

View File

@ -19,6 +19,11 @@ suite("test_string_function") {
sql "set enable_vectorized_engine = true;"
sql "set batch_size = 4096;"
qt_sql "select elt(0, \"hello\", \"doris\");"
qt_sql "select elt(1, \"hello\", \"doris\");"
qt_sql "select elt(2, \"hello\", \"doris\");"
qt_sql "select elt(3, \"hello\", \"doris\");"
qt_sql "select append_trailing_char_if_absent('a','c');"
qt_sql "select append_trailing_char_if_absent('ac','c');"