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 f26a25f5788f498c9088bb7b503bdacc246daee9 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]
