Skip to content

Commit

Permalink
Add IPPREFIX <-> VARCHAR cast
Browse files Browse the repository at this point in the history
  • Loading branch information
mohsaka committed Oct 28, 2024
1 parent 878388f commit bfcdffb
Show file tree
Hide file tree
Showing 6 changed files with 264 additions and 30 deletions.
137 changes: 117 additions & 20 deletions velox/docs/functions/presto/conversion.rst
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ are supported if the conversion of their element types are supported. In additio
supported conversions to/from JSON are listed in :doc:`json`.

.. list-table::
:widths: 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25
:widths: 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25
:header-rows: 1

* -
Expand All @@ -49,6 +49,7 @@ supported conversions to/from JSON are listed in :doc:`json`.
- interval day to second
- decimal
- ipaddress
- ipprefix
* - tinyint
- Y
- Y
Expand All @@ -65,6 +66,7 @@ supported conversions to/from JSON are listed in :doc:`json`.
-
- Y
-
-
* - smallint
- Y
- Y
Expand All @@ -81,6 +83,7 @@ supported conversions to/from JSON are listed in :doc:`json`.
-
- Y
-
-
* - integer
- Y
- Y
Expand All @@ -97,6 +100,7 @@ supported conversions to/from JSON are listed in :doc:`json`.
-
- Y
-
-
* - bigint
- Y
- Y
Expand All @@ -113,6 +117,7 @@ supported conversions to/from JSON are listed in :doc:`json`.
-
- Y
-
-
* - boolean
- Y
- Y
Expand All @@ -129,6 +134,7 @@ supported conversions to/from JSON are listed in :doc:`json`.
-
- Y
-
-
* - real
- Y
- Y
Expand All @@ -145,6 +151,7 @@ supported conversions to/from JSON are listed in :doc:`json`.
-
- Y
-
-
* - double
- Y
- Y
Expand All @@ -161,6 +168,7 @@ supported conversions to/from JSON are listed in :doc:`json`.
-
- Y
-
-
* - varchar
- Y
- Y
Expand All @@ -177,6 +185,7 @@ supported conversions to/from JSON are listed in :doc:`json`.
-
- Y
- Y
- Y
* - varbinary
-
-
Expand All @@ -193,6 +202,7 @@ supported conversions to/from JSON are listed in :doc:`json`.
-
-
- Y
-
* - timestamp
-
-
Expand All @@ -209,6 +219,7 @@ supported conversions to/from JSON are listed in :doc:`json`.
-
-
-
-
* - timestamp with time zone
-
-
Expand All @@ -225,6 +236,7 @@ supported conversions to/from JSON are listed in :doc:`json`.
-
-
-
-
* - date
-
-
Expand All @@ -241,6 +253,7 @@ supported conversions to/from JSON are listed in :doc:`json`.
-
-
-
-
* - interval day to second
-
-
Expand All @@ -257,6 +270,7 @@ supported conversions to/from JSON are listed in :doc:`json`.
-
-
-
-
* - decimal
- Y
- Y
Expand All @@ -273,6 +287,7 @@ supported conversions to/from JSON are listed in :doc:`json`.
-
- Y
-
-
* - ipaddress
-
-
Expand All @@ -287,8 +302,26 @@ supported conversions to/from JSON are listed in :doc:`json`.
-
-
-
-
- Y
-
* - ipprefix
-
-
-
-
-
-
-
- Y
-
-
-
-
-
-
-
- Y

Cast to Integral Types
----------------------
Expand Down Expand Up @@ -667,52 +700,79 @@ is the number of whole days in the interval, HH is then number of hours between
From IPADDRESS
^^^^^^^^^^^^^^

Casting from IPADDRESS to VARCHAR returns a string formatted as x.x.x.x for IPV4 formatted IPV6 addresses.
For all other IPV6 addresses it will be formatted in compressed alternate form IPV6 defined in `RFC 4291#section-2.2 <https://datatracker.ietf.org/doc/html/rfc4291.html#section-2.2>`_
Casting from IPADDRESS to VARCHAR returns a string formatted as x.x.x.x for IPv4 formatted IPv6 addresses.
For all other IPv6 addresses it will be formatted in compressed alternate form IPv6 defined in `RFC 4291#section-2.2 <https://datatracker.ietf.org/doc/html/rfc4291.html#section-2.2>`_.

IPV4:
IPv4:

::

SELECT cast(ipaddress '1.2.3.4' as varchar); -- '1.2.3.4'

IPV6:
IPv6:

::

