You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@doris.apache.org by li...@apache.org on 2022/06/17 03:07:55 UTC
[incubator-doris] branch master updated: [feature-wip](array-type) Add array aggregation functions (#10108)
This is an automated email from the ASF dual-hosted git repository.
lihaopeng pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-doris.git
The following commit(s) were added to refs/heads/master by this push:
new 5e47b03595 [feature-wip](array-type) Add array aggregation functions (#10108)
5e47b03595 is described below
commit 5e47b0359562ad7f9350da5232109426e7f1a572
Author: Adonis Ling <ad...@gmail.com>
AuthorDate: Fri Jun 17 11:07:49 2022 +0800
[feature-wip](array-type) Add array aggregation functions (#10108)
---
be/src/vec/CMakeLists.txt | 1 +
.../vec/aggregate_functions/aggregate_function.h | 17 ++
.../aggregate_function_product.h | 121 +++++++++
be/src/vec/columns/column_decimal.h | 19 ++
be/src/vec/core/types.h | 7 +
.../functions/array/function_array_aggregation.cpp | 287 +++++++++++++++++++++
be/src/vec/functions/array/function_array_mapped.h | 76 ++++++
.../functions/array/function_array_register.cpp | 2 +
be/src/vec/functions/function.h | 1 -
be/src/vec/functions/simple_function_factory.h | 3 +-
be/test/CMakeLists.txt | 1 +
.../function/function_array_aggregation_test.cpp | 228 ++++++++++++++++
be/test/vec/function/function_test_util.cpp | 24 +-
be/test/vec/function/function_test_util.h | 83 +++++-
.../sql-functions/array-functions/array_avg.md | 61 +++++
.../sql-functions/array-functions/array_max.md | 61 +++++
.../sql-functions/array-functions/array_min.md | 61 +++++
.../sql-functions/array-functions/array_product.md | 61 +++++
.../sql-functions/array-functions/array_sum.md | 61 +++++
.../sql-functions/array-functions/array_avg.md | 60 +++++
.../sql-functions/array-functions/array_max.md | 60 +++++
.../sql-functions/array-functions/array_min.md | 60 +++++
.../sql-functions/array-functions/array_product.md | 60 +++++
.../sql-functions/array-functions/array_sum.md | 60 +++++
.../java/org/apache/doris/catalog/ArrayType.java | 4 +-
.../main/java/org/apache/doris/catalog/Type.java | 2 -
gensrc/script/doris_builtins_functions.py | 38 ++-
27 files changed, 1494 insertions(+), 25 deletions(-)
diff --git a/be/src/vec/CMakeLists.txt b/be/src/vec/CMakeLists.txt
index fc50adca0a..6334a92a08 100644
--- a/be/src/vec/CMakeLists.txt
+++ b/be/src/vec/CMakeLists.txt
@@ -128,6 +128,7 @@ set(VEC_FILES
functions/array/function_array_element.cpp
functions/array/function_array_register.cpp
functions/array/function_array_size.cpp
+ functions/array/function_array_aggregation.cpp
exprs/table_function/vexplode_json_array.cpp
functions/math.cpp
functions/function_bitmap.cpp
diff --git a/be/src/vec/aggregate_functions/aggregate_function.h b/be/src/vec/aggregate_functions/aggregate_function.h
index d822dada79..eca81b3199 100644
--- a/be/src/vec/aggregate_functions/aggregate_function.h
+++ b/be/src/vec/aggregate_functions/aggregate_function.h
@@ -209,4 +209,21 @@ public:
using AggregateFunctionPtr = std::shared_ptr<IAggregateFunction>;
+class AggregateFunctionGuard {
+public:
+ using AggregateData = std::remove_pointer_t<AggregateDataPtr>;
+
+ explicit AggregateFunctionGuard(const IAggregateFunction* function)
+ : _function(function),
+ _data(std::make_unique<AggregateData[]>(function->size_of_data())) {
+ _function->create(_data.get());
+ };
+ ~AggregateFunctionGuard() { _function->destroy(_data.get()); }
+ AggregateDataPtr data() { return _data.get(); };
+
+private:
+ const IAggregateFunction* _function;
+ std::unique_ptr<AggregateData[]> _data;
+};
+
} // namespace doris::vectorized
diff --git a/be/src/vec/aggregate_functions/aggregate_function_product.h b/be/src/vec/aggregate_functions/aggregate_function_product.h
new file mode 100644
index 0000000000..0e392b0e69
--- /dev/null
+++ b/be/src/vec/aggregate_functions/aggregate_function_product.h
@@ -0,0 +1,121 @@
+// 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 <cstddef>
+#include <type_traits>
+
+#include "vec/aggregate_functions/aggregate_function.h"
+#include "vec/columns/column_decimal.h"
+#include "vec/columns/column_vector.h"
+#include "vec/common/arena.h"
+#include "vec/common/string_buffer.hpp"
+#include "vec/core/types.h"
+#include "vec/data_types/data_type_decimal.h"
+#include "vec/data_types/data_type_number.h"
+#include "vec/io/io_helper.h"
+
+namespace doris {
+namespace vectorized {
+
+template <typename T>
+struct AggregateFunctionProductData {
+ T product {};
+
+ void add(T value) { product *= value; }
+
+ void merge(const AggregateFunctionProductData& other) { product *= other.product; }
+
+ void write(BufferWritable& buffer) const { write_binary(product, buffer); }
+
+ void read(BufferReadable& buffer) { read_binary(product, buffer); }
+
+ T get() const { return product; }
+
+ void reset(T value) { product = std::move(value); }
+};
+
+template <typename T, typename TResult, typename Data>
+class AggregateFunctionProduct final
+ : public IAggregateFunctionDataHelper<Data, AggregateFunctionProduct<T, TResult, Data>> {
+public:
+ using ResultDataType = std::conditional_t<IsDecimalNumber<T>, DataTypeDecimal<TResult>,
+ DataTypeNumber<TResult>>;
+ using ColVecType = std::conditional_t<IsDecimalNumber<T>, ColumnDecimal<T>, ColumnVector<T>>;
+ using ColVecResult =
+ std::conditional_t<IsDecimalNumber<T>, ColumnDecimal<TResult>, ColumnVector<TResult>>;
+
+ std::string get_name() const { return "product"; }
+
+ AggregateFunctionProduct(const DataTypes& argument_types_)
+ : IAggregateFunctionDataHelper<Data, AggregateFunctionProduct<T, TResult, Data>>(
+ argument_types_, {}),
+ scale(0) {}
+
+ AggregateFunctionProduct(const IDataType& data_type, const DataTypes& argument_types_)
+ : IAggregateFunctionDataHelper<Data, AggregateFunctionProduct<T, TResult, Data>>(
+ argument_types_, {}),
+ scale(get_decimal_scale(data_type)) {}
+
+ DataTypePtr get_return_type() const override {
+ if constexpr (IsDecimalNumber<T>) {
+ return std::make_shared<ResultDataType>(ResultDataType::max_precision(), scale);
+ } else {
+ return std::make_shared<ResultDataType>();
+ }
+ }
+
+ void add(AggregateDataPtr __restrict place, const IColumn** columns, size_t row_num,
+ Arena*) const override {
+ const auto& column = static_cast<const ColVecType&>(*columns[0]);
+ this->data(place).add(column.get_data()[row_num]);
+ }
+
+ void reset(AggregateDataPtr place) const override {
+ if constexpr (IsDecimalNumber<T>) {
+ this->data(place).reset(T(1 * ResultDataType::get_scale_multiplier(scale)));
+ } else {
+ this->data(place).reset(1);
+ }
+ }
+
+ void merge(AggregateDataPtr __restrict place, ConstAggregateDataPtr rhs,
+ Arena*) const override {
+ this->data(place).merge(this->data(rhs));
+ }
+
+ void serialize(ConstAggregateDataPtr __restrict place, BufferWritable& buf) const override {
+ this->data(place).write(buf);
+ }
+
+ void deserialize(AggregateDataPtr __restrict place, BufferReadable& buf,
+ Arena*) const override {
+ this->data(place).read(buf);
+ }
+
+ void insert_result_into(ConstAggregateDataPtr __restrict place, IColumn& to) const override {
+ auto& column = static_cast<ColVecResult&>(to);
+ column.get_data().push_back(this->data(place).get());
+ }
+
+private:
+ UInt32 scale;
+};
+
+} // namespace vectorized
+} // namespace doris
diff --git a/be/src/vec/columns/column_decimal.h b/be/src/vec/columns/column_decimal.h
index 98c2d05ef4..dd93768e2f 100644
--- a/be/src/vec/columns/column_decimal.h
+++ b/be/src/vec/columns/column_decimal.h
@@ -21,6 +21,7 @@
#pragma once
#include <cmath>
+#include <type_traits>
#include "olap/decimal12.h"
#include "vec/columns/column.h"
@@ -204,6 +205,8 @@ public:
data[self_row] = T();
}
+ UInt32 get_scale() const { return scale; }
+
protected:
Container data;
UInt32 scale;
@@ -226,6 +229,22 @@ protected:
}
};
+template <typename>
+class ColumnVector;
+
+template <typename T, bool is_decimal = false>
+struct ColumnVectorOrDecimalT {
+ using Col = ColumnVector<T>;
+};
+
+template <typename T>
+struct ColumnVectorOrDecimalT<T, true> {
+ using Col = ColumnDecimal<T>;
+};
+
+template <typename T>
+using ColumnVectorOrDecimal = typename ColumnVectorOrDecimalT<T, IsDecimalNumber<T>>::Col;
+
template <typename T>
template <typename Type>
ColumnPtr ColumnDecimal<T>::index_impl(const PaddedPODArray<Type>& indexes, size_t limit) const {
diff --git a/be/src/vec/core/types.h b/be/src/vec/core/types.h
index f4ca212d0b..650b64a627 100644
--- a/be/src/vec/core/types.h
+++ b/be/src/vec/core/types.h
@@ -345,6 +345,13 @@ inline constexpr bool IsDecimalNumber<Decimal64> = true;
template <>
inline constexpr bool IsDecimalNumber<Decimal128> = true;
+template <typename T>
+constexpr bool IsFloatNumber = false;
+template <>
+inline constexpr bool IsFloatNumber<Float32> = true;
+template <>
+inline constexpr bool IsFloatNumber<Float64> = true;
+
template <typename T>
struct NativeType {
using Type = T;
diff --git a/be/src/vec/functions/array/function_array_aggregation.cpp b/be/src/vec/functions/array/function_array_aggregation.cpp
new file mode 100644
index 0000000000..8095ff75ad
--- /dev/null
+++ b/be/src/vec/functions/array/function_array_aggregation.cpp
@@ -0,0 +1,287 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// This file is copied from
+// https://github.com/ClickHouse/ClickHouse/blob/master/src/Functions/array/arrayAggregation.cpp
+// and modified by Doris
+
+#include <type_traits>
+
+#include "vec/aggregate_functions/aggregate_function_avg.h"
+#include "vec/aggregate_functions/aggregate_function_min_max.h"
+#include "vec/aggregate_functions/aggregate_function_null.h"
+#include "vec/aggregate_functions/aggregate_function_product.h"
+#include "vec/aggregate_functions/aggregate_function_sum.h"
+#include "vec/aggregate_functions/helpers.h"
+#include "vec/columns/column_nullable.h"
+#include "vec/common/arena.h"
+#include "vec/core/types.h"
+#include "vec/data_types/data_type.h"
+#include "vec/data_types/data_type_nullable.h"
+#include "vec/functions/array/function_array_mapped.h"
+#include "vec/functions/simple_function_factory.h"
+
+namespace doris {
+namespace vectorized {
+
+enum class AggregateOperation { MIN, MAX, SUM, AVERAGE, PRODUCT };
+
+template <typename Element, AggregateOperation operation>
+struct ArrayAggregateResultImpl;
+
+template <typename Element>
+struct ArrayAggregateResultImpl<Element, AggregateOperation::MIN> {
+ using Result = Element;
+};
+
+template <typename Element>
+struct ArrayAggregateResultImpl<Element, AggregateOperation::MAX> {
+ using Result = Element;
+};
+
+template <typename Element>
+struct ArrayAggregateResultImpl<Element, AggregateOperation::AVERAGE> {
+ using Result = std::conditional_t<IsDecimalNumber<Element>, Decimal128, Float64>;
+};
+
+template <typename Element>
+struct ArrayAggregateResultImpl<Element, AggregateOperation::PRODUCT> {
+ using Result = std::conditional_t<IsDecimalNumber<Element>, Decimal128, Float64>;
+};
+
+template <typename Element>
+struct ArrayAggregateResultImpl<Element, AggregateOperation::SUM> {
+ using Result = std::conditional_t<
+ IsDecimalNumber<Element>, Decimal128,
+ std::conditional_t<IsFloatNumber<Element>, Float64,
+ std::conditional_t<std::is_same_v<Element, Int128>, Int128, Int64>>>;
+};
+
+template <typename Element, AggregateOperation operation>
+using ArrayAggregateResult = typename ArrayAggregateResultImpl<Element, operation>::Result;
+
+// For MIN/MAX, the type of result is the same as the type of elements, we can omit the
+// template specialization.
+template <AggregateOperation operation>
+struct AggregateFunctionImpl;
+
+template <>
+struct AggregateFunctionImpl<AggregateOperation::SUM> {
+ template <typename Element>
+ struct TypeTraits {
+ using ResultType = ArrayAggregateResult<Element, AggregateOperation::SUM>;
+ using AggregateDataType = AggregateFunctionSumData<ResultType>;
+ using Function = AggregateFunctionSum<Element, ResultType, AggregateDataType>;
+ };
+};
+
+template <>
+struct AggregateFunctionImpl<AggregateOperation::AVERAGE> {
+ template <typename Element>
+ struct TypeTraits {
+ using ResultType = ArrayAggregateResult<Element, AggregateOperation::AVERAGE>;
+ using AggregateDataType = AggregateFunctionAvgData<ResultType>;
+ using Function = AggregateFunctionAvg<Element, AggregateDataType>;
+ static_assert(std::is_same_v<ResultType, typename Function::ResultType>,
+ "ResultType doesn't match.");
+ };
+};
+
+template <>
+struct AggregateFunctionImpl<AggregateOperation::PRODUCT> {
+ template <typename Element>
+ struct TypeTraits {
+ using ResultType = ArrayAggregateResult<Element, AggregateOperation::PRODUCT>;
+ using AggregateDataType = AggregateFunctionProductData<Element>;
+ using Function = AggregateFunctionProduct<Element, ResultType, AggregateDataType>;
+ };
+};
+
+template <typename Derived>
+struct AggregateFunction {
+ template <typename T>
+ using Function = typename Derived::template TypeTraits<T>::Function;
+
+ static auto create(const DataTypePtr& data_type_ptr) -> AggregateFunctionPtr {
+ DataTypes data_types = {remove_nullable(data_type_ptr)};
+ auto& data_type = *data_types.front();
+ AggregateFunctionPtr nested_function;
+ if (is_decimal(data_types.front())) {
+ nested_function = AggregateFunctionPtr(
+ create_with_decimal_type<Function>(data_type, data_type, data_types));
+ } else {
+ nested_function =
+ AggregateFunctionPtr(create_with_numeric_type<Function>(data_type, data_types));
+ }
+
+ AggregateFunctionPtr function;
+ function.reset(new AggregateFunctionNullUnary<true>(nested_function,
+ {make_nullable(data_type_ptr)}, {}));
+ return function;
+ }
+};
+
+template <AggregateOperation operation>
+struct ArrayAggregateImpl {
+ using column_type = ColumnArray;
+ using data_type = DataTypeArray;
+
+ static DataTypePtr get_return_type(const DataTypeArray* data_type_array) {
+ using Function = AggregateFunction<AggregateFunctionImpl<operation>>;
+ auto function = Function::create(data_type_array->get_nested_type());
+ return function->get_return_type();
+ }
+
+ static Status execute(Block& block, size_t result, const DataTypeArray* data_type_array,
+ const ColumnArray& array) {
+ ColumnPtr res;
+ DataTypePtr type = data_type_array->get_nested_type();
+ const IColumn* data = array.get_data_ptr().get();
+
+ const auto& offsets = array.get_offsets();
+ if (execute_type<Int8>(res, type, data, offsets) ||
+ execute_type<Int16>(res, type, data, offsets) ||
+ execute_type<Int32>(res, type, data, offsets) ||
+ execute_type<Int64>(res, type, data, offsets) ||
+ execute_type<Int128>(res, type, data, offsets) ||
+ execute_type<Float32>(res, type, data, offsets) ||
+ execute_type<Float64>(res, type, data, offsets) ||
+ execute_type<Decimal128>(res, type, data, offsets)) {
+ block.replace_by_position(result, std::move(res));
+ return Status::OK();
+ } else {
+ return Status::RuntimeError("Unexpected column for aggregation: " + data->get_name());
+ }
+ }
+
+ template <typename Element>
+ static bool execute_type(ColumnPtr& res_ptr, const DataTypePtr& type, const IColumn* data,
+ const ColumnArray::Offsets& offsets) {
+ using ColVecType = ColumnVectorOrDecimal<Element>;
+ using ResultType = ArrayAggregateResult<Element, operation>;
+ using ColVecResultType = ColumnVectorOrDecimal<ResultType>;
+ using Function = AggregateFunction<AggregateFunctionImpl<operation>>;
+
+ const ColVecType* column =
+ data->is_nullable()
+ ? check_and_get_column<ColVecType>(
+ static_cast<const ColumnNullable*>(data)->get_nested_column())
+ : check_and_get_column<ColVecType>(&*data);
+ if (!column) {
+ return false;
+ }
+
+ ColumnPtr res_column;
+ if constexpr (IsDecimalNumber<Element>) {
+ res_column = ColVecResultType::create(0, column->get_scale());
+ } else {
+ res_column = ColVecResultType::create();
+ }
+ res_column = make_nullable(res_column);
+ static_cast<ColumnNullable&>(res_column->assume_mutable_ref()).reserve(offsets.size());
+
+ auto function = Function::create(type);
+ auto guard = AggregateFunctionGuard(function.get());
+ Arena arena;
+ auto nullable_column = make_nullable(data->get_ptr());
+ const IColumn* columns[] = {nullable_column.get()};
+ for (int64_t i = 0; i < offsets.size(); ++i) {
+ auto start = offsets[i - 1]; // -1 is ok.
+ auto end = offsets[i];
+ bool is_empty = (start == end);
+ if (is_empty) {
+ res_column->assume_mutable()->insert_default();
+ continue;
+ }
+ function->reset(guard.data());
+ function->add_batch_range(start, end - 1, guard.data(), columns, &arena,
+ data->is_nullable());
+ function->insert_result_into(guard.data(), res_column->assume_mutable_ref());
+ }
+ res_ptr = std::move(res_column);
+ return true;
+ };
+};
+
+struct NameArrayMin {
+ static constexpr auto name = "array_min";
+};
+
+template <>
+struct AggregateFunction<AggregateFunctionImpl<AggregateOperation::MIN>> {
+ static auto create(const DataTypePtr& data_type_ptr) -> AggregateFunctionPtr {
+ DataTypes data_types = {remove_nullable(data_type_ptr)};
+ auto nested_function = AggregateFunctionPtr(
+ create_aggregate_function_min(NameArrayMin::name, data_types, {}, false));
+
+ AggregateFunctionPtr function;
+ function.reset(new AggregateFunctionNullUnary<true>(nested_function,
+ {make_nullable(data_type_ptr)}, {}));
+ return function;
+ }
+};
+
+struct NameArrayMax {
+ static constexpr auto name = "array_max";
+};
+
+template <>
+struct AggregateFunction<AggregateFunctionImpl<AggregateOperation::MAX>> {
+ static auto create(const DataTypePtr& data_type_ptr) -> AggregateFunctionPtr {
+ DataTypes data_types = {remove_nullable(data_type_ptr)};
+ auto nested_function = AggregateFunctionPtr(
+ create_aggregate_function_max(NameArrayMax::name, data_types, {}, false));
+
+ AggregateFunctionPtr function;
+ function.reset(new AggregateFunctionNullUnary<true>(nested_function,
+ {make_nullable(data_type_ptr)}, {}));
+ return function;
+ }
+};
+
+struct NameArraySum {
+ static constexpr auto name = "array_sum";
+};
+
+struct NameArrayAverage {
+ static constexpr auto name = "array_avg";
+};
+
+struct NameArrayProduct {
+ static constexpr auto name = "array_product";
+};
+
+using FunctionArrayMin =
+ FunctionArrayMapped<ArrayAggregateImpl<AggregateOperation::MIN>, NameArrayMin>;
+using FunctionArrayMax =
+ FunctionArrayMapped<ArrayAggregateImpl<AggregateOperation::MAX>, NameArrayMax>;
+using FunctionArraySum =
+ FunctionArrayMapped<ArrayAggregateImpl<AggregateOperation::SUM>, NameArraySum>;
+using FunctionArrayAverage =
+ FunctionArrayMapped<ArrayAggregateImpl<AggregateOperation::AVERAGE>, NameArrayAverage>;
+using FunctionArrayProduct =
+ FunctionArrayMapped<ArrayAggregateImpl<AggregateOperation::PRODUCT>, NameArrayProduct>;
+
+void register_function_array_aggregation(SimpleFunctionFactory& factory) {
+ factory.register_function<FunctionArrayMin>();
+ factory.register_function<FunctionArrayMax>();
+ factory.register_function<FunctionArraySum>();
+ factory.register_function<FunctionArrayAverage>();
+ factory.register_function<FunctionArrayProduct>();
+}
+
+} // namespace vectorized
+} // namespace doris
diff --git a/be/src/vec/functions/array/function_array_mapped.h b/be/src/vec/functions/array/function_array_mapped.h
new file mode 100644
index 0000000000..6a38993fb4
--- /dev/null
+++ b/be/src/vec/functions/array/function_array_mapped.h
@@ -0,0 +1,76 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// This file is copied from
+// https://github.com/ClickHouse/ClickHouse/blob/master/src/Functions/array/FunctionArrayMapped.h
+// and modified by Doris
+
+#include "vec/columns/column.h"
+#include "vec/columns/column_nullable.h"
+#include "vec/data_types/data_type_array.h"
+#include "vec/data_types/data_type_nullable.h"
+#include "vec/functions/function.h"
+
+namespace doris {
+namespace vectorized {
+
+/** Higher-order functions for arrays.
+ * These functions optionally apply a map (transform) to array (or multiple arrays of identical size) by lambda function,
+ * and return some result based on that transformation.
+ *
+ * Examples:
+ * arrayMap(x1,...,xn -> expression, array1,...,arrayn) - apply the expression to each element of the array (or set of parallel arrays).
+ * arrayFilter(x -> predicate, array) - leave in the array only the elements for which the expression is true.
+ *
+ * For some functions arrayCount, arrayExists, arrayAll, an overload of the form f(array) is available,
+ * which works in the same way as f(x -> x, array).
+ *
+ * See the example of Impl template parameter in arrayMap.cpp
+ */
+template <typename Impl, typename Name>
+class FunctionArrayMapped : public IFunction {
+public:
+ static constexpr auto name = Name::name;
+ static FunctionPtr create() { return std::make_shared<FunctionArrayMapped>(); }
+
+ String get_name() const override { return name; }
+ Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
+ size_t result, size_t input_rows_count) override {
+ const auto& typed_column = block.get_by_position(arguments[0]);
+ const typename Impl::column_type* column_array;
+ if (typed_column.column->is_nullable()) {
+ column_array = check_and_get_column<const typename Impl::column_type>(
+ static_cast<const ColumnNullable*>(typed_column.column.get())
+ ->get_nested_column_ptr()
+ .get());
+ } else {
+ column_array = check_and_get_column<const typename Impl::column_type>(
+ typed_column.column.get());
+ }
+ const auto* data_type_array =
+ static_cast<const DataTypeArray*>(remove_nullable(typed_column.type).get());
+ return Impl::execute(block, result, data_type_array, *column_array);
+ }
+ size_t get_number_of_arguments() const override { return 1; }
+ DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
+ const DataTypeArray* data_type_array =
+ static_cast<const DataTypeArray*>(remove_nullable(arguments[0]).get());
+ return Impl::get_return_type(data_type_array);
+ }
+};
+
+} // namespace vectorized
+} // namespace doris
diff --git a/be/src/vec/functions/array/function_array_register.cpp b/be/src/vec/functions/array/function_array_register.cpp
index 3c5dc4fd19..833bc9fbd8 100644
--- a/be/src/vec/functions/array/function_array_register.cpp
+++ b/be/src/vec/functions/array/function_array_register.cpp
@@ -25,11 +25,13 @@ namespace doris::vectorized {
void register_function_array_element(SimpleFunctionFactory&);
void register_function_array_index(SimpleFunctionFactory&);
void register_function_array_size(SimpleFunctionFactory&);
+void register_function_array_aggregation(SimpleFunctionFactory&);
void register_function_array(SimpleFunctionFactory& factory) {
register_function_array_element(factory);
register_function_array_index(factory);
register_function_array_size(factory);
+ register_function_array_aggregation(factory);
}
} // namespace doris::vectorized
diff --git a/be/src/vec/functions/function.h b/be/src/vec/functions/function.h
index 802ef6fdf4..c4464e4956 100644
--- a/be/src/vec/functions/function.h
+++ b/be/src/vec/functions/function.h
@@ -25,7 +25,6 @@
#include "common/status.h"
#include "vec/core/block.h"
#include "vec/core/column_numbers.h"
-#include "vec/core/names.h"
#include "vec/data_types/data_type.h"
namespace doris::vectorized {
diff --git a/be/src/vec/functions/simple_function_factory.h b/be/src/vec/functions/simple_function_factory.h
index 7e56dbac99..32042095ff 100644
--- a/be/src/vec/functions/simple_function_factory.h
+++ b/be/src/vec/functions/simple_function_factory.h
@@ -80,6 +80,7 @@ void register_function_geo(SimpleFunctionFactory& factory);
void register_function_encryption(SimpleFunctionFactory& factory);
void register_function_regexp_extract(SimpleFunctionFactory& factory);
void register_function_hex_variadic(SimpleFunctionFactory& factory);
+
class SimpleFunctionFactory {
using Creator = std::function<FunctionBuilderPtr()>;
using FunctionCreators = phmap::flat_hash_map<std::string, Creator>;
@@ -161,7 +162,7 @@ public:
static SimpleFunctionFactory& instance() {
static std::once_flag oc;
static SimpleFunctionFactory instance;
- std::call_once(oc, [&]() {
+ std::call_once(oc, []() {
register_function_bitmap(instance);
register_function_bitmap_variadic(instance);
register_function_hll_cardinality(instance);
diff --git a/be/test/CMakeLists.txt b/be/test/CMakeLists.txt
index dabd56304e..8928363ec6 100644
--- a/be/test/CMakeLists.txt
+++ b/be/test/CMakeLists.txt
@@ -336,6 +336,7 @@ set(VEC_TEST_FILES
vec/exec/vorc_scanner_test.cpp
vec/exec/vparquet_scanner_test.cpp
vec/exprs/vexpr_test.cpp
+ vec/function/function_array_aggregation_test.cpp
vec/function/function_array_element_test.cpp
vec/function/function_array_index_test.cpp
vec/function/function_array_size_test.cpp
diff --git a/be/test/vec/function/function_array_aggregation_test.cpp b/be/test/vec/function/function_array_aggregation_test.cpp
new file mode 100644
index 0000000000..54f8eaa945
--- /dev/null
+++ b/be/test/vec/function/function_array_aggregation_test.cpp
@@ -0,0 +1,228 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include <gtest/gtest.h>
+
+#include <cstddef>
+#include <string>
+#include <type_traits>
+
+#include "function_test_util.h"
+#include "vec/core/field.h"
+#include "vec/data_types/data_type_number.h"
+
+namespace doris {
+namespace vectorized {
+
+template <typename T>
+struct AnyValue {
+ T value {};
+ bool is_null = false;
+
+ AnyValue(T v) : value(std::move(v)) {}
+
+ AnyValue(std::nullptr_t) : is_null(true) {}
+};
+
+using IntDataSet = std::vector<std::pair<std::vector<AnyValue<int>>, AnyValue<int>>>;
+
+template <typename T, typename ReturnType = T>
+void check_function(const std::string& func_name, const IntDataSet data_set,
+ bool nullable = false) {
+ InputTypeSet input_types;
+ if (!nullable) {
+ input_types = {TypeIndex::Array, ut_type::get_type_index<T>()};
+ } else {
+ input_types = {TypeIndex::Array, TypeIndex::Nullable, ut_type::get_type_index<T>()};
+ }
+ DataSet converted_data_set;
+ for (const auto& row : data_set) {
+ Array array;
+ for (auto any_value : row.first) {
+ if (any_value.is_null) {
+ array.push_back(Field());
+ } else {
+ array.push_back(ut_type::convert_to<T>(any_value.value));
+ }
+ }
+ if (!row.second.is_null) {
+ converted_data_set.emplace_back(std::make_pair<CellSet, Expect>(
+ {array}, ut_type::convert_to<ReturnType>(row.second.value)));
+ } else {
+ converted_data_set.emplace_back(std::make_pair<CellSet, Expect>({array}, Null()));
+ }
+ }
+ check_function<ReturnType, true>(func_name, input_types, converted_data_set);
+}
+
+TEST(VFunctionArrayAggregationTest, TestArrayMin) {
+ const std::string func_name = "array_min";
+ IntDataSet data_set = {
+ {{}, nullptr},
+ {{1, 2, 3}, 1},
+ };
+ check_function<DataTypeInt8>(func_name, data_set);
+ check_function<DataTypeInt16>(func_name, data_set);
+ check_function<DataTypeInt32>(func_name, data_set);
+ check_function<DataTypeInt64>(func_name, data_set);
+ check_function<DataTypeInt128>(func_name, data_set);
+ check_function<DataTypeFloat32>(func_name, data_set);
+ check_function<DataTypeFloat64>(func_name, data_set);
+}
+
+TEST(VFunctionArrayAggregationTest, TestArrayMinNullable) {
+ const std::string func_name = "array_min";
+ IntDataSet data_set = {
+ {{}, nullptr},
+ {{nullptr}, nullptr},
+ {{1, nullptr, 3}, 1},
+ };
+ check_function<DataTypeInt8>(func_name, data_set, true);
+ check_function<DataTypeInt16>(func_name, data_set, true);
+ check_function<DataTypeInt32>(func_name, data_set, true);
+ check_function<DataTypeInt64>(func_name, data_set, true);
+ check_function<DataTypeInt128>(func_name, data_set, true);
+ check_function<DataTypeFloat32>(func_name, data_set, true);
+ check_function<DataTypeFloat64>(func_name, data_set, true);
+}
+
+TEST(VFunctionArrayAggregationTest, TestArrayMax) {
+ const std::string func_name = "array_max";
+ IntDataSet data_set = {
+ {{}, nullptr},
+ {{1, 2, 3}, 3},
+ };
+ check_function<DataTypeInt8>(func_name, data_set);
+ check_function<DataTypeInt16>(func_name, data_set);
+ check_function<DataTypeInt32>(func_name, data_set);
+ check_function<DataTypeInt64>(func_name, data_set);
+ check_function<DataTypeInt128>(func_name, data_set);
+ check_function<DataTypeFloat32>(func_name, data_set);
+ check_function<DataTypeFloat64>(func_name, data_set);
+}
+
+TEST(VFunctionArrayAggregationTest, TestArrayMaxNullable) {
+ const std::string func_name = "array_max";
+ IntDataSet data_set = {
+ {{}, nullptr},
+ {{nullptr}, nullptr},
+ {{1, nullptr, 3}, 3},
+ };
+ check_function<DataTypeInt8>(func_name, data_set, true);
+ check_function<DataTypeInt16>(func_name, data_set, true);
+ check_function<DataTypeInt32>(func_name, data_set, true);
+ check_function<DataTypeInt64>(func_name, data_set, true);
+ check_function<DataTypeInt128>(func_name, data_set, true);
+ check_function<DataTypeFloat32>(func_name, data_set, true);
+ check_function<DataTypeFloat64>(func_name, data_set, true);
+}
+
+TEST(VFunctionArrayAggregationTest, TestArraySum) {
+ const std::string func_name = "array_sum";
+ IntDataSet data_set = {
+ {{}, nullptr},
+ {{1, 2, 3}, 6},
+ };
+ check_function<DataTypeInt8, DataTypeInt64>(func_name, data_set);
+ check_function<DataTypeInt16, DataTypeInt64>(func_name, data_set);
+ check_function<DataTypeInt32, DataTypeInt64>(func_name, data_set);
+ check_function<DataTypeInt64, DataTypeInt64>(func_name, data_set);
+ check_function<DataTypeInt128, DataTypeInt128>(func_name, data_set);
+ check_function<DataTypeFloat32, DataTypeFloat64>(func_name, data_set);
+ check_function<DataTypeFloat64, DataTypeFloat64>(func_name, data_set);
+}
+
+TEST(VFunctionArrayAggregationTest, TestArraySumNullable) {
+ const std::string func_name = "array_sum";
+ IntDataSet data_set = {
+ {{}, nullptr},
+ {{nullptr}, nullptr},
+ {{1, nullptr, 3}, 4},
+ };
+ check_function<DataTypeInt8, DataTypeInt64>(func_name, data_set, true);
+ check_function<DataTypeInt16, DataTypeInt64>(func_name, data_set, true);
+ check_function<DataTypeInt32, DataTypeInt64>(func_name, data_set, true);
+ check_function<DataTypeInt64, DataTypeInt64>(func_name, data_set, true);
+ check_function<DataTypeInt128, DataTypeInt128>(func_name, data_set, true);
+ check_function<DataTypeFloat32, DataTypeFloat64>(func_name, data_set, true);
+ check_function<DataTypeFloat64, DataTypeFloat64>(func_name, data_set, true);
+}
+
+TEST(VFunctionArrayAggregationTest, TestArrayAverage) {
+ const std::string func_name = "array_avg";
+ IntDataSet data_set = {
+ {{}, nullptr},
+ {{1, 2, 3}, 2},
+ };
+ check_function<DataTypeInt8, DataTypeFloat64>(func_name, data_set);
+ check_function<DataTypeInt16, DataTypeFloat64>(func_name, data_set);
+ check_function<DataTypeInt32, DataTypeFloat64>(func_name, data_set);
+ check_function<DataTypeInt64, DataTypeFloat64>(func_name, data_set);
+ check_function<DataTypeInt128, DataTypeFloat64>(func_name, data_set);
+ check_function<DataTypeFloat32, DataTypeFloat64>(func_name, data_set);
+ check_function<DataTypeFloat64, DataTypeFloat64>(func_name, data_set);
+}
+
+TEST(VFunctionArrayAggregationTest, TestArrayAverageNullable) {
+ const std::string func_name = "array_avg";
+ IntDataSet data_set = {
+ {{}, nullptr},
+ {{nullptr}, nullptr},
+ {{1, nullptr, 3}, 2},
+ };
+ check_function<DataTypeInt8, DataTypeFloat64>(func_name, data_set, true);
+ check_function<DataTypeInt16, DataTypeFloat64>(func_name, data_set, true);
+ check_function<DataTypeInt32, DataTypeFloat64>(func_name, data_set, true);
+ check_function<DataTypeInt64, DataTypeFloat64>(func_name, data_set, true);
+ check_function<DataTypeInt128, DataTypeFloat64>(func_name, data_set, true);
+ check_function<DataTypeFloat32, DataTypeFloat64>(func_name, data_set, true);
+ check_function<DataTypeFloat64, DataTypeFloat64>(func_name, data_set, true);
+}
+
+TEST(VFunctionArrayAggregationTest, TestArrayProduct) {
+ const std::string func_name = "array_product";
+ IntDataSet data_set = {
+ {{}, nullptr},
+ {{1, 2, 3}, 6},
+ };
+ check_function<DataTypeInt8, DataTypeFloat64>(func_name, data_set);
+ check_function<DataTypeInt16, DataTypeFloat64>(func_name, data_set);
+ check_function<DataTypeInt32, DataTypeFloat64>(func_name, data_set);
+ check_function<DataTypeInt64, DataTypeFloat64>(func_name, data_set);
+ check_function<DataTypeInt128, DataTypeFloat64>(func_name, data_set);
+ check_function<DataTypeFloat32, DataTypeFloat64>(func_name, data_set);
+ check_function<DataTypeFloat64, DataTypeFloat64>(func_name, data_set);
+}
+
+TEST(VFunctionArrayAggregationTest, TestArrayProductNullable) {
+ const std::string func_name = "array_product";
+ IntDataSet data_set = {
+ {{}, nullptr},
+ {{nullptr}, nullptr},
+ {{1, nullptr, 3}, 3},
+ };
+ check_function<DataTypeInt8, DataTypeFloat64>(func_name, data_set, true);
+ check_function<DataTypeInt16, DataTypeFloat64>(func_name, data_set, true);
+ check_function<DataTypeInt32, DataTypeFloat64>(func_name, data_set, true);
+ check_function<DataTypeInt64, DataTypeFloat64>(func_name, data_set, true);
+ check_function<DataTypeInt128, DataTypeFloat64>(func_name, data_set, true);
+ check_function<DataTypeFloat32, DataTypeFloat64>(func_name, data_set, true);
+ check_function<DataTypeFloat64, DataTypeFloat64>(func_name, data_set, true);
+}
+
+} // namespace vectorized
+} // namespace doris
diff --git a/be/test/vec/function/function_test_util.cpp b/be/test/vec/function/function_test_util.cpp
index 9587805b21..0e25aa1781 100644
--- a/be/test/vec/function/function_test_util.cpp
+++ b/be/test/vec/function/function_test_util.cpp
@@ -33,7 +33,8 @@ int64_t str_to_date_time(std::string datetime_str, bool data_time) {
return binary_cast<VecDateTimeValue, Int64>(v);
}
size_t type_index_to_data_type(const std::vector<std::any>& input_types, size_t index,
- doris_udf::FunctionContext::TypeDesc& desc, DataTypePtr& type) {
+ ut_type::UTDataTypeDesc& ut_desc, DataTypePtr& type) {
+ doris_udf::FunctionContext::TypeDesc& desc = ut_desc.type_desc;
if (index < 0 || index >= input_types.size()) {
return -1;
}
@@ -96,14 +97,25 @@ size_t type_index_to_data_type(const std::vector<std::any>& input_types, size_t
return 1;
case TypeIndex::Array: {
desc.type = doris_udf::FunctionContext::TYPE_ARRAY;
- doris_udf::FunctionContext::TypeDesc sub_desc;
+ ut_type::UTDataTypeDesc sub_desc;
DataTypePtr sub_type = nullptr;
- size_t ret = type_index_to_data_type(input_types, index + 1, sub_desc, sub_type);
+ ++index;
+ size_t ret = type_index_to_data_type(input_types, index, sub_desc, sub_type);
if (ret <= 0) {
return ret;
}
- desc.children.push_back(doris_udf::FunctionContext::TypeDesc());
- type = std::make_shared<DataTypeArray>(std::move(sub_type));
+ desc.children.push_back(sub_desc.type_desc);
+ type = std::make_shared<DataTypeArray>(sub_type);
+ return ret + 1;
+ }
+ case TypeIndex::Nullable: {
+ ++index;
+ size_t ret = type_index_to_data_type(input_types, index, ut_desc, type);
+ if (ret <= 0) {
+ return ret;
+ }
+ ut_desc.is_nullable = true;
+ type = make_nullable(type);
return ret + 1;
}
default:
@@ -119,7 +131,7 @@ bool parse_ut_data_type(const std::vector<std::any>& input_types, ut_type::UTDat
if (input_types[i].type() == typeid(Consted)) {
desc.is_const = true;
}
- size_t res = type_index_to_data_type(input_types, i, desc.type_desc, desc.data_type);
+ size_t res = type_index_to_data_type(input_types, i, desc, desc.data_type);
if (res <= 0) {
return false;
}
diff --git a/be/test/vec/function/function_test_util.h b/be/test/vec/function/function_test_util.h
index 42ba1185b7..6ad30a9b6a 100644
--- a/be/test/vec/function/function_test_util.h
+++ b/be/test/vec/function/function_test_util.h
@@ -38,7 +38,10 @@
namespace doris::vectorized {
using InputDataSet = std::vector<std::vector<std::any>>; // without result
-using DataSet = std::vector<std::pair<std::vector<std::any>, std::any>>;
+using CellSet = std::vector<std::any>;
+using Expect = std::any;
+using Row = std::pair<CellSet, Expect>;
+using DataSet = std::vector<Row>;
using InputTypeSet = std::vector<std::any>;
int64_t str_to_date_time(std::string datetime_str, bool data_time = true);
@@ -64,6 +67,69 @@ inline auto DECIMALFIELD = [](double v) {
using DATETIME = std::string;
+template <typename T>
+struct DataTypeTraits;
+
+template <>
+struct DataTypeTraits<DataTypeInt8> {
+ using type = Int8;
+};
+
+template <>
+struct DataTypeTraits<DataTypeInt16> {
+ using type = Int16;
+};
+
+template <>
+struct DataTypeTraits<DataTypeInt32> {
+ using type = Int32;
+};
+
+template <>
+struct DataTypeTraits<DataTypeInt64> {
+ using type = Int64;
+};
+
+template <>
+struct DataTypeTraits<DataTypeInt128> {
+ using type = Int128;
+};
+
+template <>
+struct DataTypeTraits<DataTypeFloat32> {
+ using type = Float32;
+};
+
+template <>
+struct DataTypeTraits<DataTypeFloat64> {
+ using type = Float64;
+};
+
+template <typename To, typename From>
+constexpr decltype(auto) convert_to(From value) {
+ using ToType = typename DataTypeTraits<To>::type;
+ return ToType(value);
+}
+
+template <typename T>
+constexpr TypeIndex get_type_index() {
+ if constexpr (std::is_same_v<T, DataTypeInt8>) {
+ return TypeIndex::Int8;
+ } else if constexpr (std::is_same_v<T, DataTypeInt16>) {
+ return TypeIndex::Int16;
+ } else if constexpr (std::is_same_v<T, DataTypeInt32>) {
+ return TypeIndex::Int32;
+ } else if constexpr (std::is_same_v<T, DataTypeInt64>) {
+ return TypeIndex::Int64;
+ } else if constexpr (std::is_same_v<T, DataTypeInt128>) {
+ return TypeIndex::Int128;
+ } else if constexpr (std::is_same_v<T, DataTypeFloat32>) {
+ return TypeIndex::Float32;
+ } else if constexpr (std::is_same_v<T, DataTypeFloat64>) {
+ return TypeIndex::Float64;
+ }
+}
+
struct UTDataTypeDesc {
DataTypePtr data_type;
doris_udf::FunctionContext::TypeDesc type_desc;
@@ -76,7 +142,7 @@ using UTDataTypeDescs = std::vector<UTDataTypeDesc>;
} // namespace ut_type
size_t type_index_to_data_type(const std::vector<std::any>& input_types, size_t index,
- doris_udf::FunctionContext::TypeDesc& desc, DataTypePtr& type);
+ ut_type::UTDataTypeDesc& ut_desc, DataTypePtr& type);
bool parse_ut_data_type(const std::vector<std::any>& input_types, ut_type::UTDataTypeDescs& descs);
bool insert_cell(MutableColumnPtr& column, DataTypePtr type_ptr, const std::any& cell);
@@ -146,13 +212,13 @@ void check_function(const std::string& func_name, const InputTypeSet& input_type
EXPECT_TRUE(func != nullptr);
doris_udf::FunctionContext::TypeDesc fn_ctx_return;
- if (std::is_same_v<ReturnType, DataTypeUInt8>) {
+ if constexpr (std::is_same_v<ReturnType, DataTypeUInt8>) {
fn_ctx_return.type = doris_udf::FunctionContext::TYPE_BOOLEAN;
- } else if (std::is_same_v<ReturnType, DataTypeFloat64>) {
- fn_ctx_return.type = doris_udf::FunctionContext::TYPE_DOUBLE;
- } else if (std::is_same_v<ReturnType, DataTypeInt32>) {
+ } else if constexpr (std::is_same_v<ReturnType, DataTypeInt32>) {
fn_ctx_return.type = doris_udf::FunctionContext::TYPE_INT;
- } else if (std::is_same_v<ReturnType, DateTime>) {
+ } else if constexpr (std::is_same_v<ReturnType, DataTypeFloat64>) {
+ fn_ctx_return.type = doris_udf::FunctionContext::TYPE_DOUBLE;
+ } else if constexpr (std::is_same_v<ReturnType, DateTime>) {
fn_ctx_return.type = doris_udf::FunctionContext::TYPE_DATETIME;
} else {
fn_ctx_return.type = doris_udf::FunctionContext::INVALID_TYPE;
@@ -187,6 +253,9 @@ void check_function(const std::string& func_name, const InputTypeSet& input_type
if constexpr (std::is_same_v<ReturnType, DataTypeDecimal<Decimal128>>) {
const auto& column_data = field.get<DecimalField<Decimal128>>().get_value();
EXPECT_EQ(column_data.value, expect_data.value);
+ } else if constexpr (std::is_same_v<ReturnType, DataTypeFloat32>) {
+ const auto& column_data = field.get<DataTypeFloat64::FieldType>();
+ EXPECT_EQ(column_data, expect_data);
} else {
const auto& column_data = field.get<typename ReturnType::FieldType>();
EXPECT_EQ(column_data, expect_data);
diff --git a/docs/en/sql-manual/sql-functions/array-functions/array_avg.md b/docs/en/sql-manual/sql-functions/array-functions/array_avg.md
new file mode 100644
index 0000000000..0b47f51461
--- /dev/null
+++ b/docs/en/sql-manual/sql-functions/array-functions/array_avg.md
@@ -0,0 +1,61 @@
+---
+{
+ "title": "ARRAY_AVG Function",
+ "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_AVG
+
+### Name
+
+ARRAY_AVG
+
+### description
+
+Get the average of all elements in an array (`NULL` values are skipped).
+When the array is empty or all elements in the array are `NULL` values, the function returns `NULL`.
+
+### example
+
+```shell
+mysql> create table array_type_table(k1 INT, k2 Array<int>) duplicate key (k1)
+ -> distributed by hash(k1) buckets 1 properties('replication_num' = '1');
+mysql> insert into array_type_table values (0, []), (1, [NULL]), (2, [1, 2, 3]), (3, [1, NULL, 3]);
+mysql> set enable_vectorized_engine = true; # enable vectorized engine
+mysql> select k2, array_avg(k2) from array_type_table;
++--------------+-----------------+
+| k2 | array_avg(`k2`) |
++--------------+-----------------+
+| [] | NULL |
+| [NULL] | NULL |
+| [1, 2, 3] | 2 |
+| [1, NULL, 3] | 2 |
++--------------+-----------------+
+4 rows in set (0.01 sec)
+
+```
+
+### keywords
+
+ARRAY_AVG
+
diff --git a/docs/en/sql-manual/sql-functions/array-functions/array_max.md b/docs/en/sql-manual/sql-functions/array-functions/array_max.md
new file mode 100644
index 0000000000..68dafcf2b3
--- /dev/null
+++ b/docs/en/sql-manual/sql-functions/array-functions/array_max.md
@@ -0,0 +1,61 @@
+---
+{
+ "title": "ARRAY_MAX Function",
+ "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_MAX
+
+### Name
+
+ARRAY_MAX
+
+### description
+
+Get the maximum element in an array (`NULL` values are skipped).
+When the array is empty or all elements in the array are `NULL` values, the function returns `NULL`.
+
+### example
+
+```shell
+mysql> create table array_type_table(k1 INT, k2 Array<int>) duplicate key (k1)
+ -> distributed by hash(k1) buckets 1 properties('replication_num' = '1');
+mysql> insert into array_type_table values (0, []), (1, [NULL]), (2, [1, 2, 3]), (3, [1, NULL, 3]);
+mysql> set enable_vectorized_engine = true; # enable vectorized engine
+mysql> select k2, array_max(k2) from array_type_table;
++--------------+-----------------+
+| k2 | array_max(`k2`) |
++--------------+-----------------+
+| [] | NULL |
+| [NULL] | NULL |
+| [1, 2, 3] | 3 |
+| [1, NULL, 3] | 3 |
++--------------+-----------------+
+4 rows in set (0.02 sec)
+
+```
+
+### keywords
+
+ARRAY_MAX
+
diff --git a/docs/en/sql-manual/sql-functions/array-functions/array_min.md b/docs/en/sql-manual/sql-functions/array-functions/array_min.md
new file mode 100644
index 0000000000..935992f26f
--- /dev/null
+++ b/docs/en/sql-manual/sql-functions/array-functions/array_min.md
@@ -0,0 +1,61 @@
+---
+{
+ "title": "ARRAY_MIN Function",
+ "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_MIN
+
+### Name
+
+ARRAY_MIN
+
+### description
+
+Get the minimum element in an array (`NULL` values are skipped).
+When the array is empty or all elements in the array are `NULL` values, the function returns `NULL`.
+
+### example
+
+```shell
+mysql> create table array_type_table(k1 INT, k2 Array<int>) duplicate key (k1)
+ -> distributed by hash(k1) buckets 1 properties('replication_num' = '1');
+mysql> insert into array_type_table values (0, []), (1, [NULL]), (2, [1, 2, 3]), (3, [1, NULL, 3]);
+mysql> set enable_vectorized_engine = true; # enable vectorized engine
+mysql> select k2, array_min(k2) from array_type_table;
++--------------+-----------------+
+| k2 | array_min(`k2`) |
++--------------+-----------------+
+| [] | NULL |
+| [NULL] | NULL |
+| [1, 2, 3] | 1 |
+| [1, NULL, 3] | 1 |
++--------------+-----------------+
+4 rows in set (0.02 sec)
+
+```
+
+### keywords
+
+ARRAY_MIN
+
diff --git a/docs/en/sql-manual/sql-functions/array-functions/array_product.md b/docs/en/sql-manual/sql-functions/array-functions/array_product.md
new file mode 100644
index 0000000000..18c9896dd0
--- /dev/null
+++ b/docs/en/sql-manual/sql-functions/array-functions/array_product.md
@@ -0,0 +1,61 @@
+---
+{
+ "title": "ARRAY_PRODUCT Function",
+ "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_PRODUCT
+
+### Name
+
+ARRAY_PRODUCT
+
+### description
+
+Get the product of all elements in an array (`NULL` values are skipped).
+When the array is empty or all elements in the array are `NULL` values, the function returns `NULL`.
+
+### example
+
+```shell
+mysql> create table array_type_table(k1 INT, k2 Array<int>) duplicate key (k1)
+ -> distributed by hash(k1) buckets 1 properties('replication_num' = '1');
+mysql> insert into array_type_table values (0, []), (1, [NULL]), (2, [1, 2, 3]), (3, [1, NULL, 3]);
+mysql> set enable_vectorized_engine = true; # enable vectorized engine
+mysql> select k2, array_product(k2) from array_type_table;
++--------------+---------------------+
+| k2 | array_product(`k2`) |
++--------------+---------------------+
+| [] | NULL |
+| [NULL] | NULL |
+| [1, 2, 3] | 6 |
+| [1, NULL, 3] | 3 |
++--------------+---------------------+
+4 rows in set (0.01 sec)
+
+```
+
+### keywords
+
+ARRAY_PRODUCT
+
diff --git a/docs/en/sql-manual/sql-functions/array-functions/array_sum.md b/docs/en/sql-manual/sql-functions/array-functions/array_sum.md
new file mode 100644
index 0000000000..af0316bbcc
--- /dev/null
+++ b/docs/en/sql-manual/sql-functions/array-functions/array_sum.md
@@ -0,0 +1,61 @@
+---
+{
+ "title": "ARRAY_SUM Function",
+ "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_SUM
+
+### Name
+
+ARRAY_SUM
+
+### description
+
+Get the sum of all elements in an array (`NULL` values are skipped).
+When the array is empty or all elements in the array are `NULL` values, the function returns `NULL`.
+
+### example
+
+```shell
+mysql> create table array_type_table(k1 INT, k2 Array<int>) duplicate key (k1)
+ -> distributed by hash(k1) buckets 1 properties('replication_num' = '1');
+mysql> insert into array_type_table values (0, []), (1, [NULL]), (2, [1, 2, 3]), (3, [1, NULL, 3]);
+mysql> set enable_vectorized_engine = true; # enable vectorized engine
+mysql> select k2, array_sum(k2) from array_type_table;
++--------------+-----------------+
+| k2 | array_sum(`k2`) |
++--------------+-----------------+
+| [] | NULL |
+| [NULL] | NULL |
+| [1, 2, 3] | 6 |
+| [1, NULL, 3] | 4 |
++--------------+-----------------+
+4 rows in set (0.01 sec)
+
+```
+
+### keywords
+
+ARRAY_SUM
+
diff --git a/docs/zh-CN/sql-manual/sql-functions/array-functions/array_avg.md b/docs/zh-CN/sql-manual/sql-functions/array-functions/array_avg.md
new file mode 100644
index 0000000000..39ab60fe18
--- /dev/null
+++ b/docs/zh-CN/sql-manual/sql-functions/array-functions/array_avg.md
@@ -0,0 +1,60 @@
+---
+{
+ "title": "ARRAY_AVG 函数",
+ "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_AVG
+
+### Name
+
+ARRAY_AVG
+
+### description
+
+返回数组中所有元素的平均值,数组中的`NULL`值会被跳过。空数组以及元素全为`NULL`值的数组,结果返回`NULL`值。
+
+### example
+
+```shell
+mysql> create table array_type_table(k1 INT, k2 Array<int>) duplicate key (k1)
+ -> distributed by hash(k1) buckets 1 properties('replication_num' = '1');
+mysql> insert into array_type_table values (0, []), (1, [NULL]), (2, [1, 2, 3]), (3, [1, NULL, 3]);
+mysql> set enable_vectorized_engine = true; # enable vectorized engine
+mysql> select k2, array_avg(k2) from array_type_table;
++--------------+-----------------+
+| k2 | array_avg(`k2`) |
++--------------+-----------------+
+| [] | NULL |
+| [NULL] | NULL |
+| [1, 2, 3] | 2 |
+| [1, NULL, 3] | 2 |
++--------------+-----------------+
+4 rows in set (0.01 sec)
+
+```
+
+### keywords
+
+ARRAY_AVG
+
diff --git a/docs/zh-CN/sql-manual/sql-functions/array-functions/array_max.md b/docs/zh-CN/sql-manual/sql-functions/array-functions/array_max.md
new file mode 100644
index 0000000000..c112eda8d9
--- /dev/null
+++ b/docs/zh-CN/sql-manual/sql-functions/array-functions/array_max.md
@@ -0,0 +1,60 @@
+---
+{
+ "title": "ARRAY_MAX 函数",
+ "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_MAX
+
+### Name
+
+ARRAY_MAX
+
+### description
+
+返回数组中最大的元素,数组中的`NULL`值会被跳过。空数组以及元素全为`NULL`值的数组,结果返回`NULL`值。
+
+### example
+
+```shell
+mysql> create table array_type_table(k1 INT, k2 Array<int>) duplicate key (k1)
+ -> distributed by hash(k1) buckets 1 properties('replication_num' = '1');
+mysql> insert into array_type_table values (0, []), (1, [NULL]), (2, [1, 2, 3]), (3, [1, NULL, 3]);
+mysql> set enable_vectorized_engine = true; # enable vectorized engine
+mysql> select k2, array_max(k2) from array_type_table;
++--------------+-----------------+
+| k2 | array_max(`k2`) |
++--------------+-----------------+
+| [] | NULL |
+| [NULL] | NULL |
+| [1, 2, 3] | 3 |
+| [1, NULL, 3] | 3 |
++--------------+-----------------+
+4 rows in set (0.02 sec)
+
+```
+
+### keywords
+
+ARRAY_MAX
+
diff --git a/docs/zh-CN/sql-manual/sql-functions/array-functions/array_min.md b/docs/zh-CN/sql-manual/sql-functions/array-functions/array_min.md
new file mode 100644
index 0000000000..1681d681f5
--- /dev/null
+++ b/docs/zh-CN/sql-manual/sql-functions/array-functions/array_min.md
@@ -0,0 +1,60 @@
+---
+{
+ "title": "ARRAY_MIN 函数",
+ "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_MIN
+
+### Name
+
+ARRAY_MIN
+
+### description
+
+返回数组中最小的元素,数组中的`NULL`值会被跳过。空数组以及元素全为`NULL`值的数组,结果返回`NULL`值。
+
+### example
+
+```shell
+mysql> create table array_type_table(k1 INT, k2 Array<int>) duplicate key (k1)
+ -> distributed by hash(k1) buckets 1 properties('replication_num' = '1');
+mysql> insert into array_type_table values (0, []), (1, [NULL]), (2, [1, 2, 3]), (3, [1, NULL, 3]);
+mysql> set enable_vectorized_engine = true; # enable vectorized engine
+mysql> select k2, array_min(k2) from array_type_table;
++--------------+-----------------+
+| k2 | array_min(`k2`) |
++--------------+-----------------+
+| [] | NULL |
+| [NULL] | NULL |
+| [1, 2, 3] | 1 |
+| [1, NULL, 3] | 1 |
++--------------+-----------------+
+4 rows in set (0.02 sec)
+
+```
+
+### keywords
+
+ARRAY_MIN
+
diff --git a/docs/zh-CN/sql-manual/sql-functions/array-functions/array_product.md b/docs/zh-CN/sql-manual/sql-functions/array-functions/array_product.md
new file mode 100644
index 0000000000..a2e5e510a3
--- /dev/null
+++ b/docs/zh-CN/sql-manual/sql-functions/array-functions/array_product.md
@@ -0,0 +1,60 @@
+---
+{
+ "title": "ARRAY_PRODUCT 函数",
+ "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_PRODUCT
+
+### Name
+
+ARRAY_PRODUCT
+
+### description
+
+返回数组中所有元素的乘积,数组中的`NULL`值会被跳过。空数组以及元素全为`NULL`值的数组,结果返回`NULL`值。
+
+### example
+
+```shell
+mysql> create table array_type_table(k1 INT, k2 Array<int>) duplicate key (k1)
+ -> distributed by hash(k1) buckets 1 properties('replication_num' = '1');
+mysql> insert into array_type_table values (0, []), (1, [NULL]), (2, [1, 2, 3]), (3, [1, NULL, 3]);
+mysql> set enable_vectorized_engine = true; # enable vectorized engine
+mysql> select k2, array_product(k2) from array_type_table;
++--------------+---------------------+
+| k2 | array_product(`k2`) |
++--------------+---------------------+
+| [] | NULL |
+| [NULL] | NULL |
+| [1, 2, 3] | 6 |
+| [1, NULL, 3] | 3 |
++--------------+---------------------+
+4 rows in set (0.01 sec)
+
+```
+
+### keywords
+
+ARRAY_PRODUCT
+
diff --git a/docs/zh-CN/sql-manual/sql-functions/array-functions/array_sum.md b/docs/zh-CN/sql-manual/sql-functions/array-functions/array_sum.md
new file mode 100644
index 0000000000..c84b83261c
--- /dev/null
+++ b/docs/zh-CN/sql-manual/sql-functions/array-functions/array_sum.md
@@ -0,0 +1,60 @@
+---
+{
+ "title": "ARRAY_SUM 函数",
+ "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_SUM
+
+### Name
+
+ARRAY_SUM
+
+### description
+
+返回数组中所有元素之和,数组中的`NULL`值会被跳过。空数组以及元素全为`NULL`值的数组,结果返回`NULL`值。
+
+### example
+
+```shell
+mysql> create table array_type_table(k1 INT, k2 Array<int>) duplicate key (k1)
+ -> distributed by hash(k1) buckets 1 properties('replication_num' = '1');
+mysql> insert into array_type_table values (0, []), (1, [NULL]), (2, [1, 2, 3]), (3, [1, NULL, 3]);
+mysql> set enable_vectorized_engine = true; # enable vectorized engine
+mysql> select k2, array_sum(k2) from array_type_table;
++--------------+-----------------+
+| k2 | array_sum(`k2`) |
++--------------+-----------------+
+| [] | NULL |
+| [NULL] | NULL |
+| [1, 2, 3] | 6 |
+| [1, NULL, 3] | 4 |
++--------------+-----------------+
+4 rows in set (0.01 sec)
+
+```
+
+### keywords
+
+ARRAY_SUM
+
diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/ArrayType.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/ArrayType.java
index 4748d4cad9..8ad8bb9935 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/ArrayType.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/ArrayType.java
@@ -81,8 +81,8 @@ public class ArrayType extends Type {
if (itemType.isNull() || ((ArrayType) t).getItemType().isNull()) {
return true;
}
- return itemType.matchesType(((ArrayType) t).itemType)
- && ((ArrayType) t).containsNull == containsNull;
+ return Type.isImplicitlyCastable(itemType, ((ArrayType) t).itemType, true)
+ && (((ArrayType) t).containsNull || !containsNull);
}
public static ArrayType create() {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/Type.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/Type.java
index 0ffbcdd37a..8a89b0ffe3 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/Type.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/Type.java
@@ -401,8 +401,6 @@ public abstract class Type {
}
if (t1.isComplexType() || t2.isComplexType()) {
if (t1.isArrayType() && t2.isArrayType()) {
- // Subtype of Array do not support cast now, for example:
- // Array<Int8> can not cast to Array<Int32>
return t1.matchesType(t2);
} else if (t1.isMapType() && t2.isMapType()) {
return true;
diff --git a/gensrc/script/doris_builtins_functions.py b/gensrc/script/doris_builtins_functions.py
index af88200166..fc57c9bda2 100755
--- a/gensrc/script/doris_builtins_functions.py
+++ b/gensrc/script/doris_builtins_functions.py
@@ -161,6 +161,32 @@ visible_functions = [
[['cardinality', 'size'], 'BIGINT', ['ARRAY'], '', '', '', 'vec', ''],
+ [['array_min'], 'TINYINT', ['ARRAY_TINYINT'], '', '', '', 'vec', 'ALWAYS_NULLABLE'],
+ [['array_min'], 'SMALLINT', ['ARRAY_SMALLINT'], '', '', '', 'vec', 'ALWAYS_NULLABLE'],
+ [['array_min'], 'INT', ['ARRAY_INT'], '', '', '', 'vec', 'ALWAYS_NULLABLE'],
+ [['array_min'], 'BIGINT', ['ARRAY_BIGINT'], '', '', '', 'vec', 'ALWAYS_NULLABLE'],
+ [['array_min'], 'LARGEINT', ['ARRAY_LARGEINT'], '', '', '', 'vec', 'ALWAYS_NULLABLE'],
+ [['array_max'], 'TINYINT', ['ARRAY_TINYINT'], '', '', '', 'vec', 'ALWAYS_NULLABLE'],
+ [['array_max'], 'SMALLINT', ['ARRAY_SMALLINT'], '', '', '', 'vec', 'ALWAYS_NULLABLE'],
+ [['array_max'], 'INT', ['ARRAY_INT'], '', '', '', 'vec', 'ALWAYS_NULLABLE'],
+ [['array_max'], 'BIGINT', ['ARRAY_BIGINT'], '', '', '', 'vec', 'ALWAYS_NULLABLE'],
+ [['array_max'], 'LARGEINT', ['ARRAY_LARGEINT'], '', '', '', 'vec', 'ALWAYS_NULLABLE'],
+ [['array_sum'], 'BIGINT', ['ARRAY_TINYINT'], '', '', '', 'vec', 'ALWAYS_NULLABLE'],
+ [['array_sum'], 'BIGINT', ['ARRAY_SMALLINT'], '', '', '', 'vec', 'ALWAYS_NULLABLE'],
+ [['array_sum'], 'BIGINT', ['ARRAY_INT'], '', '', '', 'vec', 'ALWAYS_NULLABLE'],
+ [['array_sum'], 'BIGINT', ['ARRAY_BIGINT'], '', '', '', 'vec', 'ALWAYS_NULLABLE'],
+ [['array_sum'], 'LARGEINT', ['ARRAY_LARGEINT'], '', '', '', 'vec', 'ALWAYS_NULLABLE'],
+ [['array_avg'], 'DOUBLE', ['ARRAY_TINYINT'], '', '', '', 'vec', 'ALWAYS_NULLABLE'],
+ [['array_avg'], 'DOUBLE', ['ARRAY_SMALLINT'], '', '', '', 'vec', 'ALWAYS_NULLABLE'],
+ [['array_avg'], 'DOUBLE', ['ARRAY_INT'], '', '', '', 'vec', 'ALWAYS_NULLABLE'],
+ [['array_avg'], 'DOUBLE', ['ARRAY_BIGINT'], '', '', '', 'vec', 'ALWAYS_NULLABLE'],
+ [['array_avg'], 'DOUBLE', ['ARRAY_LARGEINT'], '', '', '', 'vec', 'ALWAYS_NULLABLE'],
+ [['array_product'], 'DOUBLE', ['ARRAY_TINYINT'], '', '', '', 'vec', 'ALWAYS_NULLABLE'],
+ [['array_product'], 'DOUBLE', ['ARRAY_SMALLINT'], '', '', '', 'vec', 'ALWAYS_NULLABLE'],
+ [['array_product'], 'DOUBLE', ['ARRAY_INT'], '', '', '', 'vec', 'ALWAYS_NULLABLE'],
+ [['array_product'], 'DOUBLE', ['ARRAY_BIGINT'], '', '', '', 'vec', 'ALWAYS_NULLABLE'],
+ [['array_product'], 'DOUBLE', ['ARRAY_LARGEINT'], '', '', '', 'vec', 'ALWAYS_NULLABLE'],
+
# Timestamp functions
[['unix_timestamp'], 'INT', [],
'_ZN5doris18TimestampFunctions7to_unixEPN9doris_udf15FunctionContextE',
@@ -899,8 +925,8 @@ visible_functions = [
'_ZN5doris15StringFunctions4rpadEPN9doris_udf'
'15FunctionContextERKNS1_9StringValERKNS1_6IntValES6_', '', '', 'vec', ''],
[['append_trailing_char_if_absent'], 'VARCHAR', ['VARCHAR', 'VARCHAR'],
- '_ZN5doris15StringFunctions30append_trailing_char_if_absentEPN9doris_udf15FunctionContextERKNS1_9StringValES6_',
- '', '', 'vec', 'ALWAYS_NULLABLE'],
+ '_ZN5doris15StringFunctions30append_trailing_char_if_absentEPN9doris_udf15FunctionContextERKNS1_9StringValES6_',
+ '', '', 'vec', 'ALWAYS_NULLABLE'],
[['length'], 'INT', ['VARCHAR'],
'_ZN5doris15StringFunctions6lengthEPN9doris_udf15FunctionContextERKNS1_9StringValE',
'', '', 'vec', ''],
@@ -1021,8 +1047,8 @@ visible_functions = [
'_ZN5doris15StringFunctions4rpadEPN9doris_udf'
'15FunctionContextERKNS1_9StringValERKNS1_6IntValES6_', '', '', 'vec', ''],
[['append_trailing_char_if_absent'], 'STRING', ['STRING', 'STRING'],
- '_ZN5doris15StringFunctions30append_trailing_char_if_absentEPN9doris_udf15FunctionContextERKNS1_9StringValES6_',
- '', '', 'vec', 'ALWAYS_NULLABLE'],
+ '_ZN5doris15StringFunctions30append_trailing_char_if_absentEPN9doris_udf15FunctionContextERKNS1_9StringValES6_',
+ '', '', 'vec', 'ALWAYS_NULLABLE'],
[['length'], 'INT', ['STRING'],
'_ZN5doris15StringFunctions6lengthEPN9doris_udf15FunctionContextERKNS1_9StringValE',
'', '', 'vec', ''],
@@ -1275,11 +1301,11 @@ visible_functions = [
[['to_quantile_state'], 'QUANTILE_STATE', ['VARCHAR', 'FLOAT'],
'_ZN5doris22QuantileStateFunctions17to_quantile_stateEPN9doris_udf15FunctionContextERKNS1_9StringValE',
'_ZN5doris22QuantileStateFunctions25to_quantile_state_prepareEPN9doris_udf15FunctionContextENS2_18FunctionStateScopeE', '', 'vec', ''],
-
+
[['quantile_percent'], 'DOUBLE', ['QUANTILE_STATE', 'FLOAT'],
'_ZN5doris22QuantileStateFunctions16quantile_percentEPN9doris_udf15FunctionContextERNS1_9StringValE',
'_ZN5doris22QuantileStateFunctions24quantile_percent_prepareEPN9doris_udf15FunctionContextENS2_18FunctionStateScopeE', '', 'vec', ''],
-
+
# hash functions
[['murmur_hash3_32'], 'INT', ['VARCHAR', '...'],
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org