You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@doris.apache.org by yi...@apache.org on 2023/06/05 02:38:55 UTC

[doris] branch master updated: [Improve](array-function)Improve array function intersect (#20085)

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

yiguolei 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 59a0f80233 [Improve](array-function)Improve array function intersect (#20085)
59a0f80233 is described below

commit 59a0f8023385bfcde842485e4179c59d59b80b36
Author: amory <wa...@selectdb.com>
AuthorDate: Mon Jun 5 10:38:48 2023 +0800

    [Improve](array-function)Improve array function intersect (#20085)
    
    now we just support array function with 2 arrays , but intersect operator can support more than 2 arrays
---
 .../functions/array/function_array_intersect.cpp   |  72 ++++----
 be/src/vec/functions/array/function_array_map.h    | 193 +++++++++++++++++++++
 be/src/vec/functions/array/function_array_nary.h   |  82 +++++++++
 be/src/vec/functions/array/function_array_set.h    |  10 +-
 .../vec/functions/array/function_array_union.cpp   |   1 +
 be/src/vec/functions/array/function_array_utils.h  |  46 ++++-
 .../main/java/org/apache/doris/catalog/Type.java   |   4 +-
 gensrc/script/doris_builtins_functions.py          |  36 ++--
 .../array_functions/test_array_functions.out       |   6 +-
 .../test_array_functions_by_literal.out            |  16 +-
 .../test_array_functions_by_literal.groovy         |   6 +
 11 files changed, 390 insertions(+), 82 deletions(-)

diff --git a/be/src/vec/functions/array/function_array_intersect.cpp b/be/src/vec/functions/array/function_array_intersect.cpp
index ed14195bca..cc27e1a665 100644
--- a/be/src/vec/functions/array/function_array_intersect.cpp
+++ b/be/src/vec/functions/array/function_array_intersect.cpp
@@ -17,11 +17,10 @@
 
 #include "vec/columns/column_const.h"
 #include "vec/common/assert_cast.h"
-#include "vec/common/string_ref.h"
-#include "vec/data_types/data_type.h"
-#include "vec/data_types/data_type_nullable.h"
+#include "vec/common/hash_table/hash_map.h"
 #include "vec/functions/array/function_array_binary.h"
-#include "vec/functions/array/function_array_set.h"
+#include "vec/functions/array/function_array_map.h"
+#include "vec/functions/array/function_array_nary.h"
 #include "vec/functions/simple_function_factory.h"
 
 namespace doris::vectorized {
@@ -30,57 +29,52 @@ struct NameArrayIntersect {
     static constexpr auto name = "array_intersect";
 };
 
-template <typename Set, typename Element>
+template <typename Map, typename ColumnType>
 struct IntersectAction {
-    // True if set has null element
-    bool null_flag = false;
+    // True if current has null element
+    bool current_null_flag = false;
     // True if result_set has null element
-    bool result_null_flag = false;
+    bool result_null_flag = true;
     // True if it should execute the left array first.
-    static constexpr auto execute_left_column_first = false;
+    typename Map::mapped_type* value = nullptr;
 
     // 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;
-    }
+    bool apply_null() { return result_null_flag; }
 
     // 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);
+    void apply(Map& map, const int arg_idx, const int row_idx,
+               const ColumnArrayExecutionData& param) {
+        current_null_flag = false;
+        size_t start_off = (*param.offsets_ptr)[row_idx - 1];
+        size_t end_off = (*param.offsets_ptr)[row_idx];
+        for (size_t off = start_off; off < end_off; ++off) {
+            if (param.nested_nullmap_data && param.nested_nullmap_data[off]) {
+                current_null_flag = true;
+            } else {
+                if constexpr (std::is_same_v<ColumnString, ColumnType>) {
+                    value = &map[param.nested_col->get_data_at(off)];
+                } else {
+                    auto& data_col = static_cast<const ColumnType&>(*param.nested_col);
+                    value = &map[data_col.get_element(off)];
+                }
+                if (*value == arg_idx) {
+                    ++(*value);
+                }
             }
         }
-        return false;
+        if (!current_null_flag) {
+            result_null_flag = false;
+        }
     }
 
     void reset() {
-        null_flag = false;
-        result_null_flag = false;
+        current_null_flag = false;
+        result_null_flag = true;
     }
 };
 
 using FunctionArrayIntersect =
-        FunctionArrayBinary<ArraySetImpl<SetOperation::INTERSECT>, NameArrayIntersect>;
+        FunctionArrayNary<ArrayMapImpl<MapOperation::INTERSECT>, NameArrayIntersect>;
 
 void register_function_array_intersect(SimpleFunctionFactory& factory) {
     factory.register_function<FunctionArrayIntersect>();
diff --git a/be/src/vec/functions/array/function_array_map.h b/be/src/vec/functions/array/function_array_map.h
new file mode 100644
index 0000000000..ccf5603942
--- /dev/null
+++ b/be/src/vec/functions/array/function_array_map.h
@@ -0,0 +1,193 @@
+// 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 <type_traits>
+
+#include "vec/columns/column_array.h"
+#include "vec/columns/column_string.h"
+#include "vec/common/hash_table/hash_map.h"
+#include "vec/common/hash_table/hash_set.h"
+#include "vec/data_types/data_type_array.h"
+#include "vec/functions/array/function_array_utils.h"
+#include "vec/functions/function_helpers.h"
+
+namespace doris::vectorized {
+
+enum class MapOperation { INTERSECT };
+
+template <typename Map, typename ColumnType>
+struct IntersectAction;
+
+template <typename Map, typename ColumnType, MapOperation operation>
+struct MapActionImpl;
+
+template <typename Map, typename ColumnType>
+struct MapActionImpl<Map, ColumnType, MapOperation::INTERSECT> {
+    using Action = IntersectAction<Map, ColumnType>;
+};
+
+template <MapOperation operation, typename ColumnType>
+struct OpenMapImpl {
+    using Element = typename ColumnType::value_type;
+    using ElementNativeType = typename NativeType<Element>::Type;
+    using Map =
+            HashMapWithStackMemory<ElementNativeType, size_t, DefaultHash<ElementNativeType>, 6>;
+    using Action = typename MapActionImpl<Map, ColumnType, operation>::Action;
+
+    Action action;
+    Map map;
+    void reset() {
+        map.clear();
+        action.reset();
+    }
+
+    // this method calculate rows to get a rest dst data
+    void apply(ColumnArrayMutableData& dst, const ColumnArrayExecutionDatas params,
+               std::vector<bool>& col_const, int start_row, int end_row) {
+        size_t dst_off = 0;
+        for (int row = start_row; row < end_row; ++row) {
+            map.clear();
+            for (int i = 0; i < params.size(); ++i) {
+                action.apply(map, i, index_check_const(row, col_const[i]), params[i]);
+            }
+            // nullmap
+            if (action.apply_null()) {
+                ++dst_off;
+                dst.nested_col->insert_default();
+                if (dst.nested_nullmap_data) {
+                    dst.nested_nullmap_data->push_back(1);
+                }
+            }
+            // make map result to dst
+            for (const auto& entry : map) {
+                if (entry.get_mapped() == params.size()) {
+                    ++dst_off;
+                    auto& dst_data = static_cast<ColumnType&>(*dst.nested_col).get_data();
+                    dst_data.push_back(entry.get_first());
+                    if (dst.nested_nullmap_data) {
+                        dst.nested_nullmap_data->push_back(0);
+                    }
+                }
+            }
+            dst.offsets_ptr->push_back(dst_off);
+        }
+    }
+};
+
+template <MapOperation operation>
+struct OpenMapImpl<operation, ColumnString> {
+    using Map = HashMapWithStackMemory<StringRef, size_t, StringRefHash, 6>;
+    using Action = typename MapActionImpl<Map, ColumnString, operation>::Action;
+
+    Action action;
+    Map map;
+
+    void reset() {
+        map.clear();
+        action.reset();
+    }
+
+    void apply(ColumnArrayMutableData& dst, const ColumnArrayExecutionDatas params,
+               std::vector<bool>& col_const, int start_row, int end_row) {
+        size_t dst_off = 0;
+        for (int row = start_row; row < end_row; ++row) {
+            map.clear();
+            for (int i = 0; i < params.size(); ++i) {
+                action.apply(map, i, index_check_const(row, col_const[i]), params[i]);
+            }
+            // nullmap
+            if (action.apply_null()) {
+                ++dst_off;
+                dst.nested_col->insert_default();
+                if (dst.nested_nullmap_data) {
+                    dst.nested_nullmap_data->push_back(1);
+                }
+            }
+            // make map result to dst
+            for (const auto& entry : map) {
+                if (entry.get_mapped() == params.size()) {
+                    auto& dst_col = static_cast<ColumnString&>(*dst.nested_col);
+                    StringRef key = entry.get_first();
+                    ++dst_off;
+                    dst_col.insert_data(key.data, key.size);
+                    if (dst.nested_nullmap_data) {
+                        dst.nested_nullmap_data->push_back(0);
+                    }
+                }
+            }
+            dst.offsets_ptr->push_back(dst_off);
+        }
+    }
+};
+
+template <MapOperation operation>
+struct ArrayMapImpl {
+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, ColumnArrayExecutionDatas datas,
+                          std::vector<bool>& col_const, int start_row, int end_row) {
+        ColumnArrayMutableData dst =
+                create_mutable_data(datas[0].nested_col, datas[0].nested_nullmap_data);
+        if (_execute_internal<ALL_COLUMNS_SIMPLE>(dst, datas, col_const, start_row, end_row)) {
+            res_ptr = assemble_column_array(dst);
+            return Status::OK();
+        }
+        return Status::RuntimeError("Unexpected columns");
+    }
+
+private:
+    template <typename ColumnType>
+    static bool _execute_internal(ColumnArrayMutableData& dst, ColumnArrayExecutionDatas datas,
+                                  std::vector<bool>& col_const, int start_row, int end_row) {
+        for (auto data : datas) {
+            if (!check_column<ColumnType>(*data.nested_col)) {
+                return false;
+            }
+        }
+        // do check staff
+        using Impl = OpenMapImpl<operation, ColumnType>;
+        Impl impl;
+        ColumnPtr res_column;
+        impl.apply(dst, datas, col_const, start_row, end_row);
+        return true;
+    }
+
+    template <typename T, typename... Ts, std::enable_if_t<(sizeof...(Ts) > 0), int> = 0>
+    static bool _execute_internal(ColumnArrayMutableData& dst, ColumnArrayExecutionDatas datas,
+                                  std::vector<bool>& col_const, int start_row, int end_row) {
+        return _execute_internal<T>(dst, datas, col_const, start_row, end_row) ||
+               _execute_internal<Ts...>(dst, datas, col_const, start_row, end_row);
+    }
+};
+
+} // namespace doris::vectorized
\ No newline at end of file
diff --git a/be/src/vec/functions/array/function_array_nary.h b/be/src/vec/functions/array/function_array_nary.h
new file mode 100644
index 0000000000..bc42585439
--- /dev/null
+++ b/be/src/vec/functions/array/function_array_nary.h
@@ -0,0 +1,82 @@
+// 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 more than two arrays of the same element type.
+template <typename Impl, typename Name>
+class FunctionArrayNary : public IFunction {
+public:
+    static constexpr auto name = Name::name;
+    static FunctionPtr create() { return std::make_shared<FunctionArrayNary>(); }
+    String get_name() const override { return name; }
+    bool is_variadic() const override { return true; }
+    size_t get_number_of_arguments() const override { return 0; }
+
+    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
+        DCHECK(arguments.size() >= 2)
+                << "function: " << get_name() << ", arguments should large equals than 2";
+        CHECK(is_array(remove_nullable(arguments[0])))
+                << "0-th element is " << arguments[0]->get_name() << ",not array type";
+        auto nested_type = remove_nullable(
+                assert_cast<const DataTypeArray&>(*(arguments[0])).get_nested_type());
+        for (size_t i = 1; i < arguments.size(); ++i) {
+            CHECK(is_array(remove_nullable(arguments[i])))
+                    << i << "-th element is " << arguments[i]->get_name() << ", not array type";
+            auto right_nested_type = remove_nullable(
+                    assert_cast<const DataTypeArray&>(*(remove_nullable(arguments[i])))
+                            .get_nested_type());
+            // do check array nested data type, now we just support same nested data type
+            CHECK(nested_type->equals(*right_nested_type))
+                    << "data type " << arguments[i]->get_name() << " not equal with "
+                    << arguments[0]->get_name();
+        }
+        DataTypePtr res_data_type = Impl::get_return_type(arguments);
+        return res_data_type;
+    }
+
+    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
+                        size_t result, size_t input_rows_count) override {
+        ColumnPtr res_ptr;
+        ColumnArrayExecutionDatas datas(arguments.size());
+        std::vector<bool> col_const(arguments.size());
+        for (int i = 0; i < arguments.size(); ++i) {
+            const auto& [col, is_const] =
+                    unpack_if_const(block.get_by_position(arguments[i]).column);
+            col_const[i] = is_const;
+            extract_column_array_info(*col, datas[i]);
+        }
+        if (Status st = Impl::execute(res_ptr, datas, col_const, 0, input_rows_count);
+            st != Status::OK()) {
+            return Status::RuntimeError(
+                    fmt::format("function {} execute failed {} ", get_name(), st.to_string()));
+        }
+        block.replace_by_position(result, std::move(res_ptr));
+        return Status::OK();
+    }
+};
+
+} // 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
index f81c04b7d2..d8e0a156ba 100644
--- a/be/src/vec/functions/array/function_array_set.h
+++ b/be/src/vec/functions/array/function_array_set.h
@@ -28,7 +28,7 @@
 
 namespace doris::vectorized {
 
-enum class SetOperation { UNION, EXCEPT, INTERSECT };
+enum class SetOperation { UNION, EXCEPT };
 
 template <typename Set, typename Element>
 struct UnionAction;
@@ -36,9 +36,6 @@ 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;
 
@@ -52,11 +49,6 @@ 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;
diff --git a/be/src/vec/functions/array/function_array_union.cpp b/be/src/vec/functions/array/function_array_union.cpp
index 641063103c..68c9c2043f 100644
--- a/be/src/vec/functions/array/function_array_union.cpp
+++ b/be/src/vec/functions/array/function_array_union.cpp
@@ -21,6 +21,7 @@
 #include "vec/data_types/data_type.h"
 #include "vec/data_types/data_type_nullable.h"
 #include "vec/functions/array/function_array_binary.h"
+#include "vec/functions/array/function_array_nary.h"
 #include "vec/functions/array/function_array_set.h"
 #include "vec/functions/simple_function_factory.h"
 
diff --git a/be/src/vec/functions/array/function_array_utils.h b/be/src/vec/functions/array/function_array_utils.h
index a9b303934c..36bf811b77 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/columns/columns_number.h"
 #include "vec/core/types.h"
 #include "vec/data_types/data_type.h"
@@ -29,6 +30,15 @@ class IColumn;
 
 namespace doris::vectorized {
 
+struct ColumnArrayMutableData {
+public:
+    MutableColumnPtr array_nested_col = nullptr;
+    ColumnUInt8::Container* nested_nullmap_data = nullptr;
+    MutableColumnPtr offsets_col = nullptr;
+    ColumnArray::Offsets64* offsets_ptr = nullptr;
+    IColumn* nested_col = nullptr;
+};
+
 struct ColumnArrayExecutionData {
 public:
     void reset() {
@@ -45,17 +55,34 @@ public:
     const ColumnArray::Offsets64* offsets_ptr = nullptr;
     const UInt8* nested_nullmap_data = nullptr;
     const IColumn* nested_col = nullptr;
-};
 
-struct ColumnArrayMutableData {
-public:
-    MutableColumnPtr array_nested_col = nullptr;
-    ColumnUInt8::Container* nested_nullmap_data = nullptr;
-    MutableColumnPtr offsets_col = nullptr;
-    ColumnArray::Offsets64* offsets_ptr = nullptr;
-    IColumn* nested_col = nullptr;
+    ColumnArrayMutableData to_mutable_data() const {
+        ColumnArrayMutableData dst;
+        dst.offsets_col = ColumnArray::ColumnOffsets::create();
+        dst.offsets_ptr =
+                &reinterpret_cast<ColumnArray::ColumnOffsets*>(dst.offsets_col.get())->get_data();
+        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();
+        for (size_t row = 0; row < offsets_ptr->size(); ++row) {
+            dst.offsets_ptr->push_back((*offsets_ptr)[row]);
+            size_t off = (*offsets_ptr)[row - 1];
+            size_t len = (*offsets_ptr)[row] - off;
+            for (int start = off; start < off + len; ++start) {
+                if (nested_nullmap_data && nested_nullmap_data[start]) {
+                    dst.nested_col->insert_default();
+                    dst.nested_nullmap_data->push_back(1);
+                } else {
+                    dst.nested_col->insert_from(*nested_col, start);
+                    dst.nested_nullmap_data->push_back(0);
+                }
+            }
+        }
+        return dst;
+    }
 };
-
 bool extract_column_array_info(const IColumn& src, ColumnArrayExecutionData& data);
 
 ColumnArrayMutableData create_mutable_data(const IColumn* nested_col, bool is_nullable);
@@ -66,4 +93,5 @@ MutableColumnPtr assemble_column_array(ColumnArrayMutableData& data);
 void slice_array(ColumnArrayMutableData& dst, ColumnArrayExecutionData& src,
                  const IColumn& offset_column, const IColumn* length_column);
 
+using ColumnArrayExecutionDatas = std::vector<ColumnArrayExecutionData>;
 } // namespace doris::vectorized
diff --git a/fe/fe-common/src/main/java/org/apache/doris/catalog/Type.java b/fe/fe-common/src/main/java/org/apache/doris/catalog/Type.java
index 22d0bcd65c..9785988f31 100644
--- a/fe/fe-common/src/main/java/org/apache/doris/catalog/Type.java
+++ b/fe/fe-common/src/main/java/org/apache/doris/catalog/Type.java
@@ -710,8 +710,8 @@ public abstract class Type {
         } else if (sourceType.isMapType() && targetType.isMapType()) {
             return MapType.canCastTo((MapType) sourceType, (MapType) targetType);
         } else if (targetType.isArrayType() && !((ArrayType) targetType).getItemType().isScalarType()
-                && !sourceType.isNull()) {
-            // TODO: current not support cast any non-array type(except for null) to nested array type.
+                && !sourceType.isNull() && !sourceType.isStringType()) {
+            // TODO: current not support cast any non-array type(except null and charFamily) to nested array type.
             return false;
         } else if ((targetType.isStructType() || targetType.isMapType()) && sourceType.isStringType()) {
             return true;
diff --git a/gensrc/script/doris_builtins_functions.py b/gensrc/script/doris_builtins_functions.py
index 611569520e..464d665390 100644
--- a/gensrc/script/doris_builtins_functions.py
+++ b/gensrc/script/doris_builtins_functions.py
@@ -544,24 +544,24 @@ visible_functions = {
         [['array_compact'], 'ARRAY_DECIMAL128', ['ARRAY_DECIMAL128'], ''],
         [['array_compact'], 'ARRAY_VARCHAR',   ['ARRAY_VARCHAR'], ''],
 
-        [['array_intersect'], 'ARRAY_BOOLEAN',  ['ARRAY_BOOLEAN', 'ARRAY_BOOLEAN'],  ''],
-        [['array_intersect'], 'ARRAY_TINYINT',  ['ARRAY_TINYINT', 'ARRAY_TINYINT'],  ''],
-        [['array_intersect'], 'ARRAY_SMALLINT', ['ARRAY_SMALLINT', 'ARRAY_SMALLINT'], ''],
-        [['array_intersect'], 'ARRAY_INT',      ['ARRAY_INT', 'ARRAY_INT'], ''],
-        [['array_intersect'], 'ARRAY_BIGINT',   ['ARRAY_BIGINT', 'ARRAY_BIGINT'],   ''],
-        [['array_intersect'], 'ARRAY_LARGEINT', ['ARRAY_LARGEINT', 'ARRAY_LARGEINT'], ''],
-        [['array_intersect'], 'ARRAY_FLOAT',     ['ARRAY_FLOAT', 'ARRAY_FLOAT'],  ''],
-        [['array_intersect'], 'ARRAY_DOUBLE',    ['ARRAY_DOUBLE', 'ARRAY_DOUBLE'], ''],
-        [['array_intersect'], 'ARRAY_DECIMALV2', ['ARRAY_DECIMALV2', 'ARRAY_DECIMALV2'], ''],
-        [['array_intersect'], 'ARRAY_DECIMAL32', ['ARRAY_DECIMAL32', 'ARRAY_DECIMAL32'], ''],
-        [['array_intersect'], 'ARRAY_DECIMAL64', ['ARRAY_DECIMAL64', 'ARRAY_DECIMAL64'], ''],
-        [['array_intersect'], 'ARRAY_DECIMAL128', ['ARRAY_DECIMAL128', 'ARRAY_DECIMAL128'], ''],
-        [['array_intersect'], 'ARRAY_DATETIME',  ['ARRAY_DATETIME', 'ARRAY_DATETIME'], ''],
-        [['array_intersect'], 'ARRAY_DATE',      ['ARRAY_DATE', 'ARRAY_DATE'], ''],
-        [['array_intersect'], 'ARRAY_DATETIMEV2',  ['ARRAY_DATETIMEV2', 'ARRAY_DATETIMEV2'], ''],
-        [['array_intersect'], 'ARRAY_DATEV2',      ['ARRAY_DATEV2', 'ARRAY_DATEV2'], ''],
-        [['array_intersect'], 'ARRAY_VARCHAR',   ['ARRAY_VARCHAR', 'ARRAY_VARCHAR'], ''],
-        [['array_intersect'], 'ARRAY_STRING',    ['ARRAY_STRING', 'ARRAY_STRING'], ''],
+        [['array_intersect'], 'ARRAY_BOOLEAN',  ['ARRAY_BOOLEAN', 'ARRAY_BOOLEAN', '...'],  ''],
+        [['array_intersect'], 'ARRAY_TINYINT',  ['ARRAY_TINYINT', 'ARRAY_TINYINT', '...'],  ''],
+        [['array_intersect'], 'ARRAY_SMALLINT', ['ARRAY_SMALLINT', 'ARRAY_SMALLINT', '...'], ''],
+        [['array_intersect'], 'ARRAY_INT',      ['ARRAY_INT', 'ARRAY_INT', '...'], ''],
+        [['array_intersect'], 'ARRAY_BIGINT',   ['ARRAY_BIGINT', 'ARRAY_BIGINT', '...'],   ''],
+        [['array_intersect'], 'ARRAY_LARGEINT', ['ARRAY_LARGEINT', 'ARRAY_LARGEINT', '...'], ''],
+        [['array_intersect'], 'ARRAY_FLOAT',     ['ARRAY_FLOAT', 'ARRAY_FLOAT', '...'],  ''],
+        [['array_intersect'], 'ARRAY_DOUBLE',    ['ARRAY_DOUBLE', 'ARRAY_DOUBLE', '...'], ''],
+        [['array_intersect'], 'ARRAY_DECIMALV2', ['ARRAY_DECIMALV2', 'ARRAY_DECIMALV2', '...'], ''],
+        [['array_intersect'], 'ARRAY_DECIMAL32', ['ARRAY_DECIMAL32', 'ARRAY_DECIMAL32', '...'], ''],
+        [['array_intersect'], 'ARRAY_DECIMAL64', ['ARRAY_DECIMAL64', 'ARRAY_DECIMAL64', '...'], ''],
+        [['array_intersect'], 'ARRAY_DECIMAL128', ['ARRAY_DECIMAL128', 'ARRAY_DECIMAL128', '...'], ''],
+        [['array_intersect'], 'ARRAY_DATETIME',  ['ARRAY_DATETIME', 'ARRAY_DATETIME', '...'], ''],
+        [['array_intersect'], 'ARRAY_DATE',      ['ARRAY_DATE', 'ARRAY_DATE', '...'], ''],
+        [['array_intersect'], 'ARRAY_DATETIMEV2',  ['ARRAY_DATETIMEV2', 'ARRAY_DATETIMEV2', '...'], ''],
+        [['array_intersect'], 'ARRAY_DATEV2',      ['ARRAY_DATEV2', 'ARRAY_DATEV2', '...'], ''],
+        [['array_intersect'], 'ARRAY_VARCHAR',   ['ARRAY_VARCHAR', 'ARRAY_VARCHAR', '...'], ''],
+        [['array_intersect'], 'ARRAY_STRING',    ['ARRAY_STRING', 'ARRAY_STRING', '...'], ''],
 
         [['array_slice', '%element_slice%'], 'ARRAY_BOOLEAN', ['ARRAY_BOOLEAN', 'BIGINT'], ''],
         [['array_slice', '%element_slice%'], 'ARRAY_TINYINT', ['ARRAY_TINYINT', 'BIGINT'], ''],
diff --git a/regression-test/data/query_p0/sql_functions/array_functions/test_array_functions.out b/regression-test/data/query_p0/sql_functions/array_functions/test_array_functions.out
index f3c72dc7aa..fc2b267878 100644
--- a/regression-test/data/query_p0/sql_functions/array_functions/test_array_functions.out
+++ b/regression-test/data/query_p0/sql_functions/array_functions/test_array_functions.out
@@ -297,15 +297,15 @@
 9	\N
 
 -- !select --
-1	[1, 2]
+1	[2, 1]
 2	[]
 3	\N
 4	[]
 5	\N
 6	\N
 7	\N
-8	[1, 2, 3]
-9	[1, 2]
+8	[3, 2, 1]
+9	[2, 1]
 
 -- !select --
 1	[2023-02-06]
diff --git a/regression-test/data/query_p0/sql_functions/array_functions/test_array_functions_by_literal.out b/regression-test/data/query_p0/sql_functions/array_functions/test_array_functions_by_literal.out
index 6adaea2c39..804e8472d1 100644
--- a/regression-test/data/query_p0/sql_functions/array_functions/test_array_functions_by_literal.out
+++ b/regression-test/data/query_p0/sql_functions/array_functions/test_array_functions_by_literal.out
@@ -414,7 +414,7 @@ true
 [1]
 
 -- !sql --
-[2, 3]
+[3, 2]
 
 -- !sql --
 [1, 2, 3, 4, NULL]
@@ -423,7 +423,7 @@ true
 [1]
 
 -- !sql --
-[2, 3]
+[3, 2]
 
 -- !sql --
 [1, 0]
@@ -533,6 +533,18 @@ true
 -- !sql --
 [111.111, 222.222]
 
+-- !sql_intersect_1 --
+[]
+
+-- !sql_intersect_2 --
+[NULL, 1]
+
+-- !sql_intersect_3 --
+[NULL, 1]
+
+-- !sql_intersect_4 --
+[]
+
 -- !sql --
 [2, 3, 4, 5, 6]
 
diff --git a/regression-test/suites/query_p0/sql_functions/array_functions/test_array_functions_by_literal.groovy b/regression-test/suites/query_p0/sql_functions/array_functions/test_array_functions_by_literal.groovy
index 35ca5f3cd9..584750d1ca 100644
--- a/regression-test/suites/query_p0/sql_functions/array_functions/test_array_functions_by_literal.groovy
+++ b/regression-test/suites/query_p0/sql_functions/array_functions/test_array_functions_by_literal.groovy
@@ -219,6 +219,12 @@ suite("test_array_functions_by_literal") {
     qt_sql "select (array(cast ('2023-02-06' as datev2), cast ('2023-02-05' as datev2)))[1:2]"
     qt_sql "select (array(cast (111.111 as decimalv3(6,3)),cast (222.222 as decimalv3(6,3))))[1:2]"
 
+    // array_intersect
+    qt_sql_intersect_1 "select array_intersect([1,2,3], [1,2,3], [null])"
+    qt_sql_intersect_2 "select array_intersect([1, 2, null], [1, 3, null], [1,2,3,null])"
+    qt_sql_intersect_3 "select array_intersect([1,2,3, null], [1,2,3,null], [1,2,null], [1, null])"
+    qt_sql_intersect_4 "select array_intersect([1,2,3], [1,2,3], [null], [])"
+
     // array_popfront function
     qt_sql "select array_popfront([1,2,3,4,5,6])"
     qt_sql "select array_popfront([])"


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