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 64947d8f8c7 branch-4.1: [fix](function) Skip the rows with a NULL 
argument in array_range #68620 (#68644)
64947d8f8c7 is described below

commit 64947d8f8c7bf5b756e7d7f725b3da6caf8fa376
Author: github-actions[bot] 
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Tue Sep 29 23:34:36 2026 +0800

    branch-4.1: [fix](function) Skip the rows with a NULL argument in 
array_range #68620 (#68644)
    
    Cherry-picked from #68620
    
    Co-authored-by: Chenyang Sun <[email protected]>
    Co-authored-by: Claude Opus 5.5 <[email protected]>
---
 .../exprs/function/array/function_array_range.cpp  | 12 +++++
 .../exprs/function/function_array_range_test.cpp   | 12 +++++
 .../test_array_range_null_argument.out             | 15 +++++++
 .../test_array_range_null_argument.groovy          | 51 ++++++++++++++++++++++
 4 files changed, 90 insertions(+)

diff --git a/be/src/exprs/function/array/function_array_range.cpp 
b/be/src/exprs/function/array/function_array_range.cpp
index 24d4de938bd..c24e6afe527 100644
--- a/be/src/exprs/function/array/function_array_range.cpp
+++ b/be/src/exprs/function/array/function_array_range.cpp
@@ -41,6 +41,7 @@
 #include "core/pod_array_fwd.h"
 #include "core/types.h"
 #include "core/value/vdatetime_value.h"
+#include "exec/common/util.hpp"
 #include "exprs/aggregate/aggregate_function.h"
 #include "exprs/function/function.h"
 #include "exprs/function/function_date_or_datetime_computation.h"
@@ -79,6 +80,10 @@ public:
         return make_nullable(res);
     }
 
+    // range_execute skips the rows with a NULL argument. The default NULL 
handling would build a
+    // range from the value under the NULL, which can be larger than the array 
size limit.
+    bool use_default_implementation_for_nulls() const override { return false; 
}
+
     Status execute_impl(FunctionContext* context, Block& block, const 
ColumnNumbers& arguments,
                         uint32_t result, size_t input_rows_count) const 
override {
         return Impl::execute_impl(context, block, arguments, result, 
input_rows_count);
@@ -147,6 +152,13 @@ struct RangeImplUtil {
         for (int i = 0; i < 3; ++i) {
             argument_columns[i] =
                     
block.get_by_position(arguments[i]).column->convert_to_full_column_if_const();
+            if (const auto* nullable = 
check_and_get_column<ColumnNullable>(*argument_columns[i])) {
+                // Read the null map before replacing the column, because the 
replacement can free
+                // the nullable column.
+                VectorizedUtils::update_null_map(args_null_map->get_data(),
+                                                 
nullable->get_null_map_data());
+                argument_columns[i] = nullable->get_nested_column_ptr();
+            }
         }
         auto start_column =
                 assert_cast<const 
ColumnVector<SourceDataPType>*>(argument_columns[0].get());
diff --git a/be/test/exprs/function/function_array_range_test.cpp 
b/be/test/exprs/function/function_array_range_test.cpp
index d6026f84005..c91d17918ca 100644
--- a/be/test/exprs/function/function_array_range_test.cpp
+++ b/be/test/exprs/function/function_array_range_test.cpp
@@ -193,5 +193,17 @@ TEST(FunctionArrayRangeTest, ArraySizeLimit) {
     }
 }
 
+TEST(FunctionArrayRangeTest, NullStartSkipsTheRange) {
+    // The value under a NULL start is 0. A range from 0 to this end is larger 
than the limit, so
+    // the row must give NULL without building the range, even next to rows 
that are not NULL.
+    const auto large_end = static_cast<Int32>(max_array_size_as_field) * 4;
+    for (const auto* name : {"array_range", "sequence"}) {
+        check_range(name, {{1, 3, 1}, {std::nullopt, large_end, 1}, {2, 6, 2}},
+                    {std::vector<Int32> {1, 2}, std::nullopt, 
std::vector<Int32> {2, 4}});
+        check_range(name, {{1, 3, 0}, {std::nullopt, large_end, 0}},
+                    {std::vector<Int32> {1, 2}, std::nullopt}, 0, 2);
+    }
+}
+
 } // namespace
 } // namespace doris
diff --git 
a/regression-test/data/query_p0/sql_functions/array_functions/test_array_range_null_argument.out
 
b/regression-test/data/query_p0/sql_functions/array_functions/test_array_range_null_argument.out
new file mode 100644
index 00000000000..89f0569b5f3
--- /dev/null
+++ 
b/regression-test/data/query_p0/sql_functions/array_functions/test_array_range_null_argument.out
@@ -0,0 +1,15 @@
+-- This file is automatically generated. You should know what you did if you 
want to edit this
+-- !int_range --
+1      [1, 2, 3]       [1, 2, 3]       [1, 2, 3]
+2      \N      \N      \N
+3      \N      \N      \N
+4      [2, 3, 4, 5, 6, 7]      \N      \N
+5      [0, 1, 2]       [0, 2]  [0, 2]
+
+-- !datetime_range --
+1      ["2024-01-01 00:00:00.123456", "2024-01-01 00:00:01.123456", 
"2024-01-01 00:00:02.123456"]
+2      \N
+3      \N
+4      ["2024-01-01 00:00:00.000000", "2024-01-01 00:00:01.000000"]
+5      \N
+
diff --git 
a/regression-test/suites/query_p0/sql_functions/array_functions/test_array_range_null_argument.groovy
 
b/regression-test/suites/query_p0/sql_functions/array_functions/test_array_range_null_argument.groovy
new file mode 100644
index 00000000000..6336e214313
--- /dev/null
+++ 
b/regression-test/suites/query_p0/sql_functions/array_functions/test_array_range_null_argument.groovy
@@ -0,0 +1,51 @@
+// 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_null_argument") {
+    sql "DROP TABLE IF EXISTS test_array_range_null_argument"
+    sql """
+        CREATE TABLE test_array_range_null_argument (
+            id INT,
+            s INT NULL,
+            e INT NULL,
+            st INT NULL,
+            ds DATETIME(6) NULL,
+            de DATETIME(6) NULL
+        ) DUPLICATE KEY(id)
+        DISTRIBUTED BY HASH(id) BUCKETS 1
+        PROPERTIES ("replication_num" = "1")
+    """
+    // The rows are read in one block. A row with a NULL argument gives NULL, 
and must not build a
+    // range from the value under the NULL, which can be larger than the array 
size limit.
+    sql """
+        INSERT INTO test_array_range_null_argument VALUES
+            (1, 1, 4, 1, '2024-01-01 00:00:00.123456', '2024-01-01 
00:00:03.123456'),
+            (2, NULL, 5000000, 1, NULL, '2024-01-02 00:00:00'),
+            (3, 2, NULL, 1, '2024-01-01 00:00:00', NULL),
+            (4, 2, 8, NULL, '2024-01-01 00:00:00', '2024-01-01 00:00:02'),
+            (5, 0, 3, 2, NULL, NULL)
+    """
+
+    order_qt_int_range """
+        SELECT id, array_range(s, e), array_range(s, e, st), sequence(s, e, st)
+        FROM test_array_range_null_argument
+    """
+    order_qt_datetime_range """
+        SELECT id, sequence(ds, de, INTERVAL 1 SECOND)
+        FROM test_array_range_null_argument
+    """
+}


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

Reply via email to