[Function](ELT)Add elt function (#12321)
This commit is contained in:
@ -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) {
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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>();
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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")));
|
||||
|
||||
@ -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";
|
||||
{
|
||||
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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', ''],
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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');"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user