From cec9d8574e1a8abf6ae320caf0c3e6dd4d970247 Mon Sep 17 00:00:00 2001 From: slymit Date: Sun, 7 Apr 2024 13:33:32 +0300 Subject: [PATCH] Add support for like and ilike operators for the PhoneNumberType type --- sqlalchemy_utils/types/phone_number.py | 9 ++++++++- tests/types/test_phonenumber.py | 22 ++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/sqlalchemy_utils/types/phone_number.py b/sqlalchemy_utils/types/phone_number.py index 4f94f1cf..32f730d6 100644 --- a/sqlalchemy_utils/types/phone_number.py +++ b/sqlalchemy_utils/types/phone_number.py @@ -6,7 +6,8 @@ .. _phonenumbers: https://github.com/daviddrysdale/python-phonenumbers """ -from sqlalchemy import exc, types +from sqlalchemy import exc, String, types +from sqlalchemy.sql.operators import ilike_op, like_op, notilike_op, notlike_op from ..exceptions import ImproperlyConfigured from ..utils import str_coercible @@ -180,6 +181,12 @@ def __init__(self, region="US", max_length=20, *args, **kwargs): self.region = region self.impl = types.Unicode(max_length) + def coerce_compared_value(self, op, value): + if op in (like_op, notlike_op, ilike_op, notilike_op): + return String() + else: + return self + def process_bind_param(self, value, dialect): if value: if not isinstance(value, PhoneNumber): diff --git a/tests/types/test_phonenumber.py b/tests/types/test_phonenumber.py index 7a7f52d1..a56c800a 100644 --- a/tests/types/test_phonenumber.py +++ b/tests/types/test_phonenumber.py @@ -163,6 +163,28 @@ def test_compilation(self, User, session): # the type should be cacheable and not throw exception session.execute(query) + def test_op_like_notlike_and_ilike_notilike(self, session, User): + user1 = User(phone_number="040 1234567") + user2 = User(phone_number="040 1234568") + user3 = User(phone_number="041 1234568") + + session.add_all([user1, user2, user3]) + session.commit() + + result = session.query(User).filter(User.phone_number.like("%568")) + assert len(result.all()) == 2 + + result = session.query(User).filter(User.phone_number.notlike("+1040%")) + assert len(result.all()) == 1 + assert result[0] == user3 + + result = session.query(User).filter(User.phone_number.ilike("%568")) + assert len(result.all()) == 2 + + result = session.query(User).filter(User.phone_number.notilike("+1040%")) + assert len(result.all()) == 1 + assert result[0] == user3 + @pytest.mark.skipif("types.phone_number.phonenumbers is None") class TestPhoneNumberComposite: