Coverage Report

Created: 2026-03-17 02:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/exprs/function/array/function_array_element.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
// This file is copied from
18
// https://github.com/ClickHouse/ClickHouse/blob/master/src/Functions/array/arrayElement.cpp
19
// and modified by Doris
20
21
#pragma once
22
23
#include <glog/logging.h>
24
#include <string.h>
25
26
#include <algorithm>
27
#include <boost/iterator/iterator_facade.hpp>
28
#include <memory>
29
#include <ostream>
30
#include <string>
31
#include <utility>
32
33
#include "common/status.h"
34
#include "core/assert_cast.h"
35
#include "core/block/block.h"
36
#include "core/block/column_numbers.h"
37
#include "core/block/column_with_type_and_name.h"
38
#include "core/block/columns_with_type_and_name.h"
39
#include "core/call_on_type_index.h"
40
#include "core/column/column.h"
41
#include "core/column/column_array.h"
42
#include "core/column/column_decimal.h"
43
#include "core/column/column_map.h"
44
#include "core/column/column_nullable.h"
45
#include "core/column/column_string.h"
46
#include "core/column/column_struct.h"
47
#include "core/column/column_vector.h"
48
#include "core/data_type/data_type.h"
49
#include "core/data_type/data_type_array.h"
50
#include "core/data_type/data_type_map.h"
51
#include "core/data_type/data_type_nullable.h"
52
#include "core/data_type/data_type_number.h"
53
#include "core/data_type/primitive_type.h"
54
#include "core/types.h"
55
#include "exprs/function/function.h"
56
#include "exprs/function/function_helpers.h"
57
58
namespace doris {
59
class FunctionContext;
60
} // namespace doris
61
62
namespace doris {
63
#include "common/compile_check_begin.h"
64
65
class FunctionArrayElement : public IFunction {
66
public:
67
    /// The count of items in the map may exceed 128(Int8).
68
    using MapIndiceDataType = DataTypeInt16;
69
70
    static constexpr auto name = "element_at";
71
8
    static FunctionPtr create() { return std::make_shared<FunctionArrayElement>(); }
72
73
    /// Get function name.
74
1
    String get_name() const override { return name; }
75
76
7
    bool is_variadic() const override { return false; }
77
78
12
    bool use_default_implementation_for_nulls() const override { return false; }
79
80
6
    size_t get_number_of_arguments() const override { return 2; }
81
82
6
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
83
6
        DataTypePtr arg_0 = remove_nullable(arguments[0]);
84
6
        DCHECK(arg_0->get_primitive_type() == TYPE_ARRAY || arg_0->get_primitive_type() == TYPE_MAP)
85
0
                << "first argument for function: " << name
86
0
                << " should be DataTypeArray or DataTypeMap, but it is " << arg_0->get_name();
87
6
        if (arg_0->get_primitive_type() == TYPE_ARRAY) {
88
6
            DCHECK(is_int_or_bool(arguments[1]->get_primitive_type()))
89
0
                    << "second argument for function: " << name
90
0
                    << " should be Integer for array element";
91
6
            return make_nullable(
92
6
                    check_and_get_data_type<DataTypeArray>(arg_0.get())->get_nested_type());
93
6
        } else if (arg_0->get_primitive_type() == TYPE_MAP) {
94
0
            return make_nullable(
95
0
                    check_and_get_data_type<DataTypeMap>(arg_0.get())->get_value_type());
96
0
        } else {
97
0
            throw doris::Exception(
98
0
                    ErrorCode::INVALID_ARGUMENT,
99
0
                    fmt::format("element_at only support array and map so far, but got {}",
100
0
                                arg_0->get_name()));
101
0
        }
102
6
    }
103
104
    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
105
6
                        uint32_t result, size_t input_rows_count) const override {
106
6
        auto dst_null_column = ColumnUInt8::create(input_rows_count, 0);
107
6
        UInt8* dst_null_map = dst_null_column->get_data().data();
108
6
        const UInt8* src_null_map = nullptr;
109
6
        ColumnsWithTypeAndName args;
110
6
        block.replace_by_position(
111
6
                arguments[0],
112
6
                block.get_by_position(arguments[0]).column->convert_to_full_column_if_const());
113
6
        auto col_left = block.get_by_position(arguments[0]);
114
6
        if (col_left.column->is_nullable()) {
115
6
            auto null_col = check_and_get_column<ColumnNullable>(*col_left.column);
116
6
            src_null_map = null_col->get_null_map_column().get_data().data();
117
6
            args = {{null_col->get_nested_column_ptr(), remove_nullable(col_left.type),
118
6
                     col_left.name},
119
6
                    block.get_by_position(arguments[1])};
120
6
        } else {
121
0
            args = {col_left, block.get_by_position(arguments[1])};
122
0
        }
123
6
        ColumnPtr res_column = nullptr;
124
6
        if (is_column<ColumnMap>(args[0].column.get()) ||
125
6
            check_column_const<ColumnMap>(args[0].column.get())) {
126
0
            res_column = _execute_map(args, input_rows_count, src_null_map, dst_null_map);
127
6
        } else {
128
6
            res_column = _execute_nullable(args, input_rows_count, src_null_map, dst_null_map);
129
6
        }
130
6
        if (!res_column) {
131
0
            return Status::RuntimeError("unsupported types for function {}({}, {})", get_name(),
132
0
                                        block.get_by_position(arguments[0]).type->get_name(),
133
0
                                        block.get_by_position(arguments[1]).type->get_name());
134
0
        }
135
6
        block.replace_by_position(result,
136
6
                                  ColumnNullable::create(res_column, std::move(dst_null_column)));
137
6
        return Status::OK();
138
6
    }
