Coverage Report

Created: 2026-03-13 19:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/exprs/function/function_map.cpp
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 <glog/logging.h>
19
#include <stddef.h>
20
21
#include <algorithm>
22
#include <boost/iterator/iterator_facade.hpp>
23
#include <memory>
24
#include <ostream>
25
#include <string>
26
#include <string_view>
27
#include <tuple>
28
#include <utility>
29
30
#include "common/status.h"
31
#include "core/assert_cast.h"
32
#include "core/block/block.h"
33
#include "core/block/column_numbers.h"
34
#include "core/block/column_with_type_and_name.h"
35
#include "core/call_on_type_index.h"
36
#include "core/column/column.h"
37
#include "core/column/column_array.h"
38
#include "core/column/column_const.h"
39
#include "core/column/column_map.h"
40
#include "core/column/column_nullable.h"
41
#include "core/column/column_vector.h"
42
#include "core/data_type/data_type.h"
43
#include "core/data_type/data_type_array.h"
44
#include "core/data_type/data_type_map.h"
45
#include "core/data_type/data_type_nullable.h"
46
#include "core/data_type/data_type_number.h"
47
#include "core/data_type/data_type_string.h"
48
#include "core/data_type/data_type_struct.h"
49
#include "core/data_type/primitive_type.h"
50
#include "core/typeid_cast.h"
51
#include "core/types.h"
52
#include "exprs/aggregate/aggregate_function.h"
53
#include "exprs/function/array/function_array_index.h"
54
#include "exprs/function/function.h"
55
#include "exprs/function/simple_function_factory.h"
56
#include "util/simd/vstring_function.h"
57
58
namespace doris {
59
class FunctionContext;
60
} // namespace doris
61
62
namespace doris {
63
64
// construct a map
65
// map(key1, value2, key2, value2) -> {key1: value2, key2: value2}
66
class FunctionMap : public IFunction {
67
public:
68
    static constexpr auto name = "map";
69
2
    static FunctionPtr create() { return std::make_shared<FunctionMap>(); }
70
71
    /// Get function name.
72
0
    String get_name() const override { return name; }
73
74
1
    bool is_variadic() const override { return true; }
75
76
0
    bool use_default_implementation_for_nulls() const override { return false; }
77
78
0
    size_t get_number_of_arguments() const override { return 0; }
79
80
0
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
81
0
        DCHECK(arguments.size() % 2 == 0)
82
0
                << "function: " << get_name() << ", arguments should not be even number";
83
0
        return std::make_shared<DataTypeMap>(make_nullable(arguments[0]),
84
0
                                             make_nullable(arguments[1]));
85
0
    }
86
87
    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
88
0
                        uint32_t result, size_t input_rows_count) const override {
89
0
        DCHECK(arguments.size() % 2 == 0)
90
0
                << "function: " << get_name() << ", arguments should not be even number";
91
92
0
        size_t num_element = arguments.size();
93
94
0
        auto result_col = block.get_by_position(result).type->create_column();
95
0
        auto* map_column = assert_cast<ColumnMap*>(result_col.get());
96
97
        // map keys column
98
0
        auto& result_col_map_keys_data = map_column->get_keys();
99
0
        result_col_map_keys_data.reserve(input_rows_count * num_element / 2);
100
        // map values column
101
0
        auto& result_col_map_vals_data = map_column->get_values();
102
0
        result_col_map_vals_data.reserve(input_rows_count * num_element / 2);
103
        // map offsets column
104
0
        auto& result_col_map_offsets = map_column->get_offsets();
105
0
        result_col_map_offsets.resize(input_rows_count);
106
107
0
        std::unique_ptr<bool[]> col_const = std::make_unique_for_overwrite<bool[]>(num_element);
108
0
        std::vector<ColumnPtr> arg(num_element);
109
0
        for (size_t i = 0; i < num_element; ++i) {
110
0
            auto& col = block.get_by_position(arguments[i]).column;
111
0
            std::tie(col, col_const[i]) = unpack_if_const(col);
112
0
            bool is_nullable = i % 2 == 0 ? result_col_map_keys_data.is_nullable()
113
0
                                          : result_col_map_vals_data.is_nullable();
114
            // convert to nullable column
115
0
            arg[i] = col;
116
0
            if (is_nullable && !col->is_nullable()) {
117
0
                arg[i] = ColumnNullable::create(col, ColumnUInt8::create(col->size(), 0));
118
0
            }
119
0
        }
120
121
        // insert value into map
122
0
        ColumnArray::Offset64 offset = 0;
123
0
        for (size_t row = 0; row < input_rows_count; ++row) {
124
0
            for (size_t i = 0; i < num_element; i += 2) {
125
0
                result_col_map_keys_data.insert_from(*arg[i], index_check_const(row, col_const[i]));
126
0
                result_col_map_vals_data.insert_from(*arg[i + 1],
127
0
                                                     index_check_const(row, col_const[i + 1]));
128
0
            }
129
0
            offset += num_element / 2;
130
0
            result_col_map_offsets[row] = offset;
131
0
        }
132
133
0
        RETURN_IF_ERROR(map_column->deduplicate_keys());
134
0
        block.replace_by_position(result, std::move(result_col));
135
0
        return Status::OK();
136
0
    }
137
};
138
139
template <bool is_key, bool OldVersion = false>
140
class FunctionMapContains : public IFunction {
141
public:
142
    static constexpr auto name = is_key ? "map_contains_key" : "map_contains_value";
143
4
    static FunctionPtr create() { return std::make_shared<FunctionMapContains>(); }
_ZN5doris19FunctionMapContainsILb1ELb0EE6createEv
Line
Count
Source
143
2
    static FunctionPtr create() { return std::make_shared<FunctionMapContains>(); }
_ZN5doris19FunctionMapContainsILb0ELb0EE6createEv
Line
Count
Source
143
2
    static FunctionPtr create() { return std::make_shared<FunctionMapContains>(); }
144
145
    /// Get function name.
146
2
    String get_name() const override { return name; }
_ZNK5doris19FunctionMapContainsILb1ELb0EE8get_nameB5cxx11Ev
Line
Count
Source
146
1
    String get_name() const override { return name; }
_ZNK5doris19FunctionMapContainsILb0ELb0EE8get_nameB5cxx11Ev
Line
Count
Source
146
1
    String get_name() const override { return name; }
147
148
2
    bool is_variadic() const override { return false; }
_ZNK5doris19FunctionMapContainsILb1ELb0EE11is_variadicEv
Line
Count
Source
148
1
    bool is_variadic() const override { return false; }
_ZNK5doris19FunctionMapContainsILb0ELb0EE11is_variadicEv
Line
Count
Source
148
1
    bool is_variadic() const override { return false; }
149
150
0
    size_t get_number_of_arguments() const override { return 2; }
Unexecuted instantiation: _ZNK5doris19FunctionMapContainsILb1ELb0EE23get_number_of_argumentsEv
Unexecuted instantiation: _ZNK5doris19FunctionMapContainsILb0ELb0EE23get_number_of_argumentsEv
151
152
0
    bool use_default_implementation_for_nulls() const override {
153
0
        return FunctionArrayIndex<ArrayContainsAction> {}.use_default_implementation_for_nulls();
154
0
    }
Unexecuted instantiation: _ZNK5doris19FunctionMapContainsILb1ELb0EE36use_default_implementation_for_nullsEv
Unexecuted instantiation: _ZNK5doris19FunctionMapContainsILb0ELb0EE36use_default_implementation_for_nullsEv
155
156
0
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
157
0
        DataTypePtr datatype = arguments[0];
158
0
        if (datatype->is_nullable()) {
159
0
            datatype = assert_cast<const DataTypeNullable*>(datatype.get())->get_nested_type();
160
0
        }
161
0
        DCHECK(datatype->get_primitive_type() == TYPE_MAP)
162
0
                << "first argument for function: " << name << " should be DataTypeMap";
163
164
        if constexpr (OldVersion) {
165
            return make_nullable(std::make_shared<DataTypeBool>());
166
0
        } else {
167
0
            if (arguments[0]->is_nullable()) {
168
0
                return make_nullable(std::make_shared<DataTypeBool>());
169
0
            } else {
170
0
                return std::make_shared<DataTypeBool>();
171
0
            }
172
0
        }
173
0
    }
