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