139
140
private:
141
    //=========================== map element===========================//
142
    ColumnPtr _get_mapped_idx(const ColumnArray& column,
143
0
                              const ColumnWithTypeAndName& argument) const {
144
0
        auto right_column = make_nullable(argument.column->convert_to_full_column_if_const());
145
0
        const ColumnArray::Offsets64& offsets = column.get_offsets();
146
0
        ColumnPtr nested_ptr = make_nullable(column.get_data_ptr());
147
0
        size_t rows = offsets.size();
148
        // prepare return data
149
0
        auto matched_indices = ColumnVector<MapIndiceDataType::PType>::create();
150
0
        matched_indices->reserve(rows);
151
152
0
        for (size_t i = 0; i < rows; i++) {
153
0
            bool matched = false;
154
0
            size_t begin = offsets[i - 1];
155
0
            size_t end = offsets[i];
156
0
            for (size_t j = begin; j < end; j++) {
157
0
                if (nested_ptr->compare_at(j, i, *right_column, -1) == 0) {
158
0
                    matched_indices->insert_value(
159
0
                            cast_set<MapIndiceDataType::FieldType, size_t, false>(j - begin + 1));
160
0
                    matched = true;
161
0
                    break;
162
0
                }
163
0
            }
164
165
0
            if (!matched) {
166
0
                matched_indices->insert_value(cast_set<MapIndiceDataType::FieldType, size_t, false>(
167
0
                        end - begin + 1)); // make indices for null
168
0
            }
169
0
        }
170
171
0
        return matched_indices;
172
0
    }
173
174
    template <typename ColumnType>
175
    ColumnPtr _execute_number(const ColumnArray::Offsets64& offsets, const IColumn& nested_column,
176
                              const UInt8* arr_null_map, const IColumn& indices,
177
5
                              const UInt8* nested_null_map, UInt8* dst_null_map) const {
178
5
        const auto& nested_data = reinterpret_cast<const ColumnType&>(nested_column).get_data();
179
180
5
        auto dst_column = nested_column.clone_empty();
181
5
        auto& dst_data = reinterpret_cast<ColumnType&>(*dst_column).get_data();
182
5
        dst_data.resize(offsets.size());
183
184
        // process
185
50
        for (size_t row = 0; row < offsets.size(); ++row) {
186
45
            size_t off = offsets[row - 1];
187
45
            size_t len = offsets[row] - off;
188
45
            auto index = indices.get_int(row);
189
            // array is nullable
190
45
            bool null_flag = bool(arr_null_map && arr_null_map[row]);
191
            // calc index in nested column
192
45
            if (!null_flag && index > 0 && index <= len) {
193
5
                index += off - 1;
194
40
            } else if (!null_flag && index < 0 && -index <= len) {
195
10
                index += off + len;
196
30
            } else {
197
30
                null_flag = true;
198
30
            }
199
            // nested column nullable check
200
45
            if (!null_flag && nested_null_map && nested_null_map[index]) {
201
0
                null_flag = true;
202
0
            }
203
            // actual data copy
204
45
            if (null_flag) {
205
30
                dst_null_map[row] = true;
206
30
                dst_data[row] = typename ColumnType::value_type();
207
30
            } else {
208
15
                DCHECK(index >= 0 && index < nested_data.size());
209
15
                dst_null_map[row] = false;
210
15
                dst_data[row] = nested_data[index];
211
15
            }
212
45
        }
213
5
        return dst_column;
214
5
    }
