mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-12-02 12:32:04 +00:00
Support expressions as IP function arguments
This commit is contained in:
parent
8582543816
commit
bfa2820985
@ -55,6 +55,15 @@ The config setting to allow modify dialect setting.
|
|||||||
- [make_set_if()](https://docs.microsoft.com/en-us/azure/data-explorer/kusto/query/makesetif-aggfunction)
|
- [make_set_if()](https://docs.microsoft.com/en-us/azure/data-explorer/kusto/query/makesetif-aggfunction)
|
||||||
`Customers | summarize t = make_set_if(FirstName, Age > 10) by FirstName`
|
`Customers | summarize t = make_set_if(FirstName, Age > 10) by FirstName`
|
||||||
`Customers | summarize t = make_set_if(FirstName, Age > 10, 10) by FirstName`
|
`Customers | summarize t = make_set_if(FirstName, Age > 10, 10) by FirstName`
|
||||||
|
# July XX, 2022
|
||||||
|
|
||||||
|
## IP functions
|
||||||
|
|
||||||
|
The following functions now support arbitrary expressions as their argument.
|
||||||
|
|
||||||
|
- [ipv4_is_private](https://docs.microsoft.com/en-us/azure/data-explorer/kusto/query/ipv4-is-privatefunction)
|
||||||
|
- [ipv4_is_in_range](https://docs.microsoft.com/en-us/azure/data-explorer/kusto/query/ipv4-is-in-range-function)
|
||||||
|
- [ipv4_netmask_suffix](https://docs.microsoft.com/en-us/azure/data-explorer/kusto/query/ipv4-netmask-suffix-function)
|
||||||
|
|
||||||
|
|
||||||
# July 17, 2022
|
# July 17, 2022
|
||||||
|
@ -22,21 +22,6 @@ namespace DB::ErrorCodes
|
|||||||
extern const int SYNTAX_ERROR;
|
extern const int SYNTAX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
String trimQuotes(const String & str)
|
|
||||||
{
|
|
||||||
static constexpr auto QUOTE = '\'';
|
|
||||||
|
|
||||||
const auto first_index = str.find(QUOTE);
|
|
||||||
const auto last_index = str.rfind(QUOTE);
|
|
||||||
if (first_index == String::npos || last_index == String::npos)
|
|
||||||
throw DB::Exception("Syntax error, improper quotation: " + str, DB::ErrorCodes::SYNTAX_ERROR);
|
|
||||||
|
|
||||||
return str.substr(first_index + 1, last_index - first_index - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace DB
|
namespace DB
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -59,8 +44,7 @@ bool Ipv4IsInRange::convertImpl(String & out, IParser::Pos & pos)
|
|||||||
++pos;
|
++pos;
|
||||||
|
|
||||||
const auto ip_range = getConvertedArgument(function_name, pos);
|
const auto ip_range = getConvertedArgument(function_name, pos);
|
||||||
const auto slash_index = ip_range.find('/');
|
out = std::format("isIPAddressInRange({0}, concat({1}, if(position({1}, '/') > 0, '', '/32')))", ip_address, ip_range);
|
||||||
out = std::format(slash_index == String::npos ? "{0} = {1}" : "isIPAddressInRange({0}, {1})", ip_address, ip_range);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,8 +63,9 @@ bool Ipv4IsPrivate::convertImpl(String & out, IParser::Pos & pos)
|
|||||||
if (function_name.empty())
|
if (function_name.empty())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const auto ip_address = trimQuotes(getConvertedArgument(function_name, pos));
|
++pos;
|
||||||
const auto slash_index = ip_address.find('/');
|
|
||||||
|
const auto ip_address = getConvertedArgument(function_name, pos);
|
||||||
|
|
||||||
out += "or(";
|
out += "or(";
|
||||||
for (int i = 0; i < std::ssize(PRIVATE_SUBNETS); ++i)
|
for (int i = 0; i < std::ssize(PRIVATE_SUBNETS); ++i)
|
||||||
@ -88,14 +73,13 @@ bool Ipv4IsPrivate::convertImpl(String & out, IParser::Pos & pos)
|
|||||||
out += i > 0 ? ", " : "";
|
out += i > 0 ? ", " : "";
|
||||||
|
|
||||||
const auto & subnet = PRIVATE_SUBNETS[i];
|
const auto & subnet = PRIVATE_SUBNETS[i];
|
||||||
out += slash_index == String::npos
|
out += std::format(
|
||||||
? std::format("isIPAddressInRange('{0}', '{1}')", ip_address, subnet)
|
"or(and(length(splitByChar('/', {0}) as tokens) = 1, isIPAddressInRange(tokens[1] as ip, '{1}')), "
|
||||||
: std::format(
|
"and(length(tokens) = 2, isIPAddressInRange(IPv4NumToString(tupleElement((IPv4CIDRToRange(toIPv4(ip), "
|
||||||
"and(isIPAddressInRange(IPv4NumToString(tupleElement((IPv4CIDRToRange(toIPv4('{0}'), {1}) as range), 1)) as begin, '{2}'), "
|
"if(isNull(toUInt8OrNull(tokens[-1]) as suffix), throwIf(true, 'Unable to parse suffix'), assumeNotNull(suffix))) as range), "
|
||||||
"isIPAddressInRange(IPv4NumToString(tupleElement(range, 2)) as end, '{2}'))",
|
"1)) as begin, '{1}'), isIPAddressInRange(IPv4NumToString(tupleElement(range, 2)) as end, '{1}')))",
|
||||||
std::string_view(ip_address.c_str(), slash_index),
|
ip_address,
|
||||||
std::string_view(ip_address.c_str() + slash_index + 1, ip_address.length() - slash_index - 1),
|
subnet);
|
||||||
subnet);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
out += ")";
|
out += ")";
|
||||||
@ -104,19 +88,18 @@ bool Ipv4IsPrivate::convertImpl(String & out, IParser::Pos & pos)
|
|||||||
|
|
||||||
bool Ipv4NetmaskSuffix::convertImpl(String & out, IParser::Pos & pos)
|
bool Ipv4NetmaskSuffix::convertImpl(String & out, IParser::Pos & pos)
|
||||||
{
|
{
|
||||||
static constexpr auto DEFAULT_NETMASK = 32;
|
|
||||||
|
|
||||||
const auto function_name = getKQLFunctionName(pos);
|
const auto function_name = getKQLFunctionName(pos);
|
||||||
if (function_name.empty())
|
if (function_name.empty())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
++pos;
|
++pos;
|
||||||
|
|
||||||
const auto ip_range = trimQuotes(getConvertedArgument(function_name, pos));
|
const auto ip_range = getConvertedArgument(function_name, pos);
|
||||||
const auto slash_index = ip_range.find('/');
|
out = std::format(
|
||||||
const std::string_view ip_address(ip_range.c_str(), std::min(ip_range.length(), slash_index));
|
"if(length(splitByChar('/', {0}) as tokens) <= 2 and isIPv4String(tokens[1]), if(length(tokens) != 2, 32, "
|
||||||
const auto netmask = slash_index == String::npos ? DEFAULT_NETMASK : std::strtol(ip_range.c_str() + slash_index + 1, nullptr, 10);
|
"if((toInt8OrNull(tokens[-1]) as suffix) between 1 and 32, suffix, throwIf(true, 'Suffix must be between 1 and 32'))), "
|
||||||
out = std::format("if(and(isIPv4String('{0}'), {1} between 1 and 32), {1}, null)", ip_address, netmask);
|
"throwIf(true, 'Unable to recognize and IP address with or without a suffix'))",
|
||||||
|
ip_range);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user