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 bf963dfc5fc [fix](expr) Fix DATETIMEV2 array range tail omission 
(#68855)
bf963dfc5fc is described below

commit bf963dfc5fcb364bba881ba77a81b21748a12589
Author: Mryange <[email protected]>
AuthorDate: Sat Oct 10 16:35:42 2026 +0800

    [fix](expr) Fix DATETIMEV2 array range tail omission (#68855)
    
    ### What problem does this PR solve?
    
    Issue Number: N/A
    
    Related PR: #68566
    
    Problem Summary:
    
    Backport the DATETIMEV2 fix from #68566 to branch-4.1. Date-based
    array_range and sequence omitted valid tail values when less than one
    complete interval remained. Root cause: datetime_diff was used as the
    loop condition. Compare directly with the exclusive end, enforce the
    array size limit, and stop safely when the successor exceeds the date
    range.
    
    TIMESTAMP_NS changes are excluded because branch-4.1 does not support
    this type. Add DATETIMEV2 regression coverage and update existing
    expected results.
    
    ### Release note
    
    None
    
    ### Check List (For Author)
    
    - Test
        - [ ] Regression test
        - [ ] Unit Test
        - [ ] Manual test
        - [ ] No need to test or manual test
    
    Regression cases are included. Build and tests have not been run for
    this backport. clang-format 16 and git diff --check passed.
    
    - Behavior changed:
        - [ ] No.
    - [x] Yes. DATETIMEV2 ranges include all valid values below the
    exclusive end.
    
    - Does this need documentation?
        - [x] No.
        - [ ] Yes.
    
    ### Check List (For Reviewer who merge this PR)
    
    - [ ] Confirm the release note
    - [ ] Confirm test cases
    - [ ] Confirm document
    - [ ] Add branch pick label
---
 .../exprs/function/array/function_array_range.cpp  | 24 +++++++++++----
 .../test_array_range_datetime_tail.out             | 29 ++++++++++++++++++
 .../array_functions/test_array_functions.out       | 14 ++++-----
 .../test_array_range_datetime_tail.groovy          | 35 ++++++++++++++++++++++
 4 files changed, 90 insertions(+), 12 deletions(-)

diff --git a/be/src/exprs/function/array/function_array_range.cpp 
b/be/src/exprs/function/array/function_array_range.cpp
index c24e6afe527..358d4ac9370 100644
--- a/be/src/exprs/function/array/function_array_range.cpp
+++ b/be/src/exprs/function/array/function_array_range.cpp
@@ -243,9 +243,9 @@ private:
                                                     
std::integral_constant<TimeUnit, TimeUnit::DAY>,
                                                     TimeUnitOrVoid>;
                     int move = 0;
-                    while (doris::datetime_diff<UNIT::value, 
DateTimeV2ValueType,
-                                                DateTimeV2ValueType>(idx, 
end_row) > 0) {
-                        if (move > max_array_size_as_field) {
+                    // A value below end belongs to the range even if less 
than one unit remains.
+                    while (idx < end_row) {
+                        if (move >= max_array_size_as_field) {
                             return Status::InvalidArgument("Array size exceeds 
the limit {}",
                                                            
max_array_size_as_field);
                         }
@@ -253,8 +253,22 @@ private:
                         dest_nested_null_map.push_back(0);
                         offset++;
                         move++;
-                        idx = doris::date_time_add<UNIT::value, 
TYPE_DATETIMEV2, Int32>(idx,
-                                                                               
         step_row);
+                        auto next = idx;
+                        bool advanced;
+                        if constexpr (UNIT::value == TimeUnit::DAY ||
+                                      UNIT::value == TimeUnit::WEEK) {
+                            const Int64 days = static_cast<Int64>(step_row) *
+                                               (UNIT::value == TimeUnit::WEEK 
? 7 : 1);
+                            advanced = next.template 
date_add_days<false>(days);
+                        } else {
+                            advanced = next.template 
date_add_interval<UNIT::value>(
+                                    TimeInterval(UNIT::value, step_row, 
false));
+                        }
+                        // The successor can exceed the date range after 
emitting a valid value.
+                        if (!advanced) {
+                            break;
+                        }
+                        idx = next;
                     }
                     dest_offsets.push_back(offset);
                 }
diff --git 
a/regression-test/data/nereids_function_p0/scalar_function/test_array_range_datetime_tail.out
 
b/regression-test/data/nereids_function_p0/scalar_function/test_array_range_datetime_tail.out
new file mode 100644
index 00000000000..5b4753a60eb
--- /dev/null
+++ 
b/regression-test/data/nereids_function_p0/scalar_function/test_array_range_datetime_tail.out
@@ -0,0 +1,29 @@
+-- This file is automatically generated. You should know what you did if you 
want to edit this
+-- !day_partial --
+["2024-01-01 00:00:00.000000", "2024-01-02 00:00:00.000000"]
+
+-- !day_exact --
+["2024-01-01 00:00:00.000000"]
+
+-- !day_empty --
+[]
+
+-- !day_vector --
+["2024-01-01 00:00:00.000000", "2024-01-02 00:00:00.000000"]
+["2024-01-02 00:00:00.000000"]
+
+-- !second_partial --
+["2024-01-01 00:00:00.000000", "2024-01-01 00:00:01.000000"]
+
+-- !second_exact --
+["2024-01-01 00:00:00.000000"]
+
+-- !second_vector --
+["2024-01-01 00:00:00.000000", "2024-01-01 00:00:01.000000"]
+["2024-01-01 00:00:01.000000"]
+
+-- !month_end --
+["2020-01-31 00:00:00.000000", "2020-02-29 00:00:00.000000", "2020-03-29 
00:00:00.000000"]
+
+-- !upper_bound --
+["9999-12-31 23:59:59.999998"]
diff --git 
a/regression-test/data/query_p0/sql_functions/array_functions/test_array_functions.out
 
b/regression-test/data/query_p0/sql_functions/array_functions/test_array_functions.out
index d604e6acb20..ca0ae11a101 100644
--- 
a/regression-test/data/query_p0/sql_functions/array_functions/test_array_functions.out
+++ 
b/regression-test/data/query_p0/sql_functions/array_functions/test_array_functions.out
@@ -1877,19 +1877,19 @@
 9      [9]
 
 -- !table_select --
-2022-05-15T12:00       2022-05-18T12:00:00.123 ["2022-05-15 12:00:00.000", 
"2022-05-16 12:00:00.000", "2022-05-17 12:00:00.000"]
+2022-05-15T12:00       2022-05-18T12:00:00.123 ["2022-05-15 12:00:00.000", 
"2022-05-16 12:00:00.000", "2022-05-17 12:00:00.000", "2022-05-18 12:00:00.000"]
 
 -- !table_select --
-2022-05-15T12:00       2022-05-18T12:00:00.123456      ["2022-05-15 
12:00:00.000000", "2022-05-16 12:00:00.000000", "2022-05-17 12:00:00.000000"]
+2022-05-15T12:00       2022-05-18T12:00:00.123456      ["2022-05-15 
12:00:00.000000", "2022-05-16 12:00:00.000000", "2022-05-17 12:00:00.000000", 
"2022-05-18 12:00:00.000000"]
 
 -- !table_select --
-2022-05-15T12:00       2022-05-18T12:00:00.123 1       ["2022-05-15 
12:00:00.000", "2022-05-16 12:00:00.000", "2022-05-17 12:00:00.000"]
+2022-05-15T12:00       2022-05-18T12:00:00.123 1       ["2022-05-15 
12:00:00.000", "2022-05-16 12:00:00.000", "2022-05-17 12:00:00.000", 
"2022-05-18 12:00:00.000"]
 
 -- !table_select --
-2022-04-22T12:00:00.123        2022-05-08T12:00:00.123456      1       
["2022-04-22 12:00:00.123000", "2022-04-29 12:00:00.123000"]
+2022-04-22T12:00:00.123        2022-05-08T12:00:00.123456      1       
["2022-04-22 12:00:00.123000", "2022-04-29 12:00:00.123000", "2022-05-06 
12:00:00.123000"]
 
 -- !table_select --
-2022-01-15T12:00:00.123        2022-05-18T12:00:00.123456      2       
["2022-01-15 12:00:00.123000", "2022-03-15 12:00:00.123000"]
+2022-01-15T12:00:00.123        2022-05-18T12:00:00.123456      2       
["2022-01-15 12:00:00.123000", "2022-03-15 12:00:00.123000", "2022-05-15 
12:00:00.123000"]
 
 -- !table_select --
 2015-05-15T12:00:00.123        2022-05-18T12:00:00.123456      3       
["2015-05-15 12:00:00.123000", "2018-05-15 12:00:00.123000", "2021-05-15 
12:00:00.123000"]
@@ -1898,7 +1898,7 @@
 2022-05-18T12:00:00.123        2022-05-18T23:10:00.123456      4       
["2022-05-18 12:00:00.123000", "2022-05-18 16:00:00.123000", "2022-05-18 
20:00:00.123000"]
 
 -- !table_select --
-2022-05-18T12:00:00.123        2022-05-18T12:16        5       ["2022-05-18 
12:00:00.123000", "2022-05-18 12:05:00.123000", "2022-05-18 12:10:00.123000"]
+2022-05-18T12:00:00.123        2022-05-18T12:16        5       ["2022-05-18 
12:00:00.123000", "2022-05-18 12:05:00.123000", "2022-05-18 12:10:00.123000", 
"2022-05-18 12:15:00.123000"]
 
 -- !table_select --
 2022-05-18T12:00:10    2022-05-18T12:00:30     6       ["2022-05-18 
12:00:10.000000", "2022-05-18 12:00:16.000000", "2022-05-18 12:00:22.000000", 
"2022-05-18 12:00:28.000000"]
@@ -1931,7 +1931,7 @@
 ["2022-05-15 12:00:00", "2022-05-16 12:00:00"]
 
 -- !const_select --
-["2022-05-01 12:00:00"]
+["2022-05-01 12:00:00", "2022-05-15 12:00:00"]
 
 -- !const_select --
 ["2022-01-15 12:00:00", "2022-04-15 12:00:00"]
diff --git 
a/regression-test/suites/nereids_function_p0/scalar_function/test_array_range_datetime_tail.groovy
 
b/regression-test/suites/nereids_function_p0/scalar_function/test_array_range_datetime_tail.groovy
new file mode 100644
index 00000000000..7e242650e18
--- /dev/null
+++ 
b/regression-test/suites/nereids_function_p0/scalar_function/test_array_range_datetime_tail.groovy
@@ -0,0 +1,35 @@
+// 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_range_datetime_tail") {
+    qt_day_partial """select array_range(cast('2024-01-01 00:00:00.000000' as 
datetimev2(6)), cast('2024-01-02 12:00:00.000000' as datetimev2(6)))"""
+    qt_day_exact """select array_range(cast('2024-01-01 00:00:00.000000' as 
datetimev2(6)), cast('2024-01-02 00:00:00.000000' as datetimev2(6)))"""
+    qt_day_empty """select array_range(cast('2024-01-02 00:00:00.000000' as 
datetimev2(6)), cast('2024-01-01 00:00:00.000000' as datetimev2(6)))"""
+    order_qt_day_vector """select array_range(date_add(cast('2024-01-01 
00:00:00.000000' as datetimev2(6)), interval number day), cast('2024-01-02 
12:00:00.000000' as datetimev2(6))) from numbers("number" = "2") order by 
number"""
+
+    qt_second_partial """select sequence(cast('2024-01-01 00:00:00.000000' as 
datetimev2(6)), cast('2024-01-01 00:00:01.500000' as datetimev2(6)), interval 1 
second)"""
+    qt_second_exact """select sequence(cast('2024-01-01 00:00:00.000000' as 
datetimev2(6)), cast('2024-01-01 00:00:01.000000' as datetimev2(6)), interval 1 
second)"""
+    order_qt_second_vector """select sequence(date_add(cast('2024-01-01 
00:00:00.000000' as datetimev2(6)), interval number second), cast('2024-01-01 
00:00:01.500000' as datetimev2(6)), interval 1 second) from numbers("number" = 
"2") order by number"""
+
+    qt_month_end """select array_range(cast('2020-01-31 00:00:00' as 
datetimev2(6)), cast('2020-03-30 00:00:00' as datetimev2(6)), interval 1 
month)"""
+    qt_upper_bound """select array_range(cast('9999-12-31 23:59:59.999998' as 
datetimev2(6)), cast('9999-12-31 23:59:59.999999' as datetimev2(6)), interval 1 
second)"""
+
+    test {
+        sql """select array_range(date_add(cast('2024-01-01 00:00:00' as 
datetimev2(6)), interval number second), cast('2024-01-12 13:46:41' as 
datetimev2(6)), interval 1 second) from numbers("number" = "1")"""
+        exception "Array size exceeds the limit 1000000"
+    }
+}


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

Reply via email to