Merge pull request #16155 from nikitamikhaylov/vladimir-golovchenko-fix-IPvXCIDRToRange

Merging #15856
This commit is contained in:
Nikita Mikhaylov 2020-10-21 15:01:30 +03:00 committed by GitHub
commit ef5dd73ae0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 56 additions and 17 deletions

View File

@ -1659,7 +1659,7 @@ public:
if (!isUInt8(second_argument)) if (!isUInt8(second_argument))
throw Exception{"Illegal type " + second_argument->getName() throw Exception{"Illegal type " + second_argument->getName()
+ " of second argument of function " + getName() + " of second argument of function " + getName()
+ ", expected numeric type.", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT}; + ", expected UInt8", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT};
DataTypePtr element = DataTypeFactory::instance().get("IPv6"); DataTypePtr element = DataTypeFactory::instance().get("IPv6");
return std::make_shared<DataTypeTuple>(DataTypes{element, element}); return std::make_shared<DataTypeTuple>(DataTypes{element, element});
@ -1673,19 +1673,21 @@ public:
const auto & col_type_name_ip = columns[arguments[0]]; const auto & col_type_name_ip = columns[arguments[0]];
const ColumnPtr & column_ip = col_type_name_ip.column; const ColumnPtr & column_ip = col_type_name_ip.column;
const auto col_const_ip_in = checkAndGetColumnConst<ColumnFixedString>(column_ip.get());
const auto col_ip_in = checkAndGetColumn<ColumnFixedString>(column_ip.get()); const auto col_ip_in = checkAndGetColumn<ColumnFixedString>(column_ip.get());
if (!col_ip_in) if (!col_ip_in && !col_const_ip_in)
throw Exception("Illegal column " + columns[arguments[0]].column->getName() throw Exception("Illegal column " + columns[arguments[0]].column->getName()
+ " of argument of function " + getName(), + " of argument of function " + getName(),
ErrorCodes::ILLEGAL_COLUMN); ErrorCodes::ILLEGAL_COLUMN);
if (col_ip_in->getN() != IPV6_BINARY_LENGTH) if ((col_const_ip_in && col_const_ip_in->getValue<String>().size() != IPV6_BINARY_LENGTH) ||
throw Exception("Illegal type " + col_type_name_ip.type->getName() + (col_ip_in && col_ip_in->getN() != IPV6_BINARY_LENGTH))
" of column " + col_ip_in->getName() + throw Exception("Illegal type " + col_type_name_ip.type->getName() +
" argument of function " + getName() + " of column " + column_ip->getName() +
", expected FixedString(" + toString(IPV6_BINARY_LENGTH) + ")", " argument of function " + getName() +
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); ", expected FixedString(" + toString(IPV6_BINARY_LENGTH) + ")",
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
const auto & col_type_name_cidr = columns[arguments[1]]; const auto & col_type_name_cidr = columns[arguments[1]];
const ColumnPtr & column_cidr = col_type_name_cidr.column; const ColumnPtr & column_cidr = col_type_name_cidr.column;
@ -1698,8 +1700,6 @@ public:
+ " of argument of function " + getName(), + " of argument of function " + getName(),
ErrorCodes::ILLEGAL_COLUMN); ErrorCodes::ILLEGAL_COLUMN);
const auto & vec_in = col_ip_in->getChars();
auto col_res_lower_range = ColumnFixedString::create(IPV6_BINARY_LENGTH); auto col_res_lower_range = ColumnFixedString::create(IPV6_BINARY_LENGTH);
auto col_res_upper_range = ColumnFixedString::create(IPV6_BINARY_LENGTH); auto col_res_upper_range = ColumnFixedString::create(IPV6_BINARY_LENGTH);
@ -1711,14 +1711,24 @@ public:
static constexpr UInt8 max_cidr_mask = IPV6_BINARY_LENGTH * 8; static constexpr UInt8 max_cidr_mask = IPV6_BINARY_LENGTH * 8;
const String col_const_ip_str = col_const_ip_in ? col_const_ip_in->getValue<String>() : "";
const UInt8 * col_const_ip_value = col_const_ip_in ? reinterpret_cast<const UInt8 *>(col_const_ip_str.c_str()) : nullptr;
for (size_t offset = 0; offset < input_rows_count; ++offset) for (size_t offset = 0; offset < input_rows_count; ++offset)
{ {
const size_t offset_ipv6 = offset * IPV6_BINARY_LENGTH; const size_t offset_ipv6 = offset * IPV6_BINARY_LENGTH;
const UInt8 * ip = col_const_ip_in
? col_const_ip_value
: &col_ip_in->getChars()[offset_ipv6];
UInt8 cidr = col_const_cidr_in UInt8 cidr = col_const_cidr_in
? col_const_cidr_in->getValue<UInt8>() ? col_const_cidr_in->getValue<UInt8>()
: col_cidr_in->getData()[offset]; : col_cidr_in->getData()[offset];
cidr = std::min(cidr, max_cidr_mask); cidr = std::min(cidr, max_cidr_mask);
applyCIDRMask(&vec_in[offset_ipv6], &vec_res_lower_range[offset_ipv6], &vec_res_upper_range[offset_ipv6], cidr);
applyCIDRMask(ip, &vec_res_lower_range[offset_ipv6], &vec_res_upper_range[offset_ipv6], cidr);
} }
columns[result].column = ColumnTuple::create(Columns{std::move(col_res_lower_range), std::move(col_res_upper_range)}); columns[result].column = ColumnTuple::create(Columns{std::move(col_res_lower_range), std::move(col_res_upper_range)});
@ -1763,7 +1773,7 @@ public:
if (!isUInt8(second_argument)) if (!isUInt8(second_argument))
throw Exception{"Illegal type " + second_argument->getName() throw Exception{"Illegal type " + second_argument->getName()
+ " of second argument of function " + getName() + " of second argument of function " + getName()
+ ", expected numeric type.", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT}; + ", expected UInt8", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT};
DataTypePtr element = DataTypeFactory::instance().get("IPv4"); DataTypePtr element = DataTypeFactory::instance().get("IPv4");
return std::make_shared<DataTypeTuple>(DataTypes{element, element}); return std::make_shared<DataTypeTuple>(DataTypes{element, element});
@ -1777,8 +1787,9 @@ public:
const auto & col_type_name_ip = columns[arguments[0]]; const auto & col_type_name_ip = columns[arguments[0]];
const ColumnPtr & column_ip = col_type_name_ip.column; const ColumnPtr & column_ip = col_type_name_ip.column;
const auto col_const_ip_in = checkAndGetColumnConst<ColumnUInt32>(column_ip.get());
const auto col_ip_in = checkAndGetColumn<ColumnUInt32>(column_ip.get()); const auto col_ip_in = checkAndGetColumn<ColumnUInt32>(column_ip.get());
if (!col_ip_in) if (!col_const_ip_in && !col_ip_in)
throw Exception("Illegal column " + columns[arguments[0]].column->getName() throw Exception("Illegal column " + columns[arguments[0]].column->getName()
+ " of argument of function " + getName(), + " of argument of function " + getName(),
ErrorCodes::ILLEGAL_COLUMN); ErrorCodes::ILLEGAL_COLUMN);
@ -1794,8 +1805,6 @@ public:
+ " of argument of function " + getName(), + " of argument of function " + getName(),
ErrorCodes::ILLEGAL_COLUMN); ErrorCodes::ILLEGAL_COLUMN);
const auto & vec_in = col_ip_in->getData();
auto col_res_lower_range = ColumnUInt32::create(); auto col_res_lower_range = ColumnUInt32::create();
auto col_res_upper_range = ColumnUInt32::create(); auto col_res_upper_range = ColumnUInt32::create();
@ -1807,11 +1816,15 @@ public:
for (size_t i = 0; i < input_rows_count; ++i) for (size_t i = 0; i < input_rows_count; ++i)
{ {
UInt32 ip = col_const_ip_in
? col_const_ip_in->getValue<UInt32>()
: col_ip_in->getData()[i];
UInt8 cidr = col_const_cidr_in UInt8 cidr = col_const_cidr_in
? col_const_cidr_in->getValue<UInt8>() ? col_const_cidr_in->getValue<UInt8>()
: col_cidr_in->getData()[i]; : col_cidr_in->getData()[i];
std::tie(vec_res_lower_range[i], vec_res_upper_range[i]) = applyCIDRMask(vec_in[i], cidr); std::tie(vec_res_lower_range[i], vec_res_upper_range[i]) = applyCIDRMask(ip, cidr);
} }
columns[result].column = ColumnTuple::create(Columns{std::move(col_res_lower_range), std::move(col_res_upper_range)}); columns[result].column = ColumnTuple::create(Columns{std::move(col_res_lower_range), std::move(col_res_upper_range)});