Unexecuted instantiation: _ZNK5doris20FunctionArrayElement15_execute_numberINS_12ColumnVectorILNS_13PrimitiveTypeE2EEEEENS_3COWINS_7IColumnEE13immutable_ptrIS6_EERKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERKS6_PKhSI_SK_Ph
_ZNK5doris20FunctionArrayElement15_execute_numberINS_12ColumnVectorILNS_13PrimitiveTypeE3EEEEENS_3COWINS_7IColumnEE13immutable_ptrIS6_EERKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERKS6_PKhSI_SK_Ph
Line
Count
Source
177
1
                              const UInt8* nested_null_map, UInt8* dst_null_map) const {
178
1
        const auto& nested_data = reinterpret_cast<const ColumnType&>(nested_column).get_data();
179
180
1
        auto dst_column = nested_column.clone_empty();
181
1
        auto& dst_data = reinterpret_cast<ColumnType&>(*dst_column).get_data();
182
1
        dst_data.resize(offsets.size());
183
184
        // process
185
10
        for (size_t row = 0; row < offsets.size(); ++row) {
186
9
            size_t off = offsets[row - 1];
187
9
            size_t len = offsets[row] - off;
188
9
            auto index = indices.get_int(row);
189
            // array is nullable
190
9
            bool null_flag = bool(arr_null_map && arr_null_map[row]);
191
            // calc index in nested column
192
9
            if (!null_flag && index > 0 && index <= len) {
193
1
                index += off - 1;
194
8
            } else if (!null_flag && index < 0 && -index <= len) {
195
2
                index += off + len;
196
6
            } else {
197
6
                null_flag = true;
198
6
            }
199
            // nested column nullable check
200
9
            if (!null_flag && nested_null_map && nested_null_map[index]) {
201
0
                null_flag = true;
202
0
            }
203
            // actual data copy
204
9
            if (null_flag) {
205
6
                dst_null_map[row] = true;
206
6
                dst_data[row] = typename ColumnType::value_type();
207
6
            } else {
208
                DCHECK(index >= 0 && index < nested_data.size());
209
3
                dst_null_map[row] = false;
210
3
                dst_data[row] = nested_data[index];
211
3
            }
212
9
        }
213
1
        return dst_column;
214
1
    }
Unexecuted instantiation: _ZNK5doris20FunctionArrayElement15_execute_numberINS_12ColumnVectorILNS_13PrimitiveTypeE4EEEEENS_3COWINS_7IColumnEE13immutable_ptrIS6_EERKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERKS6_PKhSI_SK_Ph
_ZNK5doris20FunctionArrayElement15_execute_numberINS_12ColumnVectorILNS_13PrimitiveTypeE5EEEEENS_3COWINS_7IColumnEE13immutable_ptrIS6_EERKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERKS6_PKhSI_SK_Ph
Line
Count
Source
177
1
                              const UInt8* nested_null_map, UInt8* dst_null_map) const {
178
1
        const auto& nested_data = reinterpret_cast<const ColumnType&>(nested_column).get_data();
179
180
1
        auto dst_column = nested_column.clone_empty();
181
1
        auto& dst_data = reinterpret_cast<ColumnType&>(*dst_column).get_data();
182
1
        dst_data.resize(offsets.size());
183
184
        // process
185
10
        for (size_t row = 0; row < offsets.size(); ++row) {
186
9
            size_t off = offsets[row - 1];
187
9
            size_t len = offsets[row] - off;
188
9
            auto index = indices.get_int(row);
189
            // array is nullable
190
9
            bool null_flag = bool(arr_null_map && arr_null_map[row]);
191
            // calc index in nested column
192
9
            if (!null_flag && index > 0 && index <= len) {
193
1
                index += off - 1;
194
8
            } else if (!null_flag && index < 0 && -index <= len) {
195
2
                index += off + len;
196
6
            } else {
197
6
                null_flag = true;
198
6
            }
199
            // nested column nullable check
200
9
            if (!null_flag && nested_null_map && nested_null_map[index]) {
201
0
                null_flag = true;
202
0
            }
203
            // actual data copy
204
9
            if (null_flag) {
205
6
                dst_null_map[row] = true;
206
6
                dst_data[row] = typename ColumnType::value_type();
207
6
            } else {
208
                DCHECK(index >= 0 && index < nested_data.size());
209
3
                dst_null_map[row] = false;
210
3
                dst_data[row] = nested_data[index];
211
3
            }
212
9
        }
213
1
        return dst_column;
214
1
    }
Unexecuted instantiation: _ZNK5doris20FunctionArrayElement15_execute_numberINS_12ColumnVectorILNS_13PrimitiveTypeE6EEEEENS_3COWINS_7IColumnEE13immutable_ptrIS6_EERKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERKS6_PKhSI_SK_Ph
_ZNK5doris20FunctionArrayElement15_execute_numberINS_12ColumnVectorILNS_13PrimitiveTypeE7EEEEENS_3COWINS_7IColumnEE13immutable_ptrIS6_EERKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERKS6_PKhSI_SK_Ph
Line
Count
Source
177
1
                              const UInt8* nested_null_map, UInt8* dst_null_map) const {
178
1
        const auto& nested_data = reinterpret_cast<const ColumnType&>(nested_column).get_data();
179
180
1
        auto dst_column = nested_column.clone_empty();
181
1
        auto& dst_data = reinterpret_cast<ColumnType&>(*dst_column).get_data();
182
1
        dst_data.resize(offsets.size());
183
184
        // process
185
10
        for (size_t row = 0; row < offsets.size(); ++row) {
186
9
            size_t off = offsets[row - 1];
187
9
            size_t len = offsets[row] - off;
188
9
            auto index = indices.get_int(row);
189
            // array is nullable
190
9
            bool null_flag = bool(arr_null_map && arr_null_map[row]);
191
            // calc index in nested column
192
9
            if (!null_flag && index > 0 && index <= len) {
193
1
                index += off - 1;
194
8
            } else if (!null_flag && index < 0 && -index <= len) {
195
2
                index += off + len;
196
6
            } else {
197
6
                null_flag = true;
198
6
            }
199
            // nested column nullable check
200
9
            if (!null_flag && nested_null_map && nested_null_map[index]) {
201
0
                null_flag = true;
202
0
            }
203
            // actual data copy
204
9
            if (null_flag) {
205
6
                dst_null_map[row] = true;
206
6
                dst_data[row] = typename ColumnType::value_type();
207
6
            } else {
208
                DCHECK(index >= 0 && index < nested_data.size());
209
3
                dst_null_map[row] = false;
210
3
                dst_data[row] = nested_data[index];
211
3
            }
212
9
        }
213
1
        return dst_column;
214
1
    }