SELECT cast(ipaddress '2001:0db8:0000:0000:0000:ff00:0042:8329' as varchar); -- '2001:db8::ff00:42:8329'
SELECT cast(ipaddress '0:0:0:0:0:0:13.1.68.3' as varchar); -- '::13.1.68.3'

IPV4 mapped IPV6:
IPv4 mapped IPv6:

::

SELECT cast(ipaddress '::ffff:ffff:ffff' as varchar); -- '255.255.255.255'

From IPPREFIX
^^^^^^^^^^^^^

Casting from IPPREFIX to VARCHAR returns a string formatted as *x.x.x.x/<prefix-length>* for IPv4 formatted IPv6 addresses.

For all other IPv6 addresses it will be formatted in compressed alternate form IPv6 defined in `RFC 4291#section-2.2 <https://datatracker.ietf.org/doc/html/rfc4291.html#section-2.2>`_
followed by */<prefix-length>*. [`RFC 4291#section-2.3 <https://datatracker.ietf.org/doc/html/rfc4291.html#section-2.3>`_]

IPv4:

::

SELECT cast(ipprefix '1.2.0.0/16' as varchar); -- '1.2.0.0/16'

IPv6:

::

SELECT cast(ipprefix '2001:db8::ff00:42:8329/128' as varchar); -- '2001:db8::ff00:42:8329/128'
SELECT cast(ipprefix '0:0:0:0:0:0:13.1.68.3/32' as varchar); -- '::/32'

IPv4 mapped IPv6:

::

SELECT cast(ipaddress '::ffff:ffff:0000/16' as varchar); -- '255.255.0.0/16'

Cast to VARBINARY
-----------------

From IPADDRESS
^^^^^^^^^^^^^^

Returns the IPV6 address as a 16 byte varbinary string in network byte order.
Returns the IPv6 address as a 16 byte varbinary string in network byte order.

Internally, the type is a pure IPv6 address. Support for IPv4 is handled using the IPv4-mapped IPv6 address range `(RFC 4291#section-2.5.5.2) <https://datatracker.ietf.org/doc/html/rfc4291.html#section-2.5.5.2>`_.
Internally, the type is a pure IPv6 address. Support for IPv4 is handled using the IPv4-mapped IPv6 address range. [`RFC 4291#section-2.5.5.2 <https://datatracker.ietf.org/doc/html/rfc4291.html#section-2.5.5.2>`_]
When creating an IPADDRESS, IPv4 addresses will be mapped into that range.

IPV6:
IPv6:

::

SELECT cast(ipaddress '2001:0db8:0000:0000:0000:ff00:0042:8329' as varbinary); -- 0x20010db8000000000000ff0000428329

IPV4:
IPv4:

::

SELECT cast('1.2.3.4' as ipaddress); -- 0x00000000000000000000ffff01020304

IPV4 mapped IPV6:
IPv4 mapped IPv6:

::

Expand Down Expand Up @@ -1036,16 +1096,18 @@ Invalid example
Cast to IPADDRESS
-----------------

.. _ipaddress-from-varchar:

From VARCHAR
^^^^^^^^^^^^

To cast a varchar to IPAddress input string must be in the form of either
IPV4 or IPV6.
IPv4 or IPv6.

For IPV4 it must be in the form of:
For IPv4 it must be in the form of:
x.x.x.x where each x is an integer value between 0-255.

For IPV6 it must follow any of the forms defined in `RFC 4291#section-2.2 <https://datatracker.ietf.org/doc/html/rfc4291.html#section-2.2>`_.
For IPv6 it must follow any of the forms defined in `RFC 4291#section-2.2 <https://datatracker.ietf.org/doc/html/rfc4291.html#section-2.2>`_.

Full form:

Expand Down Expand Up @@ -1087,16 +1149,16 @@ Invalid examples:
From VARBINARY
^^^^^^^^^^^^^^

To cast a varbinary to IPAddress it must be either IPV4(4 Bytes)
or IPV6(16 Bytes) in network byte order.
To cast a varbinary to IPAddress it must be either IPv4(4 Bytes)
or IPv6(16 Bytes) in network byte order.

IPV4:
IPv4:

::

[01, 02, 03, 04] -> 1.2.3.4

IPV6:
IPv6:

::

Expand All @@ -1108,7 +1170,7 @@ When creating an IPADDRESS, IPv4 addresses will be mapped into that range.
When formatting an IPADDRESS, any address within the mapped range will be formatted as an IPv4 address.
Other addresses will be formatted as IPv6 using the canonical format defined in `RFC 5952 <https://datatracker.ietf.org/doc/html/rfc5952.html>`_.

IPV6 mapped IPV4 address:
IPv6 mapped IPv4 address:

::

Expand All @@ -1128,6 +1190,41 @@ Invalid examples:

SELECT cast(from_hex('f000001100') as ipaddress); -- Invalid IP address binary length: 5

Cast to IPPREFIX
----------------

From VARCHAR
^^^^^^^^^^^^

The IPPREFIX string must be in the form of *<ip_address>/<ip_prefix>* as defined in `RFC 4291#section-2.3 <https://datatracker.ietf.org/doc/html/rfc4291.html#section-2.3>`_.
The IPADDRESS portion of the IPPREFIX follows the same rules as casting
`IPADDRESS from VARCHAR <#ipaddress-from-varchar>`_.

The prefix portion must be <= 32 if the IP is an IPv4 address or <= 128 for an IPv6 address.
As with IPADDRESS, any IPv6 address in the form of an IPv4 mapped IPv6 address will be
interpreted as an IPv4 address. Only the canonical(smallest) IP address will be stored
in the IPPREFIX.

Examples:

Valid examples:

::

SELECT cast('2001:0db8:0000:0000:0000:ff00:0042:8329/32' as ipprefix); -- ipprefix '2001:0db8::/32'
SELECT cast('1.2.3.4/24' as ipprefix); -- ipprefix '1.2.3.0/24'
SELECT cast('::ffff:ffff:ffff/16' as ipprefix); -- ipprefix '255.255.0.0/16'

Invalid examples:

::

SELECT cast('2001:db8::1::1/1' as ipprefix); -- Cannot cast value to IPPREFIX: 2001:db8::1::1/1
SELECT cast('2001:0db8:0000:0000:0000:ff00:0042:8329/129' as ipprefix); -- Cannot cast value to IPPREFIX: 2001:0db8:0000:0000:0000:ff00:0042:8329/129
SELECT cast('2001:0db8:0000:0000:0000:ff00:0042:8329/-1' as ipprefix); -- Cannot cast value to IPPREFIX: 2001:0db8:0000:0000:0000:ff00:0042:8329/-1
SELECT cast('255.2.3.4/33' as ipprefix); -- Cannot cast value to IPPREFIX: 255.2.3.4/33
SELECT cast('::ffff:ffff:ffff/33' as ipprefix); -- Cannot cast value to IPPREFIX: ::ffff:ffff:ffff/33

Miscellaneous
-------------

Expand All @@ -1137,4 +1234,4 @@ Miscellaneous

SELECT typeof(123); -- integer
SELECT typeof(1.5); -- double
SELECT typeof(array[1,2,3]); -- array(integer)
SELECT typeof(array[1,2,3]); -- array(integer)
5 changes: 3 additions & 2 deletions velox/functions/prestosql/TypeOf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,6 @@ std::string typeName(const TypePtr& type) {
case TypeKind::VARBINARY:
if (isHyperLogLogType(type)) {
return "HyperLogLog";
} else if (isIPPrefixType(type)) {
return "ipprefix";
}
return "varbinary";
case TypeKind::TIMESTAMP:
Expand All @@ -93,6 +91,9 @@ std::string typeName(const TypePtr& type) {
typeName(type->childAt(0)),
typeName(type->childAt(1)));
case TypeKind::ROW: {
if (isIPPrefixType(type)) {
return "ipprefix";
}
const auto& rowType = type->asRow();
std::ostringstream out;
out << "row(";
Expand Down
2 changes: 1 addition & 1 deletion velox/functions/prestosql/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ add_executable(
HyperLogLogFunctionsTest.cpp
InPredicateTest.cpp
IPAddressCastTest.cpp
IPPrefixCastTest.cpp
JsonCastTest.cpp
JsonExtractScalarTest.cpp
JsonFunctionsTest.cpp
Expand Down Expand Up @@ -105,7 +106,6 @@ add_executable(
WordStemTest.cpp
ZipTest.cpp
ZipWithTest.cpp)

add_test(velox_functions_test velox_functions_test)

target_link_libraries(
Expand Down
1 change: 0 additions & 1 deletion velox/functions/prestosql/types/IPAddressType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
static constexpr int kIPV4AddressBytes = 4;
static constexpr int kIPV4ToV6FFIndex = 10;
static constexpr int kIPV4ToV6Index = 12;
static constexpr int kIPAddressBytes = 16;

namespace facebook::velox {

Expand Down
2 changes: 2 additions & 0 deletions velox/functions/prestosql/types/IPAddressType.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
#include "velox/type/SimpleFunctionApi.h"
#include "velox/type/Type.h"

static constexpr int kIPAddressBytes = 16;

namespace facebook::velox {

class IPAddressType : public HugeintType {
Expand Down
Loading

0 comments on commit bfcdffb

Please sign in to comment.