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


The following commit(s) were added to refs/heads/branch-4.2 by this push:
     new 21df1d0b5cb branch-4.2: [fix](be) Support TIMEV2 in topn_array #68845 
(#69654)
21df1d0b5cb is described below

commit 21df1d0b5cb9fd5ea6084db1ae89d835a634b61e
Author: github-actions[bot] 
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Mon Nov 2 09:17:31 2026 +0800

    branch-4.2: [fix](be) Support TIMEV2 in topn_array #68845 (#69654)
    
    Cherry-picked from #68845
    
    Co-authored-by: TengJianPing <[email protected]>
---
 .../aggregate/aggregate_function_topn_array.cpp    |   4 +-
 be/test/exprs/aggregate/agg_topn_timev2_test.cpp   | 117 +++++++++++++++++++++
 .../agg_function/topn/topn_array_timev2.out        |  64 +++++++++++
 .../agg_function/topn/topn_array_timev2.groovy     |  76 +++++++++++++
 4 files changed, 259 insertions(+), 2 deletions(-)

diff --git a/be/src/exprs/aggregate/aggregate_function_topn_array.cpp 
b/be/src/exprs/aggregate/aggregate_function_topn_array.cpp
index 08829a1db5c..96ee87ca7be 100644
--- a/be/src/exprs/aggregate/aggregate_function_topn_array.cpp
+++ b/be/src/exprs/aggregate/aggregate_function_topn_array.cpp
@@ -32,8 +32,8 @@ using topn_array_creator =
         creator_with_type_list<TYPE_BOOLEAN, TYPE_TINYINT, TYPE_SMALLINT, 
TYPE_INT, TYPE_BIGINT,
                                TYPE_LARGEINT, TYPE_FLOAT, TYPE_DOUBLE, 
TYPE_DECIMAL32,
                                TYPE_DECIMAL64, TYPE_DECIMAL128I, 
TYPE_DECIMAL256, TYPE_VARCHAR,
-                               TYPE_DATEV2, TYPE_DATETIMEV2, 
TYPE_TIMESTAMP_NS, TYPE_TIMESTAMPTZ,
-                               TYPE_IPV4, TYPE_IPV6, TYPE_UUID>;
+                               TYPE_DATEV2, TYPE_DATETIMEV2, TYPE_TIMEV2, 
TYPE_TIMESTAMP_NS,
+                               TYPE_TIMESTAMPTZ, TYPE_IPV4, TYPE_IPV6, 
TYPE_UUID>;
 
 AggregateFunctionPtr create_aggregate_function_topn_array(const std::string& 
name,
                                                           const DataTypes& 
argument_types,
diff --git a/be/test/exprs/aggregate/agg_topn_timev2_test.cpp 
b/be/test/exprs/aggregate/agg_topn_timev2_test.cpp
new file mode 100644
index 00000000000..1d003dbb75c
--- /dev/null
+++ b/be/test/exprs/aggregate/agg_topn_timev2_test.cpp
@@ -0,0 +1,117 @@
+// 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 "agent/be_exec_version_manager.h"
+#include "core/data_type/data_type_array.h"
+#include "core/data_type/data_type_nullable.h"
+#include "core/data_type/data_type_number.h"
+#include "core/data_type/data_type_time.h"
+#include "core/value/time_value.h"
+#include "exprs/aggregate/agg_function_test.h"
+#include "exprs/aggregate/aggregate_function_simple_factory.h"
+
+namespace doris {
+
+struct AggregateFunctionTopNTimeV2Test : public AggregateFunctiontest {
+    void check_topn(const ColumnWithTypeAndName& values, int top_num, const 
Field& expected_array,
+                    bool expanded) {
+        SCOPED_TRACE(values.type->get_name());
+        SCOPED_TRACE(expanded);
+        SCOPED_TRACE(top_num);
+        Block block({values});
+        auto top_column = ColumnHelper::create_column_with_name<DataTypeInt32>(
+                std::vector<Int32>(values.column->size(), top_num));
+        block.insert(top_column);
+        DataTypes argument_types {values.type, top_column.type};
+        if (expanded) {
+            auto rate_column = 
ColumnHelper::create_column_with_name<DataTypeInt32>(
+                    std::vector<Int32>(values.column->size(), 100));
+            block.insert(rate_column);
+            argument_types.push_back(rate_column.type);
+        }
+
+        const bool nullable = values.type->is_nullable();
+        DataTypePtr result_type = 
std::make_shared<DataTypeArray>(make_nullable(values.type));
+        if (nullable) {
+            result_type = make_nullable(result_type);
+        }
+        auto function = AggregateFunctionSimpleFactory::instance().get(
+                "topn_array", argument_types, result_type, nullable,
+                BeExecVersionManager::get_newest_version());
+        ASSERT_NE(function, nullptr);
+        EXPECT_TRUE(function->get_return_type()->equals(*result_type));
+
+        auto expected_column = result_type->create_column();
+        expected_column->insert(expected_array);
+        create_agg("topn_array", nullable, argument_types, result_type);
+        execute(block, ColumnWithTypeAndName(std::move(expected_column), 
result_type, "expected"));
+    }
+
+    static Field time_array(std::initializer_list<Float64> values) {
+        Array array;
+        for (auto value : values) {
+            array.push_back(Field::create_field<TYPE_TIMEV2>(value));
+        }
+        return Field::create_field<TYPE_ARRAY>(std::move(array));
+    }
+};
+
+TEST_F(AggregateFunctionTopNTimeV2Test, PrecisionAndLimits) {
+    const Float64 large = TimeValue::make_time(838, 59, 58, 0);
+    Float64 step = TimeValue::ONE_SECOND_MICROSECONDS;
+    for (UInt32 scale = 0; scale <= DataTypeTimeV2::MAX_SCALE; ++scale, step 
/= 10) {
+        for (bool expanded : {false, true}) {
+            ColumnWithTypeAndName 
values(ColumnHelper::create_column<DataTypeTimeV2>(
+                                                 {large, large, large + step, 
-step}),
+                                         
std::make_shared<DataTypeTimeV2>(scale), "values");
+            check_topn(values, 1, time_array({large}), expanded);
+            check_topn(values, 5, time_array({large, large + step, -step}), 
expanded);
+        }
+    }
+}
+
+TEST_F(AggregateFunctionTopNTimeV2Test, NegativeValuesAndZero) {
+    const Float64 minimum = TimeValue::make_time(838, 59, 59, 0, true);
+    for (bool expanded : {false, true}) {
+        ColumnWithTypeAndName values(
+                ColumnHelper::create_column<DataTypeTimeV2>({minimum, 
-1000000, 0}),
+                std::make_shared<DataTypeTimeV2>(6), "values");
+        check_topn(values, 3, time_array({0, -1000000, minimum}), expanded);
+    }
+}
+
+TEST_F(AggregateFunctionTopNTimeV2Test, NullableValues) {
+    Float64 step = TimeValue::ONE_SECOND_MICROSECONDS;
+    for (UInt32 scale = 0; scale <= DataTypeTimeV2::MAX_SCALE; ++scale, step 
/= 10) {
+        for (bool expanded : {false, true}) {
+            auto type = make_nullable(std::make_shared<DataTypeTimeV2>(scale));
+            ColumnWithTypeAndName 
values(ColumnHelper::create_nullable_column<DataTypeTimeV2>(
+                                                 {step, step, -step, 0}, {0, 
0, 0, 1}),
+                                         type, "values");
+            check_topn(values, 2, time_array({step, -step}), expanded);
+
+            ColumnWithTypeAndName nulls(
+                    ColumnHelper::create_nullable_column<DataTypeTimeV2>({0, 
-step}, {1, 1}), type,
+                    "values");
+            check_topn(nulls, 2, Field(), expanded);
+        }
+    }
+}
+
+} // namespace doris
diff --git 
a/regression-test/data/nereids_function_p0/agg_function/topn/topn_array_timev2.out
 
b/regression-test/data/nereids_function_p0/agg_function/topn/topn_array_timev2.out
new file mode 100644
index 00000000000..22277553830
--- /dev/null
+++ 
b/regression-test/data/nereids_function_p0/agg_function/topn/topn_array_timev2.out
@@ -0,0 +1,64 @@
+-- This file is automatically generated. You should know what you did if you 
want to edit this
+-- !reproduction --
+["02:00:00", "01:00:00"]       ["02:00:00", "01:00:00"]
+
+-- !timev2_0 --
+["01:00:00"]   ["01:00:00"]    ["01:00:00", "-12:34:56"]       ["01:00:00", 
"-12:34:56"]       ["01:00:00", "-12:34:56", "838:59:59", "27:00:01", 
"02:00:01", "-838:59:59"]    ["01:00:00", "-12:34:56", "838:59:59", "27:00:01", 
"02:00:01", "-838:59:59"]    01:00:00
+
+-- !grouped_0 --
+1      ["01:00:00", "02:00:01"]        ["01:00:00", "02:00:01"]
+2      ["-12:34:56", "838:59:59"]      ["-12:34:56", "838:59:59"]
+3      \N      \N
+
+-- !distinct_0 --
+["838:59:59", "27:00:01", "02:00:01", "01:00:00", "-12:34:56", "-838:59:59"]   
["838:59:59", "27:00:01", "02:00:01", "01:00:00", "-12:34:56", "-838:59:59"]
+
+-- !state_0 --
+["01:00:00", "-12:34:56"]      ["01:00:00", "-12:34:56"]
+
+-- !null_0 --
+\N     \N
+
+-- !empty_0 --
+\N     \N
+
+-- !timev2_3 --
+["01:00:00.123"]       ["01:00:00.123"]        ["01:00:00.123", 
"-12:34:56.123"]       ["01:00:00.123", "-12:34:56.123"]       ["01:00:00.123", 
"-12:34:56.123", "838:59:59.000", "27:00:00.654", "02:00:00.654", 
"-838:59:59.000"]    ["01:00:00.123", "-12:34:56.123", "838:59:59.000", 
"27:00:00.654", "02:00:00.654", "-838:59:59.000"]    01:00:00.123
+
+-- !grouped_3 --
+1      ["01:00:00.123", "02:00:00.654"]        ["01:00:00.123", "02:00:00.654"]
+2      ["-12:34:56.123", "838:59:59.000"]      ["-12:34:56.123", 
"838:59:59.000"]
+3      \N      \N
+
+-- !distinct_3 --
+["838:59:59.000", "27:00:00.654", "02:00:00.654", "01:00:00.123", 
"-12:34:56.123", "-838:59:59.000"]   ["838:59:59.000", "27:00:00.654", 
"02:00:00.654", "01:00:00.123", "-12:34:56.123", "-838:59:59.000"]
+
+-- !state_3 --
+["01:00:00.123", "-12:34:56.123"]      ["01:00:00.123", "-12:34:56.123"]
+
+-- !null_3 --
+\N     \N
+
+-- !empty_3 --
+\N     \N
+
+-- !timev2_6 --
+["01:00:00.123456"]    ["01:00:00.123456"]     ["01:00:00.123456", 
"-12:34:56.123456"] ["01:00:00.123456", "-12:34:56.123456"] ["01:00:00.123456", 
"-12:34:56.123456", "838:59:59.000000", "27:00:00.654321", "02:00:00.654321", 
"-838:59:59.000000"]  ["01:00:00.123456", "-12:34:56.123456", 
"838:59:59.000000", "27:00:00.654321", "02:00:00.654321", "-838:59:59.000000"]  
01:00:00.123456
+
+-- !grouped_6 --
+1      ["01:00:00.123456", "02:00:00.654321"]  ["01:00:00.123456", 
"02:00:00.654321"]
+2      ["-12:34:56.123456", "838:59:59.000000"]        ["-12:34:56.123456", 
"838:59:59.000000"]
+3      \N      \N
+
+-- !distinct_6 --
+["838:59:59.000000", "27:00:00.654321", "02:00:00.654321", "01:00:00.123456", 
"-12:34:56.123456", "-838:59:59.000000"] ["838:59:59.000000", 
"27:00:00.654321", "02:00:00.654321", "01:00:00.123456", "-12:34:56.123456", 
"-838:59:59.000000"]
+
+-- !state_6 --
+["01:00:00.123456", "-12:34:56.123456"]        ["01:00:00.123456", 
"-12:34:56.123456"]
+
+-- !null_6 --
+\N     \N
+
+-- !empty_6 --
+\N     \N
+
diff --git 
a/regression-test/suites/nereids_function_p0/agg_function/topn/topn_array_timev2.groovy
 
b/regression-test/suites/nereids_function_p0/agg_function/topn/topn_array_timev2.groovy
new file mode 100644
index 00000000000..3b5702d65e1
--- /dev/null
+++ 
b/regression-test/suites/nereids_function_p0/agg_function/topn/topn_array_timev2.groovy
@@ -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.
+
+suite("topn_array_timev2") {
+    order_qt_reproduction """
+        SELECT topn_array(v, 2), topn_array(v, 2, 100) FROM (
+            SELECT CAST('01:00:00' AS TIME) v
+            UNION ALL SELECT CAST('02:00:00' AS TIME)
+        ) t
+    """
+
+    sql "DROP TABLE IF EXISTS test_topn_array_timev2"
+    sql """
+        CREATE TABLE test_topn_array_timev2 (
+            id INT,
+            g INT,
+            value_string STRING
+        ) DUPLICATE KEY(id)
+        DISTRIBUTED BY HASH(id) BUCKETS 3
+        PROPERTIES ("replication_num" = "1")
+    """
+    sql """
+        INSERT INTO test_topn_array_timev2 VALUES
+            (1, 1, '01:00:00.123456'), (2, 1, '01:00:00.123456'),
+            (3, 1, '02:00:00.654321'), (4, 2, '-12:34:56.123456'),
+            (5, 2, '-12:34:56.123456'), (6, 2, '27:00:00.654321'),
+            (7, 2, '838:59:59'), (8, 2, '-838:59:59'), (9, 1, NULL), (10, 3, 
NULL)
+    """
+
+    [0, 3, 6].each { scale ->
+        "order_qt_timev2_${scale}" """
+            SELECT topn_array(v, 1), topn_array(v, 1, 100),
+                   topn_array(v, 2), topn_array(v, 2, 100),
+                   topn_array(v, 10), topn_array(v, 10, 100),
+                   topn_array(v, 2)[1]
+            FROM (SELECT CAST(value_string AS TIME(${scale})) v FROM 
test_topn_array_timev2) t
+        """
+        "order_qt_grouped_${scale}" """
+            SELECT g, topn_array(v, 2), topn_array(v, 2, 100)
+            FROM (SELECT g, CAST(value_string AS TIME(${scale})) v FROM 
test_topn_array_timev2) t
+            GROUP BY g
+        """
+        "order_qt_distinct_${scale}" """
+            SELECT topn_array(DISTINCT v, 10), topn_array(DISTINCT v, 10, 100)
+            FROM (SELECT CAST(value_string AS TIME(${scale})) v FROM 
test_topn_array_timev2) t
+        """
+        "order_qt_state_${scale}" """
+            SELECT topn_array_merge(topn_array_state(CAST(value_string AS 
TIME(${scale})), 2)),
+                   topn_array_merge(topn_array_state(CAST(value_string AS 
TIME(${scale})), 2, 100))
+            FROM test_topn_array_timev2
+        """
+        "order_qt_null_${scale}" """
+            SELECT topn_array(CAST(NULL AS TIME(${scale})), 2),
+                   topn_array(CAST(NULL AS TIME(${scale})), 2, 100)
+        """
+        "order_qt_empty_${scale}" """
+            SELECT topn_array(v, 2), topn_array(v, 2, 100)
+            FROM (SELECT CAST(value_string AS TIME(${scale})) v
+                  FROM test_topn_array_timev2 WHERE id < 0) t
+        """
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to