Unexecuted instantiation: _ZNK5doris20FunctionArrayElement15_execute_numberINS_12ColumnVectorILNS_13PrimitiveTypeE8EEEEENS_3COWINS_7IColumnEE13immutable_ptrIS6_EERKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERKS6_PKhSI_SK_Ph
_ZNK5doris20FunctionArrayElement15_execute_numberINS_12ColumnVectorILNS_13PrimitiveTypeE9EEEEENS_3COWINS_7IColumnEE13immutable_ptrIS6_EERKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERKS6_PKhSI_SK_Ph
Line
Count
Source
177
1
                              const UInt8* nested_null_map, UInt8* dst_null_map) const {
178
1
        const auto& nested_data = reinterpret_cast<const ColumnType&>(nested_column).get_data();
179
180
1
        auto dst_column = nested_column.clone_empty();
181
1
        auto& dst_data = reinterpret_cast<ColumnType&>(*dst_column).get_data();
182
1
        dst_data.resize(offsets.size());
183
184
        // process
185
10
        for (size_t row = 0; row < offsets.size(); ++row) {
186
9
            size_t off = offsets[row - 1];
187
9
            size_t len = offsets[row] - off;
188
9
            auto index = indices.get_int(row);
189
            // array is nullable
190
9
            bool null_flag = bool(arr_null_map && arr_null_map[row]);
191
            // calc index in nested column
192
9
            if (!null_flag && index > 0 && index <= len) {
193
1
                index += off - 1;
194
8
            } else if (!null_flag && index < 0 && -index <= len) {
195
2
                index += off + len;
196
6
            } else {
197
6
                null_flag = true;
198
6
            }
199
            // nested column nullable check
200
9
            if (!null_flag && nested_null_map && nested_null_map[index]) {
201
0
                null_flag = true;
202
0
            }
203
            // actual data copy
204
9
            if (null_flag) {
205
6
                dst_null_map[row] = true;
206
6
                dst_data[row] = typename ColumnType::value_type();
207
6
            } else {
208
                DCHECK(index >= 0 && index < nested_data.size());
209
3
                dst_null_map[row] = false;
210
3
                dst_data[row] = nested_data[index];
211
3
            }
212
9
        }
213
1
        return dst_column;
214
1
    }
Unexecuted instantiation: _ZNK5doris20FunctionArrayElement15_execute_numberINS_13ColumnDecimalILNS_13PrimitiveTypeE28EEEEENS_3COWINS_7IColumnEE13immutable_ptrIS6_EERKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERKS6_PKhSI_SK_Ph
Unexecuted instantiation: _ZNK5doris20FunctionArrayElement15_execute_numberINS_13ColumnDecimalILNS_13PrimitiveTypeE29EEEEENS_3COWINS_7IColumnEE13immutable_ptrIS6_EERKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERKS6_PKhSI_SK_Ph
_ZNK5doris20FunctionArrayElement15_execute_numberINS_13ColumnDecimalILNS_13PrimitiveTypeE20EEEEENS_3COWINS_7IColumnEE13immutable_ptrIS6_EERKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERKS6_PKhSI_SK_Ph
Line
Count
Source
177
1
                              const UInt8* nested_null_map, UInt8* dst_null_map) const {
178
1
        const auto& nested_data = reinterpret_cast<const ColumnType&>(nested_column).get_data();
179
180
1
        auto dst_column = nested_column.clone_empty();
181
1
        auto& dst_data = reinterpret_cast<ColumnType&>(*dst_column).get_data();
182
1
        dst_data.resize(offsets.size());
183
184
        // process
185
10
        for (size_t row = 0; row < offsets.size(); ++row) {
186
9
            size_t off = offsets[row - 1];
187
9
            size_t len = offsets[row] - off;
188
9
            auto index = indices.get_int(row);
189
            // array is nullable
190
9
            bool null_flag = bool(arr_null_map && arr_null_map[row]);
191
            // calc index in nested column
192
9
            if (!null_flag && index > 0 && index <= len) {
193
1
                index += off - 1;
194
8
            } else if (!null_flag && index < 0 && -index <= len) {
195
2
                index += off + len;
196
6
            } else {
197
6
                null_flag = true;
198
6
            }
199
            // nested column nullable check
200
9
            if (!null_flag && nested_null_map && nested_null_map[index]) {
201
0
                null_flag = true;
202
0
            }
203
            // actual data copy
204
9
            if (null_flag) {
205
6
                dst_null_map[row] = true;
206
6
                dst_data[row] = typename ColumnType::value_type();
207
6
            } else {
208
                DCHECK(index >= 0 && index < nested_data.size());
209
3
                dst_null_map[row] = false;
210
3
                dst_data[row] = nested_data[index];
211
3
            }
212
9
        }
213
1
        return dst_column;
214
1
    }
