Coverage Report

Created: 2026-08-20 04:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/exprs/function/function_ip.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/FunctionsCodingIP.cpp
19
// and modified by Doris
20
21
#pragma once
22
#include <glog/logging.h>
23
24
#include <cstddef>
25
#include <memory>
26
27
#include "common/cast_set.h"
28
#include "core/assert_cast.h"
29
#include "core/block/column_with_type_and_name.h"
30
#include "core/column/column.h"
31
#include "core/column/column_const.h"
32
#include "core/column/column_nullable.h"
33
#include "core/column/column_string.h"
34
#include "core/column/column_struct.h"
35
#include "core/column/column_vector.h"
36
#include "core/data_type/data_type.h"
37
#include "core/data_type/data_type_ipv4.h"
38
#include "core/data_type/data_type_ipv6.h"
39
#include "core/data_type/data_type_nullable.h"
40
#include "core/data_type/data_type_number.h"
41
#include "core/data_type/data_type_string.h"
42
#include "core/data_type/data_type_struct.h"
43
#include "core/field.h"
44
#include "core/types.h"
45
#include "core/value/ip_address_cidr.h"
46
#include "exec/common/endian.h"
47
#include "exec/common/format_ip.h"
48
#include "exec/common/ipv6_to_binary.h"
49
#include "exprs/function/function.h"
50
#include "exprs/function/function_helpers.h"
51
#include "storage/index/index_reader_helper.h"
52
#include "storage/index/inverted/inverted_index_iterator.h"
53
54
namespace doris {
55
56
class FunctionIPv4NumToString : public IFunction {
57
private:
58
    template <PrimitiveType ArgPType>
59
0
    Status execute_type(Block& block, const ColumnWithTypeAndName& argument, size_t result) const {
60
0
        using ColumnType = ColumnVector<ArgPType>;
61
0
        const ColumnPtr& column = argument.column;
62
63
0
        const auto* col = assert_cast<const ColumnType*>(column.get());
64
0
        const typename ColumnType::Container& vec_in = col->get_data();
65
0
        auto col_res = ColumnString::create();
66
67
0
        ColumnString::Chars& vec_res = col_res->get_chars();
68
0
        ColumnString::Offsets& offsets_res = col_res->get_offsets();
69
70
0
        vec_res.resize(vec_in.size() *
71
0
                       (IPV4_MAX_TEXT_LENGTH + 1)); /// the longest value is: 255.255.255.255\0
72
0
        offsets_res.resize(vec_in.size());
73
0
        char* begin = reinterpret_cast<char*>(vec_res.data());
74
0
        char* pos = begin;
75
76
0
        auto null_map = ColumnUInt8::create(vec_in.size(), 0);
77
0
        size_t src_size =
78
0
                std::min(sizeof(typename PrimitiveTypeTraits<ArgPType>::CppType), (unsigned long)4);
79
0
        for (size_t i = 0; i < vec_in.size(); ++i) {
80
0
            auto value = vec_in[i];
81
0
            if (value < IPV4_MIN_NUM_VALUE || value > IPV4_MAX_NUM_VALUE) {
82
0
                null_map->get_data()[i] = 1;
83
0
            } else {
84
0
                format_ipv4(reinterpret_cast<const unsigned char*>(&vec_in[i]), src_size, pos);
85
0
            }
86
0
            offsets_res[i] = cast_set<uint32_t>(pos - begin);
87
0
        }
88
89
0
        vec_res.resize(pos - begin);
90
0
        block.replace_by_position(result,
91
0
                                  ColumnNullable::create(std::move(col_res), std::move(null_map)));
92
0
        return Status::OK();
93
0
    }
Unexecuted instantiation: _ZNK5doris23FunctionIPv4NumToString12execute_typeILNS_13PrimitiveTypeE3EEENS_6StatusERNS_5BlockERKNS_21ColumnWithTypeAndNameEm
Unexecuted instantiation: _ZNK5doris23FunctionIPv4NumToString12execute_typeILNS_13PrimitiveTypeE4EEENS_6StatusERNS_5BlockERKNS_21ColumnWithTypeAndNameEm
Unexecuted instantiation: _ZNK5doris23FunctionIPv4NumToString12execute_typeILNS_13PrimitiveTypeE5EEENS_6StatusERNS_5BlockERKNS_21ColumnWithTypeAndNameEm
Unexecuted instantiation: _ZNK5doris23FunctionIPv4NumToString12execute_typeILNS_13PrimitiveTypeE6EEENS_6StatusERNS_5BlockERKNS_21ColumnWithTypeAndNameEm
94
95
public:
96
    static constexpr auto name = "ipv4_num_to_string";
97
2
    static FunctionPtr create() { return std::make_shared<FunctionIPv4NumToString>(); }
98
99
1
    String get_name() const override { return name; }
100
101
0
    size_t get_number_of_arguments() const override { return 1; }
102
103
0
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
104
0
        return make_nullable(std::make_shared<DataTypeString>());
105
0
    }
106
107
    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
108
0
                        uint32_t result, size_t input_rows_count) const override {
109
0
        ColumnWithTypeAndName& argument = block.get_by_position(arguments[0]);
110
111
0
        switch (argument.type->get_primitive_type()) {
112
0
        case PrimitiveType::TYPE_TINYINT:
113
0
            return execute_type<TYPE_TINYINT>(block, argument, result);
114
0
            break;
115
0
        case PrimitiveType::TYPE_SMALLINT:
116
0
            return execute_type<TYPE_SMALLINT>(block, argument, result);
117
0
            break;
118
0
        case PrimitiveType::TYPE_INT:
119
0
            return execute_type<TYPE_INT>(block, argument, result);
120
0
            break;
121
0
        case PrimitiveType::TYPE_BIGINT:
122
0
            return execute_type<TYPE_BIGINT>(block, argument, result);
123
0
            break;
124
0
        default:
125
0
            break;
126
0
        }
127
128
0
        return Status::InternalError(
129
0
                "Illegal column {} of argument of function {}, expected Int8 or Int16 or Int32 or "
130
0
                "Int64",
131
0
                argument.name, get_name());
132
0
    }
133
};
134
135
/// Since IPExceptionMode means wider scope, we use more specific name here.
136
enum class IPConvertExceptionMode : uint8_t { Throw, Default, Null };
137
138
1
static inline bool try_parse_ipv4(const char* pos, Int64& result_value) {
139
1
    return parse_ipv4_whole(pos, reinterpret_cast<unsigned char*>(&result_value));
140
1
}
column_ip_test.cpp:_ZN5dorisL14try_parse_ipv4EPKcRl
Line
Count
Source
138
1
static inline bool try_parse_ipv4(const char* pos, Int64& result_value) {
139
1
    return parse_ipv4_whole(pos, reinterpret_cast<unsigned char*>(&result_value));
140
1
}
Unexecuted instantiation: function_ip_test.cpp:_ZN5dorisL14try_parse_ipv4EPKcRl
Unexecuted instantiation: unity_18_cxx.cxx:_ZN5dorisL14try_parse_ipv4EPKcRl
141
142
template <IPConvertExceptionMode exception_mode, typename ToColumn>
143
0
ColumnPtr convert_to_ipv4(ColumnPtr column, const PaddedPODArray<UInt8>* null_map = nullptr) {
144
0
    const auto* column_string = assert_cast<const ColumnString*>(column.get());
145
146
0
    size_t column_size = column_string->size();
147
148
0
    ColumnUInt8::MutablePtr col_null_map_to;
149
0
    ColumnUInt8::Container* vec_null_map_to = nullptr;
150
151
0
    if constexpr (exception_mode == IPConvertExceptionMode::Null) {
152
0
        col_null_map_to = ColumnUInt8::create(column_size, false);
153
0
        vec_null_map_to = &col_null_map_to->get_data();
154
0
    }
155
156
0
    auto col_res = ToColumn::create(column_size, 0);
157
0
    auto& vec_res = col_res->get_data();
158
159
0
    const ColumnString::Chars& vec_src = column_string->get_chars();
160
0
    const ColumnString::Offsets& offsets_src = column_string->get_offsets();
161
0
    size_t prev_offset = 0;
162
163
0
    for (size_t i = 0; i < vec_res.size(); ++i) {
164
0
        if (null_map && (*null_map)[i]) {
165
0
            if constexpr (exception_mode == IPConvertExceptionMode::Throw) {
166
0
                throw Exception(
167
0
                        ErrorCode::INVALID_ARGUMENT,
168
0
                        "Null Input, you may consider convert it to a valid default IPv4 value "
169
0
                        "like '0.0.0.0' first");
170
0
            }
171
0
            vec_res[i] = 0;
172
0
            prev_offset = offsets_src[i];
173
0
            if constexpr (exception_mode == IPConvertExceptionMode::Null) {
174
0
                (*vec_null_map_to)[i] = true;
175
0
            }
176
0
            continue;
177
0
        }
178
0
        const char* src_start = reinterpret_cast<const char*>(&vec_src[prev_offset]);
179
0
        size_t src_length = (i < vec_res.size() - 1) ? (offsets_src[i] - prev_offset)
180
0
                                                     : (vec_src.size() - prev_offset);
181
0
        std::string src(src_start, src_length);
182
0
        bool parse_result = try_parse_ipv4(src.c_str(), vec_res[i]);
183
184
0
        if (!parse_result) {
185
0
            if constexpr (exception_mode == IPConvertExceptionMode::Throw) {
186
0
                throw Exception(ErrorCode::INVALID_ARGUMENT, "Invalid IPv4 value");
187
0
            } else if constexpr (exception_mode == IPConvertExceptionMode::Default) {
188
0
                vec_res[i] = 0;
189
0
            } else if constexpr (exception_mode == IPConvertExceptionMode::Null) {
190
0
                (*vec_null_map_to)[i] = true;
191
0
                vec_res[i] = 0;
192
0
            }
193
0
        }
194
195
0
        prev_offset = offsets_src[i];
196
0
    }
197
198
0
    if constexpr (exception_mode == IPConvertExceptionMode::Null) {
199
0
        return ColumnNullable::create(std::move(col_res), std::move(col_null_map_to));
200
0
    }
201
0
    return col_res;
202
0
}
Unexecuted instantiation: _ZN5doris15convert_to_ipv4ILNS_22IPConvertExceptionModeE0ENS_12ColumnVectorILNS_13PrimitiveTypeE6EEEEENS_3COWINS_7IColumnEE13immutable_ptrIS6_EES9_PKNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEE
Unexecuted instantiation: _ZN5doris15convert_to_ipv4ILNS_22IPConvertExceptionModeE1ENS_12ColumnVectorILNS_13PrimitiveTypeE6EEEEENS_3COWINS_7IColumnEE13immutable_ptrIS6_EES9_PKNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEE
Unexecuted instantiation: _ZN5doris15convert_to_ipv4ILNS_22IPConvertExceptionModeE2ENS_12ColumnVectorILNS_13PrimitiveTypeE6EEEEENS_3COWINS_7IColumnEE13immutable_ptrIS6_EES9_PKNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEE
203
204
template <IPConvertExceptionMode exception_mode>
205
class FunctionIPv4StringToNum : public IFunction {
206
public:
207
    static constexpr auto name = exception_mode == IPConvertExceptionMode::Throw
208
                                         ? "ipv4_string_to_num"
209
                                         : (exception_mode == IPConvertExceptionMode::Default
210
                                                    ? "ipv4_string_to_num_or_default"
211
                                                    : "ipv4_string_to_num_or_null");
212
213
6
    static FunctionPtr create() {
214
6
        return std::make_shared<FunctionIPv4StringToNum<exception_mode>>();
215
6
    }
_ZN5doris23FunctionIPv4StringToNumILNS_22IPConvertExceptionModeE0EE6createEv
Line
Count
Source
213
2
    static FunctionPtr create() {
214
2
        return std::make_shared<FunctionIPv4StringToNum<exception_mode>>();
215
2
    }
_ZN5doris23FunctionIPv4StringToNumILNS_22IPConvertExceptionModeE1EE6createEv
Line
Count
Source
213
2
    static FunctionPtr create() {
214
2
        return std::make_shared<FunctionIPv4StringToNum<exception_mode>>();
215
2
    }
_ZN5doris23FunctionIPv4StringToNumILNS_22IPConvertExceptionModeE2EE6createEv
Line
Count
Source
213
2
    static FunctionPtr create() {
214
2
        return std::make_shared<FunctionIPv4StringToNum<exception_mode>>();
215
2
    }
216
217
3
    String get_name() const override { return name; }
_ZNK5doris23FunctionIPv4StringToNumILNS_22IPConvertExceptionModeE0EE8get_nameB5cxx11Ev
Line
Count
Source
217
1
    String get_name() const override { return name; }
_ZNK5doris23FunctionIPv4StringToNumILNS_22IPConvertExceptionModeE1EE8get_nameB5cxx11Ev
Line
Count
Source
217
1
    String get_name() const override { return name; }
_ZNK5doris23FunctionIPv4StringToNumILNS_22IPConvertExceptionModeE2EE8get_nameB5cxx11Ev
Line
Count
Source
217
1
    String get_name() const override { return name; }
218
219
0
    size_t get_number_of_arguments() const override { return 1; }
Unexecuted instantiation: _ZNK5doris23FunctionIPv4StringToNumILNS_22IPConvertExceptionModeE0EE23get_number_of_argumentsEv
Unexecuted instantiation: _ZNK5doris23FunctionIPv4StringToNumILNS_22IPConvertExceptionModeE1EE23get_number_of_argumentsEv
Unexecuted instantiation: _ZNK5doris23FunctionIPv4StringToNumILNS_22IPConvertExceptionModeE2EE23get_number_of_argumentsEv
220
221
0
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
222
0
        auto result_type = std::make_shared<DataTypeInt64>();
223
224
0
        if constexpr (exception_mode == IPConvertExceptionMode::Null) {
225
0
            return make_nullable(result_type);
226
0
        }
227
228
0
        return result_type;
229
0
    }
