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

morningman pushed a commit to branch array-type
in repository https://gitbox.apache.org/repos/asf/incubator-doris.git


The following commit(s) were added to refs/heads/array-type by this push:
     new 706f7ff  [feature-wip](array-type) Add codes and UT for array_contains 
and array_position functions (#8401)
706f7ff is described below

commit 706f7ff898b2e2599a29e36e63730d945bf53a5d
Author: camby <[email protected]>
AuthorDate: Mon Mar 14 11:11:56 2022 +0800

    [feature-wip](array-type) Add codes and UT for array_contains and 
array_position functions (#8401)
    
    array_contains function Usage example:
    1. create table with ARRAY column, and insert some data:
    ```
    > select * from array_test;
    +------+------+--------+
    | k1   | k2   | k3     |
    +------+------+--------+
    |    1 |    2 | [1, 2] |
    |    2 |    3 | NULL   |
    |    4 | NULL | []     |
    |    3 | NULL | NULL   |
    +------+------+--------+
    ```
    2. enable vectorized:
    ```
    > set enable_vectorized_engine=true;
    ```
    3. select with array_contains:
    ```
    > select k1,array_contains(k3,1) from array_test;
    +------+-------------------------+
    | k1   | array_contains(`k3`, 1) |
    +------+-------------------------+
    |    3 |                    NULL |
    |    1 |                       1 |
    |    2 |                    NULL |
    |    4 |                       0 |
    +------+-------------------------+
    ```
    4. also we can use array_contains in where condition
    ```
    > select * from array_test where array_contains(k3,1);
    +------+------+--------+
    | k1   | k2   | k3     |
    +------+------+--------+
    |    1 |    2 | [1, 2] |
    +------+------+--------+
    ```
    5. array_position usage example
    ```
    > select k1,k3,array_position(k3,2) from array_test;
    +------+--------+-------------------------+
    | k1   | k3     | array_position(`k3`, 2) |
    +------+--------+-------------------------+
    |    3 | NULL   |                    NULL |
    |    1 | [1, 2] |                       2 |
    |    2 | NULL   |                    NULL |
    |    4 | []     |                       0 |
    +------+--------+-------------------------+
    ```
---
 be/src/vec/CMakeLists.txt                          |   2 +
 .../vec/functions/array/function_array_index.cpp   |  31 ++
 be/src/vec/functions/array/function_array_index.h  | 196 +++++++++++
 .../functions/array/function_array_register.cpp    |  31 ++
 be/src/vec/functions/simple_function_factory.h     |   2 +
 be/src/vec/olap/vgeneric_iterators.cpp             |   3 -
 be/test/vec/exec/vgeneric_iterators_test.cpp       |   3 -
 be/test/vec/function/CMakeLists.txt                |   1 +
 be/test/vec/function/function_array_index_test.cpp | 127 +++++++
 be/test/vec/function/function_test_util.h          | 384 ++++++++++-----------
 .../java/org/apache/doris/catalog/ArrayType.java   |   4 +
 gensrc/script/doris_builtins_functions.py          |  37 ++
 12 files changed, 608 insertions(+), 213 deletions(-)

diff --git a/be/src/vec/CMakeLists.txt b/be/src/vec/CMakeLists.txt
index 0024fd0..fc81438 100644
--- a/be/src/vec/CMakeLists.txt
+++ b/be/src/vec/CMakeLists.txt
@@ -106,6 +106,8 @@ set(VEC_FILES
   exprs/vcast_expr.cpp
   exprs/vcase_expr.cpp
   exprs/vinfo_func.cpp
+  functions/array/function_array_index.cpp
+  functions/array/function_array_register.cpp
   functions/math.cpp
   functions/function_bitmap.cpp
   functions/function_bitmap_variadic.cpp
diff --git a/be/src/vec/functions/array/function_array_index.cpp 
b/be/src/vec/functions/array/function_array_index.cpp
new file mode 100644
index 0000000..474500e
--- /dev/null
+++ b/be/src/vec/functions/array/function_array_index.cpp
@@ -0,0 +1,31 @@
+// 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.
+
+#include "vec/functions/array/function_array_index.h"
+#include "vec/functions/simple_function_factory.h"
+
+namespace doris::vectorized {
+
+struct NameArrayContains { static constexpr auto name = "array_contains"; };
+struct NameArrayPosition { static constexpr auto name = "array_position"; };
+
+void register_function_array_index(SimpleFunctionFactory& factory) {
+    factory.register_function<FunctionArrayIndex<ArrayContainsAction, 
NameArrayContains>>();
+    factory.register_function<FunctionArrayIndex<ArrayPositionAction, 
NameArrayPosition>>();
+}
+
+} // namespace doris::vectorized
diff --git a/be/src/vec/functions/array/function_array_index.h 
b/be/src/vec/functions/array/function_array_index.h
new file mode 100644
index 0000000..f094811
--- /dev/null
+++ b/be/src/vec/functions/array/function_array_index.h
@@ -0,0 +1,196 @@
+// 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.
+// This file is copied from
+// 
https://github.com/ClickHouse/ClickHouse/blob/master/src/Functions/array/arrayIndex.h
+// and modified by Doris
+#pragma once
+
+#include <string_view>
+
+#include "vec/columns/column_array.h"
+#include "vec/columns/column_const.h"
+#include "vec/columns/column_string.h"
+#include "vec/data_types/data_type_number.h"
+#include "vec/functions/function.h"
+
+namespace doris::vectorized {
+
+struct ArrayContainsAction
+{
+    using ResultType = UInt8;
+    static constexpr const bool resume_execution = false;
+    static constexpr void apply(ResultType& current, size_t) noexcept { 
current = 1; }
+};
+
+struct ArrayPositionAction
+{
+    using ResultType = Int64;
+    static constexpr const bool resume_execution = false;
+    static constexpr void apply(ResultType& current, size_t j) noexcept { 
current = j + 1; }
+};
+
+template <typename ConcreteAction, typename Name>
+class FunctionArrayIndex : public IFunction
+{
+public:
+    using ResultType = typename ConcreteAction::ResultType;
+
+    static constexpr auto name = Name::name;
+    static FunctionPtr create() { return 
std::make_shared<FunctionArrayIndex>(); }
+
+    /// Get function name.
+    String get_name() const override { return name; }
+
+    bool is_variadic() const override { return false; }
+
+    size_t get_number_of_arguments() const override { return 2; }
+
+    DataTypePtr get_return_type_impl(const DataTypes& arguments) const 
override {
+        DCHECK(WhichDataType(arguments[0]).is_array());
+        return std::make_shared<DataTypeNumber<ResultType>>();
+    }
+
+    Status execute_impl(FunctionContext* context, Block& block, const 
ColumnNumbers& arguments,
+                        size_t result, size_t input_rows_count) override {
+        return execute_non_nullable(block, arguments, result, 
input_rows_count);
+    }
+
+private:
+    static bool execute_string(Block& block, const ColumnNumbers& arguments, 
size_t result, size_t input_rows_count) {
+        // check array nested column type and get data
+        auto array_column = 
check_and_get_column<ColumnArray>(*block.get_by_position(arguments[0]).column);
+        DCHECK(array_column != nullptr);
+        auto nested_column = 
check_and_get_column<ColumnString>(array_column->get_data());
+        if (!nested_column) {
+            return false;
+        }
+        const auto& arr_offs = array_column->get_offsets();
+        const auto& str_offs = nested_column->get_offsets();
+        const auto& str_chars = nested_column->get_chars();
+
+        // check right column type
+        auto ptr = block.get_by_position(arguments[1]).column;
+        if (is_column_const(*ptr)) {
+            ptr = 
check_and_get_column<ColumnConst>(ptr)->get_data_column_ptr();
+        }
+        if (!check_and_get_column<ColumnString>(*ptr)) {
+            return false;
+        }
+
+        // expand const column and get data
+        auto right_column = 
check_and_get_column<ColumnString>(*block.get_by_position(arguments[1]).column->convert_to_full_column_if_const());
+        const auto& right_offs = right_column->get_offsets();
+        const auto& right_chars = right_column->get_chars();
+
+        // prepare return data
+        auto dst = ColumnVector<ResultType>::create();
+        auto& dst_data = dst->get_data();
+        dst_data.resize(input_rows_count);
+
+        // process
+        for (size_t row = 0; row < input_rows_count; ++row) {
+            ResultType res = 0;
+            size_t off = arr_offs[row - 1];
+            size_t len = arr_offs[row] - off;
+
+            size_t right_off = right_offs[row - 1];
+            size_t right_len = right_offs[row] - right_off;
+            for (size_t pos = 0; pos < len; ++pos) {
+                size_t str_pos = str_offs[pos + off - 1];
+                size_t str_len = str_offs[pos + off] - str_pos;
+
+                const char* left_raw_v = reinterpret_cast<const 
char*>(&str_chars[str_pos]);
+                const char* right_raw_v = reinterpret_cast<const 
char*>(&right_chars[right_off]);
+                if (std::string_view(left_raw_v, str_len) == 
std::string_view(right_raw_v, right_len)) {
+                    ConcreteAction::apply(res, pos);
+                    break;
+                }
+            }
+            dst_data[row] = res;
+        }
+        block.replace_by_position(result, std::move(dst));
+        return true;
+    }
+
+#define INTEGRAL_TPL_PACK UInt8, UInt16, UInt32, UInt64, Int8, Int16, Int32, 
Int64, Float32, Float64
+    template <typename... Integral>
+    static bool execute_integral(Block& block, const ColumnNumbers& arguments, 
size_t result, size_t input_rows_count) {
+        return (execute_integral_expanded<Integral, Integral...>(block, 
arguments, result, input_rows_count) || ...);
+    }
+    template <typename A, typename... Other>
+    static bool execute_integral_expanded(Block& block, const ColumnNumbers& 
arguments, size_t result, size_t input_rows_count) {
+        return (execute_integral_impl<A, Other>(block, arguments, result, 
input_rows_count) || ...);
+    }
+    template <typename Initial, typename Resulting>
+    static bool execute_integral_impl(Block& block, const ColumnNumbers& 
arguments, size_t result, size_t input_rows_count) {
+        // check array nested column type and get data
+        auto array_column = 
check_and_get_column<ColumnArray>(*block.get_by_position(arguments[0]).column);
+        DCHECK(array_column != nullptr);
+        auto nested_column = 
check_and_get_column<ColumnVector<Initial>>(array_column->get_data());
+        if (!nested_column) {
+            return false;
+        }
+        const auto& offsets = array_column->get_offsets();
+        const auto& nested_data = nested_column->get_data();
+
+        // check right column type
+        auto ptr = block.get_by_position(arguments[1]).column;
+        if (is_column_const(*ptr)) {
+            ptr = 
check_and_get_column<ColumnConst>(ptr)->get_data_column_ptr();
+        }
+        if (!check_and_get_column<ColumnVector<Resulting>>(*ptr)) {
+            return false;
+        }
+
+        // expand const column and get data
+        auto right_column = 
block.get_by_position(arguments[1]).column->convert_to_full_column_if_const();
+        const auto& right_data = 
check_and_get_column<ColumnVector<Resulting>>(*right_column)->get_data();
+
+        // prepare return data
+        auto dst = ColumnVector<ResultType>::create();
+        auto& dst_data = dst->get_data();
+        dst_data.resize(input_rows_count);
+
+        // process
+        for (size_t row = 0; row < input_rows_count; ++row) {
+            ResultType res = 0;
+            size_t off = offsets[row - 1];
+            size_t len = offsets[row] - off;
+            for (size_t pos = 0; pos < len; ++pos) {
+                if (nested_data[pos + off] == right_data[row]) {
+                    ConcreteAction::apply(res, pos);
+                    break;
+                }
+            }
+            dst_data[row] = res;
+        }
+        block.replace_by_position(result, std::move(dst));
+        return true;
+    }
+
+    Status execute_non_nullable(Block& block, const ColumnNumbers& arguments, 
size_t result, size_t input_rows_count) {
+        WhichDataType right_type(block.get_by_position(arguments[1]).type);
+        if ((right_type.is_string() && execute_string(block, arguments, 
result, input_rows_count)) ||
+                execute_integral<INTEGRAL_TPL_PACK>(block, arguments, result, 
input_rows_count)) {
+            return Status::OK();
+        }
+        return Status::OK();
+    }
+#undef INTEGRAL_TPL_PACK
+};
+
+} // namespace doris::vectorized
diff --git a/be/src/vec/functions/array/function_array_register.cpp 
b/be/src/vec/functions/array/function_array_register.cpp
new file mode 100644
index 0000000..e9ab763
--- /dev/null
+++ b/be/src/vec/functions/array/function_array_register.cpp
@@ -0,0 +1,31 @@
+// 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.
+// This file is copied from
+// 
https://github.com/ClickHouse/ClickHouse/blob/master/src/Functions/array/registerFunctionsArray.cpp
+// and modified by Doris
+
+#include "vec/functions/simple_function_factory.h"
+
+namespace doris::vectorized {
+
+void register_function_array_index(SimpleFunctionFactory&);
+
+void register_function_array(SimpleFunctionFactory& factory) {
+    register_function_array_index(factory);
+}
+
+} // namespace doris::vectorized
diff --git a/be/src/vec/functions/simple_function_factory.h 
b/be/src/vec/functions/simple_function_factory.h
index f6fdb6c..46124b6 100644
--- a/be/src/vec/functions/simple_function_factory.h
+++ b/be/src/vec/functions/simple_function_factory.h
@@ -73,6 +73,7 @@ void 
register_function_datetime_floor_ceil(SimpleFunctionFactory& factory);
 void register_function_convert_tz(SimpleFunctionFactory& factory);
 void register_function_least_greast(SimpleFunctionFactory& factory);
 void register_function_fake(SimpleFunctionFactory& factory);
+void register_function_array(SimpleFunctionFactory& factory);
 
 void register_function_encryption(SimpleFunctionFactory& factory);
 void register_function_regexp_extract(SimpleFunctionFactory& factory);
@@ -200,6 +201,7 @@ public:
             register_function_encryption(instance);
             register_function_regexp_extract(instance);
             register_function_hex_variadic(instance);
+            register_function_array(instance);
         });
         return instance;
     }