Unexecuted instantiation: _ZNK5doris19FunctionMapContainsILb1ELb0EE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS6_EE
Unexecuted instantiation: _ZNK5doris19FunctionMapContainsILb0ELb0EE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS6_EE
174
175
    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
176
0
                        uint32_t result, size_t input_rows_count) const override {
177
        // backup original argument 0
178
0
        auto orig_arg0 = block.get_by_position(arguments[0]);
179
0
        auto left_column =
180
0
                block.get_by_position(arguments[0]).column->convert_to_full_column_if_const();
181
0
        const ColumnMap* map_column = nullptr;
182
0
        ColumnPtr nullmap_column = nullptr;
183
0
        if (left_column->is_nullable()) {
184
0
            auto nullable_column = reinterpret_cast<const ColumnNullable*>(left_column.get());
185
0
            map_column = check_and_get_column<ColumnMap>(nullable_column->get_nested_column());
186
0
            nullmap_column = nullable_column->get_null_map_column_ptr();
187
0
        } else {
188
0
            map_column = check_and_get_column<ColumnMap>(*left_column.get());
189
0
        }
190
0
        if (!map_column) {
191
0
            return Status::RuntimeError("unsupported types for function {}({})", get_name(),
192
0
                                        block.get_by_position(arguments[0]).type->get_name());
193
0
        }
194
195
0
        DataTypePtr datatype = block.get_by_position(arguments[0]).type;
196
0
        if (datatype->is_nullable()) {
197
0
            datatype = assert_cast<const DataTypeNullable*>(datatype.get())->get_nested_type();
198
0
        }
199
0
        const auto datatype_map = static_cast<const DataTypeMap*>(datatype.get());
200
0
        if constexpr (is_key) {
201
0
            const auto& array_column = map_column->get_keys_array_ptr();
202
0
            const auto datatype_array =
203
0
                    std::make_shared<DataTypeArray>(datatype_map->get_key_type());
204
0
            if (nullmap_column) {
205
0
                block.get_by_position(arguments[0]) = {
206
0
                        ColumnNullable::create(array_column, nullmap_column),
207
0
                        make_nullable(datatype_array),
208
0
                        block.get_by_position(arguments[0]).name + ".keys"};
209
0
            } else {
210
0
                block.get_by_position(arguments[0]) = {
211
0
                        array_column, datatype_array,
212
0
                        block.get_by_position(arguments[0]).name + ".keys"};
213
0
            }
214
0
        } else {
215
0
            const auto& array_column = map_column->get_values_array_ptr();
216
0
            const auto datatype_array =
217
0
                    std::make_shared<DataTypeArray>(datatype_map->get_value_type());
218
0
            if (nullmap_column) {
219
0
                block.get_by_position(arguments[0]) = {
220
0
                        ColumnNullable::create(array_column, nullmap_column),
221
0
                        make_nullable(datatype_array),
222
0
                        block.get_by_position(arguments[0]).name + ".values"};
223
0
            } else {
224
0
                block.get_by_position(arguments[0]) = {
225
0
                        array_column, datatype_array,
226
0
                        block.get_by_position(arguments[0]).name + ".values"};
227
0
            }
228
0
        }
229
230
0
        RETURN_IF_ERROR(FunctionArrayIndex<ArrayContainsAction> {}.execute_impl(
231
0
                context, block, arguments, result, input_rows_count));
232
233
        // restore original argument 0
234
0
        block.get_by_position(arguments[0]) = orig_arg0;
235
0
        return Status::OK();
236
0
    }
Unexecuted instantiation: _ZNK5doris19FunctionMapContainsILb1ELb0EE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm
Unexecuted instantiation: _ZNK5doris19FunctionMapContainsILb0ELb0EE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm
237
};
238
239
template <bool is_key>
240
class FunctionMapKeysOrValues : public IFunction {
241
public:
242
    static constexpr auto name = is_key ? "map_keys" : "map_values";
243
4
    static FunctionPtr create() { return std::make_shared<FunctionMapKeysOrValues>(); }
_ZN5doris23FunctionMapKeysOrValuesILb1EE6createEv
Line
Count
Source
243
2
    static FunctionPtr create() { return std::make_shared<FunctionMapKeysOrValues>(); }
_ZN5doris23FunctionMapKeysOrValuesILb0EE6createEv
Line
Count
Source
243
2
    static FunctionPtr create() { return std::make_shared<FunctionMapKeysOrValues>(); }
244
245
    /// Get function name.
246
2
    String get_name() const override { return name; }
_ZNK5doris23FunctionMapKeysOrValuesILb1EE8get_nameB5cxx11Ev
Line
Count
Source
246
1
    String get_name() const override { return name; }
_ZNK5doris23FunctionMapKeysOrValuesILb0EE8get_nameB5cxx11Ev
Line
Count
Source
246
1
    String get_name() const override { return name; }
247
248
2
    bool is_variadic() const override { return false; }
_ZNK5doris23FunctionMapKeysOrValuesILb1EE11is_variadicEv
Line
Count
Source
248
1
    bool is_variadic() const override { return false; }
_ZNK5doris23FunctionMapKeysOrValuesILb0EE11is_variadicEv
Line
Count
Source
248
1
    bool is_variadic() const override { return false; }
249
250
0
    size_t get_number_of_arguments() const override { return 1; }
Unexecuted instantiation: _ZNK5doris23FunctionMapKeysOrValuesILb1EE23get_number_of_argumentsEv
Unexecuted instantiation: _ZNK5doris23FunctionMapKeysOrValuesILb0EE23get_number_of_argumentsEv
251
252
0
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
253
0
        DataTypePtr datatype = arguments[0];
254
0
        if (datatype->is_nullable()) {
255
0
            datatype = assert_cast<const DataTypeNullable*>(datatype.get())->get_nested_type();
256
0
        }
257
0
        DCHECK(datatype->get_primitive_type() == TYPE_MAP)
258
0
                << "first argument for function: " << name << " should be DataTypeMap";
259
0
        const auto datatype_map = static_cast<const DataTypeMap*>(datatype.get());
260
0
        if (is_key) {
261
0
            return std::make_shared<DataTypeArray>(datatype_map->get_key_type());
262
0
        } else {
263
0
            return std::make_shared<DataTypeArray>(datatype_map->get_value_type());
264
0
        }
265
0
    }
Unexecuted instantiation: _ZNK5doris23FunctionMapKeysOrValuesILb1EE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS6_EE
Unexecuted instantiation: _ZNK5doris23FunctionMapKeysOrValuesILb0EE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS6_EE
266
267
    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
268
0
                        uint32_t result, size_t input_rows_count) const override {
269
0
        auto left_column =
270
0
                block.get_by_position(arguments[0]).column->convert_to_full_column_if_const();
271
0
        const ColumnMap* map_column = nullptr;
272
0
        if (left_column->is_nullable()) {
273
0
            auto nullable_column = reinterpret_cast<const ColumnNullable*>(left_column.get());
274
0
            map_column = check_and_get_column<ColumnMap>(nullable_column->get_nested_column());
275
0
        } else {
276
0
            map_column = check_and_get_column<ColumnMap>(*left_column.get());
277
0
        }
278
0
        if (!map_column) {
279
0
            return Status::RuntimeError("unsupported types for function {}({})", get_name(),
280
0
                                        block.get_by_position(arguments[0]).type->get_name());
281
0
        }
282
283
0
        if constexpr (is_key) {
284
0
            block.replace_by_position(result, map_column->get_keys_array_ptr());
285
0
        } else {
286
0
            block.replace_by_position(result, map_column->get_values_array_ptr());
287
0
        }
288
289
0
        return Status::OK();
290
0
    }
