1#include <Columns/ColumnsNumber.h>
2#include <Common/Exception.h>
3#include <Common/formatIPv6.h>
4#include <DataTypes/DataTypeCustomSimpleTextSerialization.h>
5#include <DataTypes/DataTypeFactory.h>
6#include <DataTypes/DataTypeCustom.h>
7#include <Functions/FunctionHelpers.h>
8#include <Functions/FunctionsCoding.h>
9
10namespace DB
11{
12
13namespace ErrorCodes
14{
15 extern const int ILLEGAL_COLUMN;
16 extern const int UNSUPPORTED_METHOD;
17 extern const int CANNOT_PARSE_DOMAIN_VALUE_FROM_STRING;
18}
19
20namespace
21{
22
23class DataTypeCustomIPv4Serialization : public DataTypeCustomSimpleTextSerialization
24{
25public:
26 void serializeText(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const override
27 {
28 const auto col = checkAndGetColumn<ColumnUInt32>(&column);
29 if (!col)
30 {
31 throw Exception("IPv4 type can only serialize columns of type UInt32." + column.getName(), ErrorCodes::ILLEGAL_COLUMN);
32 }
33
34 char buffer[IPV4_MAX_TEXT_LENGTH + 1] = {'\0'};
35 char * ptr = buffer;
36 formatIPv4(reinterpret_cast<const unsigned char *>(&col->getData()[row_num]), ptr);
37
38 ostr.write(buffer, strlen(buffer));
39 }
40
41 void deserializeText(IColumn & column, ReadBuffer & istr, const FormatSettings &) const override
42 {
43 ColumnUInt32 * col = typeid_cast<ColumnUInt32 *>(&column);
44 if (!col)
45 {
46 throw Exception("IPv4 type can only deserialize columns of type UInt32." + column.getName(), ErrorCodes::ILLEGAL_COLUMN);
47 }
48
49 char buffer[IPV4_MAX_TEXT_LENGTH + 1] = {'\0'};
50 istr.read(buffer, sizeof(buffer) - 1);
51 UInt32 ipv4_value = 0;
52 if (!parseIPv4(buffer, reinterpret_cast<unsigned char *>(&ipv4_value)))
53 {
54 throw Exception("Invalid IPv4 value.", ErrorCodes::CANNOT_PARSE_DOMAIN_VALUE_FROM_STRING);
55 }
56
57 col->insert(ipv4_value);
58 }
59};
60
61class DataTypeCustomIPv6Serialization : public DataTypeCustomSimpleTextSerialization
62{
63public:
64
65 void serializeText(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const override
66 {
67 const auto col = checkAndGetColumn<ColumnFixedString>(&column);
68 if (!col)
69 {
70 throw Exception("IPv6 type domain can only serialize columns of type FixedString(16)." + column.getName(), ErrorCodes::ILLEGAL_COLUMN);
71 }
72
73 char buffer[IPV6_MAX_TEXT_LENGTH + 1] = {'\0'};
74 char * ptr = buffer;
75 formatIPv6(reinterpret_cast<const unsigned char *>(col->getDataAt(row_num).data), ptr);
76
77 ostr.write(buffer, strlen(buffer));
78 }
79
80 void deserializeText(IColumn & column, ReadBuffer & istr, const FormatSettings &) const override
81 {
82 ColumnFixedString * col = typeid_cast<ColumnFixedString *>(&column);
83 if (!col)
84 {
85 throw Exception("IPv6 type domain can only deserialize columns of type FixedString(16)." + column.getName(), ErrorCodes::ILLEGAL_COLUMN);
86 }
87
88 char buffer[IPV6_MAX_TEXT_LENGTH + 1] = {'\0'};
89 istr.read(buffer, sizeof(buffer) - 1);
90
91 std::string ipv6_value(IPV6_BINARY_LENGTH, '\0');
92 if (!parseIPv6(buffer, reinterpret_cast<unsigned char *>(ipv6_value.data())))
93 {
94 throw Exception("Invalid IPv6 value.", ErrorCodes::CANNOT_PARSE_DOMAIN_VALUE_FROM_STRING);
95 }
96
97 col->insertString(ipv6_value);
98 }
99};
100
101}
102
103void registerDataTypeDomainIPv4AndIPv6(DataTypeFactory & factory)
104{
105 factory.registerSimpleDataTypeCustom("IPv4", [&](const String & /*type_name*/)
106 {
107 return std::make_pair(DataTypeFactory::instance().get("UInt32"),
108 std::make_unique<DataTypeCustomDesc>(std::make_unique<DataTypeCustomFixedName>("IPv4"), std::make_unique<DataTypeCustomIPv4Serialization>()));
109 });
110
111 factory.registerSimpleDataTypeCustom("IPv6", [&](const String & /*type_name*/)
112 {
113 return std::make_pair(DataTypeFactory::instance().get("FixedString(16)"),
114 std::make_unique<DataTypeCustomDesc>(std::make_unique<DataTypeCustomFixedName>("IPv6"), std::make_unique<DataTypeCustomIPv6Serialization>()));
115 });
116}
117
118}
119