Support builtin function isIPv4String && isIPv6String

This commit is contained in:
spongedc 2020-12-22 16:06:33 +08:00
parent aa7793e38f
commit 121f7ae833
4 changed files with 146 additions and 0 deletions

View File

@ -32,6 +32,8 @@ void registerFunctionsCoding(FunctionFactory & factory)
factory.registerFunction<FunctionToIPv6>();
factory.registerFunction<FunctionIPv6CIDRToRange>();
factory.registerFunction<FunctionIPv4CIDRToRange>();
factory.registerFunction<FunctionIsIPv4String>();
factory.registerFunction<FunctionIsIPv6String>();
}
}

View File

@ -1831,5 +1831,98 @@ public:
}
};
class FunctionIsIPv4String : public FunctionIPv4StringToNum
{
public:
static constexpr auto name = "isIPv4String";
static FunctionPtr create(const Context &) { return std::make_shared<FunctionIsIPv4String>(); }
String getName() const override { return name; }
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
{
if (!isString(arguments[0]))
throw Exception("Illegal type " + arguments[0]->getName() + " of argument of function " + getName(),
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
return std::make_shared<DataTypeUInt8>();
}
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const override
{
const ColumnPtr & column = arguments[0].column;
if (const ColumnString * col = checkAndGetColumn<ColumnString>(column.get()))
{
auto col_res = ColumnUInt8::create();
ColumnUInt8::Container & vec_res = col_res->getData();
vec_res.resize(col->size());
const ColumnString::Chars & vec_src = col->getChars();
const ColumnString::Offsets & offsets_src = col->getOffsets();
size_t prev_offset = 0;
UInt32 result = 0;
for (size_t i = 0; i < vec_res.size(); ++i)
{
vec_res[i] = DB::parseIPv4(reinterpret_cast<const char *>(&vec_src[prev_offset]), reinterpret_cast<unsigned char*>(&result));
prev_offset = offsets_src[i];
}
return col_res;
}
else
throw Exception("Illegal column " + arguments[0].column->getName()
+ " of argument of function " + getName(),
ErrorCodes::ILLEGAL_COLUMN);
}
};
class FunctionIsIPv6String : public FunctionIPv6StringToNum
{
public:
static constexpr auto name = "isIPv6String";
static FunctionPtr create(const Context &) { return std::make_shared<FunctionIsIPv6String>(); }
String getName() const override { return name; }
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
{
if (!isString(arguments[0]))
throw Exception("Illegal type " + arguments[0]->getName() + " of argument of function " + getName(),
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
return std::make_shared<DataTypeUInt8>();
}
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const override
{
const ColumnPtr & column = arguments[0].column;
if (const ColumnString * col = checkAndGetColumn<ColumnString>(column.get()))
{
auto col_res = ColumnUInt8::create();
ColumnUInt8::Container & vec_res = col_res->getData();
vec_res.resize(col->size());
const ColumnString::Chars & vec_src = col->getChars();
const ColumnString::Offsets & offsets_src = col->getOffsets();
size_t prev_offset = 0;
char v[IPV6_BINARY_LENGTH];
for (size_t i = 0; i < vec_res.size(); ++i)
{
vec_res[i] = DB::parseIPv6(reinterpret_cast<const char *>(&vec_src[prev_offset]), reinterpret_cast<unsigned char*>(v));
prev_offset = offsets_src[i];
}
return col_res;
}
else
throw Exception("Illegal column " + arguments[0].column->getName()
+ " of argument of function " + getName(),
ErrorCodes::ILLEGAL_COLUMN);
}
};
}

View File

@ -25,3 +25,27 @@ ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
> 127.0.0.1 2001:db8:ac10:fe01:feed:babe:cafe:f00d
> 127.0.0.1 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
= 127.0.0.1 ::ffff:127.0.0.1
0.0.0.0 is ipv4 string: 1
255.255.255.255 is ipv4 string: 1
192.168.0.91 is ipv4 string: 1
127.0.0.1 is ipv4 string: 1
8.8.8.8 is ipv4 string: 1
hello is ipv4 string: 0
0:0:0:0:0:0:0:0 is ipv4 string: 0
0000:0000:0000:0000:0000:FFFF:C1FC:110A is ipv4 string: 0
FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF is ipv4 string: 0
::ffff:127.0.0.1 is ipv4 string: 0
::ffff:8.8.8.8 is ipv4 string: 0
2001:0DB8:AC10:FE01:FEED:BABE:CAFE:F00D is ipv4 string: 0
0.0.0.0 is ipv6 string: 0
255.255.255.255 is ipv6 string: 0
192.168.0.91 is ipv6 string: 0
127.0.0.1 is ipv6 string: 0
8.8.8.8 is ipv6 string: 0
hello is ipv6 string: 0
0:0:0:0:0:0:0:0 is ipv6 string: 1
0000:0000:0000:0000:0000:FFFF:C1FC:110A is ipv6 string: 1
FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF is ipv6 string: 1
::ffff:127.0.0.1 is ipv6 string: 1
::ffff:8.8.8.8 is ipv6 string: 1
2001:0DB8:AC10:FE01:FEED:BABE:CAFE:F00D is ipv6 string: 1

View File

@ -57,3 +57,30 @@ SELECT '= 127.0.0.1', ipv6_ FROM ipv6_test
-- TODO: Assert that invalid values can't be inserted into IPv6 column.
DROP TABLE IF EXISTS ipv6_test;
SELECT '0.0.0.0 is ipv4 string: ', isIPv4String('0.0.0.0');
SELECT '255.255.255.255 is ipv4 string: ', isIPv4String('255.255.255.255');
SELECT '192.168.0.91 is ipv4 string: ', isIPv4String('192.168.0.91');
SELECT '127.0.0.1 is ipv4 string: ', isIPv4String('127.0.0.1');
SELECT '8.8.8.8 is ipv4 string: ', isIPv4String('8.8.8.8');
SELECT 'hello is ipv4 string: ', isIPv4String('hello');
SELECT '0:0:0:0:0:0:0:0 is ipv4 string: ', isIPv4String('0:0:0:0:0:0:0:0');
SELECT '0000:0000:0000:0000:0000:FFFF:C1FC:110A is ipv4 string: ', isIPv4String('0000:0000:0000:0000:0000:FFFF:C1FC:110A');
SELECT 'FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF is ipv4 string: ', isIPv4String('FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF');
SELECT '::ffff:127.0.0.1 is ipv4 string: ', isIPv4String('::ffff:127.0.0.1');
SELECT '::ffff:8.8.8.8 is ipv4 string: ', isIPv4String('::ffff:8.8.8.8');
SELECT '2001:0DB8:AC10:FE01:FEED:BABE:CAFE:F00D is ipv4 string: ', isIPv4String('2001:0DB8:AC10:FE01:FEED:BABE:CAFE:F00D');
SELECT '0.0.0.0 is ipv6 string: ', isIPv6String('0.0.0.0');
SELECT '255.255.255.255 is ipv6 string: ', isIPv6String('255.255.255.255');
SELECT '192.168.0.91 is ipv6 string: ', isIPv6String('192.168.0.91');
SELECT '127.0.0.1 is ipv6 string: ', isIPv6String('127.0.0.1');
SELECT '8.8.8.8 is ipv6 string: ', isIPv6String('8.8.8.8');
SELECT 'hello is ipv6 string: ', isIPv6String('hello');
SELECT '0:0:0:0:0:0:0:0 is ipv6 string: ', isIPv6String('0:0:0:0:0:0:0:0');
SELECT '0000:0000:0000:0000:0000:FFFF:C1FC:110A is ipv6 string: ', isIPv6String('0000:0000:0000:0000:0000:FFFF:C1FC:110A');
SELECT 'FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF is ipv6 string: ', isIPv6String('FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF');
SELECT '::ffff:127.0.0.1 is ipv6 string: ', isIPv6String('::ffff:127.0.0.1');
SELECT '::ffff:8.8.8.8 is ipv6 string: ', isIPv6String('::ffff:8.8.8.8');
SELECT '2001:0DB8:AC10:FE01:FEED:BABE:CAFE:F00D is ipv6 string: ', isIPv6String('2001:0DB8:AC10:FE01:FEED:BABE:CAFE:F00D');