Unexecuted instantiation: _ZNK5doris23FunctionMapKeysOrValuesILb1EE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm
Unexecuted instantiation: _ZNK5doris23FunctionMapKeysOrValuesILb0EE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm
291
};
292
293
class FunctionMapEntries : public IFunction {
294
public:
295
    static constexpr auto name = "map_entries";
296
2
    static FunctionPtr create() { return std::make_shared<FunctionMapEntries>(); }
297
298
    /// Get function name.
299
1
    String get_name() const override { return name; }
300
301
1
    bool is_variadic() const override { return false; }
302
303
0
    size_t get_number_of_arguments() const override { return 1; }
304
305
0
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
306
0
        const auto* const datatype_map = assert_cast<const DataTypeMap*>(arguments[0].get());
307
308
        // Create struct type with named fields "key" and "value"
309
        // key and value are always nullable
310
0
        auto struct_type = std::make_shared<DataTypeStruct>(
311
0
                DataTypes {make_nullable(datatype_map->get_key_type()),
312
0
                           make_nullable(datatype_map->get_value_type())},
313
0
                Strings {"key", "value"});
314
315
        // Theoretically, the struct element will never be null,
316
        // but FE expects the array element to be nullable
317
0
        return std::make_shared<DataTypeArray>(make_nullable(struct_type));
318
0
    }
319
320
    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
321
0
                        uint32_t result, size_t input_rows_count) const override {
322
0
        const auto* map_column =
323
0
                assert_cast<const ColumnMap*>(block.get_by_position(arguments[0]).column.get());
324
325
0
        auto struct_column = ColumnStruct::create(
326
0
                Columns {map_column->get_keys_ptr(), map_column->get_values_ptr()});
327
328
        // all struct elements are not null
329
0
        auto struct_null_map = ColumnUInt8::create(struct_column->size(), 0);
330
0
        auto nullable_struct_column =
331
0
                ColumnNullable::create(std::move(struct_column), std::move(struct_null_map));
332
333
0
        auto result_array_column = ColumnArray::create(std::move(nullable_struct_column),
334
0
                                                       map_column->get_offsets_ptr());
335
336
0
        block.replace_by_position(result, std::move(result_array_column));
337
338
0
        return Status::OK();
339
0
    }
340
};
341
342
class FunctionStrToMap : public IFunction {
343
public:
344
    static constexpr auto name = "str_to_map";
345
2
    static FunctionPtr create() { return std::make_shared<FunctionStrToMap>(); }
346
347
1
    String get_name() const override { return name; }
348
349
0
    size_t get_number_of_arguments() const override { return 3; }
350
351
0
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
352
0
        return std::make_shared<DataTypeMap>(make_nullable(std::make_shared<DataTypeString>()),
353
0
                                             make_nullable(std::make_shared<DataTypeString>()));
354
0
    }
355
356
    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
357
0
                        uint32_t result, size_t input_rows_count) const override {
358
0
        DCHECK(arguments.size() == 3);
359
360
0
        bool cols_const[2];
361
0
        ColumnPtr cols[2];
362
0
        for (size_t i = 0; i < 2; ++i) {
363
0
            cols_const[i] = is_column_const(*block.get_by_position(arguments[i]).column);
364
0
        }
365
        // convert to full column if necessary
366
0
        default_preprocess_parameter_columns(cols, cols_const, {0, 1}, block, arguments);
367
0
        const auto& [col3, col3_const] =
368
0
                unpack_if_const(block.get_by_position(arguments[2]).column);
369
370
0
        const auto& str_column = assert_cast<const ColumnString*>(cols[0].get());
371
0
        const auto& pair_delim_column = assert_cast<const ColumnString*>(cols[1].get());
372
0
        const auto& kv_delim_column = assert_cast<const ColumnString*>(col3.get());
373
374
0
        ColumnPtr result_col;
375
0
        if (cols_const[0] && cols_const[1]) {
376
0
            result_col = execute_vector<true, false>(input_rows_count, *str_column,
377
0
                                                     *pair_delim_column, *kv_delim_column);
378
0
        } else if (col3_const) {
379
0
            result_col = execute_vector<false, true>(input_rows_count, *str_column,
380
0
                                                     *pair_delim_column, *kv_delim_column);
381
0
        } else {
382
0
            result_col = execute_vector<false, false>(input_rows_count, *str_column,
383
0
                                                      *pair_delim_column, *kv_delim_column);
384
0
        }
385
386
0
        block.replace_by_position(result, std::move(result_col));
387
388
0
        return Status::OK();
389
0
    }
390
391
private:
392
    template <bool is_str_and_pair_delim_const, bool is_kv_delim_const>
393
    static ColumnPtr execute_vector(const size_t input_rows_count, const ColumnString& str_col,
394
                                    const ColumnString& pair_delim_col,
395
0
                                    const ColumnString& kv_delim_col) {
396
        // map keys column
397
0
        auto result_col_map_keys_data =
398
0
                ColumnNullable::create(ColumnString::create(), ColumnUInt8::create());
399
0
        result_col_map_keys_data->reserve(input_rows_count);
400
        // map values column
401
0
        auto result_col_map_vals_data =
402
0
                ColumnNullable::create(ColumnString::create(), ColumnUInt8::create());
403
0
        result_col_map_vals_data->reserve(input_rows_count);
404
        // map offsets column
405
0
        auto result_col_map_offsets = ColumnOffset64::create();
406
0
        result_col_map_offsets->reserve(input_rows_count);
407
408
0
        std::vector<std::string_view> kvs;
409
0
        std::string_view kv_delim;
410
0
        if constexpr (is_str_and_pair_delim_const) {
411
0
            auto str = str_col.get_data_at(0).to_string_view();
412
0
            auto pair_delim = pair_delim_col.get_data_at(0).to_string_view();
413
0
            kvs = split_pair_by_delim(str, pair_delim);
414
0
        }
415
0
        if constexpr (is_kv_delim_const) {
416
0
            kv_delim = kv_delim_col.get_data_at(0).to_string_view();
417
0
        }
418
419
0
        for (size_t i = 0; i < input_rows_count; ++i) {
420
0
            if constexpr (!is_str_and_pair_delim_const) {
421
0
                auto str = str_col.get_data_at(i).to_string_view();
422
0
                auto pair_delim = pair_delim_col.get_data_at(i).to_string_view();
423
0
                kvs = split_pair_by_delim(str, pair_delim);
424
0
            }
425
0
            if constexpr (!is_kv_delim_const) {
426
0
                kv_delim = kv_delim_col.get_data_at(i).to_string_view();
427
0
            }
428
429
0
            for (const auto& kv : kvs) {
430
0
                auto kv_parts = split_kv_by_delim(kv, kv_delim);
431
0
                if (kv_parts.size() == 2) {
432
0
                    result_col_map_keys_data->insert_data(kv_parts[0].data(), kv_parts[0].size());
433
0
                    result_col_map_vals_data->insert_data(kv_parts[1].data(), kv_parts[1].size());
434
0
                } else {
435
0
                    result_col_map_keys_data->insert_data(kv.data(), kv.size());
436
0
                    result_col_map_vals_data->insert_default();
437
0
                }
438
0
            }
439
0
            result_col_map_offsets->insert_value(result_col_map_keys_data->size());
440
0
        }
441
442
0
        auto map_column = ColumnMap::create(std::move(result_col_map_keys_data),
443
0
                                            std::move(result_col_map_vals_data),
444
0
                                            std::move(result_col_map_offsets));
445
446
        // `deduplicate_keys` always return ok
447
0
        static_cast<void>(map_column->deduplicate_keys());
448
0
        return map_column;
449
0
    }