Unexecuted instantiation: _ZNK5doris20FunctionArrayElement15_execute_numberINS_13ColumnDecimalILNS_13PrimitiveTypeE30EEEEENS_3COWINS_7IColumnEE13immutable_ptrIS6_EERKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERKS6_PKhSI_SK_Ph
Unexecuted instantiation: _ZNK5doris20FunctionArrayElement15_execute_numberINS_13ColumnDecimalILNS_13PrimitiveTypeE35EEEEENS_3COWINS_7IColumnEE13immutable_ptrIS6_EERKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERKS6_PKhSI_SK_Ph
Unexecuted instantiation: _ZNK5doris20FunctionArrayElement15_execute_numberINS_12ColumnVectorILNS_13PrimitiveTypeE11EEEEENS_3COWINS_7IColumnEE13immutable_ptrIS6_EERKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERKS6_PKhSI_SK_Ph
Unexecuted instantiation: _ZNK5doris20FunctionArrayElement15_execute_numberINS_12ColumnVectorILNS_13PrimitiveTypeE25EEEEENS_3COWINS_7IColumnEE13immutable_ptrIS6_EERKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERKS6_PKhSI_SK_Ph
Unexecuted instantiation: _ZNK5doris20FunctionArrayElement15_execute_numberINS_12ColumnVectorILNS_13PrimitiveTypeE26EEEEENS_3COWINS_7IColumnEE13immutable_ptrIS6_EERKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERKS6_PKhSI_SK_Ph
Unexecuted instantiation: _ZNK5doris20FunctionArrayElement15_execute_numberINS_12ColumnVectorILNS_13PrimitiveTypeE12EEEEENS_3COWINS_7IColumnEE13immutable_ptrIS6_EERKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERKS6_PKhSI_SK_Ph
Unexecuted instantiation: _ZNK5doris20FunctionArrayElement15_execute_numberINS_12ColumnVectorILNS_13PrimitiveTypeE27EEEEENS_3COWINS_7IColumnEE13immutable_ptrIS6_EERKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERKS6_PKhSI_SK_Ph
Unexecuted instantiation: _ZNK5doris20FunctionArrayElement15_execute_numberINS_12ColumnVectorILNS_13PrimitiveTypeE42EEEEENS_3COWINS_7IColumnEE13immutable_ptrIS6_EERKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERKS6_PKhSI_SK_Ph
Unexecuted instantiation: _ZNK5doris20FunctionArrayElement15_execute_numberINS_12ColumnVectorILNS_13PrimitiveTypeE36EEEEENS_3COWINS_7IColumnEE13immutable_ptrIS6_EERKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERKS6_PKhSI_SK_Ph
Unexecuted instantiation: _ZNK5doris20FunctionArrayElement15_execute_numberINS_12ColumnVectorILNS_13PrimitiveTypeE37EEEEENS_3COWINS_7IColumnEE13immutable_ptrIS6_EERKNS_8PODArrayImLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERKS6_PKhSI_SK_Ph
215
216
    ColumnPtr _execute_string(const ColumnArray::Offsets64& offsets, const IColumn& nested_column,
217
                              const UInt8* arr_null_map, const IColumn& indices,
218
1
                              const UInt8* nested_null_map, UInt8* dst_null_map) const {
219
1
        const auto& src_str_offs =
220
1
                reinterpret_cast<const ColumnString&>(nested_column).get_offsets();
221
1
        const auto& src_str_chars =
222
1
                reinterpret_cast<const ColumnString&>(nested_column).get_chars();
223
224
        // prepare return data
225
1
        auto dst_column = ColumnString::create();
226
1
        auto& dst_str_offs = dst_column->get_offsets();
227
1
        dst_str_offs.resize(offsets.size());
228
1
        auto& dst_str_chars = dst_column->get_chars();
229
1
        dst_str_chars.reserve(src_str_chars.size());
230
231
        // process
232
10
        for (size_t row = 0; row < offsets.size(); ++row) {
233
9
            size_t off = offsets[row - 1];
234
9
            size_t len = offsets[row] - off;
235
9
            auto index = indices.get_int(row);
236
            // array is nullable
237
9
            bool null_flag = bool(arr_null_map && arr_null_map[row]);
238
            // calc index in nested column
239
9
            if (!null_flag && index > 0 && index <= len) {
240
2
                index += off - 1;
241
7
            } else if (!null_flag && index < 0 && -index <= len) {
242
1
                index += off + len;
243
6
            } else {
244
6
                null_flag = true;
245
6
            }
246
            // nested column nullable check
247
9
            if (!null_flag && nested_null_map && nested_null_map[index]) {
248
0
                null_flag = true;
249
0
            }
250
            // actual string copy
251
9
            if (!null_flag) {
252
3
                DCHECK(index >= 0 && index < src_str_offs.size());
253
3
                dst_null_map[row] = false;
254
3
                auto element_size = src_str_offs[index] - src_str_offs[index - 1];
255
3
                dst_str_offs[row] = dst_str_offs[row - 1] + element_size;
256
3
                auto src_string_pos = src_str_offs[index - 1];
257
3
                auto dst_string_pos = dst_str_offs[row - 1];
258
3
                dst_str_chars.resize(dst_string_pos + element_size);
259
3
                memcpy(&dst_str_chars[dst_string_pos], &src_str_chars[src_string_pos],
260
3
                       element_size);
261
6
            } else {
262
6
                dst_null_map[row] = true;
263
6
                dst_str_offs[row] = dst_str_offs[row - 1];
264
6
            }
265
9
        }
266
1
        return dst_column;
267
1
    }