View File

@ -1,3 +1,5 @@
check invalid params
tests
4 4
3 3
2 2
@ -14,3 +16,5 @@
('192.168.5.2','192.168.5.2') ('192.168.5.2','192.168.5.2')
('0.0.0.0','0.255.255.255') ('0.0.0.0','0.255.255.255')
('240.0.0.0','255.255.255.255') ('240.0.0.0','255.255.255.255')
('240.0.0.0','255.255.255.255')
('248.0.0.0','255.255.255.255')

View File

@ -1,3 +1,9 @@
SELECT 'check invalid params';
SELECT IPv4CIDRToRange(1, 1); -- { serverError 43 }
SELECT IPv4CIDRToRange(toUInt32(1), 512); -- { serverError 43 }
SELECT 'tests';
DROP TABLE IF EXISTS ipv4_range; DROP TABLE IF EXISTS ipv4_range;
CREATE TABLE ipv4_range(ip IPv4, cidr UInt8) ENGINE = Memory; CREATE TABLE ipv4_range(ip IPv4, cidr UInt8) ENGINE = Memory;
@ -16,7 +22,9 @@ WITH IPv4CIDRToRange(ip, cidr) as ip_range SELECT ip, cidr, IPv4NumToString(tupl
DROP TABLE ipv4_range; DROP TABLE ipv4_range;
SELECT IPv4CIDRToRange(toIPv4('192.168.5.2'), 0); SELECT IPv4CIDRToRange(toIPv4('192.168.5.2'), 0);
SELEcT IPv4CIDRToRange(toIPv4('255.255.255.255'), 8); SELECT IPv4CIDRToRange(toIPv4('255.255.255.255'), 8);
SELECT IPv4CIDRToRange(toIPv4('192.168.5.2'), 32); SELECT IPv4CIDRToRange(toIPv4('192.168.5.2'), 32);
SELECT IPv4CIDRToRange(toIPv4('0.0.0.0'), 8); SELECT IPv4CIDRToRange(toIPv4('0.0.0.0'), 8);
SELECT IPv4CIDRToRange(toIPv4('255.0.0.0'), 4); SELECT IPv4CIDRToRange(toIPv4('255.0.0.0'), 4);
SELECT IPv4CIDRToRange(toIPv4('255.0.0.0'), toUInt8(4 + number)) FROM numbers(2);

View File

@ -1,3 +1,5 @@
check invalid params
tests
3 3
4 4
3 3
@ -16,3 +18,5 @@ ffff:: 4 ('f000::','ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff')
('::','ff:ffff:ffff:ffff:ffff:ffff:ffff:ffff') ('::','ff:ffff:ffff:ffff:ffff:ffff:ffff:ffff')
('f000::','ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff') ('f000::','ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff')
1 1
('2001:db8:0:85a3::ac1f:8001','2001:db8:0:85a3::ac1f:8001')
('2001:db8:0:85a3::ac1f:8000','2001:db8:0:85a3::ac1f:8001')

View File

@ -1,3 +1,11 @@
SELECT 'check invalid params';
SELECT IPv6CIDRToRange(1, 1); -- { serverError 43 }
SELECT IPv6CIDRToRange('1234', 1); -- { serverError 43 }
SELECT IPv6CIDRToRange(toFixedString('1234', 10), 1); -- { serverError 43 }
SELECT IPv6CIDRToRange(toFixedString('1234', 16), toUInt16(1)); -- { serverError 43 }
SELECT 'tests';
DROP TABLE IF EXISTS ipv6_range; DROP TABLE IF EXISTS ipv6_range;
CREATE TABLE ipv6_range(ip IPv6, cidr UInt8) ENGINE = Memory; CREATE TABLE ipv6_range(ip IPv6, cidr UInt8) ENGINE = Memory;
@ -23,3 +31,5 @@ SELECT IPv6CIDRToRange(IPv6StringToNum('ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff'
SELECT IPv6CIDRToRange(IPv6StringToNum('0000:0000:0000:0000:0000:0000:0000:0000'), 8); SELECT IPv6CIDRToRange(IPv6StringToNum('0000:0000:0000:0000:0000:0000:0000:0000'), 8);
SELECT IPv6CIDRToRange(IPv6StringToNum('ffff:0000:0000:0000:0000:0000:0000:0000'), 4); SELECT IPv6CIDRToRange(IPv6StringToNum('ffff:0000:0000:0000:0000:0000:0000:0000'), 4);
SELECT IPv6CIDRToRange(IPv6StringToNum('2001:0db8:0000:85a3:0000:0000:ac1f:8001'), 128) = IPv6CIDRToRange(IPv6StringToNum('2001:0db8:0000:85a3:0000:0000:ac1f:8001'), 200) ; SELECT IPv6CIDRToRange(IPv6StringToNum('2001:0db8:0000:85a3:0000:0000:ac1f:8001'), 128) = IPv6CIDRToRange(IPv6StringToNum('2001:0db8:0000:85a3:0000:0000:ac1f:8001'), 200) ;
SELECT IPv6CIDRToRange(IPv6StringToNum('2001:0db8:0000:85a3:0000:0000:ac1f:8001'), toUInt8(128 - number)) FROM numbers(2);