Unexecuted instantiation: _ZN5doris16FunctionStrToMap14execute_vectorILb1ELb0EEENS_3COWINS_7IColumnEE13immutable_ptrIS3_EEmRKNS_9ColumnStrIjEESA_SA_
Unexecuted instantiation: _ZN5doris16FunctionStrToMap14execute_vectorILb0ELb1EEENS_3COWINS_7IColumnEE13immutable_ptrIS3_EEmRKNS_9ColumnStrIjEESA_SA_
Unexecuted instantiation: _ZN5doris16FunctionStrToMap14execute_vectorILb0ELb0EEENS_3COWINS_7IColumnEE13immutable_ptrIS3_EEmRKNS_9ColumnStrIjEESA_SA_
450
451
    static std::vector<std::string_view> split_pair_by_delim(const std::string_view& str,
452
0
                                                             const std::string_view& delim) {
453
0
        if (str.empty()) {
454
0
            return {str};
455
0
        }
456
0
        if (delim.empty()) {
457
0
            std::vector<std::string_view> result;
458
0
            size_t offset = 0;
459
0
            while (offset < str.size()) {
460
0
                auto len = get_utf8_byte_length(str[offset]);
461
0
                result.push_back(str.substr(offset, len));
462
0
                offset += len;
463
0
            }
464
0
            return result;
465
0
        }
466
0
        std::vector<std::string_view> result;
467
0
        size_t offset = 0;
468
0
        while (offset < str.size()) {
469
0
            auto pos = str.find(delim, offset);
470
0
            if (pos == std::string::npos) {
471
0
                result.push_back(str.substr(offset));
472
0
                break;
473
0
            }
474
0
            result.push_back(str.substr(offset, pos - offset));
475
0
            offset = pos + delim.size();
476
0
        }
477
0
        return result;
478
0
    }
479
480
    static std::vector<std::string_view> split_kv_by_delim(const std::string_view& str,
481
0
                                                           const std::string_view& delim) {
482
0
        if (str.empty()) {
483
0
            return {str};
484
0
        }
485
0
        if (delim.empty()) {
486
0
            auto len = get_utf8_byte_length(str[0]);
487
0
            return {str.substr(0, len), str.substr(len)};
488
0
        }
489
0
        auto pos = str.find(delim);
490
0
        if (pos == std::string::npos) {
491
0
            return {str};
492
0
        } else {
493
0
            return {str.substr(0, pos), str.substr(pos + delim.size())};
494
0
        }
495
0
    }
496
};
497
498
class FunctionMapContainsEntry : public IFunction {
499
public:
500
    static constexpr auto name = "map_contains_entry";
501
2
    static FunctionPtr create() { return std::make_shared<FunctionMapContainsEntry>(); }
502
503
1
    String get_name() const override { return name; }
504
0
    size_t get_number_of_arguments() const override { return 3; }
505
0
    bool use_default_implementation_for_nulls() const override { return false; }
506
507
0
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
508
0
        DataTypePtr datatype = arguments[0];
509
0
        if (datatype->is_nullable()) {
510
0
            datatype = assert_cast<const DataTypeNullable*>(datatype.get())->get_nested_type();
511
0
        }
512
0
        DCHECK_EQ(datatype->get_primitive_type(), PrimitiveType::TYPE_MAP)
513
0
                << "first argument for function: " << name << " should be DataTypeMap";
514
515
0
        if (arguments[0]->is_nullable()) {
516
0
            return make_nullable(std::make_shared<DataTypeBool>());
517
0
        } else {
518
0
            return std::make_shared<DataTypeBool>();
519
0
        }
520
0
    }
521
522
    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
523
0
                        uint32_t result, size_t input_rows_count) const override {
524
0
        return _execute_type_check_and_dispatch(block, arguments, result);
525
0
    }
526
527
private:
528
    // assume result_matches is initialized to all 1s
529
    template <typename ColumnType>
530
    void _execute_column_comparison(const IColumn& map_entry_column, const UInt8* map_entry_nullmap,
531
                                    const IColumn& search_column, const UInt8* search_nullmap,
532
                                    const ColumnArray::Offsets64& map_offsets,
533
                                    const UInt8* map_row_nullmap, bool search_is_const,
534
0
                                    ColumnUInt8& result_matches) const {
535
0
        auto& result_data = result_matches.get_data();
536
0
        for (size_t row = 0; row < map_offsets.size(); ++row) {
537
0
            if (map_row_nullmap && map_row_nullmap[row]) {
538
0
                continue;
539
0
            }
540
0
            size_t map_start = row == 0 ? 0 : map_offsets[row - 1];
541
0
            size_t map_end = map_offsets[row];
542
            // const column always uses index 0
543
0
            size_t search_idx = search_is_const ? 0 : row;
544
0
            for (size_t i = map_start; i < map_end; ++i) {
545
0
                result_data[i] &=
546
0
                        compare_values<ColumnType>(map_entry_column, i, map_entry_nullmap,
547
0
                                                   search_column, search_idx, search_nullmap)
548
0
                                ? 1
549
0
                                : 0;
550
0
            }
551
0
        }
552
0
    }