268
269
    ColumnPtr _execute_map(const ColumnsWithTypeAndName& arguments, size_t input_rows_count,
270
0
                           const UInt8* src_null_map, UInt8* dst_null_map) const {
271
0
        auto left_column = arguments[0].column->convert_to_full_column_if_const();
272
0
        DataTypePtr val_type =
273
0
                reinterpret_cast<const DataTypeMap&>(*arguments[0].type).get_value_type();
274
0
        const auto& map_column = reinterpret_cast<const ColumnMap&>(*left_column);
275
276
        // create column array to find keys
277
0
        auto key_arr = ColumnArray::create(map_column.get_keys_ptr(), map_column.get_offsets_ptr());
278
0
        auto val_arr =
279
0
                ColumnArray::create(map_column.get_values_ptr(), map_column.get_offsets_ptr());
280
281
0
        ColumnPtr matched_indices = _get_mapped_idx(*key_arr, arguments[1]);
282
0
        if (!matched_indices) {
283
0
            return nullptr;
284
0
        }
285
0
        DataTypePtr indices_type(std::make_shared<MapIndiceDataType>());
286
0
        ColumnWithTypeAndName indices(matched_indices, indices_type, "indices");
287
0
        ColumnWithTypeAndName data(std::move(val_arr), std::make_shared<DataTypeArray>(val_type),
288
0
                                   "value");
289
0
        ColumnsWithTypeAndName args = {data, indices};
290
0
        return _execute_nullable(args, input_rows_count, src_null_map, dst_null_map);
291
0
    }
292
293
    ColumnPtr _execute_common(const ColumnArray::Offsets64& offsets, const IColumn& nested_column,
294
                              const UInt8* arr_null_map, const IColumn& indices,
295
0
                              const UInt8* nested_null_map, UInt8* dst_null_map) const {
296
        // prepare return data
297
0
        auto dst_column = nested_column.clone_empty();
298
0
        dst_column->reserve(offsets.size());
299
300
        // process
301
0
        for (size_t row = 0; row < offsets.size(); ++row) {
302
0
            size_t off = offsets[row - 1];
303
0
            size_t len = offsets[row] - off;
304
0
            auto index = indices.get_int(row);
305
            // array is nullable
306
0
            bool null_flag = bool(arr_null_map && arr_null_map[row]);
307
            // calc index in nested column
308
0
            if (!null_flag && index > 0 && index <= len) {
309
0
                index += off - 1;
310
0
            } else if (!null_flag && index < 0 && -index <= len) {
311
0
                index += off + len;
312
0
            } else {
313
0
                null_flag = true;
314
0
            }
315
            // nested column nullable check
316
0
            if (!null_flag && nested_null_map && nested_null_map[index]) {
317
0
                null_flag = true;
318
0
            }
319
            // actual data copy
320
0
            if (!null_flag) {
321
0
                dst_null_map[row] = false;
322
0
                dst_column->insert_from(nested_column, index);
323
0
            } else {
324
0
                dst_null_map[row] = true;
325
0
                dst_column->insert_default();
326
0
            }
327
0
        }
328
0
        return dst_column;
329
0
    }
