diff --git a/ibis/backends/clickhouse/registry.py b/ibis/backends/clickhouse/registry.py index 31925c081f0f..7f31229fa3b2 100644 --- a/ibis/backends/clickhouse/registry.py +++ b/ibis/backends/clickhouse/registry.py @@ -363,6 +363,9 @@ def _literal(translator, expr): return _null_literal(translator, expr) if isinstance(expr, ir.BooleanValue): return '1' if value else '0' + elif isinstance(expr, ir.INETValue): + v = str(value) + return f"toIPv6({v!r})" if ':' in v else f"toIPv4({v!r})" elif isinstance(expr, ir.StringValue): return "'{!s}'".format(value.replace("'", "\\'")) elif isinstance(expr, ir.NumericValue): diff --git a/ibis/expr/datatypes/core.py b/ibis/expr/datatypes/core.py index 5946c0f150b2..26a5d7cc8e00 100644 --- a/ibis/expr/datatypes/core.py +++ b/ibis/expr/datatypes/core.py @@ -5,6 +5,7 @@ import datetime import enum import functools +import ipaddress import numbers import re import typing @@ -1371,6 +1372,13 @@ def infer_null(value: Null | None) -> Null: return null +@infer.register((ipaddress.IPv4Address, ipaddress.IPv6Address)) +def infer_ipaddr( + _: ipaddress.IPv4Address | ipaddress.IPv6Address | None, +) -> INET: + return inet + + if IS_SHAPELY_AVAILABLE: @infer.register(shapely.geometry.Point) diff --git a/ibis/expr/operations/generic.py b/ibis/expr/operations/generic.py index 75f5fbf18303..394b9268df9f 100644 --- a/ibis/expr/operations/generic.py +++ b/ibis/expr/operations/generic.py @@ -4,6 +4,7 @@ import datetime import decimal import enum +import ipaddress import itertools import uuid from operator import attrgetter @@ -255,6 +256,8 @@ class Literal(Value): frozenset, int, frozendict, + ipaddress.IPv4Address, + ipaddress.IPv6Address, np.generic, np.ndarray, pd.Timedelta, diff --git a/ibis/tests/expr/test_value_exprs.py b/ibis/tests/expr/test_value_exprs.py index 8258113c732c..64105ad26a19 100644 --- a/ibis/tests/expr/test_value_exprs.py +++ b/ibis/tests/expr/test_value_exprs.py @@ -1,3 +1,4 @@ +import ipaddress import operator import uuid from collections import OrderedDict @@ -57,6 +58,8 @@ def test_null(): ('foo', 'string'), (b'fooblob', 'bytes'), ([1, 2, 3], 'array'), + (ipaddress.ip_address('1.2.3.4'), 'inet'), + (ipaddress.ip_address('::1'), 'inet'), ], ) def test_literal_with_implicit_type(value, expected_type): @@ -115,6 +118,8 @@ def test_listeral_with_unhashable_values(value, expected_type, expected_value): (-2147483649, 'float64'), (1.5, 'float64'), ('foo', 'string'), + (ipaddress.ip_address('1.2.3.4'), 'inet'), + (ipaddress.ip_address('::1'), 'inet'), (list(pointA), 'point'), (tuple(pointA), 'point'), (list(lineAB), 'linestring'),