You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@doris.apache.org by ga...@apache.org on 2023/02/01 03:17:13 UTC

[doris] branch master updated: [Refactor](function) Rewrite the function elt (#16287)

This is an automated email from the ASF dual-hosted git repository.

gabriellee 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 95d7c2de26 [Refactor](function) Rewrite the function elt (#16287)
95d7c2de26 is described below

commit 95d7c2de26385c5f4003a8c09f2e12df160a520e
Author: HappenLee <ha...@hotmail.com>
AuthorDate: Wed Feb 1 11:17:06 2023 +0800

    [Refactor](function) Rewrite the function elt (#16287)
---
 be/src/vec/functions/function_string.h             | 105 +++++++++++++++++----
 .../string_functions/test_string_function.out      |  17 +++-
 .../string_functions/test_string_function.groovy   |   1 +
 3 files changed, 99 insertions(+), 24 deletions(-)

diff --git a/be/src/vec/functions/function_string.h b/be/src/vec/functions/function_string.h
index 07cff73325..2a50b609e1 100644
--- a/be/src/vec/functions/function_string.h
+++ b/be/src/vec/functions/function_string.h
@@ -731,36 +731,103 @@ public:
     DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
         return make_nullable(std::make_shared<DataTypeString>());
     }
-    bool use_default_implementation_for_nulls() const override { return true; }
+    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 {
         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);
+        auto res = ColumnString::create();
+
+        if (auto const_column = check_and_get_column<ColumnConst>(
+                    *block.get_by_position(arguments[0]).column)) {
+            auto data = const_column->get_data_at(0);
+            // return NULL, pos is null or pos < 0 or pos > num_children
+            auto is_null = data.data == nullptr;
+            auto pos = is_null ? 0 : *(Int32*)data.data;
+            is_null = pos <= 0 || pos > num_children;
+
+            auto null_map = ColumnUInt8::create(input_rows_count, is_null);
+            if (is_null) {
+                res->insert_many_defaults(input_rows_count);
+            } else {
+                auto& target_column = block.get_by_position(arguments[pos]).column;
+                if (auto target_const_column = check_and_get_column<ColumnConst>(*target_column)) {
+                    auto target_data = target_const_column->get_data_at(0);
+                    if (target_data.data == nullptr) {
+                        null_map = ColumnUInt8::create(input_rows_count, is_null);
+                        res->insert_many_defaults(input_rows_count);
+                    } else {
+                        res->insert_many_data(target_data.data, target_data.size, input_rows_count);
+                    }
+                } else if (auto target_nullable_column =
+                                   check_and_get_column<ColumnNullable>(*target_column)) {
+                    auto& target_null_map = target_nullable_column->get_null_map_data();
+                    VectorizedUtils::update_null_map(
+                            assert_cast<ColumnUInt8&>(*null_map).get_data(), target_null_map);
+
+                    auto& target_str_column = assert_cast<const ColumnString&>(
+                            target_nullable_column->get_nested_column());
+                    res->get_chars().assign(target_str_column.get_chars().begin(),
+                                            target_str_column.get_chars().end());
+                    res->get_offsets().assign(target_str_column.get_offsets().begin(),
+                                              target_str_column.get_offsets().end());
+                } else {
+                    auto& target_str_column = assert_cast<const ColumnString&>(*target_column);
+                    res->get_chars().assign(target_str_column.get_chars().begin(),
+                                            target_str_column.get_chars().end());
+                    res->get_offsets().assign(target_str_column.get_offsets().begin(),
+                                              target_str_column.get_offsets().end());
+                }
+            }
+            block.get_by_position(result).column =
+                    ColumnNullable::create(std::move(res), std::move(null_map));
+        } else if (auto pos_null_column = check_and_get_column<ColumnNullable>(
+                           *block.get_by_position(arguments[0]).column)) {
+            auto& pos_column =
+                    assert_cast<const ColumnInt32&>(pos_null_column->get_nested_column());
+            auto& pos_null_map = pos_null_column->get_null_map_data();
+            auto null_map = ColumnUInt8::create(input_rows_count, false);
+            auto& res_null_map = assert_cast<ColumnUInt8&>(*null_map).get_data();
+
             for (size_t i = 0; i < input_rows_count; ++i) {
-                res_offset[i] = res_data.size();
+                auto pos = pos_column.get_element(i);
+                res_null_map[i] =
+                        pos_null_map[i] || pos <= 0 || pos > num_children ||
+                        block.get_by_position(arguments[pos]).column->get_data_at(i).data ==
+                                nullptr;
+                if (res_null_map[i]) {
+                    res->insert_default();
+                } else {
+                    auto insert_data = block.get_by_position(arguments[pos]).column->get_data_at(i);
+                    res->insert_data(insert_data.data, insert_data.size);
+                }
             }
             block.get_by_position(result).column =
                     ColumnNullable::create(std::move(res), std::move(null_map));
-            return Status::OK();
-        }
+        } else {
+            auto& pos_column =
+                    assert_cast<const ColumnInt32&>(*block.get_by_position(arguments[0]).column);
+            auto null_map = ColumnUInt8::create(input_rows_count, false);
+            auto& res_null_map = assert_cast<ColumnUInt8&>(*null_map).get_data();
 
-        block.get_by_position(result).column =
-                make_nullable(block.get_by_position(arguments[pos]).column);
+            for (size_t i = 0; i < input_rows_count; ++i) {
+                auto pos = pos_column.get_element(i);
+                res_null_map[i] =
+                        pos <= 0 || pos > num_children ||
+                        block.get_by_position(arguments[pos]).column->get_data_at(i).data ==
+                                nullptr;
+                if (res_null_map[i]) {
+                    res->insert_default();
+                } else {
+                    auto insert_data = block.get_by_position(arguments[pos]).column->get_data_at(i);
+                    res->insert_data(insert_data.data, insert_data.size);
+                }
+            }
+            block.get_by_position(result).column =
+                    ColumnNullable::create(std::move(res), std::move(null_map));
+        }
         return Status::OK();
     }
 };
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 cf6ad2c94c..671cdc2cc8 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
@@ -11,6 +11,12 @@ doris
 -- !sql --
 \N
 
+-- !sql --
+1	varchar	varchar
+2	varchar	\N
+3	varchar	\N
+4	varchar	\N
+
 -- !sql --
 ac
 
@@ -225,7 +231,7 @@ hello
 world
 
 -- !sql --
-\\N
+\N
 
 -- !sql --
 world
@@ -234,10 +240,10 @@ world
 hello
 
 -- !sql --
-\\N
+\N
 
 -- !sql --
-\\N
+\N
 
 -- !sql --
 abc
@@ -246,7 +252,7 @@ abc
 #xyz
 
 -- !sql --
-\\N
+\N
 
 -- !sql --
 xyz
@@ -255,7 +261,7 @@ xyz
 123#
 
 -- !sql --
-\\N
+\N
 
 -- !sql --
 true
@@ -367,3 +373,4 @@ tNEW-STRorigin str
 
 -- !sql --
 d***is
+
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 8975cb2c68..569e7822c5 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
@@ -22,6 +22,7 @@ suite("test_string_function") {
     qt_sql "select elt(1, \"hello\", \"doris\");"
     qt_sql "select elt(2, \"hello\", \"doris\");"
     qt_sql "select elt(3, \"hello\", \"doris\");"
+    qt_sql "select c1, c2, elt(c1, c2) from (select number as c1, 'varchar' as c2 from numbers('number'='5') where number > 0) a;"
 
     qt_sql "select append_trailing_char_if_absent('a','c');"
     qt_sql "select append_trailing_char_if_absent('ac','c');"


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org