diff --git a/be/src/vec/olap/vgeneric_iterators.cpp 
b/be/src/vec/olap/vgeneric_iterators.cpp
index 87845d6..5878f21 100644
--- a/be/src/vec/olap/vgeneric_iterators.cpp
+++ b/be/src/vec/olap/vgeneric_iterators.cpp
@@ -143,9 +143,6 @@ public:
                 if (data_type == nullptr) {
                     return Status::RuntimeError("invalid data type");
                 }
-                if (column_desc->is_nullable()) {
-                    data_type = 
std::make_shared<vectorized::DataTypeNullable>(std::move(data_type));
-                }
                 auto column = data_type->create_column();
                 column->reserve(_block_row_max);
                 _block.insert(ColumnWithTypeAndName(std::move(column), 
data_type, column_desc->name()));
diff --git a/be/test/vec/exec/vgeneric_iterators_test.cpp 
b/be/test/vec/exec/vgeneric_iterators_test.cpp
index 6606111..f7f2723 100644
--- a/be/test/vec/exec/vgeneric_iterators_test.cpp
+++ b/be/test/vec/exec/vgeneric_iterators_test.cpp
@@ -55,9 +55,6 @@ static void create_block(Schema& schema, vectorized::Block& 
block)
         ASSERT_TRUE(column_desc);
         auto data_type = Schema::get_data_type_ptr(*column_desc);
         ASSERT_NE(data_type, nullptr);