Unexecuted instantiation: _ZNK5doris23FunctionIPv4StringToNumILNS_22IPConvertExceptionModeE0EE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS7_EE
Unexecuted instantiation: _ZNK5doris23FunctionIPv4StringToNumILNS_22IPConvertExceptionModeE1EE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS7_EE
Unexecuted instantiation: _ZNK5doris23FunctionIPv4StringToNumILNS_22IPConvertExceptionModeE2EE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS7_EE
230
231
0
    bool use_default_implementation_for_nulls() const override { return false; }
Unexecuted instantiation: _ZNK5doris23FunctionIPv4StringToNumILNS_22IPConvertExceptionModeE0EE36use_default_implementation_for_nullsEv
Unexecuted instantiation: _ZNK5doris23FunctionIPv4StringToNumILNS_22IPConvertExceptionModeE1EE36use_default_implementation_for_nullsEv
Unexecuted instantiation: _ZNK5doris23FunctionIPv4StringToNumILNS_22IPConvertExceptionModeE2EE36use_default_implementation_for_nullsEv
232
233
    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
234
0
                        uint32_t result, size_t input_rows_count) const override {
235
0
        ColumnPtr column =
236
0
                block.get_by_position(arguments[0]).column->convert_to_full_column_if_const();
237
0
        ColumnPtr null_map_column;
238
0
        const NullMap* null_map = nullptr;
239
0
        if (const auto* column_nullable = check_and_get_column<ColumnNullable>(column.get())) {
240
0
            column = column_nullable->get_nested_column_ptr();
241
0
            null_map_column = column_nullable->get_null_map_column_ptr();
242
0
            null_map = &column_nullable->get_null_map_data();
243
0
        }
244
245
0
        auto col_res = convert_to_ipv4<exception_mode, ColumnInt64>(column, null_map);
246
247
0
        if (null_map && exception_mode == IPConvertExceptionMode::Null) {
248
0
            block.replace_by_position(
249
0
                    result, ColumnNullable::create(std::move(col_res), std::move(null_map_column)));
250
0
        } else {
251
0
            block.replace_by_position(result, std::move(col_res));
252
0
        }
253
0
        return Status::OK();
254
0
    }
Unexecuted instantiation: _ZNK5doris23FunctionIPv4StringToNumILNS_22IPConvertExceptionModeE0EE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm
Unexecuted instantiation: _ZNK5doris23FunctionIPv4StringToNumILNS_22IPConvertExceptionModeE1EE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm
Unexecuted instantiation: _ZNK5doris23FunctionIPv4StringToNumILNS_22IPConvertExceptionModeE2EE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm
255
};
256
257
template <typename T>
258
void process_ipv6_column(const ColumnPtr& column, size_t input_rows_count,
259
                         ColumnString::Chars& vec_res, ColumnString::Offsets& offsets_res,
260
0
                         ColumnUInt8::MutablePtr& null_map, unsigned char* ipv6_address_data) {
261
0
    auto* begin = reinterpret_cast<char*>(vec_res.data());
262
0
    auto* pos = begin;
263
264
0
    const auto* col = assert_cast<const T*>(column.get());
265
266
0
    for (size_t i = 0; i < input_rows_count; ++i) {
267
0
        bool is_empty = false;
268
269
0
        if constexpr (std::is_same_v<T, ColumnIPv6>) {
270
0
            const auto& vec_in = col->get_data();
271
0
            memcpy(ipv6_address_data, reinterpret_cast<const unsigned char*>(&vec_in[i]),
272
0
                   IPV6_BINARY_LENGTH);
273
0
        } else { // ColumnString
274
0
            const auto str_ref = col->get_data_at(i);
275
0
            const char* value = str_ref.data;
276
0
            size_t value_size = str_ref.size;
277
278
0
            if (value_size > IPV6_BINARY_LENGTH || value == nullptr || value_size == 0) {
279
0
                is_empty = true;
280
0
            } else {
281
0
                memcpy(ipv6_address_data, value, value_size);
282
0
                memset(ipv6_address_data + value_size, 0, IPV6_BINARY_LENGTH - value_size);
283
0
            }
284
0
        }
285
286
0
        if (is_empty) {
287
0
            null_map->get_data()[i] = 1;
288
0
        } else {
289
0
            if constexpr (std::is_same_v<T, ColumnIPv6>) {
290
                // ipv6 is little-endian byte order storage in doris
291
                // so parsing ipv6 in little-endian byte order
292
0
                format_ipv6(ipv6_address_data, pos);
293
0
            } else {
294
                // 16 bytes ipv6 string is big-endian byte order storage in doris
295
                // so transfer to little-endian firstly
296
0
                std::reverse(ipv6_address_data, ipv6_address_data + IPV6_BINARY_LENGTH);
297
0
                format_ipv6(ipv6_address_data, pos);
298
0
            }
299
0
        }
300
0
        offsets_res[i] = cast_set<uint32_t>(pos - begin);
301
0
    }
302
0
}
Unexecuted instantiation: _ZN5doris19process_ipv6_columnINS_12ColumnVectorILNS_13PrimitiveTypeE37EEEEEvRKNS_3COWINS_7IColumnEE13immutable_ptrIS5_EEmRNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERNSB_IjLm4096ESE_Lm16ELm15EEERNS6_11mutable_ptrINS1_ILS2_2EEEEEPh
Unexecuted instantiation: _ZN5doris19process_ipv6_columnINS_9ColumnStrIjEEEEvRKNS_3COWINS_7IColumnEE13immutable_ptrIS4_EEmRNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERNSA_IjLm4096ESD_Lm16ELm15EEERNS5_11mutable_ptrINS_12ColumnVectorILNS_13PrimitiveTypeE2EEEEEPh
303
304
class FunctionIPv6NumToString : public IFunction {
305
public:
306
    static constexpr auto name = "ipv6_num_to_string";
307
2
    static FunctionPtr create() { return std::make_shared<FunctionIPv6NumToString>(); }
308
309
1
    String get_name() const override { return name; }
310
311
0
    size_t get_number_of_arguments() const override { return 1; }
312
313
0
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
314
0
        return make_nullable(std::make_shared<DataTypeString>());
315
0
    }
316
317
    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
318
0
                        uint32_t result, size_t input_rows_count) const override {
319
0
        const ColumnPtr& column = block.get_by_position(arguments[0]).column;
320
321
0
        auto col_res = ColumnString::create();
322
0
        ColumnString::Chars& vec_res = col_res->get_chars();
323
0
        ColumnString::Offsets& offsets_res = col_res->get_offsets();
324
0
        vec_res.resize(input_rows_count * (IPV6_MAX_TEXT_LENGTH + 1));
325
0
        offsets_res.resize(input_rows_count);
326
327
0
        auto null_map = ColumnUInt8::create(input_rows_count, 0);
328
329
0
        unsigned char ipv6_address_data[IPV6_BINARY_LENGTH];
330
331
0
        if (check_and_get_column<ColumnIPv6>(column.get())) {
332
0
            process_ipv6_column<ColumnIPv6>(column, input_rows_count, vec_res, offsets_res,
333
0
                                            null_map, ipv6_address_data);
334
0
        } else { //ColumnString
335
0
            process_ipv6_column<ColumnString>(column, input_rows_count, vec_res, offsets_res,
336
0
                                              null_map, ipv6_address_data);
337
0
        }
338
0
        vec_res.resize(offsets_res[offsets_res.size() - 1]);
339
340
0
        block.replace_by_position(result,
341
0
                                  ColumnNullable::create(std::move(col_res), std::move(null_map)));
342
0
        return Status::OK();
343
0
    }