Unexecuted instantiation: _ZNK5doris24FunctionMapContainsEntry26_execute_column_comparisonINS_12ColumnVectorILNS_13PrimitiveTypeE2EEEEEvRKNS_7IColumnEPKhS7_S9_RKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb0EEELm16ELm15EEES9_bRS4_
Unexecuted instantiation: _ZNK5doris24FunctionMapContainsEntry26_execute_column_comparisonINS_12ColumnVectorILNS_13PrimitiveTypeE3EEEEEvRKNS_7IColumnEPKhS7_S9_RKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb0EEELm16ELm15EEES9_bRNS2_ILS3_2EEE
Unexecuted instantiation: _ZNK5doris24FunctionMapContainsEntry26_execute_column_comparisonINS_12ColumnVectorILNS_13PrimitiveTypeE4EEEEEvRKNS_7IColumnEPKhS7_S9_RKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb0EEELm16ELm15EEES9_bRNS2_ILS3_2EEE
Unexecuted instantiation: _ZNK5doris24FunctionMapContainsEntry26_execute_column_comparisonINS_12ColumnVectorILNS_13PrimitiveTypeE5EEEEEvRKNS_7IColumnEPKhS7_S9_RKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb0EEELm16ELm15EEES9_bRNS2_ILS3_2EEE
Unexecuted instantiation: _ZNK5doris24FunctionMapContainsEntry26_execute_column_comparisonINS_12ColumnVectorILNS_13PrimitiveTypeE6EEEEEvRKNS_7IColumnEPKhS7_S9_RKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb0EEELm16ELm15EEES9_bRNS2_ILS3_2EEE
Unexecuted instantiation: _ZNK5doris24FunctionMapContainsEntry26_execute_column_comparisonINS_12ColumnVectorILNS_13PrimitiveTypeE7EEEEEvRKNS_7IColumnEPKhS7_S9_RKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb0EEELm16ELm15EEES9_bRNS2_ILS3_2EEE
Unexecuted instantiation: _ZNK5doris24FunctionMapContainsEntry26_execute_column_comparisonINS_12ColumnVectorILNS_13PrimitiveTypeE8EEEEEvRKNS_7IColumnEPKhS7_S9_RKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb0EEELm16ELm15EEES9_bRNS2_ILS3_2EEE
Unexecuted instantiation: _ZNK5doris24FunctionMapContainsEntry26_execute_column_comparisonINS_12ColumnVectorILNS_13PrimitiveTypeE9EEEEEvRKNS_7IColumnEPKhS7_S9_RKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb0EEELm16ELm15EEES9_bRNS2_ILS3_2EEE
Unexecuted instantiation: _ZNK5doris24FunctionMapContainsEntry26_execute_column_comparisonINS_13ColumnDecimalILNS_13PrimitiveTypeE28EEEEEvRKNS_7IColumnEPKhS7_S9_RKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb0EEELm16ELm15EEES9_bRNS_12ColumnVectorILS3_2EEE
Unexecuted instantiation: _ZNK5doris24FunctionMapContainsEntry26_execute_column_comparisonINS_13ColumnDecimalILNS_13PrimitiveTypeE29EEEEEvRKNS_7IColumnEPKhS7_S9_RKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb0EEELm16ELm15EEES9_bRNS_12ColumnVectorILS3_2EEE
Unexecuted instantiation: _ZNK5doris24FunctionMapContainsEntry26_execute_column_comparisonINS_13ColumnDecimalILNS_13PrimitiveTypeE20EEEEEvRKNS_7IColumnEPKhS7_S9_RKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb0EEELm16ELm15EEES9_bRNS_12ColumnVectorILS3_2EEE
Unexecuted instantiation: _ZNK5doris24FunctionMapContainsEntry26_execute_column_comparisonINS_13ColumnDecimalILNS_13PrimitiveTypeE30EEEEEvRKNS_7IColumnEPKhS7_S9_RKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb0EEELm16ELm15EEES9_bRNS_12ColumnVectorILS3_2EEE
Unexecuted instantiation: _ZNK5doris24FunctionMapContainsEntry26_execute_column_comparisonINS_13ColumnDecimalILNS_13PrimitiveTypeE35EEEEEvRKNS_7IColumnEPKhS7_S9_RKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb0EEELm16ELm15EEES9_bRNS_12ColumnVectorILS3_2EEE
Unexecuted instantiation: _ZNK5doris24FunctionMapContainsEntry26_execute_column_comparisonINS_12ColumnVectorILNS_13PrimitiveTypeE11EEEEEvRKNS_7IColumnEPKhS7_S9_RKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb0EEELm16ELm15EEES9_bRNS2_ILS3_2EEE
Unexecuted instantiation: _ZNK5doris24FunctionMapContainsEntry26_execute_column_comparisonINS_12ColumnVectorILNS_13PrimitiveTypeE25EEEEEvRKNS_7IColumnEPKhS7_S9_RKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb0EEELm16ELm15EEES9_bRNS2_ILS3_2EEE
Unexecuted instantiation: _ZNK5doris24FunctionMapContainsEntry26_execute_column_comparisonINS_12ColumnVectorILNS_13PrimitiveTypeE26EEEEEvRKNS_7IColumnEPKhS7_S9_RKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb0EEELm16ELm15EEES9_bRNS2_ILS3_2EEE
Unexecuted instantiation: _ZNK5doris24FunctionMapContainsEntry26_execute_column_comparisonINS_12ColumnVectorILNS_13PrimitiveTypeE12EEEEEvRKNS_7IColumnEPKhS7_S9_RKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb0EEELm16ELm15EEES9_bRNS2_ILS3_2EEE
Unexecuted instantiation: _ZNK5doris24FunctionMapContainsEntry26_execute_column_comparisonINS_12ColumnVectorILNS_13PrimitiveTypeE27EEEEEvRKNS_7IColumnEPKhS7_S9_RKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb0EEELm16ELm15EEES9_bRNS2_ILS3_2EEE
Unexecuted instantiation: _ZNK5doris24FunctionMapContainsEntry26_execute_column_comparisonINS_12ColumnVectorILNS_13PrimitiveTypeE42EEEEEvRKNS_7IColumnEPKhS7_S9_RKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb0EEELm16ELm15EEES9_bRNS2_ILS3_2EEE
Unexecuted instantiation: _ZNK5doris24FunctionMapContainsEntry26_execute_column_comparisonINS_12ColumnVectorILNS_13PrimitiveTypeE36EEEEEvRKNS_7IColumnEPKhS7_S9_RKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb0EEELm16ELm15EEES9_bRNS2_ILS3_2EEE
Unexecuted instantiation: _ZNK5doris24FunctionMapContainsEntry26_execute_column_comparisonINS_12ColumnVectorILNS_13PrimitiveTypeE37EEEEEvRKNS_7IColumnEPKhS7_S9_RKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb0EEELm16ELm15EEES9_bRNS2_ILS3_2EEE
Unexecuted instantiation: _ZNK5doris24FunctionMapContainsEntry26_execute_column_comparisonINS_9ColumnStrIjEEEEvRKNS_7IColumnEPKhS6_S8_RKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb0EEELm16ELm15EEES8_bRNS_12ColumnVectorILNS_13PrimitiveTypeE2EEE
553
554
    // dispatch column comparison by type, map_entry_column is the column of map's key or value, search_column is the column of search key or value
