From 0381a6a1ec383e1b2e25de62b1f406e50b22d126 Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Thu, 2 May 2019 01:09:24 +0300 Subject: [PATCH] Better code for CIDR to range functions #5095 --- dbms/src/Functions/FunctionsCoding.h | 37 +++++++++++-------- .../0_stateless/00937_ipv4_cidr_range.sql | 20 +++++----- .../0_stateless/00938_ipv6_cidr_range.sql | 23 ++++++------ 3 files changed, 43 insertions(+), 37 deletions(-) diff --git a/dbms/src/Functions/FunctionsCoding.h b/dbms/src/Functions/FunctionsCoding.h index 85a270035af..c16652fd201 100644 --- a/dbms/src/Functions/FunctionsCoding.h +++ b/dbms/src/Functions/FunctionsCoding.h @@ -1453,13 +1453,19 @@ public: }; +enum Bound +{ + Lower, + Upper +}; + constexpr size_t ip_range_tuple_size = 2; -class FunctionIPv6CIDRtoIPv6Range : public IFunction +class FunctionIPv6CIDRToRange : public IFunction { -static constexpr size_t bits_in_uint8 = 8; + static constexpr size_t bits_in_uint8 = 8; public: - template + template static void setCIDRMask(const UInt8 * __restrict src, UInt8 * __restrict dst, UInt8 bits_to_keep) { for (size_t offset = 0, byte_offset = bits_in_uint8; offset != IPV6_BINARY_LENGTH; ++offset, byte_offset += bits_in_uint8) @@ -1477,7 +1483,7 @@ public: ? bits_in_uint8 : byte_offset - bits_to_keep; - constexpr UInt8 byte_reference = lower_range ? 0 : std::numeric_limits::max(); + constexpr UInt8 byte_reference = bound == Lower ? 0 : std::numeric_limits::max(); /// Clean the bits we don't want on byte const UInt16 src_byte_shift = (static_cast(src[offset]) >> shifts_bits) << shifts_bits; @@ -1490,8 +1496,8 @@ public: } - static constexpr auto name = "IPv6CIDRtoIPv6Range"; - static FunctionPtr create(const Context &) { return std::make_shared(); } + static constexpr auto name = "IPv6CIDRToRange"; + static FunctionPtr create(const Context &) { return std::make_shared(); } String getName() const override { return name; } @@ -1566,8 +1572,8 @@ public: ? col_const_cidr_in->getValue() : col_cidr_in->getData()[offset]; - setCIDRMask(&vec_in[offset_ipv6], &vec_res_lower_range[offset_ipv6], cidr); - setCIDRMask(&vec_in[offset_ipv6], &vec_res_upper_range[offset_ipv6], cidr); + setCIDRMask(&vec_in[offset_ipv6], &vec_res_lower_range[offset_ipv6], cidr); + setCIDRMask(&vec_in[offset_ipv6], &vec_res_upper_range[offset_ipv6], cidr); } tuple_columns[0] = std::move(col_res_lower_range); @@ -1587,15 +1593,16 @@ public: } }; -class FunctionIPv4CIDRtoIPv4Range : public IFunction + +class FunctionIPv4CIDRToRange : public IFunction { static constexpr size_t bits_in_uint32 = 32; public: - template + template static UInt32 setCIDRMask(UInt32 src, UInt8 bits_to_keep) { - UInt32 byte_reference = lower_range ? 0 : std::numeric_limits::max(); + UInt32 byte_reference = bound == Lower ? 0 : std::numeric_limits::max(); if (bits_to_keep >= bits_in_uint32) return src; @@ -1612,8 +1619,8 @@ public: return static_cast(src_byte_shift | cidr_mask_byte_shift); } - static constexpr auto name = "IPv4CIDRtoIPv4Range"; - static FunctionPtr create(const Context &) { return std::make_shared(); } + static constexpr auto name = "IPv4CIDRToRange"; + static FunctionPtr create(const Context &) { return std::make_shared(); } String getName() const override { return name; } @@ -1677,8 +1684,8 @@ public: ? col_const_cidr_in->getValue() : col_cidr_in->getData()[i]; - vec_res_lower_range[i] = setCIDRMask(vec_in[i], cidr); - vec_res_upper_range[i] = setCIDRMask(vec_in[i], cidr); + vec_res_lower_range[i] = setCIDRMask(vec_in[i], cidr); + vec_res_upper_range[i] = setCIDRMask(vec_in[i], cidr); } tuple_columns[0] = std::move(col_res_lower_range); diff --git a/dbms/tests/queries/0_stateless/00937_ipv4_cidr_range.sql b/dbms/tests/queries/0_stateless/00937_ipv4_cidr_range.sql index fb078140044..2a2aa6812ee 100644 --- a/dbms/tests/queries/0_stateless/00937_ipv4_cidr_range.sql +++ b/dbms/tests/queries/0_stateless/00937_ipv4_cidr_range.sql @@ -5,21 +5,21 @@ CREATE TABLE ipv4_range(ip IPv4, cidr UInt8) ENGINE = Memory; INSERT INTO ipv4_range (ip, cidr) VALUES (toIPv4('192.168.5.2'), 0), (toIPv4('192.168.5.20'), 32), (toIPv4('255.255.255.255'), 16), (toIPv4('192.142.32.2'), 32), (toIPv4('192.172.5.2'), 16), (toIPv4('0.0.0.0'), 8), (toIPv4('255.0.0.0'), 4); -WITH IPv4CIDRtoIPv4Range(toIPv4('192.168.0.0'), 8) as ip_range SELECT COUNT(*) FROM ipv4_range WHERE ip BETWEEN tupleElement(ip_range, 1) AND tupleElement(ip_range, 2); +WITH IPv4CIDRToRange(toIPv4('192.168.0.0'), 8) as ip_range SELECT COUNT(*) FROM ipv4_range WHERE ip BETWEEN tupleElement(ip_range, 1) AND tupleElement(ip_range, 2); -WITH IPv4CIDRtoIPv4Range(toIPv4('192.168.0.0'), 13) as ip_range SELECT COUNT(*) FROM ipv4_range WHERE ip BETWEEN tupleElement(ip_range, 1) AND tupleElement(ip_range, 2); +WITH IPv4CIDRToRange(toIPv4('192.168.0.0'), 13) as ip_range SELECT COUNT(*) FROM ipv4_range WHERE ip BETWEEN tupleElement(ip_range, 1) AND tupleElement(ip_range, 2); -WITH IPv4CIDRtoIPv4Range(toIPv4('192.168.0.0'), 16) as ip_range SELECT COUNT(*) FROM ipv4_range WHERE ip BETWEEN tupleElement(ip_range, 1) AND tupleElement(ip_range, 2); +WITH IPv4CIDRToRange(toIPv4('192.168.0.0'), 16) as ip_range SELECT COUNT(*) FROM ipv4_range WHERE ip BETWEEN tupleElement(ip_range, 1) AND tupleElement(ip_range, 2); -WITH IPv4CIDRtoIPv4Range(toIPv4('192.168.0.0'), 0) as ip_range SELECT COUNT(*) FROM ipv4_range WHERE ip BETWEEN tupleElement(ip_range, 1) AND tupleElement(ip_range, 2); +WITH IPv4CIDRToRange(toIPv4('192.168.0.0'), 0) as ip_range SELECT COUNT(*) FROM ipv4_range WHERE ip BETWEEN tupleElement(ip_range, 1) AND tupleElement(ip_range, 2); -WITH IPv4CIDRtoIPv4Range(ip, cidr) as ip_range SELECT ip, cidr, IPv4NumToString(tupleElement(ip_range, 1)), ip_range FROM ipv4_range; +WITH IPv4CIDRToRange(ip, cidr) as ip_range SELECT ip, cidr, IPv4NumToString(tupleElement(ip_range, 1)), ip_range FROM ipv4_range; DROP TABLE ipv4_range; -SELECT IPv4CIDRtoIPv4Range(toIPv4('192.168.5.2'), 0); -SELEcT IPv4CIDRtoIPv4Range(toIPv4('255.255.255.255'), 8); -SELECT IPv4CIDRtoIPv4Range(toIPv4('192.168.5.2'), 32); -SELECT IPv4CIDRtoIPv4Range(toIPv4('0.0.0.0'), 8); -SELECT IPv4CIDRtoIPv4Range(toIPv4('255.0.0.0'), 4); +SELECT IPv4CIDRToRange(toIPv4('192.168.5.2'), 0); +SELEcT IPv4CIDRToRange(toIPv4('255.255.255.255'), 8); +SELECT IPv4CIDRToRange(toIPv4('192.168.5.2'), 32); +SELECT IPv4CIDRToRange(toIPv4('0.0.0.0'), 8); +SELECT IPv4CIDRToRange(toIPv4('255.0.0.0'), 4); diff --git a/dbms/tests/queries/0_stateless/00938_ipv6_cidr_range.sql b/dbms/tests/queries/0_stateless/00938_ipv6_cidr_range.sql index 1522916072d..22efe7b4923 100644 --- a/dbms/tests/queries/0_stateless/00938_ipv6_cidr_range.sql +++ b/dbms/tests/queries/0_stateless/00938_ipv6_cidr_range.sql @@ -5,23 +5,22 @@ CREATE TABLE ipv6_range(ip IPv6, cidr UInt8) ENGINE = Memory; INSERT INTO ipv6_range (ip, cidr) VALUES (IPv6StringToNum('2001:0db8:0000:85a3:0000:0000:ac1f:8001'), 0), (IPv6StringToNum('2001:0db8:0000:85a3:ffff:ffff:ffff:ffff'), 32), (IPv6StringToNum('ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff'), 16), (IPv6StringToNum('2001:df8:0:85a3::ac1f:8001'), 32), (IPv6StringToNum('2001:0db8:85a3:85a3:0000:0000:ac1f:8001'), 16), (IPv6StringToNum('0000:0000:0000:0000:0000:0000:0000:0000'), 8), (IPv6StringToNum('ffff:0000:0000:0000:0000:0000:0000:0000'), 4); -WITH IPv6CIDRtoIPv6Range(IPv6StringToNum('2001:0db8:0000:85a3:0000:0000:ac1f:8001'), 32) as ip_range SELECT COUNT(*) FROM ipv6_range WHERE ip BETWEEN tupleElement(ip_range, 1) AND tupleElement(ip_range, 2); +WITH IPv6CIDRToRange(IPv6StringToNum('2001:0db8:0000:85a3:0000:0000:ac1f:8001'), 32) as ip_range SELECT COUNT(*) FROM ipv6_range WHERE ip BETWEEN tupleElement(ip_range, 1) AND tupleElement(ip_range, 2); -WITH IPv6CIDRtoIPv6Range(IPv6StringToNum('2001:0db8:0000:85a3:0000:0000:ac1f:8001'), 25) as ip_range SELECT COUNT(*) FROM ipv6_range WHERE ip BETWEEN tupleElement(ip_range, 1) AND tupleElement(ip_range, 2); +WITH IPv6CIDRToRange(IPv6StringToNum('2001:0db8:0000:85a3:0000:0000:ac1f:8001'), 25) as ip_range SELECT COUNT(*) FROM ipv6_range WHERE ip BETWEEN tupleElement(ip_range, 1) AND tupleElement(ip_range, 2); -WITH IPv6CIDRtoIPv6Range(IPv6StringToNum('2001:0db8:0000:85a3:0000:0000:ac1f:8001'), 26) as ip_range SELECT COUNT(*) FROM ipv6_range WHERE ip BETWEEN tupleElement(ip_range, 1) AND tupleElement(ip_range, 2); +WITH IPv6CIDRToRange(IPv6StringToNum('2001:0db8:0000:85a3:0000:0000:ac1f:8001'), 26) as ip_range SELECT COUNT(*) FROM ipv6_range WHERE ip BETWEEN tupleElement(ip_range, 1) AND tupleElement(ip_range, 2); -WITH IPv6CIDRtoIPv6Range(IPv6StringToNum('2001:0db8:0000:85a3:0000:0000:ac1f:8001'), 64) as ip_range SELECT COUNT(*) FROM ipv6_range WHERE ip BETWEEN tupleElement(ip_range, 1) AND tupleElement(ip_range, 2); +WITH IPv6CIDRToRange(IPv6StringToNum('2001:0db8:0000:85a3:0000:0000:ac1f:8001'), 64) as ip_range SELECT COUNT(*) FROM ipv6_range WHERE ip BETWEEN tupleElement(ip_range, 1) AND tupleElement(ip_range, 2); -WITH IPv6CIDRtoIPv6Range(IPv6StringToNum('2001:0db8:0000:85a3:0000:0000:ac1f:8001'), 0) as ip_range SELECT COUNT(*) FROM ipv6_range WHERE ip BETWEEN tupleElement(ip_range, 1) AND tupleElement(ip_range, 2); +WITH IPv6CIDRToRange(IPv6StringToNum('2001:0db8:0000:85a3:0000:0000:ac1f:8001'), 0) as ip_range SELECT COUNT(*) FROM ipv6_range WHERE ip BETWEEN tupleElement(ip_range, 1) AND tupleElement(ip_range, 2); -SELECT IPv6NumToString(ip), cidr, IPv6CIDRtoIPv6Range(ip, cidr) FROM ipv6_range; +SELECT IPv6NumToString(ip), cidr, IPv6CIDRToRange(ip, cidr) FROM ipv6_range; DROP TABLE ipv6_range; -SELECT IPv6CIDRtoIPv6Range(IPv6StringToNum('2001:0db8:0000:85a3:0000:0000:ac1f:8001'), 0); -SELECT IPv6CIDRtoIPv6Range(IPv6StringToNum('2001:0db8:0000:85a3:0000:0000:ac1f:8001'), 128); -SELECT IPv6CIDRtoIPv6Range(IPv6StringToNum('ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff'), 64); -SELECT IPv6CIDRtoIPv6Range(IPv6StringToNum('0000:0000:0000:0000:0000:0000:0000:0000'), 8); -SELECT IPv6CIDRtoIPv6Range(IPv6StringToNum('ffff:0000:0000:0000:0000:0000:0000:0000'), 4); - +SELECT IPv6CIDRToRange(IPv6StringToNum('2001:0db8:0000:85a3:0000:0000:ac1f:8001'), 0); +SELECT IPv6CIDRToRange(IPv6StringToNum('2001:0db8:0000:85a3:0000:0000:ac1f:8001'), 128); +SELECT IPv6CIDRToRange(IPv6StringToNum('ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff'), 64); +SELECT IPv6CIDRToRange(IPv6StringToNum('0000:0000:0000:0000:0000:0000:0000:0000'), 8); +SELECT IPv6CIDRToRange(IPv6StringToNum('ffff:0000:0000:0000:0000:0000:0000:0000'), 4);