344
};
345
346
namespace detail {
347
template <IPConvertExceptionMode exception_mode, typename ToColumn = ColumnIPv6,
348
          typename StringColumnType>
349
ColumnPtr convert_to_ipv6(const StringColumnType& string_column,
350
0
                          const PaddedPODArray<UInt8>* null_map = nullptr) {
351
0
    const size_t column_size = string_column.size();
352
353
0
    ColumnUInt8::MutablePtr col_null_map_to;
354
0
    ColumnUInt8::Container* vec_null_map_to = nullptr;
355
356
0
    if constexpr (exception_mode == IPConvertExceptionMode::Null) {
357
0
        col_null_map_to = ColumnUInt8::create(column_size, false);
358
0
        vec_null_map_to = &col_null_map_to->get_data();
359
0
    }
360
361
0
    auto column_create = [](size_t column_size) -> typename ToColumn::MutablePtr {
362
0
        if constexpr (std::is_same_v<ToColumn, ColumnString>) {
363
0
            auto column_string = ColumnString::create();
364
0
            column_string->get_chars().reserve(column_size * IPV6_BINARY_LENGTH);
365
0
            column_string->get_offsets().reserve(column_size);
366
0
            return column_string;
367
0
        } else {
368
0
            return ColumnIPv6::create();
369
0
        }
370
0
    };
Unexecuted instantiation: _ZZN5doris6detail15convert_to_ipv6ILNS_22IPConvertExceptionModeE0ENS_9ColumnStrIjEES4_EENS_3COWINS_7IColumnEE13immutable_ptrIS6_EERKT1_PKNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEEENKUlmE_clEm
Unexecuted instantiation: _ZZN5doris6detail15convert_to_ipv6ILNS_22IPConvertExceptionModeE1ENS_9ColumnStrIjEES4_EENS_3COWINS_7IColumnEE13immutable_ptrIS6_EERKT1_PKNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEEENKUlmE_clEm
Unexecuted instantiation: _ZZN5doris6detail15convert_to_ipv6ILNS_22IPConvertExceptionModeE2ENS_9ColumnStrIjEES4_EENS_3COWINS_7IColumnEE13immutable_ptrIS6_EERKT1_PKNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEEENKUlmE_clEm
Unexecuted instantiation: _ZZN5doris6detail15convert_to_ipv6ILNS_22IPConvertExceptionModeE0ENS_12ColumnVectorILNS_13PrimitiveTypeE37EEENS_9ColumnStrIjEEEENS_3COWINS_7IColumnEE13immutable_ptrIS9_EERKT1_PKNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEEENKUlmE_clEm
371
372
0
    auto get_vector = [](auto& col_res, size_t col_size) -> decltype(auto) {
373
0
        if constexpr (std::is_same_v<ToColumn, ColumnString>) {
374
0
            auto& vec_res = col_res->get_chars();
375
0
            vec_res.resize(col_size * IPV6_BINARY_LENGTH);
376
0
            return (vec_res);
377
0
        } else {
378
0
            auto& vec_res = col_res->get_data();
379
0
            vec_res.resize(col_size);
380
0
            return (vec_res);
381
0
        }
382
0
    };
Unexecuted instantiation: _ZZN5doris6detail15convert_to_ipv6ILNS_22IPConvertExceptionModeE0ENS_12ColumnVectorILNS_13PrimitiveTypeE37EEENS_9ColumnStrIjEEEENS_3COWINS_7IColumnEE13immutable_ptrIS9_EERKT1_PKNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEEENKUlRT_mE_clINSA_11mutable_ptrIS5_EEEEDcSO_m
Unexecuted instantiation: _ZZN5doris6detail15convert_to_ipv6ILNS_22IPConvertExceptionModeE0ENS_9ColumnStrIjEES4_EENS_3COWINS_7IColumnEE13immutable_ptrIS6_EERKT1_PKNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEEENKUlRT_mE_clINS7_11mutable_ptrIS4_EEEEDcSL_m
Unexecuted instantiation: _ZZN5doris6detail15convert_to_ipv6ILNS_22IPConvertExceptionModeE1ENS_9ColumnStrIjEES4_EENS_3COWINS_7IColumnEE13immutable_ptrIS6_EERKT1_PKNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEEENKUlRT_mE_clINS7_11mutable_ptrIS4_EEEEDcSL_m
Unexecuted instantiation: _ZZN5doris6detail15convert_to_ipv6ILNS_22IPConvertExceptionModeE2ENS_9ColumnStrIjEES4_EENS_3COWINS_7IColumnEE13immutable_ptrIS6_EERKT1_PKNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEEENKUlRT_mE_clINS7_11mutable_ptrIS4_EEEEDcSL_m
383
384
0
    auto col_res = column_create(column_size);
385
0
    auto& vec_res = get_vector(col_res, column_size);
386
387
0
    using Chars = typename StringColumnType::Chars;
388
0
    const Chars& vec_src = string_column.get_chars();
389
390
0
    size_t src_offset = 0;
391
392
    /// ColumnString contains not null terminated strings. But functions parseIPv6, parseIPv4 expect null terminated string.
393
    /// TODO fix this - now parseIPv6/parseIPv4 accept end iterator, so can be parsed in-place
394
0
    std::string string_buffer;
395
396
0
    int offset_inc = 1;
397
0
    ColumnString* column_string = nullptr;
398
0
    if constexpr (std::is_same_v<ToColumn, ColumnString>) {
399
0
        offset_inc = IPV6_BINARY_LENGTH;
400
0
        column_string = col_res.get();
401
0
    }
402
403
0
    for (size_t out_offset = 0, i = 0; i < column_size; out_offset += offset_inc, ++i) {
404
0
        char src_ipv4_buf[sizeof("::ffff:") + IPV4_MAX_TEXT_LENGTH + 1] = "::ffff:";
405
0
        size_t src_next_offset = src_offset;
406
407
0
        const char* src_value = nullptr;
408
0
        auto* res_value = reinterpret_cast<unsigned char*>(&vec_res[out_offset]);
409
410
0
        if constexpr (std::is_same_v<StringColumnType, ColumnString>) {
411
0
            src_value = reinterpret_cast<const char*>(&vec_src[src_offset]);
412
0
            src_next_offset = string_column.get_offsets()[i];
413
414
0
            string_buffer.assign(src_value, src_next_offset - src_offset);
415
0
            src_value = string_buffer.c_str();
416
0
        }
417
418
0
        if (null_map && (*null_map)[i]) {
419
0
            if (exception_mode == IPConvertExceptionMode::Throw) {
420
0
                throw Exception(
421
0
                        ErrorCode::INVALID_ARGUMENT,
422
0
                        "Null Input, you may consider convert it to a valid default IPv6 value "
423
0
                        "like '::' first");
424
0
            } else if (exception_mode == IPConvertExceptionMode::Default) {
425
0
                std::fill_n(&vec_res[out_offset], offset_inc, 0);
426
0
            } else {
427
0
                std::fill_n(&vec_res[out_offset], offset_inc, 0);
428
0
                (*vec_null_map_to)[i] = true;
429
0
            }
430
0
            if constexpr (std::is_same_v<ToColumn, ColumnString>) {
431
0
                DCHECK(column_string != nullptr);
432
0
                column_string->get_offsets().push_back((i + 1) * IPV6_BINARY_LENGTH);
433
0
            }
434
0
            src_offset = src_next_offset;
435
0
            continue;
436
0
        }
437
438
0
        bool parse_result = false;
439
0
        Int64 dummy_result = 0;
440
441
        /// For both cases below: In case of failure, the function parseIPv6 fills vec_res with zero bytes.
442
443
        /// If the source IP address is parsable as an IPv4 address, then transform it into a valid IPv6 address.
444
        /// Keeping it simple by just prefixing `::ffff:` to the IPv4 address to represent it as a valid IPv6 address.
445
0
        size_t string_length = src_next_offset - src_offset;
446
0
        if (string_length != 0) {
447
0
            if (try_parse_ipv4(src_value, dummy_result)) {
448
0
                strncat(src_ipv4_buf, src_value, sizeof(src_ipv4_buf) - strlen(src_ipv4_buf) - 1);
449
0
                parse_result = parse_ipv6_whole(src_ipv4_buf, res_value);
450
0
            } else {
451
0
                parse_result = parse_ipv6_whole(src_value, res_value);
452
0
            }
453
0
        }
454
455
0
        if (parse_result && string_length != 0) {
456
0
            if constexpr (std::is_same_v<ToColumn, ColumnString>) {
457
                // handling 16 bytes ipv6 string in the big-endian byte order
458
                // is aimed at conforming to human reading habits
459
0
                std::reverse(res_value, res_value + IPV6_BINARY_LENGTH);
460
0
            }
461
0
            if constexpr (std::is_same_v<ToColumn, ColumnString>) {
462
0
                auto* column_string_res = static_cast<ColumnString*>(col_res.get());
463
0
                std::copy(res_value, res_value + IPV6_BINARY_LENGTH,
464
0
                          column_string_res->get_chars().begin() + i * IPV6_BINARY_LENGTH);
465
0
                column_string_res->get_offsets().push_back((i + 1) * IPV6_BINARY_LENGTH);
466
0
            } else {
467
0
                col_res->insert_data(reinterpret_cast<const char*>(res_value), IPV6_BINARY_LENGTH);
468
0
            }
469
0
        } else {
470
0
            if (exception_mode == IPConvertExceptionMode::Throw) {
471
0
                throw Exception(ErrorCode::INVALID_ARGUMENT, "Invalid IPv6 value");
472
0
            }
473
0
            std::fill_n(&vec_res[out_offset], offset_inc, 0);
474
0
            if constexpr (std::is_same_v<ToColumn, ColumnString>) {
475
0
                auto* column_string_res = static_cast<ColumnString*>(col_res.get());
476
0
                column_string_res->get_offsets().push_back((i + 1) * IPV6_BINARY_LENGTH);
477
0
            }
478
0
            if constexpr (exception_mode == IPConvertExceptionMode::Null) {
479
0
                (*vec_null_map_to)[i] = true;
480
0
            }
481
0
        }
482
0
        src_offset = src_next_offset;
483
0
    }
484
485
0
    if constexpr (exception_mode == IPConvertExceptionMode::Null) {
486
0
        return ColumnNullable::create(std::move(col_res), std::move(col_null_map_to));
487
0
    }
488
0
    return col_res;
489
0
}
Unexecuted instantiation: _ZN5doris6detail15convert_to_ipv6ILNS_22IPConvertExceptionModeE0ENS_12ColumnVectorILNS_13PrimitiveTypeE37EEENS_9ColumnStrIjEEEENS_3COWINS_7IColumnEE13immutable_ptrIS9_EERKT1_PKNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEE
Unexecuted instantiation: _ZN5doris6detail15convert_to_ipv6ILNS_22IPConvertExceptionModeE0ENS_9ColumnStrIjEES4_EENS_3COWINS_7IColumnEE13immutable_ptrIS6_EERKT1_PKNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEE
Unexecuted instantiation: _ZN5doris6detail15convert_to_ipv6ILNS_22IPConvertExceptionModeE1ENS_9ColumnStrIjEES4_EENS_3COWINS_7IColumnEE13immutable_ptrIS6_EERKT1_PKNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEE
Unexecuted instantiation: _ZN5doris6detail15convert_to_ipv6ILNS_22IPConvertExceptionModeE2ENS_9ColumnStrIjEES4_EENS_3COWINS_7IColumnEE13immutable_ptrIS6_EERKT1_PKNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEE
490
} // namespace detail
491
492
template <IPConvertExceptionMode exception_mode, typename ToColumn = ColumnIPv6>
493
0
ColumnPtr convert_to_ipv6(ColumnPtr column, const PaddedPODArray<UInt8>* null_map = nullptr) {
494
0
    const auto* column_input_string = assert_cast<const ColumnString*>(column.get());
495
0
    auto result = detail::convert_to_ipv6<exception_mode, ToColumn>(*column_input_string, null_map);
496
0
    return result;
497
0
}
Unexecuted instantiation: _ZN5doris15convert_to_ipv6ILNS_22IPConvertExceptionModeE0ENS_12ColumnVectorILNS_13PrimitiveTypeE37EEEEENS_3COWINS_7IColumnEE13immutable_ptrIS6_EES9_PKNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEE
Unexecuted instantiation: _ZN5doris15convert_to_ipv6ILNS_22IPConvertExceptionModeE0ENS_9ColumnStrIjEEEENS_3COWINS_7IColumnEE13immutable_ptrIS5_EES8_PKNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEE
Unexecuted instantiation: _ZN5doris15convert_to_ipv6ILNS_22IPConvertExceptionModeE1ENS_9ColumnStrIjEEEENS_3COWINS_7IColumnEE13immutable_ptrIS5_EES8_PKNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEE
Unexecuted instantiation: _ZN5doris15convert_to_ipv6ILNS_22IPConvertExceptionModeE2ENS_9ColumnStrIjEEEENS_3COWINS_7IColumnEE13immutable_ptrIS5_EES8_PKNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEE
498
499
template <IPConvertExceptionMode exception_mode>
500
class FunctionIPv6StringToNum : public IFunction {
501
public:
502
    static constexpr auto name = exception_mode == IPConvertExceptionMode::Throw
503
                                         ? "ipv6_string_to_num"
504
                                         : (exception_mode == IPConvertExceptionMode::Default
505
                                                    ? "ipv6_string_to_num_or_default"
506
                                                    : "ipv6_string_to_num_or_null");
507
508
6
    static FunctionPtr create() {
509
6
        return std::make_shared<FunctionIPv6StringToNum<exception_mode>>();
510
6
    }
_ZN5doris23FunctionIPv6StringToNumILNS_22IPConvertExceptionModeE0EE6createEv
Line
Count
Source
508
2
    static FunctionPtr create() {
509
2
        return std::make_shared<FunctionIPv6StringToNum<exception_mode>>();
510
2
    }
_ZN5doris23FunctionIPv6StringToNumILNS_22IPConvertExceptionModeE1EE6createEv
Line
Count
Source
508
2
    static FunctionPtr create() {
509
2
        return std::make_shared<FunctionIPv6StringToNum<exception_mode>>();
510
2
    }
_ZN5doris23FunctionIPv6StringToNumILNS_22IPConvertExceptionModeE2EE6createEv
Line
Count
Source
508
2
    static FunctionPtr create() {
509
2
        return std::make_shared<FunctionIPv6StringToNum<exception_mode>>();
510
2
    }
511
512
3
    String get_name() const override { return name; }
_ZNK5doris23FunctionIPv6StringToNumILNS_22IPConvertExceptionModeE0EE8get_nameB5cxx11Ev
Line
Count
Source
512
1
    String get_name() const override { return name; }
_ZNK5doris23FunctionIPv6StringToNumILNS_22IPConvertExceptionModeE1EE8get_nameB5cxx11Ev
Line
Count
Source
512
1
    String get_name() const override { return name; }
_ZNK5doris23FunctionIPv6StringToNumILNS_22IPConvertExceptionModeE2EE8get_nameB5cxx11Ev
Line
Count
Source
512
1
    String get_name() const override { return name; }
513
514
0
    size_t get_number_of_arguments() const override { return 1; }
Unexecuted instantiation: _ZNK5doris23FunctionIPv6StringToNumILNS_22IPConvertExceptionModeE0EE23get_number_of_argumentsEv
Unexecuted instantiation: _ZNK5doris23FunctionIPv6StringToNumILNS_22IPConvertExceptionModeE1EE23get_number_of_argumentsEv
Unexecuted instantiation: _ZNK5doris23FunctionIPv6StringToNumILNS_22IPConvertExceptionModeE2EE23get_number_of_argumentsEv
515
516
0
    bool use_default_implementation_for_nulls() const override { return false; }
Unexecuted instantiation: _ZNK5doris23FunctionIPv6StringToNumILNS_22IPConvertExceptionModeE0EE36use_default_implementation_for_nullsEv
Unexecuted instantiation: _ZNK5doris23FunctionIPv6StringToNumILNS_22IPConvertExceptionModeE1EE36use_default_implementation_for_nullsEv
Unexecuted instantiation: _ZNK5doris23FunctionIPv6StringToNumILNS_22IPConvertExceptionModeE2EE36use_default_implementation_for_nullsEv
517
518
0
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
519
0
        auto result_type = std::make_shared<DataTypeString>();
520
521
0
        if constexpr (exception_mode == IPConvertExceptionMode::Null) {
522
0
            return make_nullable(result_type);
523
0
        }
524
525
0
        return result_type;
526
0
    }