330
331
    ColumnPtr _execute_nullable(const ColumnsWithTypeAndName& arguments, size_t input_rows_count,
332
6
                                const UInt8* src_null_map, UInt8* dst_null_map) const {
333
        // check array nested column type and get data
334
6
        auto left_column = arguments[0].column->convert_to_full_column_if_const();
335
6
        const auto& array_column = assert_cast<const ColumnArray&>(*left_column);
336
6
        const auto& offsets = array_column.get_offsets();
337
6
        DCHECK(offsets.size() == input_rows_count);
338
6
        const UInt8* nested_null_map = nullptr;
339
6
        ColumnPtr nested_column = nullptr;
340
6
        if (is_column_nullable(array_column.get_data())) {
341
6
            const auto& nested_null_column =
342
6
                    reinterpret_cast<const ColumnNullable&>(array_column.get_data());
343
6
            nested_null_map = nested_null_column.get_null_map_column().get_data().data();
344
6
            nested_column = nested_null_column.get_nested_column_ptr();
345
6
        } else {
346
0
            nested_column = array_column.get_data_ptr();
347
0
        }
348
349
6
        ColumnPtr res = nullptr;
350
6
        auto left_element_type = remove_nullable(
351
6
                assert_cast<const DataTypeArray&>(*remove_nullable(arguments[0].type))
352
6
                        .get_nested_type());
353
        // because we impl use_default_implementation_for_nulls
354
        // we should handle array index column by-self, and array index should not be nullable.
355
6
        auto idx_col = remove_nullable(arguments[1].column);
356
        // we should dispatch branch according to data type rather than column type
357
358
6
        auto call = [&](const auto& type) -> bool {
359
5
            using DispatchType = std::decay_t<decltype(type)>;
360
5
            res = _execute_number<typename DispatchType::ColumnType>(
361
5
                    offsets, *nested_column, src_null_map, *idx_col, nested_null_map, dst_null_map);
362
5
            return true;
363
5
        };
Unexecuted instantiation: _ZZNK5doris20FunctionArrayElement17_execute_nullableERKSt6vectorINS_21ColumnWithTypeAndNameESaIS2_EEmPKhPhENKUlRKT_E_clINS_16DispatchDataTypeILNS_13PrimitiveTypeE2EEEEEbSC_
_ZZNK5doris20FunctionArrayElement17_execute_nullableERKSt6vectorINS_21ColumnWithTypeAndNameESaIS2_EEmPKhPhENKUlRKT_E_clINS_16DispatchDataTypeILNS_13PrimitiveTypeE3EEEEEbSC_
Line
Count
Source
358
1
        auto call = [&](const auto& type) -> bool {
359
1
            using DispatchType = std::decay_t<decltype(type)>;
360
1
            res = _execute_number<typename DispatchType::ColumnType>(
361
1
                    offsets, *nested_column, src_null_map, *idx_col, nested_null_map, dst_null_map);
362
1
            return true;
363
1
        };
Unexecuted instantiation: _ZZNK5doris20FunctionArrayElement17_execute_nullableERKSt6vectorINS_21ColumnWithTypeAndNameESaIS2_EEmPKhPhENKUlRKT_E_clINS_16DispatchDataTypeILNS_13PrimitiveTypeE4EEEEEbSC_
_ZZNK5doris20FunctionArrayElement17_execute_nullableERKSt6vectorINS_21ColumnWithTypeAndNameESaIS2_EEmPKhPhENKUlRKT_E_clINS_16DispatchDataTypeILNS_13PrimitiveTypeE5EEEEEbSC_
Line
Count
Source
358
1
        auto call = [&](const auto& type) -> bool {
359
1
            using DispatchType = std::decay_t<decltype(type)>;
360
1
            res = _execute_number<typename DispatchType::ColumnType>(
361
1
                    offsets, *nested_column, src_null_map, *idx_col, nested_null_map, dst_null_map);
362
1
            return true;
363
1
        };
Unexecuted instantiation: _ZZNK5doris20FunctionArrayElement17_execute_nullableERKSt6vectorINS_21ColumnWithTypeAndNameESaIS2_EEmPKhPhENKUlRKT_E_clINS_16DispatchDataTypeILNS_13PrimitiveTypeE6EEEEEbSC_
_ZZNK5doris20FunctionArrayElement17_execute_nullableERKSt6vectorINS_21ColumnWithTypeAndNameESaIS2_EEmPKhPhENKUlRKT_E_clINS_16DispatchDataTypeILNS_13PrimitiveTypeE7EEEEEbSC_
Line
Count
Source
358
1
        auto call = [&](const auto& type) -> bool {
359
1
            using DispatchType = std::decay_t<decltype(type)>;
360
1
            res = _execute_number<typename DispatchType::ColumnType>(
361
1
                    offsets, *nested_column, src_null_map, *idx_col, nested_null_map, dst_null_map);
362
1
            return true;
363
1
        };
Unexecuted instantiation: _ZZNK5doris20FunctionArrayElement17_execute_nullableERKSt6vectorINS_21ColumnWithTypeAndNameESaIS2_EEmPKhPhENKUlRKT_E_clINS_16DispatchDataTypeILNS_13PrimitiveTypeE8EEEEEbSC_
_ZZNK5doris20FunctionArrayElement17_execute_nullableERKSt6vectorINS_21ColumnWithTypeAndNameESaIS2_EEmPKhPhENKUlRKT_E_clINS_16DispatchDataTypeILNS_13PrimitiveTypeE9EEEEEbSC_
Line
Count
Source
358
1
        auto call = [&](const auto& type) -> bool {
359
1
            using DispatchType = std::decay_t<decltype(type)>;
360
1
            res = _execute_number<typename DispatchType::ColumnType>(
361
1
                    offsets, *nested_column, src_null_map, *idx_col, nested_null_map, dst_null_map);
362
1
            return true;
363
1
        };
Unexecuted instantiation: _ZZNK5doris20FunctionArrayElement17_execute_nullableERKSt6vectorINS_21ColumnWithTypeAndNameESaIS2_EEmPKhPhENKUlRKT_E_clINS_16DispatchDataTypeILNS_13PrimitiveTypeE28EEEEEbSC_
Unexecuted instantiation: _ZZNK5doris20FunctionArrayElement17_execute_nullableERKSt6vectorINS_21ColumnWithTypeAndNameESaIS2_EEmPKhPhENKUlRKT_E_clINS_16DispatchDataTypeILNS_13PrimitiveTypeE29EEEEEbSC_
_ZZNK5doris20FunctionArrayElement17_execute_nullableERKSt6vectorINS_21ColumnWithTypeAndNameESaIS2_EEmPKhPhENKUlRKT_E_clINS_16DispatchDataTypeILNS_13PrimitiveTypeE20EEEEEbSC_
Line
Count
Source
358
1
        auto call = [&](const auto& type) -> bool {
359
1
            using DispatchType = std::decay_t<decltype(type)>;
360
1
            res = _execute_number<typename DispatchType::ColumnType>(
361
1
                    offsets, *nested_column, src_null_map, *idx_col, nested_null_map, dst_null_map);
362
1
            return true;
363
1
        };
Unexecuted instantiation: _ZZNK5doris20FunctionArrayElement17_execute_nullableERKSt6vectorINS_21ColumnWithTypeAndNameESaIS2_EEmPKhPhENKUlRKT_E_clINS_16DispatchDataTypeILNS_13PrimitiveTypeE30EEEEEbSC_
Unexecuted instantiation: _ZZNK5doris20FunctionArrayElement17_execute_nullableERKSt6vectorINS_21ColumnWithTypeAndNameESaIS2_EEmPKhPhENKUlRKT_E_clINS_16DispatchDataTypeILNS_13PrimitiveTypeE35EEEEEbSC_
Unexecuted instantiation: _ZZNK5doris20FunctionArrayElement17_execute_nullableERKSt6vectorINS_21ColumnWithTypeAndNameESaIS2_EEmPKhPhENKUlRKT_E_clINS_16DispatchDataTypeILNS_13PrimitiveTypeE11EEEEEbSC_
Unexecuted instantiation: _ZZNK5doris20FunctionArrayElement17_execute_nullableERKSt6vectorINS_21ColumnWithTypeAndNameESaIS2_EEmPKhPhENKUlRKT_E_clINS_16DispatchDataTypeILNS_13PrimitiveTypeE25EEEEEbSC_
Unexecuted instantiation: _ZZNK5doris20FunctionArrayElement17_execute_nullableERKSt6vectorINS_21ColumnWithTypeAndNameESaIS2_EEmPKhPhENKUlRKT_E_clINS_16DispatchDataTypeILNS_13PrimitiveTypeE26EEEEEbSC_
Unexecuted instantiation: _ZZNK5doris20FunctionArrayElement17_execute_nullableERKSt6vectorINS_21ColumnWithTypeAndNameESaIS2_EEmPKhPhENKUlRKT_E_clINS_16DispatchDataTypeILNS_13PrimitiveTypeE12EEEEEbSC_
Unexecuted instantiation: _ZZNK5doris20FunctionArrayElement17_execute_nullableERKSt6vectorINS_21ColumnWithTypeAndNameESaIS2_EEmPKhPhENKUlRKT_E_clINS_16DispatchDataTypeILNS_13PrimitiveTypeE27EEEEEbSC_
Unexecuted instantiation: _ZZNK5doris20FunctionArrayElement17_execute_nullableERKSt6vectorINS_21ColumnWithTypeAndNameESaIS2_EEmPKhPhENKUlRKT_E_clINS_16DispatchDataTypeILNS_13PrimitiveTypeE42EEEEEbSC_
Unexecuted instantiation: _ZZNK5doris20FunctionArrayElement17_execute_nullableERKSt6vectorINS_21ColumnWithTypeAndNameESaIS2_EEmPKhPhENKUlRKT_E_clINS_16DispatchDataTypeILNS_13PrimitiveTypeE36EEEEEbSC_
Unexecuted instantiation: _ZZNK5doris20FunctionArrayElement17_execute_nullableERKSt6vectorINS_21ColumnWithTypeAndNameESaIS2_EEmPKhPhENKUlRKT_E_clINS_16DispatchDataTypeILNS_13PrimitiveTypeE37EEEEEbSC_
364
365
6
        if (is_string_type(left_element_type->get_primitive_type())) {
366
1
            res = _execute_string(offsets, *nested_column, src_null_map, *idx_col, nested_null_map,
367
1
                                  dst_null_map);
368
5
        } else if (!dispatch_switch_scalar(left_element_type->get_primitive_type(), call)) {
369
0
            res = _execute_common(offsets, *nested_column, src_null_map, *idx_col, nested_null_map,
370
0
                                  dst_null_map);
371
0
        }
372
6
        return res;
373
6
    }
374
};
375
376
#include "common/compile_check_end.h"
377
} // namespace doris