You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@doris.apache.org by xu...@apache.org on 2022/07/22 05:50:21 UTC

[doris] branch master updated: [feature-wip](array-type) add function array_union/array_except/array_intersect (#10781)

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

xuyang 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 3744321f01 [feature-wip](array-type) add function array_union/array_except/array_intersect (#10781)
3744321f01 is described below

commit 3744321f01436c68099ec1db28da9777c8f913da
Author: xy720 <22...@users.noreply.github.com>
AuthorDate: Fri Jul 22 13:50:13 2022 +0800

    [feature-wip](array-type) add function array_union/array_except/array_intersect (#10781)
    
    Add array_union/array_except/array_intersect function.
---
 be/src/vec/CMakeLists.txt                          |   3 +
 be/src/vec/functions/array/function_array_binary.h |  73 +++++++
 .../vec/functions/array/function_array_except.cpp  |  79 ++++++++
 .../functions/array/function_array_intersect.cpp   |  79 ++++++++
 .../functions/array/function_array_register.cpp    |   6 +
 be/src/vec/functions/array/function_array_set.h    | 216 +++++++++++++++++++++
 .../vec/functions/array/function_array_union.cpp   |  66 +++++++
 .../vec/functions/array/function_array_utils.cpp   |  24 ++-
 be/src/vec/functions/array/function_array_utils.h  |  14 ++
 .../sql-functions/array-functions/array_except.md  |  89 +++++++++
 .../array-functions/array_intersect.md             |  89 +++++++++
 .../sql-functions/array-functions/array_union.md   |  89 +++++++++
 .../sql-functions/array-functions/array_except.md  |  89 +++++++++
 .../array-functions/array_intersect.md             |  89 +++++++++
 .../sql-functions/array-functions/array_union.md   |  89 +++++++++
 gensrc/script/doris_builtins_functions.py          |  39 ++++
 .../array_functions/test_array_functions.out       |  26 +++
 .../array_functions/test_array_functions.groovy    |   3 +
 18 files changed, 1160 insertions(+), 2 deletions(-)

diff --git a/be/src/vec/CMakeLists.txt b/be/src/vec/CMakeLists.txt
index 93e0ae3cec..33c1caccc3 100644
--- a/be/src/vec/CMakeLists.txt
+++ b/be/src/vec/CMakeLists.txt
@@ -139,6 +139,9 @@ set(VEC_FILES
   functions/array/function_arrays_overlap.cpp
   functions/array/function_array_distinct.cpp
   functions/array/function_array_remove.cpp
+  functions/array/function_array_union.cpp
+  functions/array/function_array_except.cpp
+  functions/array/function_array_intersect.cpp
   exprs/table_function/vexplode_json_array.cpp
   functions/math.cpp
   functions/function_bitmap.cpp
diff --git a/be/src/vec/functions/array/function_array_binary.h b/be/src/vec/functions/array/function_array_binary.h
new file mode 100644
index 0000000000..299d1959b4
--- /dev/null
+++ b/be/src/vec/functions/array/function_array_binary.h
@@ -0,0 +1,73 @@
+// 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.
+
+#pragma once
+
+#include "vec/columns/column_array.h"
+#include "vec/data_types/data_type_array.h"
+#include "vec/data_types/data_type_number.h"
+#include "vec/functions/array/function_array_utils.h"
+#include "vec/functions/function.h"
+#include "vec/functions/function_helpers.h"
+
+namespace doris::vectorized {
+
+// Functions with arguments is two arrays of the same element type.
+template <typename Impl, typename Name>
+class FunctionArrayBinary : public IFunction {
+public:
+    static constexpr auto name = Name::name;
+    static FunctionPtr create() { return std::make_shared<FunctionArrayBinary>(); }
+    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(is_array(arguments[0])) << arguments[0]->get_name();
+        DCHECK(is_array(arguments[1])) << arguments[1]->get_name();
+        DCHECK(arguments[0]->equals(*arguments[1]))
+                << "data type " << arguments[0]->get_name() << " not equal with "
+                << arguments[1]->get_name();
+        return Impl::get_return_type(arguments);
+    }
+
+    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
+                        size_t result, size_t input_rows_count) override {
+        auto left_column =
+                block.get_by_position(arguments[0]).column->convert_to_full_column_if_const();
+        auto right_column =
+                block.get_by_position(arguments[1]).column->convert_to_full_column_if_const();
+        Status ret = Status::RuntimeError(
+                fmt::format("execute failed, unsupported types for function {}({}, {})", get_name(),
+                            block.get_by_position(arguments[0]).type->get_name(),
+                            block.get_by_position(arguments[1]).type->get_name()));
+        // extract array column
+        ColumnArrayExecutionData left_data;
+        ColumnArrayExecutionData right_data;
+        ColumnPtr res_ptr = nullptr;
+        if (extract_column_array_info(*left_column, left_data) &&
+            extract_column_array_info(*right_column, right_data)) {
+            ret = Impl::execute(res_ptr, left_data, right_data);
+        }
+        if (ret == Status::OK()) {
+            block.replace_by_position(result, std::move(res_ptr));
+        }
+        return ret;
+    }
+};
+
+} // namespace doris::vectorized
diff --git a/be/src/vec/functions/array/function_array_except.cpp b/be/src/vec/functions/array/function_array_except.cpp
new file mode 100644
index 0000000000..574eeb3eba
--- /dev/null
+++ b/be/src/vec/functions/array/function_array_except.cpp
@@ -0,0 +1,79 @@
+// 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_binary.h"
+#include "vec/functions/array/function_array_set.h"
+#include "vec/functions/simple_function_factory.h"
+
+namespace doris::vectorized {
+
+struct NameArrayExcept {
+    static constexpr auto name = "array_except";
+};
+
+template <typename Set, typename Element>
+struct ExceptAction {
+    // True if set has null element
+    bool null_flag = false;
+    // True if result_set has null element
+    bool result_null_flag = false;
+    // True if it should execute the left array first.
+    static constexpr auto execute_left_column_first = false;
+
+    // Handle Null element.
+    // Return true means this null element should put into result column.
+    template <bool is_left>
+    bool apply_null() {
+        if constexpr (is_left) {
+            if (!null_flag) {
+                null_flag = true;
+                return true;
+            }
+        } else {
+            if (!null_flag) {
+                null_flag = true;
+            }
+        }
+        return false;
+    }
+
+    // Handle Non-Null element.
+    // Return ture means this Non-Null element should put into result column.
+    template <bool is_left>
+    bool apply(Set& set, Set& result_set, const Element& elem) {
+        if constexpr (is_left) {
+            if (!set.find(elem)) {
+                set.insert(elem);
+                return true;
+            }
+        } else {
+            if (!set.find(elem)) {
+                set.insert(elem);
+            }
+        }
+        return false;
+    }
+};
+
+using FunctionArrayExcept =
+        FunctionArrayBinary<ArraySetImpl<SetOperation::EXCEPT>, NameArrayExcept>;
+
+void register_function_array_except(SimpleFunctionFactory& factory) {
+    factory.register_function<FunctionArrayExcept>();
+}
+
+} // namespace doris::vectorized
diff --git a/be/src/vec/functions/array/function_array_intersect.cpp b/be/src/vec/functions/array/function_array_intersect.cpp
new file mode 100644
index 0000000000..c80041a599
--- /dev/null
+++ b/be/src/vec/functions/array/function_array_intersect.cpp
@@ -0,0 +1,79 @@
+// 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_binary.h"
+#include "vec/functions/array/function_array_set.h"
+#include "vec/functions/simple_function_factory.h"
+
+namespace doris::vectorized {
+
+struct NameArrayIntersect {
+    static constexpr auto name = "array_intersect";
+};
+
+template <typename Set, typename Element>
+struct IntersectAction {
+    // True if set has null element
+    bool null_flag = false;
+    // True if result_set has null element
+    bool result_null_flag = false;
+    // True if it should execute the left array first.
+    static constexpr auto execute_left_column_first = false;
+
+    // Handle Null element.
+    // Return true means this null element should put into result column.
+    template <bool is_left>
+    bool apply_null() {
+        if constexpr (is_left) {
+            if (!result_null_flag) {
+                result_null_flag = true;
+                return null_flag;
+            }
+        } else {
+            if (!null_flag) {
+                null_flag = true;
+            }
+        }
+        return false;
+    }
+
+    // Handle Non-Null element.
+    // Return ture means this Non-Null element should put into result column.
+    template <bool is_left>
+    bool apply(Set& set, Set& result_set, const Element& elem) {
+        if constexpr (is_left) {
+            if (set.find(elem) && !result_set.find(elem)) {
+                result_set.insert(elem);
+                return true;
+            }
+        } else {
+            if (!set.find(elem)) {
+                set.insert(elem);
+            }
+        }
+        return false;
+    }
+};
+
+using FunctionArrayIntersect =
+        FunctionArrayBinary<ArraySetImpl<SetOperation::INTERSECT>, NameArrayIntersect>;
+
+void register_function_array_intersect(SimpleFunctionFactory& factory) {
+    factory.register_function<FunctionArrayIntersect>();
+}
+
+} // 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
index cc8092114f..f87f28c4c1 100644
--- a/be/src/vec/functions/array/function_array_register.cpp
+++ b/be/src/vec/functions/array/function_array_register.cpp
@@ -30,6 +30,9 @@ void register_function_array_distinct(SimpleFunctionFactory&);
 void register_function_array_remove(SimpleFunctionFactory&);
 void register_function_array_sort(SimpleFunctionFactory&);
 void register_function_arrays_overlap(SimpleFunctionFactory&);
+void register_function_array_union(SimpleFunctionFactory&);
+void register_function_array_except(SimpleFunctionFactory&);
+void register_function_array_intersect(SimpleFunctionFactory&);
 
 void register_function_array(SimpleFunctionFactory& factory) {
     register_function_array_element(factory);
@@ -40,6 +43,9 @@ void register_function_array(SimpleFunctionFactory& factory) {
     register_function_array_remove(factory);
     register_function_array_sort(factory);
     register_function_arrays_overlap(factory);
+    register_function_array_union(factory);
+    register_function_array_except(factory);
+    register_function_array_intersect(factory);
 }
 
 } // namespace doris::vectorized
diff --git a/be/src/vec/functions/array/function_array_set.h b/be/src/vec/functions/array/function_array_set.h
new file mode 100644
index 0000000000..e412a9107e
--- /dev/null
+++ b/be/src/vec/functions/array/function_array_set.h
@@ -0,0 +1,216 @@
+// 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.
+
+#pragma once
+
+#include "vec/columns/column_array.h"
+#include "vec/columns/column_string.h"
+#include "vec/common/hash_table/hash_set.h"
+#include "vec/data_types/data_type_array.h"
+#include "vec/data_types/data_type_number.h"
+#include "vec/functions/array/function_array_utils.h"
+#include "vec/functions/function.h"
+#include "vec/functions/function_helpers.h"
+
+namespace doris::vectorized {
+
+enum class SetOperation { UNION, EXCEPT, INTERSECT };
+
+template <typename Set, typename Element>
+struct UnionAction;
+
+template <typename Set, typename Element>
+struct ExceptAction;
+
+template <typename Set, typename Element>
+struct IntersectAction;
+
+template <typename Set, typename Element, SetOperation operation>
+struct ActionImpl;
+
+template <typename Set, typename Element>
+struct ActionImpl<Set, Element, SetOperation::UNION> {
+    using Action = UnionAction<Set, Element>;
+};
+
+template <typename Set, typename Element>
+struct ActionImpl<Set, Element, SetOperation::EXCEPT> {
+    using Action = ExceptAction<Set, Element>;
+};
+
+template <typename Set, typename Element>
+struct ActionImpl<Set, Element, SetOperation::INTERSECT> {
+    using Action = IntersectAction<Set, Element>;
+};
+
+template <SetOperation operation, typename ColumnType>
+struct OpenSetImpl {
+    using Element = typename ColumnType::value_type;
+    using ElementNativeType = typename NativeType<Element>::Type;
+    using Set = HashSetWithStackMemory<ElementNativeType, DefaultHash<ElementNativeType>, 4>;
+    using Action = typename ActionImpl<Set, Element, operation>::Action;
+    Action action;
+    Set set;
+    Set result_set;
+    void reset() {
+        set.clear();
+        result_set.clear();
+    }
+    template <bool is_left>
+    void apply(const ColumnArrayExecutionData& src, size_t off, size_t len,
+               ColumnArrayMutableData& dst, size_t* count) {
+        const auto& src_data = assert_cast<const ColumnType&>(*src.nested_col).get_data();
+        auto& dst_data = assert_cast<ColumnType&>(*dst.nested_col).get_data();
+        for (size_t i = off; i < off + len; ++i) {
+            if (src.nested_nullmap_data && src.nested_nullmap_data[i]) {
+                if (action.template apply_null<is_left>()) {
+                    dst_data.push_back(Element());
+                    dst.nested_nullmap_data->push_back(1);
+                    ++(*count);
+                }
+            } else {
+                if (action.template apply<is_left>(set, result_set, src_data[i])) {
+                    dst_data.push_back(src_data[i]);
+                    if (dst.nested_nullmap_data) {
+                        dst.nested_nullmap_data->push_back(0);
+                    }
+                    ++(*count);
+                }
+            }
+        }
+    }
+};
+
+template <SetOperation operation>
+struct OpenSetImpl<operation, ColumnString> {
+    using Set = HashSetWithStackMemory<StringRef, DefaultHash<StringRef>, 4>;
+    using Action = typename ActionImpl<Set, StringRef, operation>::Action;
+    Action action;
+    Set set;
+    Set result_set;
+    void reset() {
+        set.clear();
+        result_set.clear();
+    }
+    template <bool is_left>
+    void apply(const ColumnArrayExecutionData& src, size_t off, size_t len,
+               ColumnArrayMutableData& dst, size_t* count) {
+        const auto& src_column = assert_cast<const ColumnString&>(*src.nested_col);
+        auto& dst_column = assert_cast<ColumnString&>(*dst.nested_col);
+        for (size_t i = off; i < off + len; ++i) {
+            if (src.nested_nullmap_data && src.nested_nullmap_data[i]) {
+                if (action.template apply_null<is_left>()) {
+                    dst_column.insert_default();
+                    dst.nested_nullmap_data->push_back(1);
+                    ++(*count);
+                }
+            } else {
+                if (action.template apply<is_left>(set, result_set, src_column.get_data_at(i))) {
+                    dst_column.insert_from(src_column, i);
+                    if (dst.nested_nullmap_data) {
+                        dst.nested_nullmap_data->push_back(0);
+                    }
+                    ++(*count);
+                }
+            }
+        }
+    }
+};
+
+template <SetOperation operation>
+struct ArraySetImpl {
+public:
+    static DataTypePtr get_return_type(const DataTypes& arguments) {
+        DataTypePtr res;
+        // if any nested type of array arguments is nullable then return array with
+        // nullable nested type.
+        for (const auto& arg : arguments) {
+            const DataTypeArray* array_type = check_and_get_data_type<DataTypeArray>(arg.get());
+            if (array_type->get_nested_type()->is_nullable()) {
+                res = arg;
+                break;
+            }
+        }
+        res = res ? res : arguments[0];
+        return res;
+    }
+
+    static Status execute(ColumnPtr& res_ptr, const ColumnArrayExecutionData& left_data,
+                          const ColumnArrayExecutionData& right_data) {
+        ColumnArrayMutableData dst;
+        if (left_data.nested_nullmap_data || right_data.nested_nullmap_data) {
+            dst = create_mutable_data(left_data.nested_col, true);
+        } else {
+            dst = create_mutable_data(left_data.nested_col, false);
+        }
+        ColumnPtr res_column;
+        if (_execute_internal<ColumnString>(dst, left_data, right_data) ||
+            _execute_internal<ColumnDate>(dst, left_data, right_data) ||
+            _execute_internal<ColumnDateTime>(dst, left_data, right_data) ||
+            _execute_internal<ColumnUInt8>(dst, left_data, right_data) ||
+            _execute_internal<ColumnInt8>(dst, left_data, right_data) ||
+            _execute_internal<ColumnInt16>(dst, left_data, right_data) ||
+            _execute_internal<ColumnInt32>(dst, left_data, right_data) ||
+            _execute_internal<ColumnInt64>(dst, left_data, right_data) ||
+            _execute_internal<ColumnInt128>(dst, left_data, right_data) ||
+            _execute_internal<ColumnFloat32>(dst, left_data, right_data) ||
+            _execute_internal<ColumnFloat64>(dst, left_data, right_data) ||
+            _execute_internal<ColumnDecimal128>(dst, left_data, right_data)) {
+            res_column = assemble_column_array(dst);
+            if (res_column) {
+                res_ptr = std::move(res_column);
+                return Status::OK();
+            }
+        }
+        return Status::RuntimeError("Unexpected columns: {}, {}", left_data.nested_col->get_name(),
+                                    right_data.nested_col->get_name());
+    }
+
+private:
+    template <typename ColumnType>
+    static bool _execute_internal(ColumnArrayMutableData& dst,
+                                  const ColumnArrayExecutionData& left_data,
+                                  const ColumnArrayExecutionData& right_data) {
+        using Impl = OpenSetImpl<operation, ColumnType>;
+        if (!check_column<ColumnType>(*left_data.nested_col)) {
+            return false;
+        }
+        constexpr auto execute_left_column_first = Impl::Action::execute_left_column_first;
+        size_t current = 0;
+        Impl impl;
+        for (size_t row = 0; row < left_data.offsets_ptr->size(); ++row) {
+            size_t count = 0;
+            size_t left_off = (*left_data.offsets_ptr)[row - 1];
+            size_t left_len = (*left_data.offsets_ptr)[row] - left_off;
+            size_t right_off = (*right_data.offsets_ptr)[row - 1];
+            size_t right_len = (*right_data.offsets_ptr)[row] - right_off;
+            if constexpr (execute_left_column_first) {
+                impl.template apply<true>(left_data, left_off, left_len, dst, &count);
+                impl.template apply<false>(right_data, right_off, right_len, dst, &count);
+            } else {
+                impl.template apply<false>(right_data, right_off, right_len, dst, &count);
+                impl.template apply<true>(left_data, left_off, left_len, dst, &count);
+            }
+            current += count;
+            dst.offsets_ptr->push_back(current);
+            impl.reset();
+        }
+        return true;
+    }
+};
+
+} // namespace doris::vectorized
\ No newline at end of file
diff --git a/be/src/vec/functions/array/function_array_union.cpp b/be/src/vec/functions/array/function_array_union.cpp
new file mode 100644
index 0000000000..bee201a843
--- /dev/null
+++ b/be/src/vec/functions/array/function_array_union.cpp
@@ -0,0 +1,66 @@
+// 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_binary.h"
+#include "vec/functions/array/function_array_set.h"
+#include "vec/functions/simple_function_factory.h"
+
+namespace doris::vectorized {
+
+struct NameArrayUnion {
+    static constexpr auto name = "array_union";
+};
+
+template <typename Set, typename Element>
+struct UnionAction {
+    // True if set has null element
+    bool null_flag = false;
+    // True if result_set has null element
+    bool result_null_flag = false;
+    // True if it should execute the left array first.
+    static constexpr auto execute_left_column_first = true;
+
+    // Handle Null element.
+    // Return true means this null element should put into result column.
+    template <bool is_left>
+    bool apply_null() {
+        if (!null_flag) {
+            null_flag = true;
+            return true;
+        }
+        return false;
+    }
+
+    // Handle Non-Null element.
+    // Return ture means this Non-Null element should put into result column.
+    template <bool is_left>
+    bool apply(Set& set, Set& result_set, const Element& elem) {
+        if (!set.find(elem)) {
+            set.insert(elem);
+            return true;
+        }
+        return false;
+    }
+};
+
+using FunctionArrayUnion = FunctionArrayBinary<ArraySetImpl<SetOperation::UNION>, NameArrayUnion>;
+
+void register_function_array_union(SimpleFunctionFactory& factory) {
+    factory.register_function<FunctionArrayUnion>();
+}
+
+} // namespace doris::vectorized
diff --git a/be/src/vec/functions/array/function_array_utils.cpp b/be/src/vec/functions/array/function_array_utils.cpp
index 582bb02c33..124b294f05 100644
--- a/be/src/vec/functions/array/function_array_utils.cpp
+++ b/be/src/vec/functions/array/function_array_utils.cpp
@@ -17,8 +17,6 @@
 
 #include "vec/functions/array/function_array_utils.h"
 
-#include "vec/columns/column_nullable.h"
-
 namespace doris::vectorized {
 
 bool extract_column_array_info(const IColumn& src, ColumnArrayExecutionData& data) {
@@ -48,4 +46,26 @@ bool extract_column_array_info(const IColumn& src, ColumnArrayExecutionData& dat
     return true;
 }
 
+ColumnArrayMutableData create_mutable_data(const IColumn* nested_col, bool is_nullable) {
+    ColumnArrayMutableData dst;
+    if (is_nullable) {
+        dst.array_nested_col =
+                ColumnNullable::create(nested_col->clone_empty(), ColumnUInt8::create());
+        auto* nullable_col = reinterpret_cast<ColumnNullable*>(dst.array_nested_col.get());
+        dst.nested_nullmap_data = &nullable_col->get_null_map_data();
+        dst.nested_col = nullable_col->get_nested_column_ptr().get();
+    } else {
+        dst.array_nested_col = nested_col->clone_empty();
+        dst.nested_col = dst.array_nested_col.get();
+    }
+    dst.offsets_col = ColumnArray::ColumnOffsets::create();
+    dst.offsets_ptr =
+            &reinterpret_cast<ColumnArray::ColumnOffsets*>(dst.offsets_col.get())->get_data();
+    return dst;
+}
+
+MutableColumnPtr assemble_column_array(ColumnArrayMutableData& data) {
+    return ColumnArray::create(std::move(data.array_nested_col), std::move(data.offsets_col));
+}
+
 } // namespace doris::vectorized
diff --git a/be/src/vec/functions/array/function_array_utils.h b/be/src/vec/functions/array/function_array_utils.h
index c0f8aca8f9..0e0ebeb3b2 100644
--- a/be/src/vec/functions/array/function_array_utils.h
+++ b/be/src/vec/functions/array/function_array_utils.h
@@ -17,6 +17,7 @@
 #pragma once
 
 #include "vec/columns/column_array.h"
+#include "vec/columns/column_nullable.h"
 #include "vec/data_types/data_type_array.h"
 
 namespace doris::vectorized {
@@ -39,6 +40,19 @@ public:
     const IColumn* nested_col = nullptr;
 };
 
+struct ColumnArrayMutableData {
+public:
+    MutableColumnPtr array_nested_col = nullptr;
+    ColumnUInt8::Container* nested_nullmap_data = nullptr;
+    MutableColumnPtr offsets_col = nullptr;
+    ColumnArray::Offsets* offsets_ptr = nullptr;
+    IColumn* nested_col = nullptr;
+};
+
 bool extract_column_array_info(const IColumn& src, ColumnArrayExecutionData& data);
 
+ColumnArrayMutableData create_mutable_data(const IColumn* nested_col, bool is_nullable);
+
+MutableColumnPtr assemble_column_array(ColumnArrayMutableData& data);
+
 } // namespace doris::vectorized
diff --git a/docs/en/docs/sql-manual/sql-functions/array-functions/array_except.md b/docs/en/docs/sql-manual/sql-functions/array-functions/array_except.md
new file mode 100644
index 0000000000..60c0863c5a
--- /dev/null
+++ b/docs/en/docs/sql-manual/sql-functions/array-functions/array_except.md
@@ -0,0 +1,89 @@
+---
+{
+    "title": "array_except",
+    "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.
+-->
+
+## array_except
+
+### description
+
+#### Syntax
+
+```
+ARRAY<T> array_except(ARRAY<T> array1, ARRAY<T> array2)
+```
+
+Returns an array of the elements in array1 but not in array2, without duplicates. If the input parameter is null, null is returned.
+
+### notice
+
+`Only supported in vectorized engine`
+
+### example
+
+```
+mysql> set enable_vectorized_engine=true;
+
+mysql> select k1,k2,k3,array_except(k2,k3) from array_type_table;
++------+-----------------+--------------+--------------------------+
+| k1   | k2              | k3           | array_except(`k2`, `k3`) |
++------+-----------------+--------------+--------------------------+
+|    1 | [1, 2, 3]       | [2, 4, 5]    | [1, 3]                   |
+|    2 | [2, 3]          | [1, 5]       | [2, 3]                   |
+|    3 | [1, 1, 1]       | [2, 2, 2]    | [1]                      |
++------+-----------------+--------------+--------------------------+
+
+mysql> select k1,k2,k3,array_except(k2,k3) from array_type_table_nullable;
++------+-----------------+--------------+--------------------------+
+| k1   | k2              | k3           | array_except(`k2`, `k3`) |
++------+-----------------+--------------+--------------------------+
+|    1 | [1, NULL, 3]    | [1, 3, 5]    | [NULL]                   |
+|    2 | [NULL, NULL, 2] | [2, NULL, 4] | []                       |
+|    3 | NULL            | [1, 2, 3]    | NULL                     |
++------+-----------------+--------------+--------------------------+
+
+mysql> select k1,k2,k3,array_except(k2,k3) from array_type_table_varchar;
++------+----------------------------+----------------------------------+--------------------------+
+| k1   | k2                         | k3                               | array_except(`k2`, `k3`) |
++------+----------------------------+----------------------------------+--------------------------+
+|    1 | ['hello', 'world', 'c++']  | ['I', 'am', 'c++']               | ['hello', 'world']       |
+|    2 | ['a1', 'equals', 'b1']     | ['a2', 'equals', 'b2']           | ['a1', 'b1']             |
+|    3 | ['hasnull', NULL, 'value'] | ['nohasnull', 'nonull', 'value'] | ['hasnull', NULL]        |
+|    3 | ['hasnull', NULL, 'value'] | ['hasnull', NULL, 'value']       | []                       |
++------+----------------------------+----------------------------------+--------------------------+
+
+mysql> select k1,k2,k3,array_except(k2,k3) from array_type_table_decimal;
++------+------------------+-------------------+--------------------------+
+| k1   | k2               | k3                | array_except(`k2`, `k3`) |
++------+------------------+-------------------+--------------------------+
+|    1 | [1.1, 2.1, 3.44] | [2.1, 3.4, 5.4]   | [1.1, 3.44]              |
+|    2 | [NULL, 2, 5]     | [NULL, NULL, 5.4] | [2, 5]                   |
+|    1 | [1, NULL, 2, 5]  | [1, 3.1, 5.4]     | [NULL, 2, 5]             |
++------+------------------+-------------------+--------------------------+
+
+```
+
+### keywords
+
+ARRAY,EXCEPT,ARRAY_EXCEPT
\ No newline at end of file
diff --git a/docs/en/docs/sql-manual/sql-functions/array-functions/array_intersect.md b/docs/en/docs/sql-manual/sql-functions/array-functions/array_intersect.md
new file mode 100644
index 0000000000..a6698ac7ce
--- /dev/null
+++ b/docs/en/docs/sql-manual/sql-functions/array-functions/array_intersect.md
@@ -0,0 +1,89 @@
+---
+{
+    "title": "array_intersect",
+    "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.
+-->
+
+## array_intersect
+
+### description
+
+#### Syntax
+
+```
+ARRAY<T> array_intersect(ARRAY<T> array1, ARRAY<T> array2)
+```
+
+Returns an array of the elements in the intersection of array1 and array2, without duplicates. If the input parameter is null, null is returned.
+
+### notice
+
+`Only supported in vectorized engine`
+
+### example
+
+```
+mysql> set enable_vectorized_engine=true;
+
+mysql> select k1,k2,k3,array_intersect(k2,k3) from array_type_table;
++------+-----------------+--------------+-----------------------------+
+| k1   | k2              | k3           | array_intersect(`k2`, `k3`) |
++------+-----------------+--------------+-----------------------------+
+|    1 | [1, 2, 3]       | [2, 4, 5]    | [2]                         |
+|    2 | [2, 3]          | [1, 5]       | []                          |
+|    3 | [1, 1, 1]       | [2, 2, 2]    | []                          |
++------+-----------------+--------------+-----------------------------+
+
+mysql> select k1,k2,k3,array_intersect(k2,k3) from array_type_table_nullable;
++------+-----------------+--------------+-----------------------------+
+| k1   | k2              | k3           | array_intersect(`k2`, `k3`) |
++------+-----------------+--------------+-----------------------------+
+|    1 | [1, NULL, 3]    | [1, 3, 5]    | [1, 3]                      |
+|    2 | [NULL, NULL, 2] | [2, NULL, 4] | [NULL, 2]                   |
+|    3 | NULL            | [1, 2, 3]    | NULL                        |
++------+-----------------+--------------+-----------------------------+
+
+mysql> select k1,k2,k3,array_intersect(k2,k3) from array_type_table_varchar;
++------+----------------------------+----------------------------------+-----------------------------+
+| k1   | k2                         | k3                               | array_intersect(`k2`, `k3`) |
++------+----------------------------+----------------------------------+-----------------------------+
+|    1 | ['hello', 'world', 'c++']  | ['I', 'am', 'c++']               | ['c++']                     |
+|    2 | ['a1', 'equals', 'b1']     | ['a2', 'equals', 'b2']           | ['equals']                  |
+|    3 | ['hasnull', NULL, 'value'] | ['nohasnull', 'nonull', 'value'] | [NULL, 'value']             |
+|    3 | ['hasnull', NULL, 'value'] | ['hasnull', NULL, 'value']       | ['hasnull', 'value']        |
++------+----------------------------+----------------------------------+-----------------------------+
+
+mysql> select k1,k2,k3,array_intersect(k2,k3) from array_type_table_decimal;
++------+------------------+-------------------+-----------------------------+
+| k1   | k2               | k3                | array_intersect(`k2`, `k3`) |
++------+------------------+-------------------+-----------------------------+
+|    1 | [1.1, 2.1, 3.44] | [2.1, 3.4, 5.4]   | [2.1]                       |
+|    2 | [NULL, 2, 5]     | [NULL, NULL, 5.4] | [NULL]                      |
+|    3 | [1, NULL, 2, 5]  | [1, 3.1, 5.4]     | [1]                         |
++------+------------------+-------------------+-----------------------------+
+
+```
+
+### keywords
+
+ARRAY,INTERSECT,ARRAY_INTERSECT
\ No newline at end of file
diff --git a/docs/en/docs/sql-manual/sql-functions/array-functions/array_union.md b/docs/en/docs/sql-manual/sql-functions/array-functions/array_union.md
new file mode 100644
index 0000000000..96e71c0b95
--- /dev/null
+++ b/docs/en/docs/sql-manual/sql-functions/array-functions/array_union.md
@@ -0,0 +1,89 @@
+---
+{
+    "title": "array_union",
+    "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.
+-->
+
+## array_union
+
+### description
+
+#### Syntax
+
+```
+ARRAY<T> array_union(ARRAY<T> array1, ARRAY<T> array2)
+```
+
+Returns an array of the elements in the union of array1 and array2, without duplicates. If the input parameter is null, null is returned.
+
+### notice
+
+`Only supported in vectorized engine`
+
+### example
+
+```
+mysql> set enable_vectorized_engine=true;
+
+mysql> select k1,k2,k3,array_union(k2,k3) from array_type_table;
++------+-----------------+--------------+-------------------------+
+| k1   | k2              | k3           | array_union(`k2`, `k3`) |
++------+-----------------+--------------+-------------------------+
+|    1 | [1, 2, 3]       | [2, 4, 5]    | [1, 2, 3, 4, 5]         |
+|    2 | [2, 3]          | [1, 5]       | [2, 3, 1, 5]            |
+|    3 | [1, 1, 1]       | [2, 2, 2]    | [1, 2]                  |
++------+-----------------+--------------+-------------------------+
+
+mysql> select k1,k2,k3,array_union(k2,k3) from array_type_table_nullable;
++------+-----------------+--------------+-------------------------+
+| k1   | k2              | k3           | array_union(`k2`, `k3`) |
++------+-----------------+--------------+-------------------------+
+|    1 | [1, NULL, 3]    | [1, 3, 5]    | [1, NULL, 3, 5]         |
+|    2 | [NULL, NULL, 2] | [2, NULL, 4] | [NULL, 2, 4]            |
+|    3 | NULL            | [1, 2, 3]    | NULL                    |
++------+-----------------+--------------+-------------------------+
+
+mysql> select k1,k2,k3,array_union(k2,k3) from array_type_table_varchar;
++------+----------------------------+----------------------------------+---------------------------------------------------+
+| k1   | k2                         | k3                               | array_union(`k2`, `k3`)                           |
++------+----------------------------+----------------------------------+---------------------------------------------------+
+|    1 | ['hello', 'world', 'c++']  | ['I', 'am', 'c++']               | ['hello', 'world', 'c++', 'I', 'am']              |
+|    2 | ['a1', 'equals', 'b1']     | ['a2', 'equals', 'b2']           | ['a1', 'equals', 'b1', 'a2', 'b2']                |
+|    3 | ['hasnull', NULL, 'value'] | ['nohasnull', 'nonull', 'value'] | ['hasnull', NULL, 'value', 'nohasnull', 'nonull'] |
+|    4 | ['hasnull', NULL, 'value'] | ['hasnull', NULL, 'value']       | ['hasnull', NULL, 'value']                        |
++------+----------------------------+----------------------------------+---------------------------------------------------+
+
+mysql> select k1,k2,k3,array_union(k2,k3) from array_type_table_decimal;
++------+------------------+-------------------+----------------------------+
+| k1   | k2               | k3                | array_union(`k2`, `k3`)    |
++------+------------------+-------------------+----------------------------+
+|    1 | [1.1, 2.1, 3.44] | [2.1, 3.4, 5.4]   | [1.1, 2.1, 3.44, 3.4, 5.4] |
+|    2 | [NULL, 2, 5]     | [NULL, NULL, 5.4] | [NULL, 2, 5, 5.4]          |
+|    4 | [1, NULL, 2, 5]  | [1, 3.1, 5.4]     | [1, NULL, 2, 5, 3.1, 5.4]  |
++------+------------------+-------------------+----------------------------+
+
+```
+
+### keywords
+
+ARRAY,UNION,ARRAY_UNION
\ No newline at end of file
diff --git a/docs/zh-CN/docs/sql-manual/sql-functions/array-functions/array_except.md b/docs/zh-CN/docs/sql-manual/sql-functions/array-functions/array_except.md
new file mode 100644
index 0000000000..e962c46e51
--- /dev/null
+++ b/docs/zh-CN/docs/sql-manual/sql-functions/array-functions/array_except.md
@@ -0,0 +1,89 @@
+---
+{
+    "title": "array_except",
+    "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.
+-->
+
+## array_except
+
+### description
+
+#### Syntax
+
+```
+ARRAY<T> array_except(ARRAY<T> array1, ARRAY<T> array2)
+```
+
+返回一个数组,包含所有在array1内但不在array2内的元素,不包含重复项,如果输入参数为NULL,则返回NULL
+
+### notice
+
+`仅支持向量化引擎中使用`
+
+### example
+
+```
+mysql> set enable_vectorized_engine=true;
+
+mysql> select k1,k2,k3,array_except(k2,k3) from array_type_table;
++------+-----------------+--------------+--------------------------+
+| k1   | k2              | k3           | array_except(`k2`, `k3`) |
++------+-----------------+--------------+--------------------------+
+|    1 | [1, 2, 3]       | [2, 4, 5]    | [1, 3]                   |
+|    2 | [2, 3]          | [1, 5]       | [2, 3]                   |
+|    3 | [1, 1, 1]       | [2, 2, 2]    | [1]                      |
++------+-----------------+--------------+--------------------------+
+
+mysql> select k1,k2,k3,array_except(k2,k3) from array_type_table_nullable;
++------+-----------------+--------------+--------------------------+
+| k1   | k2              | k3           | array_except(`k2`, `k3`) |
++------+-----------------+--------------+--------------------------+
+|    1 | [1, NULL, 3]    | [1, 3, 5]    | [NULL]                   |
+|    2 | [NULL, NULL, 2] | [2, NULL, 4] | []                       |
+|    3 | NULL            | [1, 2, 3]    | NULL                     |
++------+-----------------+--------------+--------------------------+
+
+mysql> select k1,k2,k3,array_except(k2,k3) from array_type_table_varchar;
++------+----------------------------+----------------------------------+--------------------------+
+| k1   | k2                         | k3                               | array_except(`k2`, `k3`) |
++------+----------------------------+----------------------------------+--------------------------+
+|    1 | ['hello', 'world', 'c++']  | ['I', 'am', 'c++']               | ['hello', 'world']       |
+|    2 | ['a1', 'equals', 'b1']     | ['a2', 'equals', 'b2']           | ['a1', 'b1']             |
+|    3 | ['hasnull', NULL, 'value'] | ['nohasnull', 'nonull', 'value'] | ['hasnull', NULL]        |
+|    3 | ['hasnull', NULL, 'value'] | ['hasnull', NULL, 'value']       | []                       |
++------+----------------------------+----------------------------------+--------------------------+
+
+mysql> select k1,k2,k3,array_except(k2,k3) from array_type_table_decimal;
++------+------------------+-------------------+--------------------------+
+| k1   | k2               | k3                | array_except(`k2`, `k3`) |
++------+------------------+-------------------+--------------------------+
+|    1 | [1.1, 2.1, 3.44] | [2.1, 3.4, 5.4]   | [1.1, 3.44]              |
+|    2 | [NULL, 2, 5]     | [NULL, NULL, 5.4] | [2, 5]                   |
+|    1 | [1, NULL, 2, 5]  | [1, 3.1, 5.4]     | [NULL, 2, 5]             |
++------+------------------+-------------------+--------------------------+
+
+```
+
+### keywords
+
+ARRAY,EXCEPT,ARRAY_EXCEPT
\ No newline at end of file
diff --git a/docs/zh-CN/docs/sql-manual/sql-functions/array-functions/array_intersect.md b/docs/zh-CN/docs/sql-manual/sql-functions/array-functions/array_intersect.md
new file mode 100644
index 0000000000..9419d59a8b
--- /dev/null
+++ b/docs/zh-CN/docs/sql-manual/sql-functions/array-functions/array_intersect.md
@@ -0,0 +1,89 @@
+---
+{
+    "title": "array_intersect",
+    "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.
+-->
+
+## array_intersect
+
+### description
+
+#### Syntax
+
+```
+ARRAY<T> array_intersect(ARRAY<T> array1, ARRAY<T> array2)
+```
+
+返回一个数组,包含array1和array2的交集中的所有元素,不包含重复项,如果输入参数为NULL,则返回NULL
+
+### notice
+
+`仅支持向量化引擎中使用`
+
+### example
+
+```
+mysql> set enable_vectorized_engine=true;
+
+mysql> select k1,k2,k3,array_intersect(k2,k3) from array_type_table;
++------+-----------------+--------------+-----------------------------+
+| k1   | k2              | k3           | array_intersect(`k2`, `k3`) |
++------+-----------------+--------------+-----------------------------+
+|    1 | [1, 2, 3]       | [2, 4, 5]    | [2]                         |
+|    2 | [2, 3]          | [1, 5]       | []                          |
+|    3 | [1, 1, 1]       | [2, 2, 2]    | []                          |
++------+-----------------+--------------+-----------------------------+
+
+mysql> select k1,k2,k3,array_intersect(k2,k3) from array_type_table_nullable;
++------+-----------------+--------------+-----------------------------+
+| k1   | k2              | k3           | array_intersect(`k2`, `k3`) |
++------+-----------------+--------------+-----------------------------+
+|    1 | [1, NULL, 3]    | [1, 3, 5]    | [1, 3]                      |
+|    2 | [NULL, NULL, 2] | [2, NULL, 4] | [NULL, 2]                   |
+|    3 | NULL            | [1, 2, 3]    | NULL                        |
++------+-----------------+--------------+-----------------------------+
+
+mysql> select k1,k2,k3,array_intersect(k2,k3) from array_type_table_varchar;
++------+----------------------------+----------------------------------+-----------------------------+
+| k1   | k2                         | k3                               | array_intersect(`k2`, `k3`) |
++------+----------------------------+----------------------------------+-----------------------------+
+|    1 | ['hello', 'world', 'c++']  | ['I', 'am', 'c++']               | ['c++']                     |
+|    2 | ['a1', 'equals', 'b1']     | ['a2', 'equals', 'b2']           | ['equals']                  |
+|    3 | ['hasnull', NULL, 'value'] | ['nohasnull', 'nonull', 'value'] | [NULL, 'value']             |
+|    3 | ['hasnull', NULL, 'value'] | ['hasnull', NULL, 'value']       | ['hasnull', 'value']        |
++------+----------------------------+----------------------------------+-----------------------------+
+
+mysql> select k1,k2,k3,array_intersect(k2,k3) from array_type_table_decimal;
++------+------------------+-------------------+-----------------------------+
+| k1   | k2               | k3                | array_intersect(`k2`, `k3`) |
++------+------------------+-------------------+-----------------------------+
+|    1 | [1.1, 2.1, 3.44] | [2.1, 3.4, 5.4]   | [2.1]                       |
+|    2 | [NULL, 2, 5]     | [NULL, NULL, 5.4] | [NULL]                      |
+|    3 | [1, NULL, 2, 5]  | [1, 3.1, 5.4]     | [1]                         |
++------+------------------+-------------------+-----------------------------+
+
+```
+
+### keywords
+
+ARRAY,INTERSECT,ARRAY_INTERSECT
\ No newline at end of file
diff --git a/docs/zh-CN/docs/sql-manual/sql-functions/array-functions/array_union.md b/docs/zh-CN/docs/sql-manual/sql-functions/array-functions/array_union.md
new file mode 100644
index 0000000000..b90d2069f6
--- /dev/null
+++ b/docs/zh-CN/docs/sql-manual/sql-functions/array-functions/array_union.md
@@ -0,0 +1,89 @@
+---
+{
+    "title": "array_union",
+    "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.
+-->
+
+## array_union
+
+### description
+
+#### Syntax
+
+```
+ARRAY<T> array_union(ARRAY<T> array1, ARRAY<T> array2)
+```
+
+返回一个数组,包含array1和array2的并集中的所有元素,不包含重复项,如果输入参数为NULL,则返回NULL
+
+### notice
+
+`仅支持向量化引擎中使用`
+
+### example
+
+```
+mysql> set enable_vectorized_engine=true;
+
+mysql> select k1,k2,k3,array_union(k2,k3) from array_type_table;
++------+-----------------+--------------+-------------------------+
+| k1   | k2              | k3           | array_union(`k2`, `k3`) |
++------+-----------------+--------------+-------------------------+
+|    1 | [1, 2, 3]       | [2, 4, 5]    | [1, 2, 3, 4, 5]         |
+|    2 | [2, 3]          | [1, 5]       | [2, 3, 1, 5]            |
+|    3 | [1, 1, 1]       | [2, 2, 2]    | [1, 2]                  |
++------+-----------------+--------------+-------------------------+
+
+mysql> select k1,k2,k3,array_union(k2,k3) from array_type_table_nullable;
++------+-----------------+--------------+-------------------------+
+| k1   | k2              | k3           | array_union(`k2`, `k3`) |
++------+-----------------+--------------+-------------------------+
+|    1 | [1, NULL, 3]    | [1, 3, 5]    | [1, NULL, 3, 5]         |
+|    2 | [NULL, NULL, 2] | [2, NULL, 4] | [NULL, 2, 4]            |
+|    3 | NULL            | [1, 2, 3]    | NULL                    |
++------+-----------------+--------------+-------------------------+
+
+mysql> select k1,k2,k3,array_union(k2,k3) from array_type_table_varchar;
++------+----------------------------+----------------------------------+---------------------------------------------------+
+| k1   | k2                         | k3                               | array_union(`k2`, `k3`)                           |
++------+----------------------------+----------------------------------+---------------------------------------------------+
+|    1 | ['hello', 'world', 'c++']  | ['I', 'am', 'c++']               | ['hello', 'world', 'c++', 'I', 'am']              |
+|    2 | ['a1', 'equals', 'b1']     | ['a2', 'equals', 'b2']           | ['a1', 'equals', 'b1', 'a2', 'b2']                |
+|    3 | ['hasnull', NULL, 'value'] | ['nohasnull', 'nonull', 'value'] | ['hasnull', NULL, 'value', 'nohasnull', 'nonull'] |
+|    4 | ['hasnull', NULL, 'value'] | ['hasnull', NULL, 'value']       | ['hasnull', NULL, 'value']                        |
++------+----------------------------+----------------------------------+---------------------------------------------------+
+
+mysql> select k1,k2,k3,array_union(k2,k3) from array_type_table_decimal;
++------+------------------+-------------------+----------------------------+
+| k1   | k2               | k3                | array_union(`k2`, `k3`)    |
++------+------------------+-------------------+----------------------------+
+|    1 | [1.1, 2.1, 3.44] | [2.1, 3.4, 5.4]   | [1.1, 2.1, 3.44, 3.4, 5.4] |
+|    2 | [NULL, 2, 5]     | [NULL, NULL, 5.4] | [NULL, 2, 5, 5.4]          |
+|    4 | [1, NULL, 2, 5]  | [1, 3.1, 5.4]     | [1, NULL, 2, 5, 3.1, 5.4]  |
++------+------------------+-------------------+----------------------------+
+
+```
+
+### keywords
+
+ARRAY,UNION,ARRAY_UNION
\ No newline at end of file
diff --git a/gensrc/script/doris_builtins_functions.py b/gensrc/script/doris_builtins_functions.py
index 8a4aad385c..e3bb5e9ab5 100755
--- a/gensrc/script/doris_builtins_functions.py
+++ b/gensrc/script/doris_builtins_functions.py
@@ -238,6 +238,45 @@ visible_functions = [
     [['array_remove'], 'ARRAY_VARCHAR',   ['ARRAY_VARCHAR', 'VARCHAR'], '', '', '', 'vec', ''],
     [['array_remove'], 'ARRAY_STRING',    ['ARRAY_STRING', 'STRING'], '', '', '', 'vec', ''],    
 
+    [['array_union'], 'ARRAY_TINYINT',  ['ARRAY_TINYINT', 'ARRAY_TINYINT'],  '', '', '', 'vec', ''],
+    [['array_union'], 'ARRAY_SMALLINT', ['ARRAY_SMALLINT', 'ARRAY_SMALLINT'], '', '', '', 'vec', ''],
+    [['array_union'], 'ARRAY_INT',      ['ARRAY_INT', 'ARRAY_INT'], '', '', '', 'vec', ''],
+    [['array_union'], 'ARRAY_BIGINT',   ['ARRAY_BIGINT', 'ARRAY_BIGINT'],   '', '', '', 'vec', ''],
+    [['array_union'], 'ARRAY_LARGEINT', ['ARRAY_LARGEINT', 'ARRAY_LARGEINT'], '', '', '', 'vec', ''],
+    [['array_union'], 'ARRAY_FLOAT',     ['ARRAY_FLOAT', 'ARRAY_FLOAT'],  '', '', '', 'vec', ''],
+    [['array_union'], 'ARRAY_DOUBLE',    ['ARRAY_DOUBLE', 'ARRAY_DOUBLE'], '', '', '', 'vec', ''],
+    [['array_union'], 'ARRAY_DECIMALV2', ['ARRAY_DECIMALV2', 'ARRAY_DECIMALV2'], '', '', '', 'vec', ''],
+    [['array_union'], 'ARRAY_DATETIME',  ['ARRAY_DATETIME', 'ARRAY_DATETIME'], '', '', '', 'vec', ''],
+    [['array_union'], 'ARRAY_DATE',      ['ARRAY_DATE', 'ARRAY_DATE'], '', '', '', 'vec', ''],
+    [['array_union'], 'ARRAY_VARCHAR',   ['ARRAY_VARCHAR', 'ARRAY_VARCHAR'], '', '', '', 'vec', ''],
+    [['array_union'], 'ARRAY_STRING',    ['ARRAY_STRING', 'ARRAY_STRING'], '', '', '', 'vec', ''],
+
+    [['array_except'], 'ARRAY_TINYINT',  ['ARRAY_TINYINT', 'ARRAY_TINYINT'],  '', '', '', 'vec', ''],
+    [['array_except'], 'ARRAY_SMALLINT', ['ARRAY_SMALLINT', 'ARRAY_SMALLINT'], '', '', '', 'vec', ''],
+    [['array_except'], 'ARRAY_INT',      ['ARRAY_INT', 'ARRAY_INT'], '', '', '', 'vec', ''],
+    [['array_except'], 'ARRAY_BIGINT',   ['ARRAY_BIGINT', 'ARRAY_BIGINT'],   '', '', '', 'vec', ''],
+    [['array_except'], 'ARRAY_LARGEINT', ['ARRAY_LARGEINT', 'ARRAY_LARGEINT'], '', '', '', 'vec', ''],
+    [['array_except'], 'ARRAY_FLOAT',     ['ARRAY_FLOAT', 'ARRAY_FLOAT'],  '', '', '', 'vec', ''],
+    [['array_except'], 'ARRAY_DOUBLE',    ['ARRAY_DOUBLE', 'ARRAY_DOUBLE'], '', '', '', 'vec', ''],
+    [['array_except'], 'ARRAY_DECIMALV2', ['ARRAY_DECIMALV2', 'ARRAY_DECIMALV2'], '', '', '', 'vec', ''],
+    [['array_except'], 'ARRAY_DATETIME',  ['ARRAY_DATETIME', 'ARRAY_DATETIME'], '', '', '', 'vec', ''],
+    [['array_except'], 'ARRAY_DATE',      ['ARRAY_DATE', 'ARRAY_DATE'], '', '', '', 'vec', ''],
+    [['array_except'], 'ARRAY_VARCHAR',   ['ARRAY_VARCHAR', 'ARRAY_VARCHAR'], '', '', '', 'vec', ''],
+    [['array_except'], 'ARRAY_STRING',    ['ARRAY_STRING', 'ARRAY_STRING'], '', '', '', 'vec', ''],
+
+    [['array_intersect'], 'ARRAY_TINYINT',  ['ARRAY_TINYINT', 'ARRAY_TINYINT'],  '', '', '', 'vec', ''],
+    [['array_intersect'], 'ARRAY_SMALLINT', ['ARRAY_SMALLINT', 'ARRAY_SMALLINT'], '', '', '', 'vec', ''],
+    [['array_intersect'], 'ARRAY_INT',      ['ARRAY_INT', 'ARRAY_INT'], '', '', '', 'vec', ''],
+    [['array_intersect'], 'ARRAY_BIGINT',   ['ARRAY_BIGINT', 'ARRAY_BIGINT'],   '', '', '', 'vec', ''],
+    [['array_intersect'], 'ARRAY_LARGEINT', ['ARRAY_LARGEINT', 'ARRAY_LARGEINT'], '', '', '', 'vec', ''],
+    [['array_intersect'], 'ARRAY_FLOAT',     ['ARRAY_FLOAT', 'ARRAY_FLOAT'],  '', '', '', 'vec', ''],
+    [['array_intersect'], 'ARRAY_DOUBLE',    ['ARRAY_DOUBLE', 'ARRAY_DOUBLE'], '', '', '', 'vec', ''],
+    [['array_intersect'], 'ARRAY_DECIMALV2', ['ARRAY_DECIMALV2', 'ARRAY_DECIMALV2'], '', '', '', 'vec', ''],
+    [['array_intersect'], 'ARRAY_DATETIME',  ['ARRAY_DATETIME', 'ARRAY_DATETIME'], '', '', '', 'vec', ''],
+    [['array_intersect'], 'ARRAY_DATE',      ['ARRAY_DATE', 'ARRAY_DATE'], '', '', '', 'vec', ''],
+    [['array_intersect'], 'ARRAY_VARCHAR',   ['ARRAY_VARCHAR', 'ARRAY_VARCHAR'], '', '', '', 'vec', ''],
+    [['array_intersect'], 'ARRAY_STRING',    ['ARRAY_STRING', 'ARRAY_STRING'], '', '', '', 'vec', ''],
+
     # Timestamp functions
     [['unix_timestamp'], 'INT', [],
         '_ZN5doris18TimestampFunctions7to_unixEPN9doris_udf15FunctionContextE',
diff --git a/regression-test/data/query/sql_functions/array_functions/test_array_functions.out b/regression-test/data/query/sql_functions/array_functions/test_array_functions.out
index 02dd5d80e4..9b6cc814fe 100644
--- a/regression-test/data/query/sql_functions/array_functions/test_array_functions.out
+++ b/regression-test/data/query/sql_functions/array_functions/test_array_functions.out
@@ -53,3 +53,29 @@
 6	[1, 1, 2, 2, 3, 3, 4, 4, 5]	['a', 'a', 'b', 'b', 'c', 'c', 'd']	\N
 7	[NULL, NULL, 8, 9, 10]	[NULL, NULL, 'f', 'g', 'h']	\N
 
+-- !select --
+1	[1, 2, 3]
+2	[4, 5]
+3	\N
+4	[1, 2, 3, 4, 5]
+5	\N
+6	\N
+7	\N
+
+-- !select --
+1	[3]
+2	[4]
+3	\N
+4	[1, 2, 3, 4, 5]
+5	\N
+6	\N
+7	\N
+
+-- !select --
+1	[1, 2]
+2	[]
+3	\N
+4	[]
+5	\N
+6	\N
+7	\N
diff --git a/regression-test/suites/query/sql_functions/array_functions/test_array_functions.groovy b/regression-test/suites/query/sql_functions/array_functions/test_array_functions.groovy
index 20ae65a6ed..a0292418b3 100644
--- a/regression-test/suites/query/sql_functions/array_functions/test_array_functions.groovy
+++ b/regression-test/suites/query/sql_functions/array_functions/test_array_functions.groovy
@@ -51,4 +51,7 @@ suite("test_array_functions", "query") {
     qt_select "SELECT k1, array_distinct(k2), array_distinct(k3) FROM ${tableName} ORDER BY k1"
     qt_select "SELECT array_remove(k2, k1), k1 FROM ${tableName} ORDER BY k1"
     qt_select "SELECT k1, array_sort(k2), array_sort(k3), array_sort(k4) FROM ${tableName} ORDER BY k1"
+    qt_select "select k1, array_union(k2, k4) FROM ${tableName} ORDER BY k1"
+    qt_select "select k1, array_except(k2, k4) FROM ${tableName} ORDER BY k1"
+    qt_select "select k1, array_intersect(k2, k4) FROM ${tableName} ORDER BY k1"
 }


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