Unexecuted instantiation: _ZNK5doris23FunctionIPv6StringToNumILNS_22IPConvertExceptionModeE0EE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS7_EE
Unexecuted instantiation: _ZNK5doris23FunctionIPv6StringToNumILNS_22IPConvertExceptionModeE1EE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS7_EE
Unexecuted instantiation: _ZNK5doris23FunctionIPv6StringToNumILNS_22IPConvertExceptionModeE2EE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS7_EE
527
528
    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
529
0
                        uint32_t result, size_t input_rows_count) const override {
530
0
        ColumnPtr column =
531
0
                block.get_by_position(arguments[0]).column->convert_to_full_column_if_const();
532
0
        ColumnPtr null_map_column;
533
0
        const NullMap* null_map = nullptr;
534
535
0
        if (const auto* column_nullable = check_and_get_column<ColumnNullable>(column.get())) {
536
0
            column = column_nullable->get_nested_column_ptr();
537
0
            null_map_column = column_nullable->get_null_map_column_ptr();
538
0
            null_map = &column_nullable->get_null_map_data();
539
0
        }
540
541
0
        auto col_res = convert_to_ipv6<exception_mode, ColumnString>(column, null_map);
542
543
0
        if (null_map && exception_mode == IPConvertExceptionMode::Null) {
544
0
            block.replace_by_position(
545
0
                    result, ColumnNullable::create(std::move(col_res), std::move(null_map_column)));
546
0
        } else {
547
0
            block.replace_by_position(result, std::move(col_res));
548
0
        }
549
0
        return Status::OK();
550
0
    }
Unexecuted instantiation: _ZNK5doris23FunctionIPv6StringToNumILNS_22IPConvertExceptionModeE0EE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm
Unexecuted instantiation: _ZNK5doris23FunctionIPv6StringToNumILNS_22IPConvertExceptionModeE1EE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm
Unexecuted instantiation: _ZNK5doris23FunctionIPv6StringToNumILNS_22IPConvertExceptionModeE2EE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm
551
};
552
553
template <typename Type>
554
class FunctionIsIPString : public IFunction {
555
    static_assert(std::is_same_v<Type, IPv4> || std::is_same_v<Type, IPv6>);
556
557
public:
558
    static constexpr auto name = std::is_same_v<Type, IPv4> ? "is_ipv4_string" : "is_ipv6_string";
559
4
    static FunctionPtr create() { return std::make_shared<FunctionIsIPString<Type>>(); }
_ZN5doris18FunctionIsIPStringIjE6createEv
Line
Count
Source
559
2
    static FunctionPtr create() { return std::make_shared<FunctionIsIPString<Type>>(); }
_ZN5doris18FunctionIsIPStringIoE6createEv
Line
Count
Source
559
2
    static FunctionPtr create() { return std::make_shared<FunctionIsIPString<Type>>(); }
560
561
2
    String get_name() const override { return name; }
_ZNK5doris18FunctionIsIPStringIjE8get_nameB5cxx11Ev
Line
Count
Source
561
1
    String get_name() const override { return name; }
_ZNK5doris18FunctionIsIPStringIoE8get_nameB5cxx11Ev
Line
Count
Source
561
1
    String get_name() const override { return name; }
562
563
0
    size_t get_number_of_arguments() const override { return 1; }
Unexecuted instantiation: _ZNK5doris18FunctionIsIPStringIjE23get_number_of_argumentsEv
Unexecuted instantiation: _ZNK5doris18FunctionIsIPStringIoE23get_number_of_argumentsEv
564
565
0
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
566
0
        return std::make_shared<DataTypeUInt8>();
567
0
    }
Unexecuted instantiation: _ZNK5doris18FunctionIsIPStringIjE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS6_EE
Unexecuted instantiation: _ZNK5doris18FunctionIsIPStringIoE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS6_EE
568
569
    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
570
0
                        uint32_t result, size_t input_rows_count) const override {
571
0
        const auto& addr_column_with_type_and_name = block.get_by_position(arguments[0]);
572
0
        const ColumnPtr& addr_column = addr_column_with_type_and_name.column;
573
0
        const auto* str_addr_column = assert_cast<const ColumnString*>(addr_column.get());
574
0
        auto col_res = ColumnUInt8::create(input_rows_count, 0);
575
0
        auto& col_res_data = col_res->get_data();
576
577
0
        for (size_t i = 0; i < input_rows_count; ++i) {
578
0
            if constexpr (std::is_same_v<Type, IPv4>) {
579
0
                StringRef ipv4_str = str_addr_column->get_data_at(i);
580
0
                if (IPv4Value::is_valid_string(ipv4_str.data, ipv4_str.size)) {
581
0
                    col_res_data[i] = 1;
582
0
                }
583
0
            } else {
584
0
                StringRef ipv6_str = str_addr_column->get_data_at(i);
585
0
                if (IPv6Value::is_valid_string(ipv6_str.data, ipv6_str.size)) {
586
0
                    col_res_data[i] = 1;
587
0
                }
588
0
            }
589
0
        }
590
591
0
        block.replace_by_position(result, std::move(col_res));
592
0
        return Status::OK();
593
0
    }
Unexecuted instantiation: _ZNK5doris18FunctionIsIPStringIjE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm
Unexecuted instantiation: _ZNK5doris18FunctionIsIPStringIoE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm
594
};
595
596
class FunctionIsIPAddressInRange : public IFunction {
597
public:
598
    static constexpr auto name = "is_ip_address_in_range";
599
55
    static FunctionPtr create() { return std::make_shared<FunctionIsIPAddressInRange>(); }
600
601
1
    String get_name() const override { return name; }
602
603
53
    size_t get_number_of_arguments() const override { return 2; }
604
605
53
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
606
53
        return std::make_shared<DataTypeUInt8>();
607
53
    }
608
609
    template <PrimitiveType PT, typename ColumnType>
610
    void execute_impl_with_ip(size_t input_rows_count, bool addr_const, bool cidr_const,
611
                              const ColumnString* str_cidr_column, const ColumnPtr addr_column,
612
0
                              ColumnUInt8* col_res) const {
613
0
        auto& col_res_data = col_res->get_data();
614
0
        const auto& ip_data = assert_cast<const ColumnType*>(addr_column.get())->get_data();
615
0
        for (size_t i = 0; i < input_rows_count; ++i) {
616
0
            auto addr_idx = index_check_const(i, addr_const);
617
0
            auto cidr_idx = index_check_const(i, cidr_const);
618
0
            auto cidr_data = str_cidr_column->get_data_at(cidr_idx);
619
            // cidr_data maybe NULL, But the input column is nested column, so check here avoid throw exception
620
0
            if (cidr_data.data == nullptr || cidr_data.size == 0) {
621
0
                col_res_data[i] = 0;
622
0
                continue;
623
0
            }
624
0
            const auto cidr = parse_ip_with_cidr(cidr_data.to_string_view());
625
0
            if constexpr (PT == PrimitiveType::TYPE_IPV4) {
626
0
                if (cidr._address.as_v4()) {
627
0
                    col_res_data[i] = match_ipv4_subnet(ip_data[addr_idx], cidr._address.as_v4(),
628
0
                                                        cidr._prefix)
629
0
                                              ? 1
630
0
                                              : 0;
631
0
                } else {
632
0
                    col_res_data[i] = 0;
633
0
                }
634
0
            } else if constexpr (PT == PrimitiveType::TYPE_IPV6) {
635
0
                if (cidr._address.as_v6()) {
636
0
                    col_res_data[i] = match_ipv6_subnet((uint8_t*)(&ip_data[addr_idx]),
637
0
                                                        cidr._address.as_v6(), cidr._prefix)
638
0
                                              ? 1
639
0
                                              : 0;
640
0
                } else {
641
0
                    col_res_data[i] = 0;
642
0
                }
643
0
            }
644
0
        }
645
0
    }