555
    void _dispatch_column_comparison(PrimitiveType type, const IColumn& map_entry_column,
556
                                     const UInt8* map_entry_nullmap, const IColumn& search_column,
557
                                     const UInt8* search_nullmap,
558
                                     const ColumnArray::Offsets64& map_offsets,
559
                                     const UInt8* map_row_nullmap, bool search_is_const,
560
0
                                     ColumnUInt8& result_matches) const {
561
0
        auto call = [&](const auto& type) -> bool {
562
0
            using DispatchType = std::decay_t<decltype(type)>;
563
564
0
            _execute_column_comparison<typename DispatchType::ColumnType>(
565
0
                    map_entry_column, map_entry_nullmap, search_column, search_nullmap, map_offsets,
566
0
                    map_row_nullmap, search_is_const, result_matches);
567
568
0
            return true;
569
0
        };
Unexecuted instantiation: _ZZNK5doris24FunctionMapContainsEntry27_dispatch_column_comparisonENS_13PrimitiveTypeERKNS_7IColumnEPKhS4_S6_RKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb0EEELm16ELm15EEES6_bRNS_12ColumnVectorILS1_2EEEENKUlRKT_E_clINS_16DispatchDataTypeILS1_2EEEEEbSJ_
Unexecuted instantiation: _ZZNK5doris24FunctionMapContainsEntry27_dispatch_column_comparisonENS_13PrimitiveTypeERKNS_7IColumnEPKhS4_S6_RKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb0EEELm16ELm15EEES6_bRNS_12ColumnVectorILS1_2EEEENKUlRKT_E_clINS_16DispatchDataTypeILS1_3EEEEEbSJ_
Unexecuted instantiation: _ZZNK5doris24FunctionMapContainsEntry27_dispatch_column_comparisonENS_13PrimitiveTypeERKNS_7IColumnEPKhS4_S6_RKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb0EEELm16ELm15EEES6_bRNS_12ColumnVectorILS1_2EEEENKUlRKT_E_clINS_16DispatchDataTypeILS1_4EEEEEbSJ_
Unexecuted instantiation: _ZZNK5doris24FunctionMapContainsEntry27_dispatch_column_comparisonENS_13PrimitiveTypeERKNS_7IColumnEPKhS4_S6_RKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb0EEELm16ELm15EEES6_bRNS_12ColumnVectorILS1_2EEEENKUlRKT_E_clINS_16DispatchDataTypeILS1_5EEEEEbSJ_
Unexecuted instantiation: _ZZNK5doris24FunctionMapContainsEntry27_dispatch_column_comparisonENS_13PrimitiveTypeERKNS_7IColumnEPKhS4_S6_RKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb0EEELm16ELm15EEES6_bRNS_12ColumnVectorILS1_2EEEENKUlRKT_E_clINS_16DispatchDataTypeILS1_6EEEEEbSJ_
Unexecuted instantiation: _ZZNK5doris24FunctionMapContainsEntry27_dispatch_column_comparisonENS_13PrimitiveTypeERKNS_7IColumnEPKhS4_S6_RKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb0EEELm16ELm15EEES6_bRNS_12ColumnVectorILS1_2EEEENKUlRKT_E_clINS_16DispatchDataTypeILS1_7EEEEEbSJ_
Unexecuted instantiation: _ZZNK5doris24FunctionMapContainsEntry27_dispatch_column_comparisonENS_13PrimitiveTypeERKNS_7IColumnEPKhS4_S6_RKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb0EEELm16ELm15EEES6_bRNS_12ColumnVectorILS1_2EEEENKUlRKT_E_clINS_16DispatchDataTypeILS1_8EEEEEbSJ_
Unexecuted instantiation: _ZZNK5doris24FunctionMapContainsEntry27_dispatch_column_comparisonENS_13PrimitiveTypeERKNS_7IColumnEPKhS4_S6_RKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb0EEELm16ELm15EEES6_bRNS_12ColumnVectorILS1_2EEEENKUlRKT_E_clINS_16DispatchDataTypeILS1_9EEEEEbSJ_
Unexecuted instantiation: _ZZNK5doris24FunctionMapContainsEntry27_dispatch_column_comparisonENS_13PrimitiveTypeERKNS_7IColumnEPKhS4_S6_RKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb0EEELm16ELm15EEES6_bRNS_12ColumnVectorILS1_2EEEENKUlRKT_E_clINS_16DispatchDataTypeILS1_28EEEEEbSJ_
Unexecuted instantiation: _ZZNK5doris24FunctionMapContainsEntry27_dispatch_column_comparisonENS_13PrimitiveTypeERKNS_7IColumnEPKhS4_S6_RKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb0EEELm16ELm15EEES6_bRNS_12ColumnVectorILS1_2EEEENKUlRKT_E_clINS_16DispatchDataTypeILS1_29EEEEEbSJ_
Unexecuted instantiation: _ZZNK5doris24FunctionMapContainsEntry27_dispatch_column_comparisonENS_13PrimitiveTypeERKNS_7IColumnEPKhS4_S6_RKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb0EEELm16ELm15EEES6_bRNS_12ColumnVectorILS1_2EEEENKUlRKT_E_clINS_16DispatchDataTypeILS1_20EEEEEbSJ_
Unexecuted instantiation: _ZZNK5doris24FunctionMapContainsEntry27_dispatch_column_comparisonENS_13PrimitiveTypeERKNS_7IColumnEPKhS4_S6_RKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb0EEELm16ELm15EEES6_bRNS_12ColumnVectorILS1_2EEEENKUlRKT_E_clINS_16DispatchDataTypeILS1_30EEEEEbSJ_
Unexecuted instantiation: _ZZNK5doris24FunctionMapContainsEntry27_dispatch_column_comparisonENS_13PrimitiveTypeERKNS_7IColumnEPKhS4_S6_RKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb0EEELm16ELm15EEES6_bRNS_12ColumnVectorILS1_2EEEENKUlRKT_E_clINS_16DispatchDataTypeILS1_35EEEEEbSJ_
Unexecuted instantiation: _ZZNK5doris24FunctionMapContainsEntry27_dispatch_column_comparisonENS_13PrimitiveTypeERKNS_7IColumnEPKhS4_S6_RKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb0EEELm16ELm15EEES6_bRNS_12ColumnVectorILS1_2EEEENKUlRKT_E_clINS_16DispatchDataTypeILS1_11EEEEEbSJ_
Unexecuted instantiation: _ZZNK5doris24FunctionMapContainsEntry27_dispatch_column_comparisonENS_13PrimitiveTypeERKNS_7IColumnEPKhS4_S6_RKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb0EEELm16ELm15EEES6_bRNS_12ColumnVectorILS1_2EEEENKUlRKT_E_clINS_16DispatchDataTypeILS1_25EEEEEbSJ_
Unexecuted instantiation: _ZZNK5doris24FunctionMapContainsEntry27_dispatch_column_comparisonENS_13PrimitiveTypeERKNS_7IColumnEPKhS4_S6_RKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb0EEELm16ELm15EEES6_bRNS_12ColumnVectorILS1_2EEEENKUlRKT_E_clINS_16DispatchDataTypeILS1_26EEEEEbSJ_
Unexecuted instantiation: _ZZNK5doris24FunctionMapContainsEntry27_dispatch_column_comparisonENS_13PrimitiveTypeERKNS_7IColumnEPKhS4_S6_RKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb0EEELm16ELm15EEES6_bRNS_12ColumnVectorILS1_2EEEENKUlRKT_E_clINS_16DispatchDataTypeILS1_12EEEEEbSJ_
Unexecuted instantiation: _ZZNK5doris24FunctionMapContainsEntry27_dispatch_column_comparisonENS_13PrimitiveTypeERKNS_7IColumnEPKhS4_S6_RKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb0EEELm16ELm15EEES6_bRNS_12ColumnVectorILS1_2EEEENKUlRKT_E_clINS_16DispatchDataTypeILS1_27EEEEEbSJ_
Unexecuted instantiation: _ZZNK5doris24FunctionMapContainsEntry27_dispatch_column_comparisonENS_13PrimitiveTypeERKNS_7IColumnEPKhS4_S6_RKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb0EEELm16ELm15EEES6_bRNS_12ColumnVectorILS1_2EEEENKUlRKT_E_clINS_16DispatchDataTypeILS1_42EEEEEbSJ_
Unexecuted instantiation: _ZZNK5doris24FunctionMapContainsEntry27_dispatch_column_comparisonENS_13PrimitiveTypeERKNS_7IColumnEPKhS4_S6_RKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb0EEELm16ELm15EEES6_bRNS_12ColumnVectorILS1_2EEEENKUlRKT_E_clINS_16DispatchDataTypeILS1_36EEEEEbSJ_
Unexecuted instantiation: _ZZNK5doris24FunctionMapContainsEntry27_dispatch_column_comparisonENS_13PrimitiveTypeERKNS_7IColumnEPKhS4_S6_RKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb0EEELm16ELm15EEES6_bRNS_12ColumnVectorILS1_2EEEENKUlRKT_E_clINS_16DispatchDataTypeILS1_37EEEEEbSJ_
Unexecuted instantiation: _ZZNK5doris24FunctionMapContainsEntry27_dispatch_column_comparisonENS_13PrimitiveTypeERKNS_7IColumnEPKhS4_S6_RKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb0EEELm16ELm15EEES6_bRNS_12ColumnVectorILS1_2EEEENKUlRKT_E_clINS_16DispatchDataTypeILS1_23EEEEEbSJ_
570
571
0
        if (!dispatch_switch_all(type, call)) {
572
0
            throw doris::Exception(ErrorCode::INTERNAL_ERROR, "not support type {}",
573
0
                                   type_to_string(type));
574
0
        }
575
0
    }
576
577
    // main loop function
