Coverage Report

Created: 2026-05-29 15:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/exprs/function/cast/cast_to_map.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_map.h"
19
#include "core/column/column_nullable.h"
20
#include "core/data_type/data_type_map.h"
21
#include "exprs/function/cast/cast_base.h"
22
23
namespace doris::CastWrapper {
24
25
3
inline Status deduplicate_map_keys_in_result(Block& block, uint32_t result) {
26
3
    auto result_column_name = block.get_by_position(result).column->get_name();
27
3
    auto mutable_result_column = IColumn::mutate(std::move(block.get_by_position(result).column));
28
29
3
    if (auto* nullable_column = check_and_get_column<ColumnNullable>(*mutable_result_column)) {
30
3
        auto nested_column = IColumn::mutate(nullable_column->get_nested_column_ptr());
31
3
        auto* map_column = check_and_get_column<ColumnMap>(*nested_column);
32
3
        if (!map_column) {
33
0
            return Status::RuntimeError("Illegal column {} for function CAST AS MAP",
34
0
                                        result_column_name);
35
0
        }
36
37
3
        RETURN_IF_ERROR(map_column->deduplicate_keys(true));
38
3
        ColumnPtr nested_column_ptr = std::move(nested_column);
39
3
        nullable_column->change_nested_column(nested_column_ptr);
40
3
    } else {
41
0
        auto* map_column = check_and_get_column<ColumnMap>(*mutable_result_column);
42
0
        if (!map_column) {
43
0
            return Status::RuntimeError("Illegal column {} for function CAST AS MAP",
44
0
                                        result_column_name);
45
0
        }
46
47
0
        RETURN_IF_ERROR(map_column->deduplicate_keys(true));
48
0
    }
49
50
3
    block.get_by_position(result).column = std::move(mutable_result_column);
51
3
    return Status::OK();
52
3
}
53
54
3
inline WrapperType wrap_string_to_map_wrapper(WrapperType wrapper) {
55
3
    return [wrapper = std::move(wrapper)](FunctionContext* context, Block& block,
56
3
                                          const ColumnNumbers& arguments, uint32_t result,
57
3
                                          size_t input_rows_count,
58
3
                                          const NullMap::value_type* null_map = nullptr) {
59
3
        RETURN_IF_ERROR(wrapper(context, block, arguments, result, input_rows_count, null_map));
60
3
        return deduplicate_map_keys_in_result(block, result);
61
3
    };
62
3
}
63
64
//TODO(Amory) . Need support more cast for key , value for map
65
WrapperType create_map_wrapper(FunctionContext* context, const DataTypePtr& from_type,
66
3
                               const DataTypeMap& to_type) {
67
3
    if (is_string_type(from_type->get_primitive_type())) {
68
3
        auto wrapper = context->enable_strict_mode() ? cast_from_string_to_complex_type_strict_mode
69
3
                                                     : cast_from_string_to_complex_type;
70
3
        return wrap_string_to_map_wrapper(wrapper);
71
3
    }
72
0
    const auto* from = check_and_get_data_type<DataTypeMap>(from_type.get());
73
0
    if (!from) {
74
0
        return CastWrapper::create_unsupport_wrapper(
75
0
                fmt::format("CAST AS Map can only be performed between Map types or from "
76
0
                            "String. from type: {}, to type: {}",
77
0
                            from_type->get_name(), to_type.get_name()));
78
0
    }
79
0
    DataTypes from_kv_types;
80
0
    DataTypes to_kv_types;
81
0
    from_kv_types.reserve(2);
82
0
    to_kv_types.reserve(2);
83
0
    from_kv_types.push_back(from->get_key_type());
84
0
    from_kv_types.push_back(from->get_value_type());
85
0
    to_kv_types.push_back(to_type.get_key_type());
86
0
    to_kv_types.push_back(to_type.get_value_type());
87
88
0
    auto kv_wrappers = get_element_wrappers(context, from_kv_types, to_kv_types);
89
0
    return [kv_wrappers, from_kv_types, to_kv_types](
90
0
                   FunctionContext* context, Block& block, const ColumnNumbers& arguments,
91
0
                   uint32_t result, size_t /*input_rows_count*/,
92
0
                   const NullMap::value_type* null_map = nullptr) -> Status {
93
0
        auto& from_column = block.get_by_position(arguments.front()).column;
94
0
        const auto* from_col_map = check_and_get_column<ColumnMap>(from_column.get());
95
0
        if (!from_col_map) {
96
0
            return Status::RuntimeError("Illegal column {} for function CAST AS MAP",
97
0
                                        from_column->get_name());
98
0
        }
99
100
0
        Columns converted_columns(2);
101
0
        ColumnsWithTypeAndName columnsWithTypeAndName(2);
102
0
        columnsWithTypeAndName[0] = {from_col_map->get_keys_ptr(), from_kv_types[0], ""};
103
0
        columnsWithTypeAndName[1] = {from_col_map->get_values_ptr(), from_kv_types[1], ""};
104
105
0
        for (size_t i = 0; i < 2; ++i) {
106
0
            ColumnNumbers element_arguments {block.columns()};
107
0
            block.insert(columnsWithTypeAndName[i]);
108
0
            auto element_result = block.columns();
109
0
            block.insert({to_kv_types[i], ""});
110
0
            RETURN_IF_ERROR(kv_wrappers[i](context, block, element_arguments, element_result,
111
0
                                           columnsWithTypeAndName[i].column->size(), null_map));
112
0
            converted_columns[i] = block.get_by_position(element_result).column;
113
0
        }
114
115
0
        auto map_column = ColumnMap::create(converted_columns[0], converted_columns[1],
116
0
                                            from_col_map->get_offsets_ptr());
117
0
        static_cast<void>(map_column->deduplicate_keys());
118
0
        block.get_by_position(result).column = std::move(map_column);
119
0
        return Status::OK();
120
0
    };
121
0
}
122
} // namespace doris::CastWrapper