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

yiguolei pushed a commit to branch branch-4.2
in repository https://gitbox.apache.org/repos/asf/doris.git

commit 4981796ac3895be74584f9773ebc120a89c3022d
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]

Reply via email to