Coverage Report

Created: 2026-10-28 17:14

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(const CastOptions& options, const DataTypePtr& from_type_untyped,
33
40
                                 const DataTypeArray& to_type) {
34
    /// Conversion from String through parsing.
35
40
    if (check_and_get_data_type<DataTypeString>(from_type_untyped.get())) {
36
9
        if (options.strict_mode) {
37
1
            return cast_from_string_to_complex_type_strict_mode;
38
8
        } else {
39
8
            return cast_from_string_to_complex_type;
40
8
        }
41
9
    }
42
43
31
    const auto* from_type = check_and_get_data_type<DataTypeArray>(from_type_untyped.get());
44
45
31
    if (!from_type) {
46
2
        return CastWrapper::create_unsupport_wrapper(
47
2
                "CAST AS Array can only be performed between same-dimensional Array, String "
48
2
                "types");
49
2
    }
50
51
29
    DataTypePtr from_nested_type = from_type->get_nested_type();
52
53
29
    if (from_type->get_number_of_dimensions() != to_type.get_number_of_dimensions() &&
54
29
        !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
29
    DataTypePtr to_nested_type = to_type.get_nested_type();
60
61
    /// Prepare nested type conversion
62
29
    const auto nested_function = bind_cast_executor(options, from_nested_type, to_nested_type);
63
64
29
    return [nested_function, from_nested_type, to_nested_type](
65
29
                   RuntimeState* state, const ColumnWithTypeAndName& source_column,
66
29
                   ColumnWithTypeAndName& target_column, size_t /*input_rows_count*/,
67
38
                   const NullMap::value_type* parent_null_map = nullptr) -> Status {
68
38
        const auto* from_col_array = check_and_get_column<ColumnArray>(source_column.column.get());
69
70
38
        if (from_col_array) {
71
            /// The elements of a row that is NULL are hidden payloads, so the NULL of the row has to
72
            /// be inherited by the elements that belong to it before they are cast.
73
38
            auto child_mask = build_child_null_mask(parent_null_map, &from_col_array->get_offsets(),
74
38
                                                    from_col_array->get_data_ptr());
75
38
            ColumnWithTypeAndName from_nested_column {child_mask.column, from_nested_type, ""};
76
38
            ColumnWithTypeAndName nested_result {nullptr, to_nested_type, ""};
77
38
            RETURN_IF_ERROR(nested_function(state, from_nested_column, nested_result,
78
38
                                            child_mask.column->size(), child_mask.null_map));
79
33
            target_column.column =
80
33
                    ColumnArray::create(nested_result.column, from_col_array->get_offsets_ptr());
81
33
        } else {
82
0
            return Status::RuntimeError("Illegal column {} for function CAST AS Array",
83
0
                                        source_column.column->get_name());
84
0
        }
85
33
        return Status::OK();
86
38
    };
87
29
}
88
} // namespace doris::CastWrapper