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