This is an automated email from the ASF dual-hosted git repository.
yiguolei pushed a commit to branch branch-4.1
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/branch-4.1 by this push:
new 844dfd223bb branch-4.1: [fix](function) Sum integers exactly in
array_avg #68632 (#68831)
844dfd223bb is described below
commit 844dfd223bb659a358e755feb246baa90116e576
Author: github-actions[bot]
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Sat Oct 10 09:29:40 2026 +0800
branch-4.1: [fix](function) Sum integers exactly in array_avg #68632
(#68831)
Cherry-picked from #68632
Co-authored-by: Chenyang Sun <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
---
be/src/exprs/aggregate/aggregate_function_avg.cpp | 17 +-----
be/src/exprs/aggregate/aggregate_function_avg.h | 15 ++++++
.../function/array/function_array_aggregation.cpp | 3 +-
.../function/function_array_aggregation_test.cpp | 17 ++++++
.../data/doc/sql-manual/ArrayNullsafe.out | 2 +-
.../nereids_function_p0/scalar_function/Array1.out | 24 ++++-----
.../array_functions/test_array_avg_integer_sum.out | 21 ++++++++
.../test_array_avg_integer_sum.groovy | 60 ++++++++++++++++++++++
8 files changed, 130 insertions(+), 29 deletions(-)
diff --git a/be/src/exprs/aggregate/aggregate_function_avg.cpp
b/be/src/exprs/aggregate/aggregate_function_avg.cpp
index acf2cd8d830..7d1117de15e 100644
--- a/be/src/exprs/aggregate/aggregate_function_avg.cpp
+++ b/be/src/exprs/aggregate/aggregate_function_avg.cpp
@@ -28,25 +28,12 @@
namespace doris {
#include "common/compile_check_begin.h"
-constexpr PrimitiveType result_type(PrimitiveType T) {
- if (T == TYPE_LARGEINT || T == TYPE_BIGINT) {
- return TYPE_LARGEINT;
- } else if (is_int_or_bool(T)) {
- return TYPE_BIGINT;
- } else if (is_float_or_double(T) || is_time_type(T)) {
- return TYPE_DOUBLE;
- } else if (is_decimalv3(T) && T != TYPE_DECIMAL256) {
- return TYPE_DECIMAL128I;
- } else {
- return T;
- }
-}
-
// TODO: use result type got from FE plan
template <PrimitiveType T>
struct Avg {
static constexpr PrimitiveType ResultPType = T == TYPE_DECIMALV2 ? T :
TYPE_DOUBLE;
- using Function = AggregateFunctionAvg<T, ResultPType,
AggregateFunctionAvgData<result_type(T)>>;
+ using Function =
+ AggregateFunctionAvg<T, ResultPType,
AggregateFunctionAvgData<avg_sum_type(T)>>;
};
template <PrimitiveType T>
diff --git a/be/src/exprs/aggregate/aggregate_function_avg.h
b/be/src/exprs/aggregate/aggregate_function_avg.h
index 665757ab343..0e9152ba1fa 100644
--- a/be/src/exprs/aggregate/aggregate_function_avg.h
+++ b/be/src/exprs/aggregate/aggregate_function_avg.h
@@ -52,6 +52,21 @@ class DataTypeNumber;
template <PrimitiveType T>
class ColumnVector;
+// avg() adds up the values in this type and divides only at the end, so
integers keep all digits.
+constexpr PrimitiveType avg_sum_type(PrimitiveType T) {
+ if (T == TYPE_LARGEINT || T == TYPE_BIGINT) {
+ return TYPE_LARGEINT;
+ } else if (is_int_or_bool(T)) {
+ return TYPE_BIGINT;
+ } else if (is_float_or_double(T) || is_time_type(T)) {
+ return TYPE_DOUBLE;
+ } else if (is_decimalv3(T) && T != TYPE_DECIMAL256) {
+ return TYPE_DECIMAL128I;
+ } else {
+ return T;
+ }
+}
+
template <PrimitiveType T>
struct AggregateFunctionAvgData {
using ResultType = typename PrimitiveTypeTraits<T>::CppType;
diff --git a/be/src/exprs/function/array/function_array_aggregation.cpp
b/be/src/exprs/function/array/function_array_aggregation.cpp
index cc1ec65c100..d2c6e65452f 100644
--- a/be/src/exprs/function/array/function_array_aggregation.cpp
+++ b/be/src/exprs/function/array/function_array_aggregation.cpp
@@ -90,7 +90,8 @@ struct AggregateFunctionTraits<AggregateOperation::AVERAGE> {
struct TypeTraits {
static constexpr PrimitiveType ResultType =
Element == TYPE_DECIMALV2 ? TYPE_DECIMALV2 : TYPE_DOUBLE;
- using AggregateDataType = AggregateFunctionAvgData<ResultType>;
+ // Add up the values in the same type as avg(). A double sum loses
digits of large integers.
+ using AggregateDataType =
AggregateFunctionAvgData<avg_sum_type(Element)>;
using Function = AggregateFunctionAvg<Element, ResultType,
AggregateDataType>;
static_assert(std::is_same_v<typename
PrimitiveTypeTraits<ResultType>::CppType,
typename Function::ResultType>,
diff --git a/be/test/exprs/function/function_array_aggregation_test.cpp
b/be/test/exprs/function/function_array_aggregation_test.cpp
index 9a99e482876..2427d053165 100644
--- a/be/test/exprs/function/function_array_aggregation_test.cpp
+++ b/be/test/exprs/function/function_array_aggregation_test.cpp
@@ -16,6 +16,7 @@
// under the License.
#include <cstddef>
+#include <limits>
#include <string>
#include <utility>
#include <vector>
@@ -336,6 +337,22 @@ TEST(VFunctionArrayAggregationTest,
TestArrayAverageNullable) {
func_name, data_set, PrimitiveType::TYPE_DOUBLE,
PrimitiveType::TYPE_DOUBLE, true));
}
+TEST(VFunctionArrayAggregationTest, TestArrayAverageLargeIntegers) {
+ const std::string func_name = "array_avg";
+ // The sum is 1. A double sum loses the 1 next to the large values and
gives 0.
+ std::vector<std::pair<std::vector<AnyValue<Int64>>, AnyValue<double>>>
bigint_data_set = {
+ {{std::numeric_limits<Int64>::max(), 1,
-std::numeric_limits<Int64>::max()}, 1.0 / 3},
+ };
+ static_cast<void>(check_function_array_wrapper<DataTypeInt64,
DataTypeFloat64>(
+ func_name, bigint_data_set, PrimitiveType::TYPE_BIGINT,
PrimitiveType::TYPE_DOUBLE));
+ std::vector<std::pair<std::vector<AnyValue<Int128>>, AnyValue<double>>>
largeint_data_set = {
+ {{std::numeric_limits<Int128>::max(), 1,
-std::numeric_limits<Int128>::max()}, 1.0 / 3},
+ };
+ static_cast<void>(check_function_array_wrapper<DataTypeInt128,
DataTypeFloat64>(
+ func_name, largeint_data_set, PrimitiveType::TYPE_LARGEINT,
+ PrimitiveType::TYPE_DOUBLE));
+}
+
TEST(VFunctionArrayAggregationTest, TestArrayProduct) {
const std::string func_name = "array_product";
IntDataSet data_set = {
diff --git a/regression-test/data/doc/sql-manual/ArrayNullsafe.out
b/regression-test/data/doc/sql-manual/ArrayNullsafe.out
index 64a056a2cdf..85431c5197e 100644
--- a/regression-test/data/doc/sql-manual/ArrayNullsafe.out
+++ b/regression-test/data/doc/sql-manual/ArrayNullsafe.out
@@ -879,7 +879,7 @@ false
\N
-- !sql_array_avg --
-1.7014118346046923e+38
+5.671372782015641e+37
3
2
\N
diff --git
a/regression-test/data/nereids_function_p0/scalar_function/Array1.out
b/regression-test/data/nereids_function_p0/scalar_function/Array1.out
index 2efd01b377c..67c41ff960c 100644
--- a/regression-test/data/nereids_function_p0/scalar_function/Array1.out
+++ b/regression-test/data/nereids_function_p0/scalar_function/Array1.out
@@ -123,8 +123,8 @@
\N
\N
\N
-0
-0
+-0.5
+-0.5
0
7.5
7.875
@@ -149,8 +149,8 @@
\N
\N
\N
-0
-0
+-0.5
+-0.5
0
7.5
7.875
@@ -172,10 +172,10 @@
\N
\N
\N
+-0.5
-9.055674363474186e+18
-9.223372036854776e+18
0
-0
3037000499.5
7.5
7.875
@@ -198,10 +198,10 @@
\N
\N
\N
+-0.5
-9.055674363474186e+18
-9.223372036854776e+18
0
-0
3037000499.5
7.5
7.875
@@ -24095,8 +24095,8 @@ true
\N
\N
\N
-0
-0
+-0.5
+-0.5
0
7.5
7.875
@@ -24121,8 +24121,8 @@ true
\N
\N
\N
-0
-0
+-0.5
+-0.5
0
7.5
7.875
@@ -24144,10 +24144,10 @@ true
\N
\N
\N
+-0.5
-9.055674363474186e+18
-9.223372036854776e+18
0
-0
3037000499.5
7.5
7.875
@@ -24170,10 +24170,10 @@ true
\N
\N
\N
+-0.5
-9.055674363474186e+18
-9.223372036854776e+18
0
-0
3037000499.5
7.5
7.875
diff --git
a/regression-test/data/query_p0/sql_functions/array_functions/test_array_avg_integer_sum.out
b/regression-test/data/query_p0/sql_functions/array_functions/test_array_avg_integer_sum.out
new file mode 100644
index 00000000000..7bcb966e22f
--- /dev/null
+++
b/regression-test/data/query_p0/sql_functions/array_functions/test_array_avg_integer_sum.out
@@ -0,0 +1,21 @@
+-- This file is automatically generated. You should know what you did if you
want to edit this
+-- !const --
+0.3333333333333333 0.3333333333333333
+
+-- !column --
+1 0.3333333333333333 0.3333333333333333
+2 0.3333333333333333 0.3333333333333333
+3 2 2.3333333333333335
+4 \N \N
+5 \N \N
+
+-- !same_as_avg_bigint --
+1 0.3333333333333333
+2 0.3333333333333333
+3 2
+
+-- !same_as_avg_largeint --
+1 0.3333333333333333
+2 0.3333333333333333
+3 2.3333333333333335
+
diff --git
a/regression-test/suites/query_p0/sql_functions/array_functions/test_array_avg_integer_sum.groovy
b/regression-test/suites/query_p0/sql_functions/array_functions/test_array_avg_integer_sum.groovy
new file mode 100644
index 00000000000..f746b31886a
--- /dev/null
+++
b/regression-test/suites/query_p0/sql_functions/array_functions/test_array_avg_integer_sum.groovy
@@ -0,0 +1,60 @@
+// 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.
+
+suite("test_array_avg_integer_sum") {
+ // array_avg adds up integers in the same type as avg(), so the large
values cancel out
+ // and the average of the sum 1 is 1/3.
+ order_qt_const """
+ SELECT array_avg(array(9223372036854775807, 1, -9223372036854775807)),
+ array_avg(array(170141183460469231731687303715884105727, 1,
+ -170141183460469231731687303715884105727))
+ """
+
+ sql """ DROP TABLE IF EXISTS test_array_avg_integer_sum """
+ sql """
+ CREATE TABLE test_array_avg_integer_sum (
+ id INT,
+ b ARRAY<BIGINT>,
+ l ARRAY<LARGEINT>
+ ) DUPLICATE KEY(id)
+ DISTRIBUTED BY HASH(id) BUCKETS 1
+ PROPERTIES ("replication_num" = "1")
+ """
+ sql """
+ INSERT INTO test_array_avg_integer_sum VALUES
+ (1, array(9223372036854775807, 1, -9223372036854775807),
+ array(170141183460469231731687303715884105727, 1,
+ -170141183460469231731687303715884105727)),
+ (2, array(9223372036854775807, NULL, 1, -9223372036854775807),
+ array(170141183460469231731687303715884105727, NULL, 1,
+ -170141183460469231731687303715884105727)),
+ (3, array(1, 2, 3), array(1, 2, 4)),
+ (4, array(), array()),
+ (5, NULL, NULL)
+ """
+ order_qt_column """
+ SELECT id, array_avg(b), array_avg(l) FROM test_array_avg_integer_sum
+ """
+
+ // avg() over the same elements gives the same result.
+ order_qt_same_as_avg_bigint """
+ SELECT id, avg(x) FROM test_array_avg_integer_sum LATERAL VIEW
explode(b) t AS x GROUP BY id
+ """
+ order_qt_same_as_avg_largeint """
+ SELECT id, avg(x) FROM test_array_avg_integer_sum LATERAL VIEW
explode(l) t AS x GROUP BY id
+ """
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]