This is an automated email from the ASF dual-hosted git repository.

HappenLee pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/master by this push:
     new cebf71c12e5 [fix](be) Fix concat_ws nullable array handling (#64703)
cebf71c12e5 is described below

commit cebf71c12e5cce305cf4cd25c0f545c2e46c9e08
Author: HappenLee <[email protected]>
AuthorDate: Tue Jun 23 15:23:34 2026 +0800

    [fix](be) Fix concat_ws nullable array handling (#64703)
    
    Problem Summary: concat_ws has a BE execution path for a single array
    argument. When the array column row itself is NULL, the executor still
    walked the nested array data and could return values from nested storage
    instead of treating the NULL array row as empty input. Also, if the
    optimizer rewrite is disabled, multiple array arguments can reach this
    BE array path and were silently executed using only the first array
    argument. This change keeps concat_ws return nullability unchanged,
    skips nested data for NULL array rows, and rejects array-form concat_ws
    calls unless the executor receives exactly separator plus one array
    argument.
    
    ### Release note
    
    Fix wrong concat_ws results for nullable array inputs and return an
    error for unsupported multiple-array execution without optimizer
    rewrite.
---
 be/src/exprs/function/function_string_concat.h            | 12 ++++++++++++
 .../nereids_function_p0/scalar_function/concat_ws.out     |  7 +++++++
 .../nereids_function_p0/scalar_function/concat_ws.groovy  | 15 ++++++++++++++-
 3 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/be/src/exprs/function/function_string_concat.h 
b/be/src/exprs/function/function_string_concat.h
index 3cbfd035ef4..4cac63b6626 100644
--- a/be/src/exprs/function/function_string_concat.h
+++ b/be/src/exprs/function/function_string_concat.h
@@ -417,6 +417,11 @@ public:
         std::vector<std::string_view> views;
 
         if (is_column<ColumnArray>(argument_columns[1].get())) {
+            if (argument_size != 2) {
+                return Status::InvalidArgument(
+                        "concat_ws with array argument expects exactly 2 
arguments, but got {}",
+                        argument_size);
+            }
             // Determine if the nested type of the array is String
             const auto& array_column = reinterpret_cast<const 
ColumnArray&>(*argument_columns[1]);
             if (!array_column.get_data().is_column_string()) {
@@ -472,6 +477,7 @@ private:
         const auto& src_string_offsets = string_column.get_offsets();
         const auto& src_array_offsets = array_column.get_offsets();
         size_t current_src_array_offset = 0;
+        auto& array_nullmap = *null_list[1];
 
         // Concat string in array
         for (size_t i = 0; i < input_rows_count; ++i) {
@@ -485,6 +491,12 @@ private:
                 continue;
             }
 
+            if (array_nullmap[i]) {
+                StringOP::push_empty_string(i, res_data, res_offset);
+                current_src_array_offset += src_array_offsets[i] - 
src_array_offsets[i - 1];
+                continue;
+            }
+
             int sep_size = sep_offsets[i] - sep_offsets[i - 1];
             const char* sep_data = reinterpret_cast<const 
char*>(&sep_chars[sep_offsets[i - 1]]);
 
diff --git 
a/regression-test/data/nereids_function_p0/scalar_function/concat_ws.out 
b/regression-test/data/nereids_function_p0/scalar_function/concat_ws.out
index 20493bb95c9..f4768319fe6 100644
--- a/regression-test/data/nereids_function_p0/scalar_function/concat_ws.out
+++ b/regression-test/data/nereids_function_p0/scalar_function/concat_ws.out
@@ -37,3 +37,10 @@ a-b-css-d
 x-y-z
 你好-世界-Doris-Nereids
 
+-- !concat_ws_array_null_full --
+1      []      0
+2      [a,b,c] 5
+
+-- !concat_ws_array_null_filter --
+1      []      0
+
diff --git 
a/regression-test/suites/nereids_function_p0/scalar_function/concat_ws.groovy 
b/regression-test/suites/nereids_function_p0/scalar_function/concat_ws.groovy
index 44808aa999f..0517e09e7be 100644
--- 
a/regression-test/suites/nereids_function_p0/scalar_function/concat_ws.groovy
+++ 
b/regression-test/suites/nereids_function_p0/scalar_function/concat_ws.groovy
@@ -39,4 +39,17 @@ suite("nereids_scalar_fn_concat_ws") {
     sql "INSERT INTO test_concat_ws_1 VALUES (1, ['a','b'], ['css',null,'d']), 
(2, ['x',null], ['y','z']),(3,['你好','世界'],['Doris',null,'Nereids'])"
     qt_concat_ws_insert_1 "SELECT concat_ws('-', a, b) FROM test_concat_ws_1 
ORDER BY id"
 
-}
\ No newline at end of file
+    sql "DROP TABLE IF EXISTS test_concat_ws_array_null"
+    sql "CREATE TABLE test_concat_ws_array_null (id INT, a ARRAY<VARCHAR>, b 
ARRAY<VARCHAR>, c ARRAY<VARCHAR>) ENGINE=OLAP DISTRIBUTED BY HASH(id) BUCKETS 1 
PROPERTIES ('replication_num' = '1')"
+    sql "INSERT INTO test_concat_ws_array_null VALUES (1, ['a'], NULL, ['b']), 
(2, ['a'], ['b'], ['c'])"
+    qt_concat_ws_array_null_full "SELECT id, CONCAT('[', CONCAT_WS(',', a, b, 
c), ']'), LENGTH(CONCAT_WS(',', a, b, c)) FROM test_concat_ws_array_null ORDER 
BY id"
+    qt_concat_ws_array_null_filter "SELECT id, CONCAT('[', CONCAT_WS(',', a, 
b, c), ']'), LENGTH(CONCAT_WS(',', a, b, c)) FROM test_concat_ws_array_null 
WHERE id = 1"
+
+    sql "SET disable_nereids_expression_rules = 'CONCATWS_MULTI_ARRAY_TO_ONE'"
+    test {
+        sql "SELECT CONCAT_WS(',', a, b, c) FROM test_concat_ws_array_null 
ORDER BY id"
+        exception "concat_ws with array argument expects exactly 2 arguments"
+    }
+    sql "SET disable_nereids_expression_rules = ''"
+
+}


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

Reply via email to