578
    ColumnPtr _execute_all_rows(const ColumnMap* map_column, const ColumnPtr& map_row_nullmap_col,
579
                                const IColumn& key_column, const UInt8* key_nullmap,
580
                                const IColumn& value_column, const UInt8* value_nullmap,
581
                                PrimitiveType key_type, PrimitiveType value_type, bool key_is_const,
582
0
                                bool value_is_const) const {
583
0
        const auto& map_offsets = map_column->get_offsets();
584
585
        // remove the nullable wrapper of map's key and value
586
0
        const auto& map_keys_nullable =
587
0
                reinterpret_cast<const ColumnNullable&>(map_column->get_keys());
588
0
        const IColumn* map_keys_column = &map_keys_nullable.get_nested_column();
589
0
        const auto& map_keys_nullmap = map_keys_nullable.get_null_map_column().get_data().data();
590
591
0
        const auto& map_values_nullable =
592
0
                reinterpret_cast<const ColumnNullable&>(map_column->get_values());
593
0
        const IColumn* map_values_column = &map_values_nullable.get_nested_column();
594
0
        const auto& map_values_nullmap =
595
0
                map_values_nullable.get_null_map_column().get_data().data();
596
597
0
        auto result_column = ColumnUInt8::create(map_offsets.size(), 0);
598
0
        auto& result_data = result_column->get_data();
599
600
0
        const UInt8* map_row_nullmap = nullptr;
601
0
        if (map_row_nullmap_col) {
602
0
            map_row_nullmap =
603
0
                    assert_cast<const ColumnUInt8&>(*map_row_nullmap_col).get_data().data();
604
0
        }
605
606
0
        auto matches = ColumnUInt8::create(map_keys_column->size(), 1);
607
608
        // matches &= key_compare
609
0
        _dispatch_column_comparison(key_type, *map_keys_column, map_keys_nullmap, key_column,
610
0
                                    key_nullmap, map_offsets, map_row_nullmap, key_is_const,
611
0
                                    *matches);
612
613
        // matches &= value_compare
614
0
        _dispatch_column_comparison(value_type, *map_values_column, map_values_nullmap,
615
0
                                    value_column, value_nullmap, map_offsets, map_row_nullmap,
616
0
                                    value_is_const, *matches);
617
618
        // aggregate results by map boundaries
619
0
        auto& matches_data = matches->get_data();
620
0
        for (size_t row = 0; row < map_offsets.size(); ++row) {
621
0
            if (map_row_nullmap && map_row_nullmap[row]) {
622
                // result is null for this row
623
0
                continue;
624
0
            }
625
626
0
            size_t map_start = row == 0 ? 0 : map_offsets[row - 1];
627
0
            size_t map_end = map_offsets[row];
628
629
0
            bool found = false;
630
0
            for (size_t i = map_start; i < map_end && !found; ++i) {
631
0
                if (matches_data[i]) {
632
0
                    found = true;
633
0
                    break;
634
0
                }
635
0
            }
636
0
            result_data[row] = found;
637
0
        }
638
639
0
        if (map_row_nullmap_col) {
640
0
            return ColumnNullable::create(std::move(result_column), map_row_nullmap_col);
641
0
        }
642
0
        return result_column;
643
0
    }
644
645
    // type comparability check and dispatch
646
    Status _execute_type_check_and_dispatch(Block& block, const ColumnNumbers& arguments,
647
0
                                            uint32_t result) const {
648
        // get type information
649
0
        auto map_type = remove_nullable(block.get_by_position(arguments[0]).type);
650
0
        const auto* map_datatype = assert_cast<const DataTypeMap*>(map_type.get());
651
0
        auto map_key_type = remove_nullable(map_datatype->get_key_type());
652
0
        auto map_value_type = remove_nullable(map_datatype->get_value_type());
653
0
        auto search_key_type = remove_nullable(block.get_by_position(arguments[1]).type);
654
0
        auto search_value_type = remove_nullable(block.get_by_position(arguments[2]).type);
655
656
0
        PrimitiveType key_primitive_type = map_key_type->get_primitive_type();
657
0
        PrimitiveType value_primitive_type = map_value_type->get_primitive_type();
658
659
        // FE should ensure the column types are the same,
660
        // but primitive type may be different (eg. TYPE_STRING and TYPE_VARCHAR both use ColumnString)
661
662
        // check whether this function supports equality comparison for the types
663
0
        if (!is_equality_comparison_supported(key_primitive_type) ||
664
0
            !is_equality_comparison_supported(value_primitive_type)) {
665
0
            return Status::RuntimeError(
666
0
                    "Trying to do equality comparison on unsupported types for function {}. "
667
0
                    "Map key type: {}, search key type: {}. "
668
0
                    "Map value type: {}, search value type: {}. "
669
0
                    "Key primitive type: {}, value primitive type: {}.",
670
0
                    get_name(), map_key_type->get_name(), search_key_type->get_name(),
671
0
                    map_value_type->get_name(), search_value_type->get_name(),
672
0
                    type_to_string(key_primitive_type), type_to_string(value_primitive_type));
673
0
        }
674
675
        // type check passed, extract columns and execute
676
        // extract map column
677
0
        auto map_column_ptr =
678
0
                block.get_by_position(arguments[0]).column->convert_to_full_column_if_const();
679
0
        const ColumnMap* map_column = nullptr;
680
0
        ColumnPtr map_row_nullmap_col = nullptr;
681
0
        if (map_column_ptr->is_nullable()) {
682
0
            const auto* nullable_column =
683
0
                    reinterpret_cast<const ColumnNullable*>(map_column_ptr.get());
684
0
            map_column = check_and_get_column<ColumnMap>(nullable_column->get_nested_column());
685
0
            map_row_nullmap_col = nullable_column->get_null_map_column_ptr();
686
0
        } else {
687
0
            map_column = check_and_get_column<ColumnMap>(*map_column_ptr.get());
688
0
        }
689
0
        if (!map_column) {
690
0
            return Status::RuntimeError("unsupported types for function {}({})", get_name(),
691
0
                                        block.get_by_position(arguments[0]).type->get_name());
692
0
        }
693
694
        // extract (search) key and value columns
695
0
        const auto& [key_column_ptr, key_is_const] =
696
0
                unpack_if_const(block.get_by_position(arguments[1]).column);
697
0
        const auto& [value_column_ptr, value_is_const] =
698
0
                unpack_if_const(block.get_by_position(arguments[2]).column);
699
700
0
        const IColumn* key_column = nullptr;
701
0
        const IColumn* value_column = nullptr;
702
0
        const UInt8* key_nullmap = nullptr;
703
0
        const UInt8* value_nullmap = nullptr;
704
705
0
        if (key_column_ptr->is_nullable()) {
706
0
            const auto* nullable_column = assert_cast<const ColumnNullable*>(key_column_ptr.get());
707
0
            key_column = &nullable_column->get_nested_column();
708
0
            key_nullmap = nullable_column->get_null_map_column().get_data().data();
709
0
        } else {
710
0
            key_column = key_column_ptr.get();
711
0
        }
712
713
0
        if (value_column_ptr->is_nullable()) {
714
0
            const auto* nullable_column =
715
0
                    assert_cast<const ColumnNullable*>(value_column_ptr.get());
716
0
            value_column = &nullable_column->get_nested_column();
717
0
            value_nullmap = nullable_column->get_null_map_column().get_data().data();
718
0
        } else {
719
0
            value_column = value_column_ptr.get();
720
0
        }
721
722
0
        ColumnPtr return_column =
723
0
                _execute_all_rows(map_column, map_row_nullmap_col, *key_column, key_nullmap,
724
0
                                  *value_column, value_nullmap, key_primitive_type,
725
0
                                  value_primitive_type, key_is_const, value_is_const);
726
727
0
        if (return_column) {
728
0
            block.replace_by_position(result, std::move(return_column));
729
0
            return Status::OK();
730
0
        }
731
732
0
        return Status::RuntimeError(
733
0
                "execute failed or unsupported types for function {}({}, {}, {})", get_name(),
734
0
                block.get_by_position(arguments[0]).type->get_name(),
735
0
                block.get_by_position(arguments[1]).type->get_name(),
736
0
                block.get_by_position(arguments[2]).type->get_name());
737
0
    }
738
739
    // generic type-specialized comparison function
740
    template <typename ColumnType>