Unexecuted instantiation: _ZNK5doris26FunctionIsIPAddressInRange20execute_impl_with_ipILNS_13PrimitiveTypeE36ENS_12ColumnVectorILS2_36EEEEEvmbbPKNS_9ColumnStrIjEENS_3COWINS_7IColumnEE13immutable_ptrISA_EEPNS3_ILS2_2EEE
Unexecuted instantiation: _ZNK5doris26FunctionIsIPAddressInRange20execute_impl_with_ipILNS_13PrimitiveTypeE37ENS_12ColumnVectorILS2_37EEEEEvmbbPKNS_9ColumnStrIjEENS_3COWINS_7IColumnEE13immutable_ptrISA_EEPNS3_ILS2_2EEE
646
647
    Status evaluate_inverted_index(
648
            const ColumnsWithTypeAndName& arguments,
649
            const std::vector<IndexFieldNameAndTypePair>& data_type_with_names,
650
            std::vector<segment_v2::IndexIterator*> iterators, uint32_t num_rows,
651
            const InvertedIndexAnalyzerCtx* /*analyzer_ctx*/,
652
2
            segment_v2::InvertedIndexResultBitmap& bitmap_result) const override {
653
2
        DCHECK(arguments.size() == 1);
654
2
        DCHECK(data_type_with_names.size() == 1);
655
2
        DCHECK(iterators.size() == 1);
656
2
        auto* iter = iterators[0];
657
2
        auto data_type_with_name = data_type_with_names[0];
658
2
        if (iter == nullptr) {
659
0
            return Status::OK();
660
0
        }
661
662
2
        if (!segment_v2::IndexReaderHelper::has_bkd_index(iter)) {
663
            // Not support only bkd index
664
0
            return Status::Error<ErrorCode::INVERTED_INDEX_EVALUATE_SKIPPED>(
665
0
                    "Inverted index evaluate skipped, ip range reader can only support by bkd "
666
0
                    "reader");
667
0
        }
668
        // Get the is_ip_address_in_range from the arguments: cidr
669
2
        const auto& cidr_column_with_type_and_name = arguments[0];
670
        // in is_ip_address_in_range param is const Field
671
2
        ColumnPtr arg_column = cidr_column_with_type_and_name.column;
672
2
        DataTypePtr arg_type = cidr_column_with_type_and_name.type;
673
2
        if ((is_column_nullable(*arg_column) && !is_column_const(*remove_nullable(arg_column))) ||
674
2
            (!is_column_nullable(*arg_column) && !is_column_const(*arg_column))) {
675
            // if not we should skip inverted index and evaluate in expression
676
0
            return Status::Error<ErrorCode::INVERTED_INDEX_EVALUATE_SKIPPED>(
677
0
                    "Inverted index evaluate skipped, is_ip_address_in_range only support const "
678
0
                    "value");
679
0
        }
680
        // check param type is string
681
2
        if (!is_string_type(arg_type->get_primitive_type())) {
682
0
            return Status::Error<ErrorCode::INVERTED_INDEX_EVALUATE_SKIPPED>(
683
0
                    "Inverted index evaluate skipped, is_ip_address_in_range only support string "
684
0
                    "type");
685
0
        }
686
        // min && max ip address
687
2
        Field min_ip, max_ip;
688
2
        IPAddressCIDR cidr = parse_ip_with_cidr(arg_column->get_data_at(0));
689
2
        if (data_type_with_name.second->get_primitive_type() == TYPE_IPV4 &&
690
2
            cidr._address.as_v4()) {
691
1
            auto range = apply_cidr_mask(cidr._address.as_v4(), cidr._prefix);
692
1
            min_ip = Field::create_field<TYPE_IPV4>(range.first);
693
1
            max_ip = Field::create_field<TYPE_IPV4>(range.second);
694
1
        } else if (data_type_with_name.second->get_primitive_type() == TYPE_IPV6 &&
695
1
                   cidr._address.as_v6()) {
696
1
            auto cidr_range_ipv6_col = ColumnIPv6::create(2, 0);
697
1
            auto& cidr_range_ipv6_data = cidr_range_ipv6_col->get_data();
698
1
            apply_cidr_mask(reinterpret_cast<const char*>(cidr._address.as_v6()),
699
1
                            reinterpret_cast<char*>(&cidr_range_ipv6_data[0]),
700
1
                            reinterpret_cast<char*>(&cidr_range_ipv6_data[1]), cidr._prefix);
701
1
            min_ip = Field::create_field<TYPE_IPV6>(cidr_range_ipv6_data[0]);
702
1
            max_ip = Field::create_field<TYPE_IPV6>(cidr_range_ipv6_data[1]);
703
1
        } else {
704
            // if here param is invalid for current column to calcute min_ip|max_ip we just return
705
0
            return Status::Error<ErrorCode::INVERTED_INDEX_EVALUATE_SKIPPED>(
706
0
                    "Inverted index evaluate skipped, data type " + arg_type->get_name() +
707
0
                    " can not support this cidr " + arg_column->get_data_at(0).to_string());
708
0
        }
709
        // apply for inverted index
710
2
        std::shared_ptr<roaring::Roaring> null_bitmap = std::make_shared<roaring::Roaring>();
711
712
        // >= min ip
713
2
        segment_v2::InvertedIndexParam min_param;
714
2
        min_param.column_name = data_type_with_name.first;
715
2
        min_param.column_type = data_type_with_name.second;
716
2
        min_param.query_type = segment_v2::InvertedIndexQueryType::GREATER_EQUAL_QUERY;
717
2
        min_param.query_value = min_ip;
718
2
        min_param.num_rows = num_rows;
719
2
        min_param.roaring = std::make_shared<roaring::Roaring>();
720
2
        RETURN_IF_ERROR(iter->read_from_index(&min_param));
721
722
        // <= max ip
723
2
        segment_v2::InvertedIndexParam max_param;
724
2
        max_param.column_name = data_type_with_name.first;
725
2
        max_param.column_type = data_type_with_name.second;
726
2
        max_param.query_type = segment_v2::InvertedIndexQueryType::LESS_EQUAL_QUERY;
727
2
        max_param.query_value = max_ip;
728
2
        max_param.num_rows = num_rows;
729
2
        max_param.roaring = std::make_shared<roaring::Roaring>();
730
2
        RETURN_IF_ERROR(iter->read_from_index(&max_param));
731
732
2
        auto result_roaring = std::make_shared<roaring::Roaring>();
733
2
        *result_roaring = *min_param.roaring & *max_param.roaring;
734
735
2
        DBUG_EXECUTE_IF("ip.inverted_index_filtered", {
736
2
            auto req_id = DebugPoints::instance()->get_debug_param_or_default<int32_t>(
737
2
                    "ip.inverted_index_filtered", "req_id", 0);
738
2
            LOG(INFO) << "execute inverted index req_id: " << req_id
739
2
                      << " min: " << min_param.roaring->cardinality()
740
2
                      << " max: " << max_param.roaring->cardinality()
741
2
                      << " result: " << result_roaring->cardinality();
742
2
        });
743
2
        segment_v2::InvertedIndexResultBitmap result(result_roaring, null_bitmap);
744
2
        bitmap_result = result;
745
2
        bitmap_result.mask_out_null();
746
2
        return Status::OK();
747
2
    }
748
749
    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
750
53
                        uint32_t result, size_t input_rows_count) const override {
751
53
        DBUG_EXECUTE_IF("ip.inverted_index_filtered", {
752
53
            auto req_id = DebugPoints::instance()->get_debug_param_or_default<int32_t>(
753
53
                    "ip.inverted_index_filtered", "req_id", 0);
754
53
            return Status::Error<ErrorCode::INTERNAL_ERROR>(
755
53
                    "{} has already execute inverted index req_id {} , should not execute expr "
756
53
                    "with rows: {}",
757
53
                    get_name(), req_id, input_rows_count);
758
53
        });
759
53
        const auto& addr_column_with_type_and_name = block.get_by_position(arguments[0]);
760
53
        const auto& cidr_column_with_type_and_name = block.get_by_position(arguments[1]);
761
53
        const auto& [addr_column, addr_const] =
762
53
                unpack_if_const(addr_column_with_type_and_name.column);
763
53
        const auto& [cidr_column, cidr_const] =
764
53
                unpack_if_const(cidr_column_with_type_and_name.column);
765
766
53
        auto col_res = ColumnUInt8::create(input_rows_count, 0);
767
53
        auto& col_res_data = col_res->get_data();
768
769
53
        if (addr_column_with_type_and_name.type->get_primitive_type() == TYPE_IPV4) {
770
0
            execute_impl_with_ip<PrimitiveType::TYPE_IPV4, ColumnIPv4>(
771
0
                    input_rows_count, addr_const, cidr_const,
772
0
                    assert_cast<const ColumnString*>(cidr_column.get()), addr_column,
773
0
                    col_res.get());
774
53
        } else if (addr_column_with_type_and_name.type->get_primitive_type() == TYPE_IPV6) {
775
0
            execute_impl_with_ip<PrimitiveType::TYPE_IPV6, ColumnIPv6>(
776
0
                    input_rows_count, addr_const, cidr_const,
777
0
                    assert_cast<const ColumnString*>(cidr_column.get()), addr_column,
778
0
                    col_res.get());
779
53
        } else {
780
53
            const auto* str_addr_column = assert_cast<const ColumnString*>(addr_column.get());
781
53
            const auto* str_cidr_column = assert_cast<const ColumnString*>(cidr_column.get());
782
783
131
            for (size_t i = 0; i < input_rows_count; ++i) {
784
78
                auto addr_idx = index_check_const(i, addr_const);
785
78
                auto cidr_idx = index_check_const(i, cidr_const);
786
78
                auto addr_data = str_addr_column->get_data_at(addr_idx);
787
78
                auto cidr_data = str_cidr_column->get_data_at(cidr_idx);
788
                // cidr_data maybe NULL, But the input column is nested column, so check here avoid throw exception
789
78
                if (cidr_data.data == nullptr || cidr_data.size == 0) {
790
0
                    col_res_data[i] = 0;
791
0
                    continue;
792
0
                }
793
78
                const auto addr = IPAddressVariant(addr_data.to_string_view());
794
78
                const auto cidr = parse_ip_with_cidr(cidr_data.to_string_view());
795
78
                col_res_data[i] = is_address_in_range(addr, cidr) ? 1 : 0;
796
78
            }
797
53
        }
798
799
53
        block.replace_by_position(result, std::move(col_res));
800
53
        return Status::OK();
801
53
    }
802
};
803
804
class FunctionIPv4CIDRToRange : public IFunction {
805
public:
806
    static constexpr auto name = "ipv4_cidr_to_range";
807
2
    static FunctionPtr create() { return std::make_shared<FunctionIPv4CIDRToRange>(); }
808
809
1
    String get_name() const override { return name; }
810
811
0
    size_t get_number_of_arguments() const override { return 2; }
812
813
0
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
814
0
        DataTypePtr element = std::make_shared<DataTypeIPv4>();
815
0
        return std::make_shared<DataTypeStruct>(DataTypes {element, element},
816
0
                                                Strings {"min", "max"});
817
0
    }
818
819
    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
820
0
                        uint32_t result, size_t input_rows_count) const override {
821
0
        ColumnWithTypeAndName& ip_column = block.get_by_position(arguments[0]);
822
0
        ColumnWithTypeAndName& cidr_column = block.get_by_position(arguments[1]);
823
824
0
        const auto& [ip_column_ptr, ip_col_const] = unpack_if_const(ip_column.column);
825
0
        const auto& [cidr_column_ptr, cidr_col_const] = unpack_if_const(cidr_column.column);
826
827
0
        const auto* col_ip_column = assert_cast<const ColumnIPv4*>(ip_column_ptr.get());
828
0
        const auto* col_cidr_column = assert_cast<const ColumnInt16*>(cidr_column_ptr.get());
829
830
0
        const typename ColumnIPv4::Container& vec_ip_input = col_ip_column->get_data();
831
0
        const ColumnInt16::Container& vec_cidr_input = col_cidr_column->get_data();
832
0
        auto col_lower_range_output = ColumnIPv4::create(input_rows_count, 0);
833
0
        auto col_upper_range_output = ColumnIPv4::create(input_rows_count, 0);
834
835
0
        ColumnIPv4::Container& vec_lower_range_output = col_lower_range_output->get_data();
836
0
        ColumnIPv4::Container& vec_upper_range_output = col_upper_range_output->get_data();
837
838
0
        static constexpr UInt8 max_cidr_mask = IPV4_BINARY_LENGTH * 8;
839
840
0
        if (ip_col_const) {
841
0
            auto ip = vec_ip_input[0];
842
0
            for (size_t i = 0; i < input_rows_count; ++i) {
843
0
                auto cidr = vec_cidr_input[i];
844
0
                if (cidr < 0 || cidr > max_cidr_mask) {
845
0
                    throw Exception(ErrorCode::INVALID_ARGUMENT, "Illegal cidr value '{}'",
846
0
                                    std::to_string(cidr));
847
0
                }
848
0
                auto range = apply_cidr_mask(ip, cast_set<UInt8>(cidr));
849
0
                vec_lower_range_output[i] = range.first;
850
0
                vec_upper_range_output[i] = range.second;
851
0
            }
852
0
        } else if (cidr_col_const) {
853
0
            auto cidr = vec_cidr_input[0];
854
0
            if (cidr < 0 || cidr > max_cidr_mask) {
855
0
                throw Exception(ErrorCode::INVALID_ARGUMENT, "Illegal cidr value '{}'",
856
0
                                std::to_string(cidr));
857
0
            }
858
0
            for (size_t i = 0; i < input_rows_count; ++i) {
859
0
                auto ip = vec_ip_input[i];
860
0
                auto range = apply_cidr_mask(ip, cast_set<UInt8>(cidr));
861
0
                vec_lower_range_output[i] = range.first;
862
0
                vec_upper_range_output[i] = range.second;
863
0
            }
864
0
        } else {
865
0
            for (size_t i = 0; i < input_rows_count; ++i) {
866
0
                auto ip = vec_ip_input[i];
867
0
                auto cidr = vec_cidr_input[i];
868
0
                if (cidr < 0 || cidr > max_cidr_mask) {
869
0
                    throw Exception(ErrorCode::INVALID_ARGUMENT, "Illegal cidr value '{}'",
870
0
                                    std::to_string(cidr));
871
0
                }
872
0
                auto range = apply_cidr_mask(ip, cast_set<UInt8>(cidr));
873
0
                vec_lower_range_output[i] = range.first;
874
0
                vec_upper_range_output[i] = range.second;
875
0
            }
876
0
        }
877
878
0
        block.replace_by_position(
879
0
                result, ColumnStruct::create(Columns {std::move(col_lower_range_output),
880
0
                                                      std::move(col_upper_range_output)}));
881
0
        return Status::OK();
882
0
    }
