From 1ee5d859c339f0f8c344ef45ed839a2fffd26e61 Mon Sep 17 00:00:00 2001 From: Ahmed Adel Date: Tue, 6 Aug 2024 21:04:25 +0300 Subject: [PATCH] ILIKE operator translation (#35) * feat: Translating ILIKE and NOT ILIKE operators to LIKE and NOT LIKE * test: Testing ILIKE and NOT ILIKE translation --- src/sqlalchemy_solr/base.py | 7 ++++++ tests/test_operator_translation.py | 39 ++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 tests/test_operator_translation.py diff --git a/src/sqlalchemy_solr/base.py b/src/sqlalchemy_solr/base.py index c6cc3ad..3aa4af7 100644 --- a/src/sqlalchemy_solr/base.py +++ b/src/sqlalchemy_solr/base.py @@ -182,6 +182,13 @@ def visit_clauselist(self, clauselist, **kw): def visit_array(self, element, **kw): return f"ARRAY[{self.visit_clauselist(element, **kw)}]" + # Solr LIKE and NOT LIKE operators are case insensetive + def visit_ilike_op_binary(self, binary, operator, **kw): + return super().visit_like_op_binary(binary, operator, **kw) + + def visit_not_ilike_op_binary(self, binary, operator, **kw): + return super().visit_not_like_op_binary(binary, operator, **kw) + def unescape_colon(self, s: str) -> str: """Unescape colon if present in datetime value""" return s.replace(r"\:", ":") diff --git a/tests/test_operator_translation.py b/tests/test_operator_translation.py new file mode 100644 index 0000000..f54da2f --- /dev/null +++ b/tests/test_operator_translation.py @@ -0,0 +1,39 @@ +from sqlalchemy import select +from tests.setup import prepare_orm + + +class TestOperatorTranslation: + + def test_ilike_operator_translation(self, settings): + engine, t = prepare_orm(settings) + + select_statement_1 = ( + "SELECT sales_test_.`CITY_s` \nFROM sales_test_ " + "\nWHERE sales_test_.`CITY_s` LIKE ?\n LIMIT ?" + ) + + qry = (select(t.c.CITY_s).where(t.c.CITY_s.ilike("%york%"))).limit( + 1 + ) # pylint: disable=unsubscriptable-object + + with engine.connect() as connection: + result = connection.execute(qry) + + assert result.context.statement == select_statement_1 + + def test_not_ilike_operator_translation(self, settings): + engine, t = prepare_orm(settings) + + select_statement_1 = ( + "SELECT sales_test_.`CITY_s` \nFROM sales_test_ " + "\nWHERE sales_test_.`CITY_s` NOT LIKE ?\n LIMIT ?" + ) + + qry = (select(t.c.CITY_s).where(t.c.CITY_s.notilike("%york%"))).limit( + 1 + ) # pylint: disable=unsubscriptable-object + + with engine.connect() as connection: + result = connection.execute(qry) + + assert result.context.statement == select_statement_1