741
    bool compare_values(const IColumn& left_col, size_t left_idx, const UInt8* left_nullmap,
742
                        const IColumn& right_col, size_t right_idx,
743
0
                        const UInt8* right_nullmap) const {
744
        // handle null values
745
0
        bool left_is_null = left_nullmap && left_nullmap[left_idx];
746
0
        bool right_is_null = right_nullmap && right_nullmap[right_idx];
747
748
0
        if (left_is_null && right_is_null) {
749
0
            return true;
750
0
        }
751
0
        if (left_is_null || right_is_null) {
752
0
            return false;
753
0
        }
754
755
        // use compare_at from typed column
756
0
        const auto& typed_left_col = assert_cast<const ColumnType&>(left_col);
757
0
        const auto& typed_right_col = assert_cast<const ColumnType&>(right_col);
758
0
        return typed_left_col.compare_at(left_idx, right_idx, typed_right_col,
759
0
                                         /*nan_direction_hint=*/1) == 0;
760
0
    }
Unexecuted instantiation: _ZNK5doris24FunctionMapContainsEntry14compare_valuesINS_12ColumnVectorILNS_13PrimitiveTypeE2EEEEEbRKNS_7IColumnEmPKhS7_mS9_
Unexecuted instantiation: _ZNK5doris24FunctionMapContainsEntry14compare_valuesINS_12ColumnVectorILNS_13PrimitiveTypeE3EEEEEbRKNS_7IColumnEmPKhS7_mS9_
Unexecuted instantiation: _ZNK5doris24FunctionMapContainsEntry14compare_valuesINS_12ColumnVectorILNS_13PrimitiveTypeE4EEEEEbRKNS_7IColumnEmPKhS7_mS9_
Unexecuted instantiation: _ZNK5doris24FunctionMapContainsEntry14compare_valuesINS_12ColumnVectorILNS_13PrimitiveTypeE5EEEEEbRKNS_7IColumnEmPKhS7_mS9_
Unexecuted instantiation: _ZNK5doris24FunctionMapContainsEntry14compare_valuesINS_12ColumnVectorILNS_13PrimitiveTypeE6EEEEEbRKNS_7IColumnEmPKhS7_mS9_
Unexecuted instantiation: _ZNK5doris24FunctionMapContainsEntry14compare_valuesINS_12ColumnVectorILNS_13PrimitiveTypeE7EEEEEbRKNS_7IColumnEmPKhS7_mS9_
Unexecuted instantiation: _ZNK5doris24FunctionMapContainsEntry14compare_valuesINS_12ColumnVectorILNS_13PrimitiveTypeE8EEEEEbRKNS_7IColumnEmPKhS7_mS9_
Unexecuted instantiation: _ZNK5doris24FunctionMapContainsEntry14compare_valuesINS_12ColumnVectorILNS_13PrimitiveTypeE9EEEEEbRKNS_7IColumnEmPKhS7_mS9_
Unexecuted instantiation: _ZNK5doris24FunctionMapContainsEntry14compare_valuesINS_13ColumnDecimalILNS_13PrimitiveTypeE28EEEEEbRKNS_7IColumnEmPKhS7_mS9_
Unexecuted instantiation: _ZNK5doris24FunctionMapContainsEntry14compare_valuesINS_13ColumnDecimalILNS_13PrimitiveTypeE29EEEEEbRKNS_7IColumnEmPKhS7_mS9_
Unexecuted instantiation: _ZNK5doris24FunctionMapContainsEntry14compare_valuesINS_13ColumnDecimalILNS_13PrimitiveTypeE20EEEEEbRKNS_7IColumnEmPKhS7_mS9_
Unexecuted instantiation: _ZNK5doris24FunctionMapContainsEntry14compare_valuesINS_13ColumnDecimalILNS_13PrimitiveTypeE30EEEEEbRKNS_7IColumnEmPKhS7_mS9_
Unexecuted instantiation: _ZNK5doris24FunctionMapContainsEntry14compare_valuesINS_13ColumnDecimalILNS_13PrimitiveTypeE35EEEEEbRKNS_7IColumnEmPKhS7_mS9_
Unexecuted instantiation: _ZNK5doris24FunctionMapContainsEntry14compare_valuesINS_12ColumnVectorILNS_13PrimitiveTypeE11EEEEEbRKNS_7IColumnEmPKhS7_mS9_
Unexecuted instantiation: _ZNK5doris24FunctionMapContainsEntry14compare_valuesINS_12ColumnVectorILNS_13PrimitiveTypeE25EEEEEbRKNS_7IColumnEmPKhS7_mS9_
Unexecuted instantiation: _ZNK5doris24FunctionMapContainsEntry14compare_valuesINS_12ColumnVectorILNS_13PrimitiveTypeE26EEEEEbRKNS_7IColumnEmPKhS7_mS9_
Unexecuted instantiation: _ZNK5doris24FunctionMapContainsEntry14compare_valuesINS_12ColumnVectorILNS_13PrimitiveTypeE12EEEEEbRKNS_7IColumnEmPKhS7_mS9_
Unexecuted instantiation: _ZNK5doris24FunctionMapContainsEntry14compare_valuesINS_12ColumnVectorILNS_13PrimitiveTypeE27EEEEEbRKNS_7IColumnEmPKhS7_mS9_
Unexecuted instantiation: _ZNK5doris24FunctionMapContainsEntry14compare_valuesINS_12ColumnVectorILNS_13PrimitiveTypeE42EEEEEbRKNS_7IColumnEmPKhS7_mS9_
Unexecuted instantiation: _ZNK5doris24FunctionMapContainsEntry14compare_valuesINS_12ColumnVectorILNS_13PrimitiveTypeE36EEEEEbRKNS_7IColumnEmPKhS7_mS9_
Unexecuted instantiation: _ZNK5doris24FunctionMapContainsEntry14compare_valuesINS_12ColumnVectorILNS_13PrimitiveTypeE37EEEEEbRKNS_7IColumnEmPKhS7_mS9_
Unexecuted instantiation: _ZNK5doris24FunctionMapContainsEntry14compare_valuesINS_9ColumnStrIjEEEEbRKNS_7IColumnEmPKhS6_mS8_
761
762
    // whether this function supports equality comparison for the given primitive type
763
0
    bool is_equality_comparison_supported(PrimitiveType type) const {
764
0
        return is_string_type(type) || is_number(type) || is_date_type(type) ||
765
0
               is_time_type(type) || is_ip(type);
766
0
    }
767
};
768
769
class FunctionDeduplicateMap : public IFunction {
770
public:
771
    static constexpr auto name = "deduplicate_map";
772
3
    static FunctionPtr create() { return std::make_shared<FunctionDeduplicateMap>(); }
773
774
1
    String get_name() const override { return name; }
775
1
    size_t get_number_of_arguments() const override { return 1; }
776
2
    bool use_default_implementation_for_nulls() const override { return true; }
777
778
1
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
779
1
        return arguments[0];
780
1
    }
781
782
    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
783
1
                        uint32_t result, size_t input_rows_count) const override {
784
1
        DCHECK_EQ(arguments.size(), 1);
785
1
        auto col_ptr = block.get_by_position(arguments[0]).column->clone_resized(input_rows_count);
786
1
        auto& col_map = assert_cast<ColumnMap&>(*col_ptr);
787
1
        RETURN_IF_ERROR(col_map.deduplicate_keys());
788
1
        block.replace_by_position(result, std::move(col_ptr));
789
1
        return Status::OK();
790
1
    }
791
792
private:
793
};
794
795
1
void register_function_map(SimpleFunctionFactory& factory) {
796
1
    factory.register_function<FunctionMap>();
797
1
    factory.register_function<FunctionMapContains<true>>();
798
1
    factory.register_function<FunctionMapContains<false>>();
799
1
    factory.register_function<FunctionMapKeysOrValues<true>>();
800
1
    factory.register_function<FunctionMapKeysOrValues<false>>();
801
1
    factory.register_function<FunctionMapEntries>();
802
1
    factory.register_function<FunctionStrToMap>();
803
1
    factory.register_function<FunctionMapContainsEntry>();
804
1
    factory.register_function<FunctionDeduplicateMap>();
805
1
}
806
807
} // namespace doris