883
};
884
885
/**
886
 * this function accepts two arguments: an IPv6 address and a CIDR mask
887
 *  IPv6 address can be either ipv6 type or string type as ipv6 string address
888
 *  FE: PropagateNullable is used to handle nullable columns
889
 */
890
class FunctionIPv6CIDRToRange : public IFunction {
891
public:
892
    static constexpr auto name = "ipv6_cidr_to_range";
893
2
    static FunctionPtr create() { return std::make_shared<FunctionIPv6CIDRToRange>(); }
894
895
1
    String get_name() const override { return name; }
896
897
0
    size_t get_number_of_arguments() const override { return 2; }
898
899
0
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
900
0
        DataTypePtr element = std::make_shared<DataTypeIPv6>();
901
0
        return std::make_shared<DataTypeStruct>(DataTypes {element, element},
902
0
                                                Strings {"min", "max"});
903
0
    }
904
905
    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
906
0
                        uint32_t result, size_t input_rows_count) const override {
907
0
        const auto& addr_column_with_type_and_name = block.get_by_position(arguments[0]);
908
0
        const auto& cidr_column_with_type_and_name = block.get_by_position(arguments[1]);
909
0
        const auto& [addr_column, add_col_const] =
910
0
                unpack_if_const(addr_column_with_type_and_name.column);
911
0
        const auto& [cidr_column, col_const] =
912
0
                unpack_if_const(cidr_column_with_type_and_name.column);
913
914
0
        const auto* cidr_col = assert_cast<const ColumnInt16*>(cidr_column.get());
915
0
        ColumnPtr col_res = nullptr;
916
917
0
        if (addr_column_with_type_and_name.type->get_primitive_type() == TYPE_IPV6) {
918
0
            const auto* ipv6_addr_column = assert_cast<const ColumnIPv6*>(addr_column.get());
919
0
            col_res = execute_impl(*ipv6_addr_column, *cidr_col, input_rows_count, add_col_const,
920
0
                                   col_const);
921
0
        } else if (is_string_type(addr_column_with_type_and_name.type->get_primitive_type())) {
922
0
            ColumnPtr col_ipv6 =
923
0
                    convert_to_ipv6<IPConvertExceptionMode::Throw>(addr_column, nullptr);
924
0
            const auto* ipv6_addr_column = assert_cast<const ColumnIPv6*>(col_ipv6.get());
925
0
            col_res = execute_impl(*ipv6_addr_column, *cidr_col, input_rows_count, add_col_const,
926
0
                                   col_const);
927
0
        } else {
928
0
            return Status::RuntimeError(
929
0
                    "Illegal column {} of argument of function {}, Expected IPv6 or String",
930
0
                    addr_column->get_name(), get_name());
931
0
        }
932
933
0
        block.replace_by_position(result, std::move(col_res));
934
0
        return Status::OK();
935
0
    }
936
937
    static ColumnPtr execute_impl(const ColumnIPv6& from_column, const ColumnInt16& cidr_column,
938
                                  size_t input_rows_count, bool is_addr_const = false,
939
0
                                  bool is_cidr_const = false) {
940
0
        auto col_res_lower_range = ColumnIPv6::create(input_rows_count, 0);
941
0
        auto col_res_upper_range = ColumnIPv6::create(input_rows_count, 0);
942
0
        auto& vec_res_lower_range = col_res_lower_range->get_data();
943
0
        auto& vec_res_upper_range = col_res_upper_range->get_data();
944
945
0
        static constexpr UInt8 max_cidr_mask = IPV6_BINARY_LENGTH * 8;
946
947
0
        if (is_addr_const) {
948
0
            for (size_t i = 0; i < input_rows_count; ++i) {
949
0
                auto cidr = cidr_column.get_int(i);
950
0
                if (cidr < 0 || cidr > max_cidr_mask) {
951
0
                    throw Exception(ErrorCode::INVALID_ARGUMENT, "Illegal cidr value '{}'",
952
0
                                    std::to_string(cidr));
953
0
                }
954
0
                apply_cidr_mask(from_column.get_data_at(0).data,
955
0
                                reinterpret_cast<char*>(&vec_res_lower_range[i]),
956
0
                                reinterpret_cast<char*>(&vec_res_upper_range[i]),
957
0
                                cast_set<UInt8>(cidr));
958
0
            }
959
0
        } else if (is_cidr_const) {
960
0
            auto cidr = cidr_column.get_int(0);
961
0
            if (cidr < 0 || cidr > max_cidr_mask) {
962
0
                throw Exception(ErrorCode::INVALID_ARGUMENT, "Illegal cidr value '{}'",
963
0
                                std::to_string(cidr));
964
0
            }
965
0
            for (size_t i = 0; i < input_rows_count; ++i) {
966
0
                apply_cidr_mask(from_column.get_data_at(i).data,
967
0
                                reinterpret_cast<char*>(&vec_res_lower_range[i]),
968
0
                                reinterpret_cast<char*>(&vec_res_upper_range[i]),
969
0
                                cast_set<UInt8>(cidr));
970
0
            }
971
0
        } else {
972
0
            for (size_t i = 0; i < input_rows_count; ++i) {
973
0
                auto cidr = cidr_column.get_int(i);
974
0
                if (cidr < 0 || cidr > max_cidr_mask) {
975
0
                    throw Exception(ErrorCode::INVALID_ARGUMENT, "Illegal cidr value '{}'",
976
0
                                    std::to_string(cidr));
977
0
                }
978
0
                apply_cidr_mask(from_column.get_data_at(i).data,
979
0
                                reinterpret_cast<char*>(&vec_res_lower_range[i]),
980
0
                                reinterpret_cast<char*>(&vec_res_upper_range[i]),
981
0
                                cast_set<UInt8>(cidr));
982
0
            }
983
0
        }
984
0
        return ColumnStruct::create(
985
0
                Columns {std::move(col_res_lower_range), std::move(col_res_upper_range)});
986
0
    }
987
};
988
989
class FunctionIsIPv4Compat : public IFunction {
990
public:
991
    static constexpr auto name = "is_ipv4_compat";
992
2
    static FunctionPtr create() { return std::make_shared<FunctionIsIPv4Compat>(); }
993
994
1
    String get_name() const override { return name; }
995
996
0
    size_t get_number_of_arguments() const override { return 1; }
997
998
0
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
999
0
        return std::make_shared<DataTypeUInt8>();
1000
0
    }
1001
1002
    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
1003
0
                        uint32_t result, size_t input_rows_count) const override {
1004
0
        const ColumnPtr& column = block.get_by_position(arguments[0]).column;
1005
0
        const auto* col_in = assert_cast<const ColumnString*>(column.get());
1006
1007
0
        size_t col_size = col_in->size();
1008
0
        auto col_res = ColumnUInt8::create(col_size, 0);
1009
0
        auto& col_res_data = col_res->get_data();
1010
1011
0
        for (size_t i = 0; i < col_size; ++i) {
1012
0
            auto ipv4_in = col_in->get_data_at(i);
1013
0
            if (is_ipv4_compat(reinterpret_cast<const UInt8*>(ipv4_in.data))) {
1014
0
                col_res_data[i] = 1;
1015
0
            }
1016
0
        }
1017
1018
0
        block.replace_by_position(result, std::move(col_res));
1019
0
        return Status::OK();
1020
0
    }
1021
1022
private:
1023
0
    static bool is_ipv4_compat(const UInt8* address) {
1024
0
        return (LittleEndian::Load64(address) == 0) && (LittleEndian::Load32(address + 8) == 0) &&
1025
0
               (LittleEndian::Load32(address + 12) != 0);
1026
0
    }
1027
};
1028
1029
class FunctionIsIPv4Mapped : public IFunction {
1030
public:
1031
    static constexpr auto name = "is_ipv4_mapped";
1032
2
    static FunctionPtr create() { return std::make_shared<FunctionIsIPv4Mapped>(); }
1033
1034
1
    String get_name() const override { return name; }
1035
1036
0
    size_t get_number_of_arguments() const override { return 1; }
1037
1038
0
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
1039
0
        return std::make_shared<DataTypeUInt8>();
1040
0
    }
1041
1042
    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
1043
0
                        uint32_t result, size_t input_rows_count) const override {
1044
0
        const ColumnPtr& column = block.get_by_position(arguments[0]).column;
1045
0
        const auto* col_in = assert_cast<const ColumnString*>(column.get());
1046
1047
0
        size_t col_size = col_in->size();
1048
0
        auto col_res = ColumnUInt8::create(col_size, 0);
1049
0
        auto& col_res_data = col_res->get_data();
1050
1051
0
        for (size_t i = 0; i < col_size; ++i) {
1052
0
            auto ipv4_in = col_in->get_data_at(i);
1053
0
            if (is_ipv4_mapped(reinterpret_cast<const UInt8*>(ipv4_in.data))) {
1054
0
                col_res_data[i] = 1;
1055
0
            }
1056
0
        }
1057
1058
0
        block.replace_by_position(result, std::move(col_res));
1059
0
        return Status::OK();
1060
0
    }
1061
1062
private:
1063
0
    static bool is_ipv4_mapped(const UInt8* address) {
1064
0
        return (LittleEndian::Load64(address) == 0) &&
1065
0
               ((LittleEndian::Load64(address + 8) & 0x00000000FFFFFFFFULL) ==
1066
0
                0x00000000FFFF0000ULL);
1067
0
    }
