ClickHouse
1177 строк · 47.4 Кб
1#include <functional>
2#pragma clang diagnostic ignored "-Wreserved-identifier"
3
4#include <Functions/FunctionsCodingIP.h>
5
6#include <Columns/ColumnArray.h>
7#include <Columns/ColumnConst.h>
8#include <Columns/ColumnFixedString.h>
9#include <Columns/ColumnString.h>
10#include <Columns/ColumnTuple.h>
11#include <Columns/ColumnsNumber.h>
12#include <Columns/ColumnNullable.h>
13#include <DataTypes/DataTypeDate.h>
14#include <DataTypes/DataTypeFactory.h>
15#include <DataTypes/DataTypeFixedString.h>
16#include <DataTypes/DataTypeString.h>
17#include <DataTypes/DataTypeTuple.h>
18#include <DataTypes/DataTypesNumber.h>
19#include <DataTypes/DataTypeIPv4andIPv6.h>
20#include <Functions/FunctionFactory.h>
21#include <Functions/FunctionHelpers.h>
22#include <Functions/IFunction.h>
23#include <Interpreters/Context.h>
24#include <IO/WriteHelpers.h>
25#include <Common/IPv6ToBinary.h>
26#include <Common/formatIPv6.h>
27#include <base/hex.h>
28#include <Common/typeid_cast.h>
29
30#include <arpa/inet.h>
31#include <type_traits>
32#include <array>
33
34
35namespace DB
36{
37
38namespace ErrorCodes
39{
40extern const int ILLEGAL_TYPE_OF_ARGUMENT;
41extern const int ILLEGAL_COLUMN;
42}
43
44
45/** Encoding functions for network addresses:
46*
47* IPv6NumToString (num) - See below.
48* IPv6StringToNum(string) - Convert, for example, '::1' to 1 and vice versa.
49*/
50class FunctionIPv6NumToString : public IFunction
51{
52public:
53static constexpr auto name = "IPv6NumToString";
54static FunctionPtr create(ContextPtr) { return std::make_shared<FunctionIPv6NumToString>(); }
55
56String getName() const override { return name; }
57
58size_t getNumberOfArguments() const override { return 1; }
59bool isInjective(const ColumnsWithTypeAndName &) const override { return true; }
60bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override { return false; }
61
62DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
63{
64const auto * arg_string = checkAndGetDataType<DataTypeFixedString>(arguments[0].get());
65const auto * arg_ipv6 = checkAndGetDataType<DataTypeIPv6>(arguments[0].get());
66if (!arg_ipv6 && !(arg_string && arg_string->getN() == IPV6_BINARY_LENGTH))
67throw Exception(
68ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
69"Illegal type {} of argument of function {}, expected IPv6 or FixedString({})",
70arguments[0]->getName(), getName(), IPV6_BINARY_LENGTH
71);
72
73return std::make_shared<DataTypeString>();
74}
75
76bool useDefaultImplementationForConstants() const override { return true; }
77
78ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t input_rows_count) const override
79{
80const ColumnPtr & column = arguments[0].column;
81const auto * col_ipv6 = checkAndGetColumn<ColumnIPv6>(column.get());
82const auto * col_string = checkAndGetColumn<ColumnFixedString>(column.get());
83if (!col_ipv6 && !(col_string && col_string->getN() == IPV6_BINARY_LENGTH))
84throw Exception(
85ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
86"Illegal column {} of argument of function {}, expected IPv6 or FixedString({})",
87arguments[0].name, getName(), IPV6_BINARY_LENGTH
88);
89
90auto col_res = ColumnString::create();
91ColumnString::Chars & vec_res = col_res->getChars();
92ColumnString::Offsets & offsets_res = col_res->getOffsets();
93vec_res.resize(input_rows_count * (IPV6_MAX_TEXT_LENGTH + 1));
94offsets_res.resize(input_rows_count);
95
96auto * begin = reinterpret_cast<char *>(vec_res.data());
97auto * pos = begin;
98
99if (col_ipv6)
100{
101const auto & vec_in = col_ipv6->getData();
102
103for (size_t i = 0; i < input_rows_count; ++i)
104{
105formatIPv6(reinterpret_cast<const unsigned char *>(&vec_in[i]), pos);
106offsets_res[i] = pos - begin;
107}
108}
109else
110{
111const auto & vec_in = col_string->getChars();
112
113for (size_t i = 0; i < input_rows_count; ++i)
114{
115formatIPv6(reinterpret_cast<const unsigned char *>(&vec_in[i * IPV6_BINARY_LENGTH]), pos);
116offsets_res[i] = pos - begin;
117}
118}
119
120vec_res.resize(pos - begin);
121return col_res;
122}
123};
124
125
126class FunctionCutIPv6 : public IFunction
127{
128public:
129static constexpr auto name = "cutIPv6";
130static FunctionPtr create(ContextPtr) { return std::make_shared<FunctionCutIPv6>(); }
131
132String getName() const override { return name; }
133
134size_t getNumberOfArguments() const override { return 3; }
135
136bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override { return false; }
137
138DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
139{
140if (!checkAndGetDataType<DataTypeIPv6>(arguments[0].get()))
141{
142const auto * ptr = checkAndGetDataType<DataTypeFixedString>(arguments[0].get());
143if (!ptr || ptr->getN() != IPV6_BINARY_LENGTH)
144throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
145"Illegal type {} of argument 1 of function {}, expected FixedString({})",
146arguments[0]->getName(), getName(), toString(IPV6_BINARY_LENGTH));
147}
148
149if (!WhichDataType(arguments[1]).isUInt8())
150throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Illegal type {} of argument 2 of function {}",
151arguments[1]->getName(), getName());
152
153if (!WhichDataType(arguments[2]).isUInt8())
154throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Illegal type {} of argument 3 of function {}",
155arguments[2]->getName(), getName());
156
157return std::make_shared<DataTypeString>();
158}
159
160bool useDefaultImplementationForConstants() const override { return true; }
161ColumnNumbers getArgumentsThatAreAlwaysConstant() const override { return {1, 2}; }
162
163ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t input_rows_count) const override
164{
165const auto & col_type_name = arguments[0];
166const ColumnPtr & column = col_type_name.column;
167
168const auto & col_ipv6_zeroed_tail_bytes_type = arguments[1];
169const auto & col_ipv6_zeroed_tail_bytes = col_ipv6_zeroed_tail_bytes_type.column;
170const auto & col_ipv4_zeroed_tail_bytes_type = arguments[2];
171const auto & col_ipv4_zeroed_tail_bytes = col_ipv4_zeroed_tail_bytes_type.column;
172
173const auto * col_in_str = checkAndGetColumn<ColumnFixedString>(column.get());
174const auto * col_in_ip = checkAndGetColumn<ColumnIPv6>(column.get());
175
176if (!col_in_str && !col_in_ip)
177throw Exception(ErrorCodes::ILLEGAL_COLUMN, "Illegal column {} of argument of function {}",
178arguments[0].column->getName(), getName());
179
180if (col_in_str && col_in_str->getN() != IPV6_BINARY_LENGTH)
181throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
182"Illegal type {} of column {} argument of function {}, expected FixedString({})",
183col_type_name.type->getName(), col_in_str->getName(),
184getName(), toString(IPV6_BINARY_LENGTH));
185
186const auto * ipv6_zeroed_tail_bytes = checkAndGetColumnConst<ColumnVector<UInt8>>(col_ipv6_zeroed_tail_bytes.get());
187if (!ipv6_zeroed_tail_bytes)
188throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Illegal type {} of argument 2 of function {}",
189col_ipv6_zeroed_tail_bytes_type.type->getName(), getName());
190
191UInt8 ipv6_zeroed_tail_bytes_count = ipv6_zeroed_tail_bytes->getValue<UInt8>();
192if (ipv6_zeroed_tail_bytes_count > IPV6_BINARY_LENGTH)
193throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Illegal value for argument 2 {} of function {}",
194col_ipv6_zeroed_tail_bytes_type.type->getName(), getName());
195
196const auto * ipv4_zeroed_tail_bytes = checkAndGetColumnConst<ColumnVector<UInt8>>(col_ipv4_zeroed_tail_bytes.get());
197if (!ipv4_zeroed_tail_bytes)
198throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Illegal type {} of argument 3 of function {}",
199col_ipv4_zeroed_tail_bytes_type.type->getName(), getName());
200
201UInt8 ipv4_zeroed_tail_bytes_count = ipv4_zeroed_tail_bytes->getValue<UInt8>();
202if (ipv4_zeroed_tail_bytes_count > IPV6_BINARY_LENGTH)
203throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Illegal value for argument 3 {} of function {}",
204col_ipv4_zeroed_tail_bytes_type.type->getName(), getName());
205
206auto col_res = ColumnString::create();
207ColumnString::Chars & vec_res = col_res->getChars();
208ColumnString::Offsets & offsets_res = col_res->getOffsets();
209vec_res.resize(input_rows_count * (IPV6_MAX_TEXT_LENGTH + 1));
210offsets_res.resize(input_rows_count);
211
212auto * begin = reinterpret_cast<char *>(vec_res.data());
213auto * pos = begin;
214
215if (col_in_str)
216{
217const auto & vec_in = col_in_str->getChars();
218
219for (size_t offset = 0, i = 0; i < input_rows_count; offset += IPV6_BINARY_LENGTH, ++i)
220{
221const auto * address = &vec_in[offset];
222UInt8 zeroed_tail_bytes_count = isIPv4Mapped(address) ? ipv4_zeroed_tail_bytes_count : ipv6_zeroed_tail_bytes_count;
223cutAddress(reinterpret_cast<const unsigned char *>(address), pos, zeroed_tail_bytes_count);
224offsets_res[i] = pos - begin;
225}
226}
227else
228{
229const auto & vec_in = col_in_ip->getData();
230
231for (size_t i = 0; i < input_rows_count; ++i)
232{
233const auto * address = reinterpret_cast<const UInt8 *>(&vec_in[i]);
234UInt8 zeroed_tail_bytes_count = isIPv4Mapped(address) ? ipv4_zeroed_tail_bytes_count : ipv6_zeroed_tail_bytes_count;
235cutAddress(reinterpret_cast<const unsigned char *>(address), pos, zeroed_tail_bytes_count);
236offsets_res[i] = pos - begin;
237}
238}
239
240vec_res.resize(pos - begin);
241
242return col_res;
243}
244
245private:
246static bool isIPv4Mapped(const UInt8 * address)
247{
248return (unalignedLoadLittleEndian<UInt64>(address) == 0) &&
249((unalignedLoadLittleEndian<UInt64>(address + 8) & 0x00000000FFFFFFFFull) == 0x00000000FFFF0000ull);
250}
251
252static void cutAddress(const unsigned char * address, char *& dst, UInt8 zeroed_tail_bytes_count)
253{
254formatIPv6(address, dst, zeroed_tail_bytes_count);
255}
256};
257
258template <IPStringToNumExceptionMode exception_mode>
259class FunctionIPv6StringToNum : public IFunction
260{
261public:
262static constexpr auto name = exception_mode == IPStringToNumExceptionMode::Throw
263? "IPv6StringToNum"
264: (exception_mode == IPStringToNumExceptionMode::Default ? "IPv6StringToNumOrDefault" : "IPv6StringToNumOrNull");
265
266static FunctionPtr create(ContextPtr context) { return std::make_shared<FunctionIPv6StringToNum>(context); }
267
268explicit FunctionIPv6StringToNum(ContextPtr context)
269: cast_ipv4_ipv6_default_on_conversion_error(context->getSettingsRef().cast_ipv4_ipv6_default_on_conversion_error)
270{
271}
272
273String getName() const override { return name; }
274
275size_t getNumberOfArguments() const override { return 1; }
276
277bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override { return false; }
278
279bool useDefaultImplementationForConstants() const override { return true; }
280
281bool useDefaultImplementationForNulls() const override { return false; }
282
283DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
284{
285if (!isStringOrFixedString(removeNullable(arguments[0])))
286{
287throw Exception(
288ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Illegal type {} of argument of function {}", arguments[0]->getName(), getName());
289}
290
291auto result_type = std::make_shared<DataTypeFixedString>(IPV6_BINARY_LENGTH);
292
293if constexpr (exception_mode == IPStringToNumExceptionMode::Null)
294{
295return makeNullable(result_type);
296}
297
298return arguments[0]->isNullable() ? makeNullable(result_type) : result_type;
299}
300
301ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const override
302{
303ColumnPtr column = arguments[0].column;
304ColumnPtr null_map_column;
305const NullMap * null_map = nullptr;
306if (column->isNullable())
307{
308const auto * column_nullable = assert_cast<const ColumnNullable *>(column.get());
309column = column_nullable->getNestedColumnPtr();
310null_map_column = column_nullable->getNullMapColumnPtr();
311null_map = &column_nullable->getNullMapData();
312}
313
314if constexpr (exception_mode == IPStringToNumExceptionMode::Throw)
315{
316if (cast_ipv4_ipv6_default_on_conversion_error)
317{
318auto result = convertToIPv6<IPStringToNumExceptionMode::Default, ColumnFixedString>(column, null_map);
319if (null_map && !result->isNullable())
320return ColumnNullable::create(result, null_map_column);
321return result;
322}
323}
324
325auto result = convertToIPv6<exception_mode, ColumnFixedString>(column, null_map);
326if (null_map && !result->isNullable())
327return ColumnNullable::create(IColumn::mutate(result), IColumn::mutate(null_map_column));
328return result;
329}
330
331private:
332bool cast_ipv4_ipv6_default_on_conversion_error = false;
333};
334
335
336/** If mask_tail_octets > 0, the last specified number of octets will be filled with "xxx".
337*/
338template <size_t mask_tail_octets, typename Name>
339class FunctionIPv4NumToString : public IFunction
340{
341private:
342template <typename ArgType>
343ColumnPtr executeTyped(const ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const
344{
345using ColumnType = ColumnVector<ArgType>;
346
347const ColumnPtr & column = arguments[0].column;
348
349if (const ColumnType * col = typeid_cast<const ColumnType *>(column.get()))
350{
351const typename ColumnType::Container & vec_in = col->getData();
352
353auto col_res = ColumnString::create();
354
355ColumnString::Chars & vec_res = col_res->getChars();
356ColumnString::Offsets & offsets_res = col_res->getOffsets();
357
358vec_res.resize(vec_in.size() * (IPV4_MAX_TEXT_LENGTH + 1)); /// the longest value is: 255.255.255.255\0
359offsets_res.resize(vec_in.size());
360char * begin = reinterpret_cast<char *>(vec_res.data());
361char * pos = begin;
362
363for (size_t i = 0; i < vec_in.size(); ++i)
364{
365DB::formatIPv4(reinterpret_cast<const unsigned char*>(&vec_in[i]), sizeof(ArgType), pos, mask_tail_octets, "xxx");
366offsets_res[i] = pos - begin;
367}
368
369vec_res.resize(pos - begin);
370
371return col_res;
372}
373else
374throw Exception(ErrorCodes::ILLEGAL_COLUMN, "Illegal column {} of argument of function {}",
375arguments[0].column->getName(), getName());
376}
377public:
378static constexpr auto name = Name::name;
379static FunctionPtr create(ContextPtr) { return std::make_shared<FunctionIPv4NumToString<mask_tail_octets, Name>>(); }
380
381String getName() const override
382{
383return name;
384}
385
386size_t getNumberOfArguments() const override { return 1; }
387bool isInjective(const ColumnsWithTypeAndName &) const override { return mask_tail_octets == 0; }
388bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override { return false; }
389
390DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
391{
392WhichDataType arg_type(arguments[0]);
393if (!(arg_type.isIPv4() || arg_type.isUInt8() || arg_type.isUInt16() || arg_type.isUInt32()))
394throw Exception(
395ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
396"Illegal type {} of first argument of function {}, expected IPv4 or UInt8 or UInt16 or UInt32",
397arguments[0]->getName(), getName()
398);
399
400return std::make_shared<DataTypeString>();
401}
402
403bool useDefaultImplementationForConstants() const override { return true; }
404
405ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & ret_type, size_t input_rows_count) const override
406{
407
408switch (arguments[0].type->getTypeId())
409{
410case TypeIndex::IPv4: return executeTyped<IPv4>(arguments, ret_type, input_rows_count);
411case TypeIndex::UInt8: return executeTyped<UInt8>(arguments, ret_type, input_rows_count);
412case TypeIndex::UInt16: return executeTyped<UInt16>(arguments, ret_type, input_rows_count);
413case TypeIndex::UInt32: return executeTyped<UInt32>(arguments, ret_type, input_rows_count);
414default: break;
415}
416
417throw Exception(
418ErrorCodes::ILLEGAL_COLUMN,
419"Illegal column {} of argument of function {}, expected IPv4 or UInt8 or UInt16 or UInt32",
420arguments[0].column->getName(), getName()
421);
422}
423};
424
425template <IPStringToNumExceptionMode exception_mode>
426class FunctionIPv4StringToNum : public IFunction
427{
428public:
429static constexpr auto name = exception_mode == IPStringToNumExceptionMode::Throw
430? "IPv4StringToNum"
431: (exception_mode == IPStringToNumExceptionMode::Default ? "IPv4StringToNumOrDefault" : "IPv4StringToNumOrNull");
432
433static FunctionPtr create(ContextPtr context) { return std::make_shared<FunctionIPv4StringToNum>(context); }
434
435explicit FunctionIPv4StringToNum(ContextPtr context)
436: cast_ipv4_ipv6_default_on_conversion_error(context->getSettingsRef().cast_ipv4_ipv6_default_on_conversion_error)
437{
438}
439
440String getName() const override { return name; }
441
442size_t getNumberOfArguments() const override { return 1; }
443
444bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override { return false; }
445
446bool useDefaultImplementationForConstants() const override { return true; }
447
448bool useDefaultImplementationForNulls() const override { return false; }
449
450DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
451{
452if (!isString(removeNullable(arguments[0])))
453{
454throw Exception(
455ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Illegal type {} of argument of function {}", arguments[0]->getName(), getName());
456}
457
458auto result_type = std::make_shared<DataTypeUInt32>();
459
460if constexpr (exception_mode == IPStringToNumExceptionMode::Null)
461{
462return makeNullable(result_type);
463}
464
465return arguments[0]->isNullable() ? makeNullable(result_type) : result_type;
466}
467
468ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const override
469{
470ColumnPtr column = arguments[0].column;
471ColumnPtr null_map_column;
472const NullMap * null_map = nullptr;
473if (column->isNullable())
474{
475const auto * column_nullable = assert_cast<const ColumnNullable *>(column.get());
476column = column_nullable->getNestedColumnPtr();
477null_map_column = column_nullable->getNullMapColumnPtr();
478null_map = &column_nullable->getNullMapData();
479}
480
481if constexpr (exception_mode == IPStringToNumExceptionMode::Throw)
482{
483if (cast_ipv4_ipv6_default_on_conversion_error)
484{
485auto result = convertToIPv4<IPStringToNumExceptionMode::Default, ColumnUInt32>(column, null_map);
486if (null_map && !result->isNullable())
487return ColumnNullable::create(result, null_map_column);
488return result;
489}
490}
491
492auto result = convertToIPv4<exception_mode, ColumnUInt32>(column, null_map);
493if (null_map && !result->isNullable())
494return ColumnNullable::create(IColumn::mutate(result), IColumn::mutate(null_map_column));
495return result;
496}
497
498private:
499bool cast_ipv4_ipv6_default_on_conversion_error = false;
500};
501
502
503class FunctionIPv4ToIPv6 : public IFunction
504{
505public:
506static constexpr auto name = "IPv4ToIPv6";
507static FunctionPtr create(ContextPtr) { return std::make_shared<FunctionIPv4ToIPv6>(); }
508
509String getName() const override { return name; }
510
511size_t getNumberOfArguments() const override { return 1; }
512bool isInjective(const ColumnsWithTypeAndName &) const override { return true; }
513bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override { return false; }
514
515/// for backward compatibility IPv4ToIPv6 is overloaded, and result type depends on type of argument -
516/// if it is UInt32 (presenting IPv4) then result is FixedString(16), if IPv4 - result is IPv6
517DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
518{
519const auto * dt_uint32 = checkAndGetDataType<DataTypeUInt32>(arguments[0].get());
520const auto * dt_ipv4 = checkAndGetDataType<DataTypeIPv4>(arguments[0].get());
521if (!dt_uint32 && !dt_ipv4)
522throw Exception(
523ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
524"Illegal type {} of argument of function {}", arguments[0]->getName(), getName()
525);
526
527if (dt_uint32)
528return std::make_shared<DataTypeFixedString>(16);
529return std::make_shared<DataTypeIPv6>();
530}
531
532bool useDefaultImplementationForConstants() const override { return true; }
533
534ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const override
535{
536const auto & col_type_name = arguments[0];
537const ColumnPtr & column = col_type_name.column;
538
539if (const auto * col_in = checkAndGetColumn<ColumnIPv4>(*column))
540{
541auto col_res = ColumnIPv6::create();
542
543auto & vec_res = col_res->getData();
544vec_res.resize(col_in->size());
545
546const auto & vec_in = col_in->getData();
547
548for (size_t i = 0; i < vec_res.size(); ++i)
549mapIPv4ToIPv6(vec_in[i], reinterpret_cast<UInt8 *>(&vec_res[i].toUnderType()));
550
551return col_res;
552}
553
554if (const auto * col_in = checkAndGetColumn<ColumnUInt32>(*column))
555{
556auto col_res = ColumnFixedString::create(IPV6_BINARY_LENGTH);
557
558auto & vec_res = col_res->getChars();
559vec_res.resize(col_in->size() * IPV6_BINARY_LENGTH);
560
561const auto & vec_in = col_in->getData();
562
563for (size_t out_offset = 0, i = 0; out_offset < vec_res.size(); out_offset += IPV6_BINARY_LENGTH, ++i)
564mapIPv4ToIPv6(vec_in[i], &vec_res[out_offset]);
565
566return col_res;
567}
568
569throw Exception(
570ErrorCodes::ILLEGAL_COLUMN,
571"Illegal column {} of argument of function {}", arguments[0].column->getName(), getName()
572);
573}
574
575private:
576static void mapIPv4ToIPv6(UInt32 in, UInt8 * buf)
577{
578unalignedStore<UInt64>(buf, 0);
579
580#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
581unalignedStoreLittleEndian<UInt64>(buf + 8, 0x00000000FFFF0000ull | (static_cast<UInt64>(ntohl(in)) << 32));
582#else
583unalignedStoreLittleEndian<UInt64>(buf + 8, 0x00000000FFFF0000ull | (static_cast<UInt64>(std::byteswap(in)) << 32));
584#endif
585}
586};
587
588class FunctionMACNumToString : public IFunction
589{
590public:
591static constexpr auto name = "MACNumToString";
592static FunctionPtr create(ContextPtr) { return std::make_shared<FunctionMACNumToString>(); }
593
594String getName() const override
595{
596return name;
597}
598
599size_t getNumberOfArguments() const override { return 1; }
600bool isInjective(const ColumnsWithTypeAndName &) const override { return true; }
601bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override { return false; }
602
603DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
604{
605if (!WhichDataType(arguments[0]).isUInt64())
606throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Illegal type {} of argument of function {}, expected UInt64",
607arguments[0]->getName(), getName());
608
609return std::make_shared<DataTypeString>();
610}
611
612static void formatMAC(UInt64 mac, UInt8 * out)
613{
614/// MAC address is represented in UInt64 in natural order (so, MAC addresses are compared in same order as UInt64).
615/// Higher two bytes in UInt64 are just ignored.
616
617writeHexByteUppercase(mac >> 40, &out[0]);
618out[2] = ':';
619writeHexByteUppercase(mac >> 32, &out[3]);
620out[5] = ':';
621writeHexByteUppercase(mac >> 24, &out[6]);
622out[8] = ':';
623writeHexByteUppercase(mac >> 16, &out[9]);
624out[11] = ':';
625writeHexByteUppercase(mac >> 8, &out[12]);
626out[14] = ':';
627writeHexByteUppercase(mac, &out[15]);
628out[17] = '\0';
629}
630
631bool useDefaultImplementationForConstants() const override { return true; }
632
633ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const override
634{
635const ColumnPtr & column = arguments[0].column;
636
637if (const ColumnUInt64 * col = typeid_cast<const ColumnUInt64 *>(column.get()))
638{
639const ColumnUInt64::Container & vec_in = col->getData();
640
641auto col_res = ColumnString::create();
642
643ColumnString::Chars & vec_res = col_res->getChars();
644ColumnString::Offsets & offsets_res = col_res->getOffsets();
645
646vec_res.resize(vec_in.size() * 18); /// the value is: xx:xx:xx:xx:xx:xx\0
647offsets_res.resize(vec_in.size());
648
649size_t current_offset = 0;
650for (size_t i = 0; i < vec_in.size(); ++i)
651{
652formatMAC(vec_in[i], &vec_res[current_offset]);
653current_offset += 18;
654offsets_res[i] = current_offset;
655}
656
657return col_res;
658}
659else
660throw Exception(ErrorCodes::ILLEGAL_COLUMN, "Illegal column {} of argument of function {}",
661arguments[0].column->getName(), getName());
662}
663};
664
665
666struct ParseMACImpl
667{
668static constexpr size_t min_string_size = 17;
669static constexpr size_t max_string_size = 17;
670
671/** Example: 01:02:03:04:05:06.
672* There could be any separators instead of : and them are just ignored.
673* The order of resulting integers are correspond to the order of MAC address.
674* If there are any chars other than valid hex digits for bytes, the behaviour is implementation specific.
675*/
676static UInt64 parse(const char * pos)
677{
678return (static_cast<UInt64>(unhex(pos[0])) << 44)
679| (static_cast<UInt64>(unhex(pos[1])) << 40)
680| (static_cast<UInt64>(unhex(pos[3])) << 36)
681| (static_cast<UInt64>(unhex(pos[4])) << 32)
682| (static_cast<UInt64>(unhex(pos[6])) << 28)
683| (static_cast<UInt64>(unhex(pos[7])) << 24)
684| (static_cast<UInt64>(unhex(pos[9])) << 20)
685| (static_cast<UInt64>(unhex(pos[10])) << 16)
686| (static_cast<UInt64>(unhex(pos[12])) << 12)
687| (static_cast<UInt64>(unhex(pos[13])) << 8)
688| (static_cast<UInt64>(unhex(pos[15])) << 4)
689| (static_cast<UInt64>(unhex(pos[16])));
690}
691
692static constexpr auto name = "MACStringToNum";
693};
694
695struct ParseOUIImpl
696{
697static constexpr size_t min_string_size = 8;
698static constexpr size_t max_string_size = 17;
699
700/** OUI is the first three bytes of MAC address.
701* Example: 01:02:03.
702*/
703static UInt64 parse(const char * pos)
704{
705return (static_cast<UInt64>(unhex(pos[0])) << 20)
706| (static_cast<UInt64>(unhex(pos[1])) << 16)
707| (static_cast<UInt64>(unhex(pos[3])) << 12)
708| (static_cast<UInt64>(unhex(pos[4])) << 8)
709| (static_cast<UInt64>(unhex(pos[6])) << 4)
710| (static_cast<UInt64>(unhex(pos[7])));
711}
712
713static constexpr auto name = "MACStringToOUI";
714};
715
716
717template <typename Impl>
718class FunctionMACStringTo : public IFunction
719{
720public:
721static constexpr auto name = Impl::name;
722static FunctionPtr create(ContextPtr) { return std::make_shared<FunctionMACStringTo<Impl>>(); }
723
724String getName() const override
725{
726return name;
727}
728
729size_t getNumberOfArguments() const override { return 1; }
730
731bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override { return false; }
732
733DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
734{
735if (!isString(arguments[0]))
736throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Illegal type {} of argument of function {}",
737arguments[0]->getName(), getName());
738
739return std::make_shared<DataTypeUInt64>();
740}
741
742bool useDefaultImplementationForConstants() const override { return true; }
743
744ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const override
745{
746const ColumnPtr & column = arguments[0].column;
747
748if (const ColumnString * col = checkAndGetColumn<ColumnString>(column.get()))
749{
750auto col_res = ColumnUInt64::create();
751
752ColumnUInt64::Container & vec_res = col_res->getData();
753vec_res.resize(col->size());
754
755const ColumnString::Chars & vec_src = col->getChars();
756const ColumnString::Offsets & offsets_src = col->getOffsets();
757size_t prev_offset = 0;
758
759for (size_t i = 0; i < vec_res.size(); ++i)
760{
761size_t current_offset = offsets_src[i];
762size_t string_size = current_offset - prev_offset - 1; /// mind the terminating zero byte
763
764if (string_size >= Impl::min_string_size && string_size <= Impl::max_string_size)
765vec_res[i] = Impl::parse(reinterpret_cast<const char *>(&vec_src[prev_offset]));
766else
767vec_res[i] = 0;
768
769prev_offset = current_offset;
770}
771
772return col_res;
773}
774else
775throw Exception(ErrorCodes::ILLEGAL_COLUMN, "Illegal column {} of argument of function {}",
776arguments[0].column->getName(), getName());
777}
778};
779
780class FunctionIPv6CIDRToRange : public IFunction
781{
782private:
783
784#if defined(__SSE2__)
785
786#include <emmintrin.h>
787
788static inline void applyCIDRMask(const char * __restrict src, char * __restrict dst_lower, char * __restrict dst_upper, UInt8 bits_to_keep)
789{
790__m128i mask = _mm_loadu_si128(reinterpret_cast<const __m128i *>(getCIDRMaskIPv6(bits_to_keep).data()));
791__m128i lower = _mm_and_si128(_mm_loadu_si128(reinterpret_cast<const __m128i *>(src)), mask);
792_mm_storeu_si128(reinterpret_cast<__m128i *>(dst_lower), lower);
793
794__m128i inv_mask = _mm_xor_si128(mask, _mm_cmpeq_epi32(_mm_setzero_si128(), _mm_setzero_si128()));
795__m128i upper = _mm_or_si128(lower, inv_mask);
796_mm_storeu_si128(reinterpret_cast<__m128i *>(dst_upper), upper);
797}
798
799#else
800
801/// NOTE IPv6 is stored in memory in big endian format that makes some difficulties.
802static void applyCIDRMask(const char * __restrict src, char * __restrict dst_lower, char * __restrict dst_upper, UInt8 bits_to_keep)
803{
804const auto & mask = getCIDRMaskIPv6(bits_to_keep);
805
806for (size_t i = 0; i < 16; ++i)
807{
808dst_lower[i] = src[i] & mask[i];
809dst_upper[i] = dst_lower[i] | ~mask[i];
810}
811}
812
813#endif
814
815public:
816static constexpr auto name = "IPv6CIDRToRange";
817static FunctionPtr create(ContextPtr) { return std::make_shared<FunctionIPv6CIDRToRange>(); }
818
819String getName() const override { return name; }
820size_t getNumberOfArguments() const override { return 2; }
821bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override { return false; }
822
823DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
824{
825const auto * ipv6 = checkAndGetDataType<DataTypeIPv6>(arguments[0].get());
826const auto * str = checkAndGetDataType<DataTypeFixedString>(arguments[0].get());
827if (!ipv6 && !(str && str->getN() == IPV6_BINARY_LENGTH))
828throw Exception(
829ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
830"Illegal type {} of first argument of function {}, expected IPv6 or FixedString({})",
831arguments[0]->getName(), getName(), IPV6_BINARY_LENGTH
832);
833
834const DataTypePtr & second_argument = arguments[1];
835if (!isUInt8(second_argument))
836throw Exception(
837ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
838"Illegal type {} of second argument of function {}, expected UInt8",
839second_argument->getName(), getName()
840);
841
842DataTypePtr element = std::make_shared<DataTypeIPv6>();
843return std::make_shared<DataTypeTuple>(DataTypes{element, element});
844}
845
846bool useDefaultImplementationForConstants() const override { return true; }
847
848
849ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t input_rows_count) const override
850{
851const auto & col_type_name_cidr = arguments[1];
852const ColumnPtr & column_cidr = col_type_name_cidr.column;
853
854const auto * col_const_cidr_in = checkAndGetColumnConst<ColumnUInt8>(column_cidr.get());
855const auto * col_cidr_in = checkAndGetColumn<ColumnUInt8>(column_cidr.get());
856
857if (!col_const_cidr_in && !col_cidr_in)
858throw Exception(
859ErrorCodes::ILLEGAL_COLUMN,
860"Illegal column {} of argument of function {}",
861arguments[1].column->getName(), getName()
862);
863
864const auto & col_type_name_ip = arguments[0];
865const ColumnPtr & column_ip = col_type_name_ip.column;
866
867const auto * col_const_ip_in = checkAndGetColumnConst<ColumnIPv6>(column_ip.get());
868const auto * col_ip_in = checkAndGetColumn<ColumnIPv6>(column_ip.get());
869
870const auto * col_const_str_in = checkAndGetColumnConst<ColumnFixedString>(column_ip.get());
871const auto * col_str_in = checkAndGetColumn<ColumnFixedString>(column_ip.get());
872
873std::function<const char *(size_t)> get_ip_data;
874if (col_const_ip_in)
875get_ip_data = [col_const_ip_in](size_t) { return col_const_ip_in->getDataAt(0).data; };
876else if (col_const_str_in)
877get_ip_data = [col_const_str_in](size_t) { return col_const_str_in->getDataAt(0).data; };
878else if (col_ip_in)
879get_ip_data = [col_ip_in](size_t i) { return reinterpret_cast<const char *>(&col_ip_in->getData()[i]); };
880else if (col_str_in)
881get_ip_data = [col_str_in](size_t i) { return reinterpret_cast<const char *>(&col_str_in->getChars().data()[i * IPV6_BINARY_LENGTH]); };
882else
883throw Exception(
884ErrorCodes::ILLEGAL_COLUMN,
885"Illegal column {} of argument of function {}",
886arguments[0].column->getName(), getName()
887);
888
889auto col_res_lower_range = ColumnIPv6::create();
890auto col_res_upper_range = ColumnIPv6::create();
891
892auto & vec_res_lower_range = col_res_lower_range->getData();
893vec_res_lower_range.resize(input_rows_count);
894
895auto & vec_res_upper_range = col_res_upper_range->getData();
896vec_res_upper_range.resize(input_rows_count);
897
898static constexpr UInt8 max_cidr_mask = IPV6_BINARY_LENGTH * 8;
899
900for (size_t i = 0; i < input_rows_count; ++i)
901{
902UInt8 cidr = col_const_cidr_in
903? col_const_cidr_in->getValue<UInt8>()
904: col_cidr_in->getData()[i];
905
906cidr = std::min(cidr, max_cidr_mask);
907
908applyCIDRMask(get_ip_data(i), reinterpret_cast<char *>(&vec_res_lower_range[i]), reinterpret_cast<char *>(&vec_res_upper_range[i]), cidr);
909}
910
911return ColumnTuple::create(Columns{std::move(col_res_lower_range), std::move(col_res_upper_range)});
912}
913};
914
915
916class FunctionIPv4CIDRToRange : public IFunction
917{
918private:
919static inline std::pair<UInt32, UInt32> applyCIDRMask(UInt32 src, UInt8 bits_to_keep)
920{
921if (bits_to_keep >= 8 * sizeof(UInt32))
922return { src, src };
923if (bits_to_keep == 0)
924return { static_cast<UInt32>(0), static_cast<UInt32>(-1) };
925
926UInt32 mask = static_cast<UInt32>(-1) << (8 * sizeof(UInt32) - bits_to_keep);
927UInt32 lower = src & mask;
928UInt32 upper = lower | ~mask;
929
930return { lower, upper };
931}
932
933template <typename ArgType>
934ColumnPtr executeTyped(const ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t input_rows_count) const
935{
936using ColumnType = ColumnVector<ArgType>;
937const auto & col_type_name_ip = arguments[0];
938const ColumnPtr & column_ip = col_type_name_ip.column;
939
940const auto * col_const_ip_in = checkAndGetColumnConst<ColumnType>(column_ip.get());
941const auto * col_ip_in = checkAndGetColumn<ColumnType>(column_ip.get());
942
943const auto & col_type_name_cidr = arguments[1];
944const ColumnPtr & column_cidr = col_type_name_cidr.column;
945
946const auto * col_const_cidr_in = checkAndGetColumnConst<ColumnUInt8>(column_cidr.get());
947const auto * col_cidr_in = checkAndGetColumn<ColumnUInt8>(column_cidr.get());
948
949auto col_res_lower_range = ColumnIPv4::create();
950auto col_res_upper_range = ColumnIPv4::create();
951
952auto & vec_res_lower_range = col_res_lower_range->getData();
953vec_res_lower_range.resize(input_rows_count);
954
955auto & vec_res_upper_range = col_res_upper_range->getData();
956vec_res_upper_range.resize(input_rows_count);
957
958for (size_t i = 0; i < input_rows_count; ++i)
959{
960ArgType ip = col_const_ip_in
961? col_const_ip_in->template getValue<ArgType>()
962: col_ip_in->getData()[i];
963
964UInt8 cidr = col_const_cidr_in
965? col_const_cidr_in->getValue<UInt8>()
966: col_cidr_in->getData()[i];
967
968std::tie(vec_res_lower_range[i], vec_res_upper_range[i]) = applyCIDRMask(ip, cidr);
969}
970
971return ColumnTuple::create(Columns{std::move(col_res_lower_range), std::move(col_res_upper_range)});
972}
973
974public:
975static constexpr auto name = "IPv4CIDRToRange";
976static FunctionPtr create(ContextPtr) { return std::make_shared<FunctionIPv4CIDRToRange>(); }
977
978String getName() const override { return name; }
979size_t getNumberOfArguments() const override { return 2; }
980bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override { return false; }
981
982DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
983{
984WhichDataType arg_type(arguments[0]);
985if (!(arg_type.isIPv4() || arg_type.isUInt8() || arg_type.isUInt16() || arg_type.isUInt32()))
986throw Exception(
987ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
988"Illegal type {} of first argument of function {}, expected IPv4 or UInt8 or UInt16 or UInt32",
989arguments[0]->getName(), getName()
990);
991
992
993const DataTypePtr & second_argument = arguments[1];
994if (!isUInt8(second_argument))
995throw Exception(
996ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
997"Illegal type {} of second argument of function {}, expected UInt8",
998second_argument->getName(), getName()
999);
1000
1001DataTypePtr element = DataTypeFactory::instance().get("IPv4");
1002return std::make_shared<DataTypeTuple>(DataTypes{element, element});
1003}
1004
1005bool useDefaultImplementationForConstants() const override { return true; }
1006
1007
1008ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & ret_type, size_t input_rows_count) const override
1009{
1010if (arguments[1].type->getTypeId() != TypeIndex::UInt8)
1011throw Exception(
1012ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
1013"Illegal type {} of second argument of function {}, expected UInt8", arguments[1].type->getName(), getName()
1014);
1015
1016switch (arguments[0].type->getTypeId())
1017{
1018case TypeIndex::IPv4: return executeTyped<IPv4>(arguments, ret_type, input_rows_count);
1019case TypeIndex::UInt8: return executeTyped<UInt8>(arguments, ret_type, input_rows_count);
1020case TypeIndex::UInt16: return executeTyped<UInt16>(arguments, ret_type, input_rows_count);
1021case TypeIndex::UInt32: return executeTyped<UInt32>(arguments, ret_type, input_rows_count);
1022default: break;
1023}
1024
1025throw Exception(
1026ErrorCodes::ILLEGAL_COLUMN,
1027"Illegal column {} of argument of function {}, expected IPv4 or UInt8 or UInt16 or UInt32",
1028arguments[0].column->getName(), getName()
1029);
1030}
1031};
1032
1033class FunctionIsIPv4String : public IFunction
1034{
1035public:
1036static constexpr auto name = "isIPv4String";
1037
1038static FunctionPtr create(ContextPtr) { return std::make_shared<FunctionIsIPv4String>(); }
1039
1040String getName() const override { return name; }
1041
1042size_t getNumberOfArguments() const override { return 1; }
1043
1044bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override { return false; }
1045
1046bool useDefaultImplementationForConstants() const override { return true; }
1047
1048DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
1049{
1050if (!isString(arguments[0]))
1051throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Illegal type {} of argument of function {}",
1052arguments[0]->getName(), getName());
1053return std::make_shared<DataTypeUInt8>();
1054}
1055
1056ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const override
1057{
1058const ColumnString * input_column = checkAndGetColumn<ColumnString>(arguments[0].column.get());
1059
1060if (!input_column)
1061{
1062throw Exception(
1063ErrorCodes::ILLEGAL_COLUMN, "Illegal column {} of argument of function {}", arguments[0].column->getName(), getName());
1064}
1065
1066auto col_res = ColumnUInt8::create();
1067
1068ColumnUInt8::Container & vec_res = col_res->getData();
1069vec_res.resize(input_column->size());
1070
1071const ColumnString::Chars & vec_src = input_column->getChars();
1072const ColumnString::Offsets & offsets_src = input_column->getOffsets();
1073size_t prev_offset = 0;
1074UInt32 result = 0;
1075
1076for (size_t i = 0; i < vec_res.size(); ++i)
1077{
1078vec_res[i] = DB::parseIPv4whole(reinterpret_cast<const char *>(&vec_src[prev_offset]), reinterpret_cast<unsigned char *>(&result));
1079prev_offset = offsets_src[i];
1080}
1081
1082return col_res;
1083}
1084};
1085
1086class FunctionIsIPv6String : public IFunction
1087{
1088public:
1089static constexpr auto name = "isIPv6String";
1090
1091static FunctionPtr create(ContextPtr) { return std::make_shared<FunctionIsIPv6String>(); }
1092
1093String getName() const override { return name; }
1094
1095size_t getNumberOfArguments() const override { return 1; }
1096
1097bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override { return false; }
1098
1099bool useDefaultImplementationForConstants() const override { return true; }
1100
1101DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
1102{
1103if (!isString(arguments[0]))
1104{
1105throw Exception(
1106ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Illegal type {} of argument of function {}", arguments[0]->getName(), getName());
1107}
1108
1109return std::make_shared<DataTypeUInt8>();
1110}
1111
1112ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const override
1113{
1114const ColumnString * input_column = checkAndGetColumn<ColumnString>(arguments[0].column.get());
1115if (!input_column)
1116{
1117throw Exception(
1118ErrorCodes::ILLEGAL_COLUMN, "Illegal column {} of argument of function {}", arguments[0].column->getName(), getName());
1119}
1120
1121auto col_res = ColumnUInt8::create();
1122
1123ColumnUInt8::Container & vec_res = col_res->getData();
1124vec_res.resize(input_column->size());
1125
1126const ColumnString::Chars & vec_src = input_column->getChars();
1127const ColumnString::Offsets & offsets_src = input_column->getOffsets();
1128size_t prev_offset = 0;
1129char buffer[IPV6_BINARY_LENGTH];
1130
1131for (size_t i = 0; i < vec_res.size(); ++i)
1132{
1133vec_res[i] = DB::parseIPv6whole(reinterpret_cast<const char *>(&vec_src[prev_offset]),
1134reinterpret_cast<const char *>(&vec_src[offsets_src[i] - 1]),
1135reinterpret_cast<unsigned char *>(buffer));
1136prev_offset = offsets_src[i];
1137}
1138
1139return col_res;
1140}
1141};
1142
1143struct NameFunctionIPv4NumToString { static constexpr auto name = "IPv4NumToString"; };
1144struct NameFunctionIPv4NumToStringClassC { static constexpr auto name = "IPv4NumToStringClassC"; };
1145
1146REGISTER_FUNCTION(Coding)
1147{
1148factory.registerFunction<FunctionCutIPv6>();
1149factory.registerFunction<FunctionIPv4ToIPv6>();
1150factory.registerFunction<FunctionMACNumToString>();
1151factory.registerFunction<FunctionMACStringTo<ParseMACImpl>>();
1152factory.registerFunction<FunctionMACStringTo<ParseOUIImpl>>();
1153factory.registerFunction<FunctionIPv6CIDRToRange>();
1154factory.registerFunction<FunctionIPv4CIDRToRange>();
1155factory.registerFunction<FunctionIsIPv4String>();
1156factory.registerFunction<FunctionIsIPv6String>();
1157
1158factory.registerFunction<FunctionIPv4NumToString<0, NameFunctionIPv4NumToString>>();
1159factory.registerFunction<FunctionIPv4NumToString<1, NameFunctionIPv4NumToStringClassC>>();
1160
1161factory.registerFunction<FunctionIPv4StringToNum<IPStringToNumExceptionMode::Throw>>();
1162factory.registerFunction<FunctionIPv4StringToNum<IPStringToNumExceptionMode::Default>>();
1163factory.registerFunction<FunctionIPv4StringToNum<IPStringToNumExceptionMode::Null>>();
1164
1165factory.registerFunction<FunctionIPv6NumToString>();
1166factory.registerFunction<FunctionIPv6StringToNum<IPStringToNumExceptionMode::Throw>>();
1167factory.registerFunction<FunctionIPv6StringToNum<IPStringToNumExceptionMode::Default>>();
1168factory.registerFunction<FunctionIPv6StringToNum<IPStringToNumExceptionMode::Null>>();
1169
1170/// MySQL compatibility aliases:
1171factory.registerAlias("INET_ATON", FunctionIPv4StringToNum<IPStringToNumExceptionMode::Throw>::name, FunctionFactory::CaseInsensitive);
1172factory.registerAlias("INET6_NTOA", FunctionIPv6NumToString::name, FunctionFactory::CaseInsensitive);
1173factory.registerAlias("INET6_ATON", FunctionIPv6StringToNum<IPStringToNumExceptionMode::Throw>::name, FunctionFactory::CaseInsensitive);
1174factory.registerAlias("INET_NTOA", NameFunctionIPv4NumToString::name, FunctionFactory::CaseInsensitive);
1175}
1176
1177}
1178