-        if (column_desc->is_nullable()) {
-            data_type = 
std::make_shared<vectorized::DataTypeNullable>(std::move(data_type));
-        }
         auto column = data_type->create_column();
         vectorized::ColumnWithTypeAndName ctn(std::move(column), data_type, 
column_desc->name());
         block.insert(ctn);
diff --git a/be/test/vec/function/CMakeLists.txt 
b/be/test/vec/function/CMakeLists.txt
index 6ae9b05..5ddeaa8 100644
--- a/be/test/vec/function/CMakeLists.txt
+++ b/be/test/vec/function/CMakeLists.txt
@@ -18,6 +18,7 @@
 # where to put generated libraries
 set(EXECUTABLE_OUTPUT_PATH "${BUILD_DIR}/test/vec/function")
 
+ADD_BE_TEST(function_array_index_test)
 ADD_BE_TEST(function_bitmap_test)
 ADD_BE_TEST(function_comparison_test)
 ADD_BE_TEST(function_hash_test)
diff --git a/be/test/vec/function/function_array_index_test.cpp 
b/be/test/vec/function/function_array_index_test.cpp
new file mode 100644
index 0000000..7c34c38
--- /dev/null
+++ b/be/test/vec/function/function_array_index_test.cpp
@@ -0,0 +1,127 @@
+// 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.
+
+#include <gtest/gtest.h>
+#include <time.h>
+
+#include <string>
+
+#include "function_test_util.h"
+#include "runtime/tuple_row.h"
+#include "util/url_coding.h"
+#include "vec/core/field.h"
+
+namespace doris::vectorized {
+
+TEST(function_array_index_test, array_contains) {
+    std::string func_name = "array_contains";
+    Array empty_arr;
+
+    // array_contains(Array<Int32>, Int32)
+    {
+        InputTypeSet input_types = {TypeIndex::Array, TypeIndex::Int32, 
TypeIndex::Int32};
+
+        Array vec = {Int32(1), Int32(2), Int32(3)};
+        DataSet data_set = {{{vec, 2}, UInt8(1)}, {{vec, 4}, UInt8(0)}, 
{{Null(), 1}, Null()}, {{empty_arr, 1}, UInt8(0)}};
+
+        check_function<DataTypeUInt8, true>(func_name, input_types, data_set);
+    }
+
+    // array_contains(Array<Int32>, Int8)
+    {
+        InputTypeSet input_types = {TypeIndex::Array, TypeIndex::Int32, 
TypeIndex::Int8};
+
+        Array vec = {Int32(1), Int32(2), Int32(3)};
+        DataSet data_set = {{{vec, Int8(2)}, UInt8(1)}, {{vec, Int8(4)}, 
UInt8(0)}, {{Null(), Int8(1)}, Null()}, {{empty_arr, Int8(1)}, UInt8(0)}};
+
+        check_function<DataTypeUInt8, true>(func_name, input_types, data_set);
+    }
+
+    // array_contains(Array<Int8>, Int64)
+    {
+        InputTypeSet input_types = {TypeIndex::Array, TypeIndex::Int8, 
TypeIndex::Int64};
+
+        Array vec = {Int8(1), Int8(2), Int8(3)};
+        DataSet data_set = {{{vec, Int64(2)}, UInt8(1)}, {{vec, Int64(4)}, 
UInt8(0)}, {{Null(), Int64(1)}, Null()}, {{empty_arr, Int64(1)}, UInt8(0)}};
+
+        check_function<DataTypeUInt8, true>(func_name, input_types, data_set);
+    }
+
+    // array_contains(Array<String>, String)
+    {
+        InputTypeSet input_types = {TypeIndex::Array, TypeIndex::String, 
TypeIndex::String};
+
+        Array vec = {Field("abc", 3), Field("", 0), Field("def",3)};
+        DataSet data_set = {{{vec, std::string("abc")}, UInt8(1)}, {{vec, 
std::string("aaa")}, UInt8(0)},
+                            {{vec, std::string("")}, UInt8(1)}, {{Null(), 
std::string("abc")}, Null()}, {{empty_arr, std::string("")}, UInt8(0)}};
+
+        check_function<DataTypeUInt8, true>(func_name, input_types, data_set);
+    }
+}
+
+TEST(function_array_index_test, array_position) {
+    std::string func_name = "array_position";
+    Array empty_arr;
+
+    // array_position(Array<Int32>, Int32)
+    {
+        InputTypeSet input_types = {TypeIndex::Array, TypeIndex::Int32, 
TypeIndex::Int32};
+
+        Array vec = {Int32(1), Int32(2), Int32(3)};
+        DataSet data_set = {{{vec, 2}, Int64(2)}, {{vec, 4}, Int64(0)}, 
{{Null(), 1}, Null()}, {{empty_arr, 1}, Int64(0)}};
+
+        check_function<DataTypeInt64, true>(func_name, input_types, data_set);
+    }
+
+    // array_position(Array<Int32>, Int8)
+    {
+        InputTypeSet input_types = {TypeIndex::Array, TypeIndex::Int32, 
TypeIndex::Int8};
+
+        Array vec = {Int32(1), Int32(2), Int32(3)};
+        DataSet data_set = {{{vec, Int8(2)}, Int64(2)}, {{vec, Int8(4)}, 
Int64(0)}, {{Null(), Int8(1)}, Null()}, {{empty_arr, Int8(1)}, Int64(0)}};
+
+        check_function<DataTypeInt64, true>(func_name, input_types, data_set);
+    }
+
+    // array_position(Array<Int8>, Int64)
+    {
+        InputTypeSet input_types = {TypeIndex::Array, TypeIndex::Int8, 
TypeIndex::Int64};
+
+        Array vec = {Int8(1), Int8(2), Int8(3)};
+        DataSet data_set = {{{vec, Int64(2)}, Int64(2)}, {{vec, Int64(4)}, 
Int64(0)}, {{Null(), Int64(1)}, Null()}, {{empty_arr, Int64(1)}, Int64(0)}};
+
+        check_function<DataTypeInt64, true>(func_name, input_types, data_set);
+    }
+
+    // array_position(Array<String>, String)
+    {
+        InputTypeSet input_types = {TypeIndex::Array, TypeIndex::String, 
TypeIndex::String};
+
+        Array vec = {Field("abc", 3), Field("", 0), Field("def",3)};
+        DataSet data_set = {{{vec, std::string("abc")}, Int64(1)}, {{vec, 
std::string("aaa")}, Int64(0)},
+                            {{vec, std::string("")}, Int64(2)}, {{Null(), 
std::string("abc")}, Null()}, {{empty_arr, std::string("")}, Int64(0)}};
+
+        check_function<DataTypeInt64, true>(func_name, input_types, data_set);
+    }
+}
+
+} // namespace doris::vectorized
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    return RUN_ALL_TESTS();
+}
diff --git a/be/test/vec/function/function_test_util.h 
b/be/test/vec/function/function_test_util.h
index 247c309..c345354 100644
--- a/be/test/vec/function/function_test_util.h
+++ b/be/test/vec/function/function_test_util.h
@@ -68,19 +68,114 @@ using FLOAT = float;
 inline auto DECIMAL = Decimal<Int128>::double_to_decimal;
 
 using DATETIME = std::string;