1068
};
1069
1070
template <IPConvertExceptionMode exception_mode, PrimitiveType PType>
1071
0
inline constexpr auto to_ip_func_name() {
1072
0
    if constexpr (PType == TYPE_IPV4) {
1073
0
        return exception_mode == IPConvertExceptionMode::Throw
1074
0
                       ? "to_ipv4"
1075
0
                       : (exception_mode == IPConvertExceptionMode::Default ? "to_ipv4_or_default"
1076
0
                                                                            : "to_ipv4_or_null");
1077
0
    } else {
1078
0
        return exception_mode == IPConvertExceptionMode::Throw
1079
0
                       ? "to_ipv6"
1080
0
                       : (exception_mode == IPConvertExceptionMode::Default ? "to_ipv6_or_default"
1081
0
                                                                            : "to_ipv6_or_null");
1082
0
    }
1083
0
}
Unexecuted instantiation: _ZN5doris15to_ip_func_nameILNS_22IPConvertExceptionModeE0ELNS_13PrimitiveTypeE36EEEDav
Unexecuted instantiation: _ZN5doris15to_ip_func_nameILNS_22IPConvertExceptionModeE1ELNS_13PrimitiveTypeE36EEEDav
Unexecuted instantiation: _ZN5doris15to_ip_func_nameILNS_22IPConvertExceptionModeE2ELNS_13PrimitiveTypeE36EEEDav
Unexecuted instantiation: _ZN5doris15to_ip_func_nameILNS_22IPConvertExceptionModeE0ELNS_13PrimitiveTypeE37EEEDav
Unexecuted instantiation: _ZN5doris15to_ip_func_nameILNS_22IPConvertExceptionModeE1ELNS_13PrimitiveTypeE37EEEDav
Unexecuted instantiation: _ZN5doris15to_ip_func_nameILNS_22IPConvertExceptionModeE2ELNS_13PrimitiveTypeE37EEEDav
1084
1085
template <IPConvertExceptionMode exception_mode, PrimitiveType PType>
1086
class FunctionToIP : public IFunction {
1087
    static_assert(is_ip(PType));
1088
1089
public:
1090
    static constexpr auto name = to_ip_func_name<exception_mode, PType>();
1091
1092
12
    static FunctionPtr create() { return std::make_shared<FunctionToIP<exception_mode, PType>>(); }
_ZN5doris12FunctionToIPILNS_22IPConvertExceptionModeE0ELNS_13PrimitiveTypeE36EE6createEv
Line
Count
Source
1092
2
    static FunctionPtr create() { return std::make_shared<FunctionToIP<exception_mode, PType>>(); }
_ZN5doris12FunctionToIPILNS_22IPConvertExceptionModeE1ELNS_13PrimitiveTypeE36EE6createEv
Line
Count
Source
1092
2
    static FunctionPtr create() { return std::make_shared<FunctionToIP<exception_mode, PType>>(); }
_ZN5doris12FunctionToIPILNS_22IPConvertExceptionModeE2ELNS_13PrimitiveTypeE36EE6createEv
Line
Count
Source
1092
2
    static FunctionPtr create() { return std::make_shared<FunctionToIP<exception_mode, PType>>(); }
_ZN5doris12FunctionToIPILNS_22IPConvertExceptionModeE0ELNS_13PrimitiveTypeE37EE6createEv
Line
Count
Source
1092
2
    static FunctionPtr create() { return std::make_shared<FunctionToIP<exception_mode, PType>>(); }
_ZN5doris12FunctionToIPILNS_22IPConvertExceptionModeE1ELNS_13PrimitiveTypeE37EE6createEv
Line
Count
Source
1092
2
    static FunctionPtr create() { return std::make_shared<FunctionToIP<exception_mode, PType>>(); }
_ZN5doris12FunctionToIPILNS_22IPConvertExceptionModeE2ELNS_13PrimitiveTypeE37EE6createEv
Line
Count
Source
1092
2
    static FunctionPtr create() { return std::make_shared<FunctionToIP<exception_mode, PType>>(); }
1093
1094
6
    String get_name() const override { return name; }
_ZNK5doris12FunctionToIPILNS_22IPConvertExceptionModeE0ELNS_13PrimitiveTypeE36EE8get_nameB5cxx11Ev
Line
Count
Source
1094
1
    String get_name() const override { return name; }
_ZNK5doris12FunctionToIPILNS_22IPConvertExceptionModeE1ELNS_13PrimitiveTypeE36EE8get_nameB5cxx11Ev
Line
Count
Source
1094
1
    String get_name() const override { return name; }
_ZNK5doris12FunctionToIPILNS_22IPConvertExceptionModeE2ELNS_13PrimitiveTypeE36EE8get_nameB5cxx11Ev
Line
Count
Source
1094
1
    String get_name() const override { return name; }
_ZNK5doris12FunctionToIPILNS_22IPConvertExceptionModeE0ELNS_13PrimitiveTypeE37EE8get_nameB5cxx11Ev
Line
Count
Source
1094
1
    String get_name() const override { return name; }
_ZNK5doris12FunctionToIPILNS_22IPConvertExceptionModeE1ELNS_13PrimitiveTypeE37EE8get_nameB5cxx11Ev
Line
Count
Source
1094
1
    String get_name() const override { return name; }
_ZNK5doris12FunctionToIPILNS_22IPConvertExceptionModeE2ELNS_13PrimitiveTypeE37EE8get_nameB5cxx11Ev
Line
Count
Source
1094
1
    String get_name() const override { return name; }
1095
1096
0
    size_t get_number_of_arguments() const override { return 1; }
Unexecuted instantiation: _ZNK5doris12FunctionToIPILNS_22IPConvertExceptionModeE0ELNS_13PrimitiveTypeE36EE23get_number_of_argumentsEv
Unexecuted instantiation: _ZNK5doris12FunctionToIPILNS_22IPConvertExceptionModeE1ELNS_13PrimitiveTypeE36EE23get_number_of_argumentsEv
Unexecuted instantiation: _ZNK5doris12FunctionToIPILNS_22IPConvertExceptionModeE2ELNS_13PrimitiveTypeE36EE23get_number_of_argumentsEv
Unexecuted instantiation: _ZNK5doris12FunctionToIPILNS_22IPConvertExceptionModeE0ELNS_13PrimitiveTypeE37EE23get_number_of_argumentsEv
Unexecuted instantiation: _ZNK5doris12FunctionToIPILNS_22IPConvertExceptionModeE1ELNS_13PrimitiveTypeE37EE23get_number_of_argumentsEv
Unexecuted instantiation: _ZNK5doris12FunctionToIPILNS_22IPConvertExceptionModeE2ELNS_13PrimitiveTypeE37EE23get_number_of_argumentsEv
1097
1098
0
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
1099
0
        DataTypePtr result_type;
1100
1101
0
        if constexpr (PType == TYPE_IPV4) {
1102
0
            result_type = std::make_shared<DataTypeIPv4>();
1103
0
        } else {
1104
0
            result_type = std::make_shared<DataTypeIPv6>();
1105
0
        }
1106
1107
0
        if constexpr (exception_mode == IPConvertExceptionMode::Null) {
1108
0
            return make_nullable(result_type);
1109
0
        } else {
1110
0
            return result_type;
1111
0
        }
1112
0
    }
Unexecuted instantiation: _ZNK5doris12FunctionToIPILNS_22IPConvertExceptionModeE0ELNS_13PrimitiveTypeE36EE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS8_EE
Unexecuted instantiation: _ZNK5doris12FunctionToIPILNS_22IPConvertExceptionModeE1ELNS_13PrimitiveTypeE36EE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS8_EE
Unexecuted instantiation: _ZNK5doris12FunctionToIPILNS_22IPConvertExceptionModeE2ELNS_13PrimitiveTypeE36EE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS8_EE
Unexecuted instantiation: _ZNK5doris12FunctionToIPILNS_22IPConvertExceptionModeE0ELNS_13PrimitiveTypeE37EE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS8_EE
Unexecuted instantiation: _ZNK5doris12FunctionToIPILNS_22IPConvertExceptionModeE1ELNS_13PrimitiveTypeE37EE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS8_EE
Unexecuted instantiation: _ZNK5doris12FunctionToIPILNS_22IPConvertExceptionModeE2ELNS_13PrimitiveTypeE37EE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS8_EE
1113
1114
0
    bool use_default_implementation_for_nulls() const override { return false; }
Unexecuted instantiation: _ZNK5doris12FunctionToIPILNS_22IPConvertExceptionModeE0ELNS_13PrimitiveTypeE36EE36use_default_implementation_for_nullsEv
Unexecuted instantiation: _ZNK5doris12FunctionToIPILNS_22IPConvertExceptionModeE1ELNS_13PrimitiveTypeE36EE36use_default_implementation_for_nullsEv
Unexecuted instantiation: _ZNK5doris12FunctionToIPILNS_22IPConvertExceptionModeE2ELNS_13PrimitiveTypeE36EE36use_default_implementation_for_nullsEv
Unexecuted instantiation: _ZNK5doris12FunctionToIPILNS_22IPConvertExceptionModeE0ELNS_13PrimitiveTypeE37EE36use_default_implementation_for_nullsEv
Unexecuted instantiation: _ZNK5doris12FunctionToIPILNS_22IPConvertExceptionModeE1ELNS_13PrimitiveTypeE37EE36use_default_implementation_for_nullsEv
Unexecuted instantiation: _ZNK5doris12FunctionToIPILNS_22IPConvertExceptionModeE2ELNS_13PrimitiveTypeE37EE36use_default_implementation_for_nullsEv
1115
1116
    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
1117
0
                        uint32_t result, size_t input_rows_count) const override {
1118
0
        const auto& addr_column_with_type_and_name = block.get_by_position(arguments[0]);
1119
0
        const ColumnPtr& addr_column = addr_column_with_type_and_name.column;
1120
0
        const ColumnString* str_addr_column = nullptr;
1121
0
        const NullMap* addr_null_map = nullptr;
1122
1123
0
        if (addr_column_with_type_and_name.type->is_nullable()) {
1124
0
            const auto* addr_column_nullable =
1125
0
                    assert_cast<const ColumnNullable*>(addr_column.get());
1126
0
            str_addr_column = assert_cast<const ColumnString*>(
1127
0
                    addr_column_nullable->get_nested_column_ptr().get());
1128
0
            addr_null_map = &addr_column_nullable->get_null_map_data();
1129
0
        } else {
1130
0
            str_addr_column = assert_cast<const ColumnString*>(addr_column.get());
1131
0
        }
1132
1133
0
        auto col_res = ColumnVector<PType>::create(input_rows_count, 0);
1134
0
        auto res_null_map = ColumnUInt8::create(input_rows_count, 0);
1135
0
        auto& col_res_data = col_res->get_data();
1136
0
        auto& res_null_map_data = res_null_map->get_data();
1137
1138
0
        for (size_t i = 0; i < input_rows_count; ++i) {
1139
0
            if (addr_null_map && (*addr_null_map)[i]) {
1140
0
                if constexpr (exception_mode == IPConvertExceptionMode::Throw) {
1141
0
                    throw Exception(ErrorCode::INVALID_ARGUMENT,
1142
0
                                    "The arguments of function {} must be String, not NULL",
1143
0
                                    get_name());
1144
0
                } else if constexpr (exception_mode == IPConvertExceptionMode::Default) {
1145
0
                    col_res_data[i] = 0; // '0.0.0.0' or '::'
1146
0
                    continue;
1147
0
                } else {
1148
0
                    res_null_map_data[i] = 1;
1149
0
                    continue;
1150
0
                }
1151
0
            }
1152
1153
0
            if constexpr (PType == TYPE_IPV4) {
1154
0
                StringRef ipv4_str = str_addr_column->get_data_at(i);
1155
0
                IPv4 ipv4_val = 0;
1156
0
                if (IPv4Value::from_string(ipv4_val, ipv4_str.data, ipv4_str.size)) {
1157
0
                    col_res_data[i] = ipv4_val;
1158
0
                } else {
1159
0
                    if constexpr (exception_mode == IPConvertExceptionMode::Throw) {
1160
0
                        throw Exception(ErrorCode::INVALID_ARGUMENT, "Invalid IPv4 value '{}'",
1161
0
                                        ipv4_str.to_string_view());
1162
0
                    } else if constexpr (exception_mode == IPConvertExceptionMode::Default) {
1163
0
                        col_res_data[i] = 0; // '0.0.0.0'
1164
0
                    } else {
1165
0
                        res_null_map_data[i] = 1;
1166
0
                    }
1167
0
                }
1168
0
            } else {
1169
0
                StringRef ipv6_str = str_addr_column->get_data_at(i);
1170
0
                IPv6 ipv6_val = 0;
1171
0
                if (IPv6Value::from_string(ipv6_val, ipv6_str.data, ipv6_str.size)) {
1172
0
                    col_res_data[i] = ipv6_val;
1173
0
                } else {
1174
0
                    if constexpr (exception_mode == IPConvertExceptionMode::Throw) {
1175
0
                        throw Exception(ErrorCode::INVALID_ARGUMENT, "Invalid IPv6 value '{}'",
1176
0
                                        ipv6_str.to_string_view());
1177
0
                    } else if constexpr (exception_mode == IPConvertExceptionMode::Default) {
1178
0
                        col_res_data[i] = 0; // '::'
1179
0
                    } else if constexpr (exception_mode == IPConvertExceptionMode::Null) {
1180
0
                        res_null_map_data[i] = 1;
1181
0
                    }
1182
0
                }
1183
0
            }
1184
0
        }
1185
1186
0
        if constexpr (exception_mode == IPConvertExceptionMode::Null) {
1187
0
            block.replace_by_position(
1188
0
                    result, ColumnNullable::create(std::move(col_res), std::move(res_null_map)));
1189
0
        } else {
1190
0
            block.replace_by_position(result, std::move(col_res));
1191
0
        }
1192
1193
0
        return Status::OK();
1194
0
    }
