velox
velox copied to clipboard
[WIP] Add IPADDRESS and IPPREFIX and corresponding functions
IPADDRESS/IPPREFIX
Types
IPADDRESS (HUGEINT)
All IPs are stored as IPV6. IPV4 is converted to IPV6 with a form of
0x 0000 0000 0000 0000 0000 FFFF XXXX XXXX
IPPREFIX ({HUGEINT, TINYINT})
Stored as a an opaque type of struct
{ int128_t ip, int8_t prefix}
Functions
NOTE: We cannot apply IPV4 operations on an IPV4 converted IPV6 address. Ex. We can apply a length 100 prefix on an IPV4 converted address. So we need to always convert IPV6 to IPV4 if possible.
cast(ipaddress as varchar) → varchar
memcpy int128_t from ipaddress type into boost byte array.
If we are loading from a little endian system we need to flip
the bytes since it needs to be in network byte order.
We then check if it is a v4 mapped address so we can make
the correct boost ipV4/V6 object to print correctly.
All error handling done by the boost library.
cast(ipaddressString as IPADDRESS) → IPADDRESS
Create IP address boost object with the string. Check the object,
if its V4 then convert to V6. Extract the bytes and flip if we are on
a little endian system. Copy back into the int128_t for the result.
All error handling done by the boost library.
cast(ipprefix as VARCHAR) → VARCHAR
Same as ipaddress, except we create a network with the IP
cast(ipprefixString as IPADDRESS) → IPPREFIX
Find the last occurance of '/' creating a boost IP address object
with whatever comes before it. If there are two '/' IP object creation will fail
if there is no slash ex. an IP without any prefix we will continue
but fail at a later point.
Use the address object to see if we have an IP V4 or V6 network
and create the V4/V6 network with the original string. Network
creation will fail if the IP is not parseable.
If we have an IPV6 object, there is a chance that they entered an
IPV4 formatted as an IPV6 so we need to create an IPV4 network
to properly get the canonical address and check prefix validity.
Use the network to get the canonical address, flipping the bytes
if necessary before putting it in the IPPREFIX ip variable.
Copy over the prefix from prefixBits argument.
ip_prefix(ipaddress, prefix_bits) → IPPREFIX
If ipaddress is a varchar, use same logic as cast to convert to
ip address and call with ipaddress type.
Create boost v6 ipaddress object with the ipaddress type passed in.
Create corresponding v4/v6 boost network and pass in the prefix_bits
converting it to uint8_t since the presto type is int8_t.
Get the canonical ip address from the network object as a byte array,
flipping if on little endian to prepare for placing in the HUGEINT type.
IP Parsing and prefix size restriction error handling is all done in boost.
ip_subnet_min(ipprefix) → IPADDRESS
Return the canonical IP address already stored in the IP Prefix object.
It is the smallest IP we could have.
ip_subnet_max(ipprefix) → IPADDRESS
We want to set all non prefix bits to 1. For IPV4 thats max 32 bits, for IPV6
thats max 128. Subtract prefix from the max and do some bit manipulation
to flip that many bits.
EX. Prefix is 25 on an IPV4. So we want to flip the 7 LSBs.
1 << 7 = (1,0,0,0,0,0,0,0)
(1,0,0,0,0,0,0,0) - 1 = (0,1,1,1,1,1,1,1);
We then OR this with IPPREFIX's canonical IP to set them all to 1.
Note, for ipprefix = 0 in IPV6 we should be able to overflow then subtract one
from a bit standpoint but it does not work. So added a special case.
ip_subnet_range(ipprefix) → [IPADDRESS, IPADDRESS]
Just return ip_subnet_min and ip_subnet_max in an array.
is_subnet_of(ipprefix, ipaddress) → BOOLEAN
We just need to make sure that the prefix of IPADDRESS is equal to the ip
of IPPREFIX when subject to the prefix length of IPPREFIX.
To do this we do a similar bit operation. However we flip the bits to get the prefix
side and AND them together to extract the prefix bits from the IP.
We then compare to check if the prefix are equal.
Note, for ipprefix = 0 in IPV6 we should be able to overflow then subtract one
from a bit standpoint but it does not work. So added a special case.
is_subnet_of(ipprefix1, ipprefix2) → BOOLEAN
Just call is_subnet_of(ipprefix, ipaddress) however with an additional condition
to make sure that the prefix of ipprefix2 is longer or equal to that of ipprefix1.
If its shorter than there is no way for ipprefix1 to contain all of ipprefix2.
Deploy Preview for meta-velox canceled.
| Name | Link |
|---|---|
| Latest commit | b6700c950f40dec342f0e075326c34de252778ae |
| Latest deploy log | https://app.netlify.com/sites/meta-velox/deploys/668349c6dde00200085b11a0 |
Closed for now. Merge into fork first then pushing up to OSS at a later point.