+
+struct UTDataTypeDesc {
+    DataTypePtr data_type;
+    doris_udf::FunctionContext::TypeDesc type_desc;
+    std::string col_name;
+    bool is_const = false;
+    bool is_nullable = true;
+};
+using UTDataTypeDescs = std::vector<UTDataTypeDesc>;
+
 } // namespace ut_type
 
-template <typename ColumnType, typename Column, typename NullColumn>
-void insert_column_to_block(std::list<ColumnPtr>& columns, 
ColumnsWithTypeAndName& ctn,
-                            Column&& col, NullColumn&& null_map, Block& block,
-                            const std::string& col_name, int i, bool is_const, 
int row_size) {
-    columns.emplace_back(ColumnNullable::create(std::move(col), 
std::move(null_map)));
-    ColumnWithTypeAndName type_and_name(
-            is_const ? ColumnConst::create(columns.back()->get_ptr(), row_size)
-                     : columns.back()->get_ptr(),
-            make_nullable(std::make_shared<ColumnType>()), col_name);
-    block.insert(i, type_and_name);
-    ctn.emplace_back(type_and_name);
+size_t type_index_to_data_type(const std::vector<std::any>& input_types, 
size_t index,
+                               doris_udf::FunctionContext::TypeDesc& desc,
+                               DataTypePtr& type) {
+    if(index < 0 || index >= input_types.size()) {
+        return -1;
+    }
+
+    TypeIndex tp;
+    if (input_types[index].type() == typeid(Consted)) {
+        tp = std::any_cast<Consted>(input_types[index]).tp;
+    } else {
+        tp = std::any_cast<TypeIndex>(input_types[index]);
+    }
+
+    switch (tp) {
+    case TypeIndex::String:
+        desc.type = doris_udf::FunctionContext::TYPE_STRING;
+        type = std::make_shared<DataTypeString>();
+        return 1;
+    case TypeIndex::BitMap:
+        desc.type = doris_udf::FunctionContext::TYPE_OBJECT;
+        type = std::make_shared<DataTypeBitMap>();
+        return 1;
+    case TypeIndex::Int8:
+        desc.type = doris_udf::FunctionContext::TYPE_TINYINT;
+        type = std::make_shared<DataTypeInt8>();
+        return 1;
+    case TypeIndex::Int16:
+        desc.type = doris_udf::FunctionContext::TYPE_SMALLINT;
+        type = std::make_shared<DataTypeInt16>();
+        return 1;
+    case TypeIndex::Int32:
+        desc.type = doris_udf::FunctionContext::TYPE_INT;
+        type = std::make_shared<DataTypeInt32>();
+        return 1;
+    case TypeIndex::Int64:
+        desc.type = doris_udf::FunctionContext::TYPE_BIGINT;
+        type = std::make_shared<DataTypeInt64>();
+        return 1;
+    case TypeIndex::Int128:
+        desc.type = doris_udf::FunctionContext::TYPE_LARGEINT;
+        type = std::make_shared<DataTypeInt128>();
+        return 1;
+    case TypeIndex::Float64:
+        desc.type = doris_udf::FunctionContext::TYPE_DOUBLE;
+        type = std::make_shared<DataTypeFloat64>();
+        return 1;
+    case TypeIndex::Decimal128:
+        desc.type = doris_udf::FunctionContext::TYPE_DECIMALV2;
+        type = std::make_shared<DataTypeDecimal<Decimal128>>();
+        return 1;
+    case TypeIndex::DateTime:
+        desc.type = doris_udf::FunctionContext::TYPE_DATETIME;
+        type = std::make_shared<DataTypeDateTime>();
+        return 1;
+    case TypeIndex::Date:
+        desc.type = doris_udf::FunctionContext::TYPE_DATE;
+        type = std::make_shared<DataTypeDateTime>();
+        return 1;
+    case TypeIndex::Array: {
+        desc.type = doris_udf::FunctionContext::TYPE_ARRAY;
+        doris_udf::FunctionContext::TypeDesc sub_desc;
+        DataTypePtr sub_type = nullptr;
+        size_t ret = type_index_to_data_type(input_types, index + 1, sub_desc, 
sub_type);
+        if (ret <= 0) {
+            return ret;
+        }
+        desc.children.push_back(doris_udf::FunctionContext::TypeDesc());
+        type = std::make_shared<DataTypeArray>(std::move(sub_type));
+        return ret + 1;
+    }
+    default:
+        LOG(WARNING) << "not supported TypeIndex:" << (int)tp;
+        return 0;
+    }
+}
+bool parse_ut_data_type(const std::vector<std::any>& input_types, 
ut_type::UTDataTypeDescs& descs) {
+    descs.clear();
+    descs.reserve(input_types.size());
+    for (size_t i = 0; i < input_types.size(); ) {
+        ut_type::UTDataTypeDesc desc;
+        if (input_types[i].type() == typeid(Consted)) {
+            desc.is_const = true;
+        }
+        size_t res = type_index_to_data_type(input_types, i, desc.type_desc, 
desc.data_type);
+        if (res <= 0) {
+            return false;
+        }
+        if (desc.is_nullable) {
+            desc.data_type = make_nullable(std::move(desc.data_type));
+        }
+        desc.col_name = "k" + std::to_string(i);
+        descs.emplace_back(desc);
+        i += res;
+    }
+    return true;
 }
 
 // Null values are represented by Null()
@@ -89,226 +184,101 @@ void insert_column_to_block(std::list<ColumnPtr>& 
columns, ColumnsWithTypeAndNam
 template <typename ReturnType, bool nullable = false>
 void check_function(const std::string& func_name, const std::vector<std::any>& 
input_types,
                     const DataSet& data_set) {
-    size_t row_size = data_set.size();
-    size_t column_size = input_types.size();
+    // 1.0 create data type
+    ut_type::UTDataTypeDescs descs;
+    ASSERT_TRUE(parse_ut_data_type(input_types, descs));
 
-    std::list<ColumnPtr> columns;
+    // 1.1 insert data and create block
+    auto row_size = data_set.size();
     Block block;
-    ColumnNumbers arguments;
-    ColumnsWithTypeAndName ctn;
-    std::vector<std::shared_ptr<ColumnPtrWrapper>> constant_col_ptrs;
-    std::vector<ColumnPtrWrapper*> constant_cols;
-    std::vector<doris_udf::FunctionContext::TypeDesc> arg_types;
-    doris_udf::FunctionContext::TypeDesc arg_type;
-    // 1. build block and column type and names
-    for (int i = 0; i < column_size; i++) {
-        TypeIndex tp;
-        bool is_const;
-        if (input_types[i].type() == typeid(Consted)) {
-            tp = std::any_cast<Consted>(input_types[i]).tp;
-            is_const = true;
-        } else {
-            tp = std::any_cast<TypeIndex>(input_types[i]);
-            is_const = false;
-        }
-
-        std::string col_name = "k" + std::to_string(i);
-
-        auto null_map = ColumnUInt8::create(row_size, false);
-        auto& null_map_data = null_map->get_data();
+    for (size_t i = 0; i < descs.size(); ++i) {
+        auto& desc = descs[i];
+        auto column = desc.data_type->create_column();
+        column->reserve(row_size);
+
+        auto type_ptr = desc.data_type->is_nullable() ?
+             ((DataTypeNullable*)(desc.data_type.get()))->get_nested_type() : 
desc.data_type;
+        WhichDataType type(type_ptr);
+
+        for (int j = 0; j < row_size; j++) {
+            if (data_set[j].first[i].type() == typeid(Null)) {
+                column->insert_data(nullptr, 0);
+                continue;
+            }
 
-        if (tp == TypeIndex::String) {
-            auto col = ColumnString::create();
-            for (int j = 0; j < row_size; j++) {
-                if (data_set[j].first[i].type() == typeid(Null)) {
-                    null_map_data[j] = true;
-                    col->insert_default();
-                    continue;
-                }
+            if (type.is_string()) {
                 auto str = 
std::any_cast<ut_type::STRING>(data_set[j].first[i]);
-                col->insert_data(str.c_str(), str.size());
-            }
-            insert_column_to_block<DataTypeString>(columns, ctn, 
std::move(col),
-                                                   std::move(null_map), block, 
col_name, i,
-                                                   is_const, row_size);
-            arg_type.type = doris_udf::FunctionContext::TYPE_STRING;
-        } else if (tp == TypeIndex::BitMap) {
-            auto col = ColumnBitmap::create();
-            for (int j = 0; j < row_size; j++) {
-                if (data_set[j].first[i].type() == typeid(Null)) {
-                    null_map_data[j] = true;
-                    col->insert_default();
-                    continue;
-                }
+                column->insert_data(str.c_str(), str.size());
+            }  else if (type.idx == TypeIndex::BitMap) {
                 BitmapValue* bitmap = 
std::any_cast<BitmapValue*>(data_set[j].first[i]);
-                col->insert_value(*bitmap);
-            }
-            insert_column_to_block<DataTypeBitMap>(columns, ctn, 
std::move(col),
-                                                   std::move(null_map), block, 
col_name, i,
-                                                   is_const, row_size);
-            arg_type.type = doris_udf::FunctionContext::TYPE_OBJECT;
-        } else if (tp == TypeIndex::Int8) {
-            auto col = ColumnInt8::create();
-
-            for (int j = 0; j < row_size; j++) {
-                if (data_set[j].first[i].type() == typeid(Null)) {
-                    null_map_data[j] = true;
-                    col->insert_default();
-                    continue;
-                }
+                column->insert_data((char*)bitmap, sizeof(BitmapValue));
+            } else if (type.is_int8()) {
                 auto value = 
std::any_cast<ut_type::TINYINT>(data_set[j].first[i]);
-                col->insert_data(reinterpret_cast<char*>(&value), 0);
-            }
-            insert_column_to_block<DataTypeInt8>(columns, ctn, std::move(col), 
std::move(null_map),
-                                                 block, col_name, i, is_const, 
row_size);
-            arg_type.type = doris_udf::FunctionContext::TYPE_TINYINT;
-        } else if (tp == TypeIndex::Int16) {
-            auto col = ColumnInt16::create();
-
-            for (int j = 0; j < row_size; j++) {
-                if (data_set[j].first[i].type() == typeid(Null)) {
-                    null_map_data[j] = true;
-                    col->insert_default();
-                    continue;
-                }
+                column->insert_data(reinterpret_cast<char*>(&value), 0);
+            } else if (type.is_int16()) {
                 auto value = 
std::any_cast<ut_type::SMALLINT>(data_set[j].first[i]);
-                col->insert_data(reinterpret_cast<char*>(&value), 0);
-            }
-            insert_column_to_block<DataTypeInt16>(columns, ctn, 
std::move(col), std::move(null_map),
-                                                  block, col_name, i, 
is_const, row_size);
-            arg_type.type = doris_udf::FunctionContext::TYPE_SMALLINT;
-        } else if (tp == TypeIndex::Int32) {
-            auto col = ColumnInt32::create();
-
-            for (int j = 0; j < row_size; j++) {
-                if (data_set[j].first[i].type() == typeid(Null)) {
-                    null_map_data[j] = true;
-                    col->insert_default();
-                    continue;
-                }
+                column->insert_data(reinterpret_cast<char*>(&value), 0);
+            } else if (type.is_int32()) {
                 auto value = std::any_cast<ut_type::INT>(data_set[j].first[i]);
-                col->insert_data(reinterpret_cast<char*>(&value), 0);
-            }
-            insert_column_to_block<DataTypeInt32>(columns, ctn, 
std::move(col), std::move(null_map),
-                                                  block, col_name, i, 
is_const, row_size);
-            arg_type.type = doris_udf::FunctionContext::TYPE_INT;
-        } else if (tp == TypeIndex::Int64) {
-            auto col = ColumnInt64::create();
-
-            for (int j = 0; j < row_size; j++) {
-                if (data_set[j].first[i].type() == typeid(Null)) {
-                    null_map_data[j] = true;
-                    col->insert_default();
-                    continue;
-                }
+                column->insert_data(reinterpret_cast<char*>(&value), 0);
+            } else if (type.is_int64()) {
                 auto value = 
std::any_cast<ut_type::BIGINT>(data_set[j].first[i]);
-                col->insert_data(reinterpret_cast<char*>(&value), 0);
-            }
-            insert_column_to_block<DataTypeInt64>(columns, ctn, 
std::move(col), std::move(null_map),
-                                                  block, col_name, i, 
is_const, row_size);
-            arg_type.type = doris_udf::FunctionContext::TYPE_BIGINT;
-        } else if (tp == TypeIndex::Int128) {
-            auto col = ColumnInt128::create();
-
-            for (int j = 0; j < row_size; j++) {
-                if (data_set[j].first[i].type() == typeid(Null)) {
-                    null_map_data[j] = true;
-                    col->insert_default();
-                    continue;
-                }
+                column->insert_data(reinterpret_cast<char*>(&value), 0);
+            } else if (type.is_int128()) {
                 auto value = 
std::any_cast<ut_type::LARGEINT>(data_set[j].first[i]);
-                col->insert_data(reinterpret_cast<char*>(&value), 0);
-            }
-            insert_column_to_block<DataTypeInt128>(columns, ctn, 
std::move(col),
-                                                   std::move(null_map), block, 
col_name, i,
-                                                   is_const, row_size);
-            arg_type.type = doris_udf::FunctionContext::TYPE_LARGEINT;
-        } else if (tp == TypeIndex::Float64) {
-            auto col = ColumnFloat64::create();
-
-            for (int j = 0; j < row_size; j++) {
-                if (data_set[j].first[i].type() == typeid(Null)) {
-                    null_map_data[j] = true;
-                    col->insert_default();
-                    continue;
-                }
+                column->insert_data(reinterpret_cast<char*>(&value), 0);
+            } else if (type.is_float64()) {
                 auto value = 
std::any_cast<ut_type::DOUBLE>(data_set[j].first[i]);
-                col->insert_data(reinterpret_cast<char*>(&value), 0);
-            }
-            insert_column_to_block<DataTypeFloat64>(columns, ctn, 
std::move(col),
-                                                    std::move(null_map), 
block, col_name, i,
-                                                    is_const, row_size);
-            arg_type.type = doris_udf::FunctionContext::TYPE_DOUBLE;
-        } else if (tp == TypeIndex::Decimal128) {
-            auto col = ColumnDecimal<Decimal128>::create(0, 9);
-
-            for (int j = 0; j < row_size; j++) {
-                if (data_set[j].first[i].type() == typeid(Null)) {
-                    null_map_data[j] = true;
-                    col->insert_default();
-                    continue;
-                }
+                column->insert_data(reinterpret_cast<char*>(&value), 0);
+            } else if (type.is_float64()) {
+                auto value = 
std::any_cast<ut_type::DOUBLE>(data_set[j].first[i]);
+                column->insert_data(reinterpret_cast<char*>(&value), 0);
+            } else if (type.is_decimal128()) {
                 auto value = 
std::any_cast<Decimal<Int128>>(data_set[j].first[i]);
-                col->insert_data(reinterpret_cast<char*>(&value), 0);
-            }
-            insert_column_to_block<DataTypeDecimal<Decimal128>>(columns, ctn, 
std::move(col),
-                                                                
std::move(null_map), block,
-                                                                col_name, i, 
is_const, row_size);
-            arg_type.type = doris_udf::FunctionContext::TYPE_DECIMALV2;
-        } else if (tp == TypeIndex::DateTime) {
-            static std::string date_time_format("%Y-%m-%d %H:%i:%s");
-            auto col = ColumnInt64::create();
-
-            for (int j = 0; j < row_size; j++) {
-                if (data_set[j].first[i].type() == typeid(Null)) {
-                    null_map_data[j] = true;
-                    col->insert_default();
-                    continue;
-                }
+                column->insert_data(reinterpret_cast<char*>(&value), 0);
+            } else if (type.is_date_time()) {
+                static std::string date_time_format("%Y-%m-%d %H:%i:%s");
                 auto datetime_str = 
std::any_cast<std::string>(data_set[j].first[i]);
                 VecDateTimeValue v;
                 v.from_date_format_str(date_time_format.c_str(), 
date_time_format.size(),
                                        datetime_str.c_str(), 
datetime_str.size());
                 v.to_datetime();
-                col->insert_data(reinterpret_cast<char*>(&v), 0);
-            }
-            insert_column_to_block<DataTypeDateTime>(columns, ctn, 
std::move(col),
-                                                     std::move(null_map), 
block, col_name, i,
-                                                     is_const, row_size);
-            arg_type.type = doris_udf::FunctionContext::TYPE_DATETIME;
-        } else if (tp == TypeIndex::Date) {
-            static std::string date_time_format("%Y-%m-%d");
-            auto col = ColumnInt64::create();
-
-            for (int j = 0; j < row_size; j++) {
-                if (data_set[j].first[i].type() == typeid(Null)) {
-                    null_map_data[j] = true;
-                    col->insert_default();
-                    continue;
-                }
+                column->insert_data(reinterpret_cast<char*>(&v), 0);
+            } else if (type.is_date()) {
+                static std::string date_time_format("%Y-%m-%d");
                 auto datetime_str = 
std::any_cast<std::string>(data_set[j].first[i]);
                 VecDateTimeValue v;
                 v.from_date_format_str(date_time_format.c_str(), 
date_time_format.size(),
                                        datetime_str.c_str(), 
datetime_str.size());
                 v.cast_to_date();
-                col->insert_data(reinterpret_cast<char*>(&v), 0);
+                column->insert_data(reinterpret_cast<char*>(&v), 0);
+            } else if (type.is_array()) {
+                auto v = std::any_cast<Array>(data_set[j].first[i]);
+                column->insert(v);
+            } else {
+                LOG(WARNING) << "dataset not supported for TypeIndex:" << 
(int)type.idx;
+                ASSERT_TRUE(false);
             }
-            insert_column_to_block<DataTypeDateTime>(columns, ctn, 
std::move(col),
-                                                     std::move(null_map), 
block, col_name, i,
-                                                     is_const, row_size);
-            arg_type.type = doris_udf::FunctionContext::TYPE_DATE;
-        } else {
-            ASSERT_TRUE(false);
-            arg_type.type = doris_udf::FunctionContext::INVALID_TYPE;
         }
+
+        if (desc.is_const) {
+            column = ColumnConst::create(std::move(column), row_size);
+        }
+        block.insert({std::move(column), desc.data_type, desc.col_name});
+    }
+
+    // 1.2 parepare args for function call
+    ColumnNumbers arguments;
+    std::vector<doris_udf::FunctionContext::TypeDesc> arg_types;
+    std::vector<std::shared_ptr<ColumnPtrWrapper>> constant_col_ptrs;
+    std::vector<ColumnPtrWrapper*> constant_cols;
+    for (size_t i = 0; i < descs.size(); ++i) {
+        auto& desc = descs[i];
         arguments.push_back(i);
-        arg_types.push_back(arg_type);
-        if (is_const) {
-            const auto& column = block.get_by_position(i).column;
-            std::shared_ptr<ColumnPtrWrapper> constant_col =
-                    std::make_shared<ColumnPtrWrapper>(column);
-            constant_col_ptrs.push_back(constant_col);
-            constant_cols.push_back(constant_col.get());
+        arg_types.push_back(desc.type_desc);
+        if (desc.is_const) {
+            
constant_col_ptrs.push_back(std::make_shared<ColumnPtrWrapper>(block.get_by_position(i).column));
+            constant_cols.push_back(constant_col_ptrs.back().get());
         } else {
             constant_cols.push_back(nullptr);
         }
@@ -317,7 +287,7 @@ void check_function(const std::string& func_name, const 
std::vector<std::any>& i
     // 2. execute function
     auto return_type = nullable ? make_nullable(std::make_shared<ReturnType>())
                                 : std::make_shared<ReturnType>();
-    auto func = SimpleFunctionFactory::instance().get_function(func_name, ctn, 
return_type);
+    auto func = SimpleFunctionFactory::instance().get_function(func_name, 
block.get_columns_with_type_and_name(), return_type);
     ASSERT_TRUE(func != nullptr);
 
     doris_udf::FunctionContext::TypeDesc fn_ctx_return;
diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/ArrayType.java 
b/fe/fe-core/src/main/java/org/apache/doris/catalog/ArrayType.java
index 172bb9f..f3adcc6 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/ArrayType.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/ArrayType.java
@@ -66,9 +66,13 @@ public class ArrayType extends Type {
             return false;
         }
 
+        // Array(Null) is a virtual Array type, can match any Array(...) type
         if (itemType.isNull()) {
             return true;
         }
+        if (((ArrayType) t).getItemType().isNull()) {
+            return true;
+        }
 
         return itemType.matchesType(((ArrayType) t).itemType);
     }
diff --git a/gensrc/script/doris_builtins_functions.py 
b/gensrc/script/doris_builtins_functions.py
index bf1a895..2e42f49 100755
--- a/gensrc/script/doris_builtins_functions.py
+++ b/gensrc/script/doris_builtins_functions.py
@@ -120,6 +120,43 @@ visible_functions = [
     [['%element_extract%'], 'VARCHAR', ['MAP', 'INT'],  '', '', '', '', ''],
     [['%element_extract%'], 'VARCHAR', ['STRUCT', 'INT'],  '', '', '', '', ''],
     [['%element_extract%'], 'VARCHAR', ['STRUCT', 'VARCHAR'],  '', '', '', '', 
''],
+    [['array_contains'], 'BOOLEAN', ['ARRAY', 'TINYINT'],
+        
'_ZN5doris10vectorized18FunctionArrayIndexINS0_19ArrayContainsActionENS0_17NameArrayContainsEE12execute_implEPN9doris_udf15FunctionContextERNS0_5BlockERKSt6vectorImSaImEEmm',
+        '', '', 'vec', ''],
+    [['array_contains'], 'BOOLEAN', ['ARRAY', 'SMALLINT'],
+        
'_ZN5doris10vectorized18FunctionArrayIndexINS0_19ArrayContainsActionENS0_17NameArrayContainsEE12execute_implEPN9doris_udf15FunctionContextERNS0_5BlockERKSt6vectorImSaImEEmm',
+        '', '', 'vec', ''],
+    [['array_contains'], 'BOOLEAN', ['ARRAY', 'INT'],
+        
'_ZN5doris10vectorized18FunctionArrayIndexINS0_19ArrayContainsActionENS0_17NameArrayContainsEE12execute_implEPN9doris_udf15FunctionContextERNS0_5BlockERKSt6vectorImSaImEEmm',
+        '', '', 'vec', ''],
+    [['array_contains'], 'BOOLEAN', ['ARRAY', 'BIGINT'],
+        
'_ZN5doris10vectorized18FunctionArrayIndexINS0_19ArrayContainsActionENS0_17NameArrayContainsEE12execute_implEPN9doris_udf15FunctionContextERNS0_5BlockERKSt6vectorImSaImEEmm',
+        '', '', 'vec', ''],
+    [['array_contains'], 'BOOLEAN', ['ARRAY', 'VARCHAR'],
+        
'_ZN5doris10vectorized18FunctionArrayIndexINS0_19ArrayContainsActionENS0_17NameArrayContainsEE12execute_implEPN9doris_udf15FunctionContextERNS0_5BlockERKSt6vectorImSaImEEmm',
+        '', '', 'vec', ''],
+    [['array_contains'], 'BOOLEAN', ['ARRAY', 'STRING'],
+        
'_ZN5doris10vectorized18FunctionArrayIndexINS0_19ArrayContainsActionENS0_17NameArrayContainsEE12execute_implEPN9doris_udf15FunctionContextERNS0_5BlockERKSt6vectorImSaImEEmm',
+        '', '', 'vec', ''],
+
+    [['array_position'], 'BIGINT', ['ARRAY', 'TINYINT'],
+        
'_ZN5doris10vectorized18FunctionArrayIndexINS0_19ArrayPositionActionENS0_17NameArrayPositionEE12execute_implEPN9doris_udf15FunctionContextERNS0_5BlockERKSt6vectorImSaImEEmm',
+        '', '', 'vec', ''],
+    [['array_position'], 'BIGINT', ['ARRAY', 'SMALLINT'],
+        
'_ZN5doris10vectorized18FunctionArrayIndexINS0_19ArrayPositionActionENS0_17NameArrayPositionEE12execute_implEPN9doris_udf15FunctionContextERNS0_5BlockERKSt6vectorImSaImEEmm',
+        '', '', 'vec', ''],
+    [['array_position'], 'BIGINT', ['ARRAY', 'INT'],
+        
'_ZN5doris10vectorized18FunctionArrayIndexINS0_19ArrayPositionActionENS0_17NameArrayPositionEE12execute_implEPN9doris_udf15FunctionContextERNS0_5BlockERKSt6vectorImSaImEEmm',
+        '', '', 'vec', ''],
+    [['array_position'], 'BIGINT', ['ARRAY', 'BIGINT'],
+        
'_ZN5doris10vectorized18FunctionArrayIndexINS0_19ArrayPositionActionENS0_17NameArrayPositionEE12execute_implEPN9doris_udf15FunctionContextERNS0_5BlockERKSt6vectorImSaImEEmm',
+        '', '', 'vec', ''],
+    [['array_position'], 'BIGINT', ['ARRAY', 'VARCHAR'],
+        
'_ZN5doris10vectorized18FunctionArrayIndexINS0_19ArrayPositionActionENS0_17NameArrayPositionEE12execute_implEPN9doris_udf15FunctionContextERNS0_5BlockERKSt6vectorImSaImEEmm',
+        '', '', 'vec', ''],
+    [['array_position'], 'BIGINT', ['ARRAY', 'STRING'],
+        
'_ZN5doris10vectorized18FunctionArrayIndexINS0_19ArrayPositionActionENS0_17NameArrayPositionEE12execute_implEPN9doris_udf15FunctionContextERNS0_5BlockERKSt6vectorImSaImEEmm',
+        '', '', 'vec', ''],
 
     # Timestamp functions
     [['unix_timestamp'], 'INT', [],

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to