Unexecuted instantiation: _ZNK5doris12FunctionToIPILNS_22IPConvertExceptionModeE0ELNS_13PrimitiveTypeE36EE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm
Unexecuted instantiation: _ZNK5doris12FunctionToIPILNS_22IPConvertExceptionModeE1ELNS_13PrimitiveTypeE36EE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm
Unexecuted instantiation: _ZNK5doris12FunctionToIPILNS_22IPConvertExceptionModeE2ELNS_13PrimitiveTypeE36EE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm
Unexecuted instantiation: _ZNK5doris12FunctionToIPILNS_22IPConvertExceptionModeE0ELNS_13PrimitiveTypeE37EE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm
Unexecuted instantiation: _ZNK5doris12FunctionToIPILNS_22IPConvertExceptionModeE1ELNS_13PrimitiveTypeE37EE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm
Unexecuted instantiation: _ZNK5doris12FunctionToIPILNS_22IPConvertExceptionModeE2ELNS_13PrimitiveTypeE37EE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm
1195
};
1196
1197
class FunctionIPv4ToIPv6 : public IFunction {
1198
public:
1199
    static constexpr auto name = "ipv4_to_ipv6";
1200
3
    static FunctionPtr create() { return std::make_shared<FunctionIPv4ToIPv6>(); }
1201
1202
1
    String get_name() const override { return name; }
1203
1204
1
    size_t get_number_of_arguments() const override { return 1; }
1205
1206
1
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
1207
1
        return std::make_shared<DataTypeIPv6>();
1208
1
    }
1209
1210
    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
1211
1
                        uint32_t result, size_t input_rows_count) const override {
1212
1
        const auto& ipv4_column_with_type_and_name = block.get_by_position(arguments[0]);
1213
1
        const auto& [ipv4_column, ipv4_const] =
1214
1
                unpack_if_const(ipv4_column_with_type_and_name.column);
1215
1
        const auto* ipv4_addr_column = assert_cast<const ColumnIPv4*>(ipv4_column.get());
1216
1
        const auto& ipv4_column_data = ipv4_addr_column->get_data();
1217
1
        auto col_res = ColumnIPv6::create(input_rows_count, 0);
1218
1
        auto& col_res_data = col_res->get_data();
1219
1220
7
        for (size_t i = 0; i < input_rows_count; ++i) {
1221
6
            auto ipv4_idx = index_check_const(i, ipv4_const);
1222
6
            map_ipv4_to_ipv6(ipv4_column_data[ipv4_idx],
1223
6
                             reinterpret_cast<UInt8*>(&col_res_data[i]));
1224
6
        }
1225
1226
1
        block.replace_by_position(result, std::move(col_res));
1227
1
        return Status::OK();
1228
1
    }
1229
};
1230
1231
class FunctionCutIPv6 : public IFunction {
1232
public:
1233
    static constexpr auto name = "cut_ipv6";
1234
3
    static FunctionPtr create() { return std::make_shared<FunctionCutIPv6>(); }
1235
1236
1
    String get_name() const override { return name; }
1237
1238
1
    size_t get_number_of_arguments() const override { return 3; }
1239
1240
1
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
1241
1
        return std::make_shared<DataTypeString>();
1242
1
    }
1243
1244
    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
1245
1
                        uint32_t result, size_t input_rows_count) const override {
1246
1
        const auto& ipv6_column_with_type_and_name = block.get_by_position(arguments[0]);
1247
1
        const auto& bytes_to_cut_for_ipv6_column_with_type_and_name =
1248
1
                block.get_by_position(arguments[1]);
1249
1
        const auto& bytes_to_cut_for_ipv4_column_with_type_and_name =
1250
1
                block.get_by_position(arguments[2]);
1251
1252
1
        const auto& [ipv6_column, ipv6_const] =
1253
1
                unpack_if_const(ipv6_column_with_type_and_name.column);
1254
1
        const auto& [bytes_to_cut_for_ipv6_column, bytes_to_cut_for_ipv6_const] =
1255
1
                unpack_if_const(bytes_to_cut_for_ipv6_column_with_type_and_name.column);
1256
1
        const auto& [bytes_to_cut_for_ipv4_column, bytes_to_cut_for_ipv4_const] =
1257
1
                unpack_if_const(bytes_to_cut_for_ipv4_column_with_type_and_name.column);
1258
1259
1
        const auto* ipv6_addr_column = assert_cast<const ColumnIPv6*>(ipv6_column.get());
1260
1
        const auto* to_cut_for_ipv6_bytes_column =
1261
1
                assert_cast<const ColumnInt8*>(bytes_to_cut_for_ipv6_column.get());
1262
1
        const auto* to_cut_for_ipv4_bytes_column =
1263
1
                assert_cast<const ColumnInt8*>(bytes_to_cut_for_ipv4_column.get());
1264
1265
1
        const auto& ipv6_addr_column_data = ipv6_addr_column->get_data();
1266
1
        const auto& to_cut_for_ipv6_bytes_column_data = to_cut_for_ipv6_bytes_column->get_data();
1267
1
        const auto& to_cut_for_ipv4_bytes_column_data = to_cut_for_ipv4_bytes_column->get_data();
1268
1269
1
        auto col_res = ColumnString::create();
1270
1
        ColumnString::Chars& chars_res = col_res->get_chars();
1271
1
        ColumnString::Offsets& offsets_res = col_res->get_offsets();
1272
1
        chars_res.resize(input_rows_count * (IPV6_MAX_TEXT_LENGTH + 1)); // + 1 for ending '\0'
1273
1
        offsets_res.resize(input_rows_count);
1274
1
        auto* begin = reinterpret_cast<char*>(chars_res.data());
1275
1
        auto* pos = begin;
1276
1277
10
        for (size_t i = 0; i < input_rows_count; ++i) {
1278
9
            auto ipv6_idx = index_check_const(i, ipv6_const);
1279
9
            auto bytes_to_cut_for_ipv6_idx = index_check_const(i, bytes_to_cut_for_ipv6_const);
1280
9
            auto bytes_to_cut_for_ipv4_idx = index_check_const(i, bytes_to_cut_for_ipv4_const);
1281
            // the current function logic is processed in big endian manner
1282
            // But ipv6 in doris is stored in little-endian byte order
1283
            // need transfer to big-endian byte order first, so we can't deal this process in column
1284
9
            auto val_128 = ipv6_addr_column_data[ipv6_idx];
1285
9
            auto* address = reinterpret_cast<unsigned char*>(&val_128);
1286
1287
9
            Int8 bytes_to_cut_for_ipv6_count =
1288
9
                    to_cut_for_ipv6_bytes_column_data[bytes_to_cut_for_ipv6_idx];
1289
9
            Int8 bytes_to_cut_for_ipv4_count =
1290
9
                    to_cut_for_ipv4_bytes_column_data[bytes_to_cut_for_ipv4_idx];
1291
1292
9
            if (bytes_to_cut_for_ipv6_count > IPV6_BINARY_LENGTH) [[unlikely]] {
1293
0
                throw Exception(ErrorCode::INVALID_ARGUMENT,
1294
0
                                "Illegal value for argument 2 {} of function {}",
1295
0
                                bytes_to_cut_for_ipv6_column_with_type_and_name.type->get_name(),
1296
0
                                get_name());
1297
0
            }
1298
1299
9
            if (bytes_to_cut_for_ipv4_count > IPV6_BINARY_LENGTH) [[unlikely]] {
1300
0
                throw Exception(ErrorCode::INVALID_ARGUMENT,
1301
0
                                "Illegal value for argument 3 {} of function {}",
1302
0
                                bytes_to_cut_for_ipv4_column_with_type_and_name.type->get_name(),
1303
0
                                get_name());
1304
0
            }
1305
1306
9
            UInt8 bytes_to_cut_count = is_ipv4_mapped(address) ? bytes_to_cut_for_ipv4_count
1307
9
                                                               : bytes_to_cut_for_ipv6_count;
1308
9
            cut_address(address, pos, bytes_to_cut_count);
1309
9
            offsets_res[i] = cast_set<uint32_t>(pos - begin);
1310
9
        }
1311
1312
1
        chars_res.resize(offsets_res[offsets_res.size() - 1]);
1313
1314
1
        block.replace_by_position(result, std::move(col_res));
1315
1
        return Status::OK();
1316
1
    }
1317
1318
private:
1319
9
    static bool is_ipv4_mapped(const UInt8* address) {
1320
9
        return (LittleEndian::Load64(address + 8) == 0) &&
1321
9
               ((LittleEndian::Load64(address) & 0xFFFFFFFF00000000ULL) == 0x0000FFFF00000000ULL);
1322
9
    }
1323
1324
9
    static void cut_address(unsigned char* address, char*& dst, UInt8 zeroed_tail_bytes_count) {
1325
9
        format_ipv6(address, dst, zeroed_tail_bytes_count);
1326
9
    }
1327
};
1328
1329
class FunctionIPv6FromUInt128StringOrNull : public IFunction {
1330
public:
1331
    static constexpr auto name = "ipv6_from_uint128_string_or_null";
1332
2
    static FunctionPtr create() { return std::make_shared<FunctionIPv6FromUInt128StringOrNull>(); }
1333
1334
1
    String get_name() const override { return name; }
1335
1336
0
    size_t get_number_of_arguments() const override { return 1; }
1337
1338
0
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
1339
0
        return std::make_shared<DataTypeNullable>(std::make_shared<DataTypeIPv6>());
1340
0
    }
1341
1342
    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
1343
0
                        uint32_t result, size_t input_rows_count) const override {
1344
0
        const auto& ipv6_column_with_type_and_name = block.get_by_position(arguments[0]);
1345
0
        const auto& [ipv6_column, ipv6_const] =
1346
0
                unpack_if_const(ipv6_column_with_type_and_name.column);
1347
0
        const auto* ipv6_addr_column = assert_cast<const ColumnString*>(ipv6_column.get());
1348
        // result is nullable column
1349
0
        auto col_res_nested = ColumnIPv6::create(input_rows_count, 0);
1350
0
        auto col_res_null_map = ColumnUInt8::create(input_rows_count, 1);
1351
0
        auto& col_res_data = col_res_nested->get_data();
1352
0
        auto& res_null_map_data = col_res_null_map->get_data();
1353
1354
0
        for (size_t i = 0; i < input_rows_count; ++i) {
1355
0
            IPv6 ipv6 = 0;
1356
0
            auto ipv6_idx = index_check_const(i, ipv6_const);
1357
0
            StringRef uint128_string = ipv6_addr_column->get_data_at(ipv6_idx);
1358
0
            if (!IPv6Value::from_uint128_string(ipv6, uint128_string.data, uint128_string.size)) {
1359
0
                VLOG_DEBUG << "Invalid uin128 IPv6 value '" << uint128_string.to_string_view()
1360
0
                           << "'";
1361
                // we should set null to the result not throw exception for load senior
1362
0
            } else {
1363
0
                col_res_data[i] = ipv6;
1364
0
                res_null_map_data[i] = 0;
1365
0
            }
1366
0
        }
1367
1368
0
        block.replace_by_position(result, ColumnNullable::create(std::move(col_res_nested),
1369
0
                                                                 std::move(col_res_null_map)));
1370
0
        return Status::OK();
1371
0
    }
1372
};
1373
1374
} // namespace doris