Coverage Report

Created: 2026-10-09 19:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/exprs/function/cast/cast_to_array.h
Line
Count
Source
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
18
#include "core/column/column_array.h"
19
#include "core/data_type/data_type_array.h"
20
#include "exprs/function/cast/cast_base.h"
21
22
namespace doris::CastWrapper {
23
4
inline bool has_null_literal_leaf(const DataTypePtr& type) {
24
4
    const auto type_without_nullable = remove_nullable(type);
25
4
    if (const auto* array_type =
26
4
                check_and_get_data_type<DataTypeArray>(type_without_nullable.get())) {
27
1
        return has_null_literal_leaf(array_type->get_nested_type());
28
1
    }
29
3
    return type_without_nullable->is_null_literal();
30
4
}
31
32
WrapperType create_array_wrapper(FunctionContext* context, const DataTypePtr& from_type_untyped,
33
35
                                 const DataTypeArray& to_type) {
34
    /// Conversion from String through parsing.
35
35
    if (check_and_get_data_type<DataTypeString>(from_type_untyped.get())) {
36
7
        if (context->enable_strict_mode()) {
37
0
            return cast_from_string_to_complex_type_strict_mode;
38
7
        } else {
39
7
            return cast_from_string_to_complex_type;
40
7
        }
41
7
    }
42
43
28
    const auto* from_type = check_and_get_data_type<DataTypeArray>(from_type_untyped.get());
44
45
28
    if (!from_type) {
46
1
        return CastWrapper::create_unsupport_wrapper(
47
1
                "CAST AS Array can only be performed between same-dimensional Array, String "
48
1
                "types");
49
1
    }
50
51
27
    DataTypePtr from_nested_type = from_type->get_nested_type();
52
53
27
    if (from_type->get_number_of_dimensions() != to_type.get_number_of_dimensions() &&
54
27
        !has_null_literal_leaf(from_nested_type)) {
55
0
        return CastWrapper::create_unsupport_wrapper(
56
0
                "CAST AS Array can only be performed between same-dimensional array types");
57
0
    }
58
59
27
    DataTypePtr to_nested_type = to_type.get_nested_type();
60
61
    /// Prepare nested type conversion
62
27
    const auto nested_function =
63
27
            prepare_unpack_dictionaries(context, from_nested_type, to_nested_type);
64
65
27
    return [nested_function, from_nested_type, to_nested_type](
66
27
                   FunctionContext* context, Block& block, const ColumnNumbers& arguments,
67
27
                   uint32_t result, size_t /*input_rows_count*/,
68
27
                   const NullMap::value_type* null_map = nullptr) -> Status {
69
27
        ColumnPtr from_column = block.get_by_position(arguments.front()).column;
70
71
27
        const auto* from_col_array = check_and_get_column<ColumnArray>(from_column.get());
72
73
27
        if (from_col_array) {
74
            /// The elements of a row that is NULL are hidden payloads, so the NULL of the row has to
75
            /// be inherited by the elements that belong to it before they are cast.
76
27
            auto child_mask = build_child_null_mask(null_map, &from_col_array->get_offsets(),
77
27
                                                    from_col_array->get_data_ptr());
78
            /// create columns for converting nested column containing original and result columns
79
27
            ColumnWithTypeAndName from_nested_column {child_mask.column, from_nested_type, ""};
80
81
            /// convert nested column
82
27
            ColumnNumbers new_arguments {block.columns()};
83
27
            block.insert(from_nested_column);
84
85
27
            uint32_t nested_result = block.columns();
86
27
            block.insert({to_nested_type, ""});
87
27
            RETURN_IF_ERROR(nested_function(context, block, new_arguments, nested_result,
88
27
                                            child_mask.column->size(), child_mask.null_map));
89
22
            auto nested_result_column = block.get_by_position(nested_result).column;
90
91
            /// set converted nested column to result
92
22
            block.get_by_position(result).column =
93
22
                    ColumnArray::create(nested_result_column, from_col_array->get_offsets_ptr());
94
22
        } else {
95
0
            return Status::RuntimeError("Illegal column {} for function CAST AS Array",
96
0
                                        from_column->get_name());
97
0
        }
98
22
        return Status::OK();
99
27
    };
100
27
}
101
} // namespace doris::CastWrapper