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]