Repository: kayak/pypika
Pull request #107 (2018-03-21 16:03:54)

add (NOT) ILIKE to terms
making ILIKE and NOT ILIKE available.

this means one can do 
```Query.from_(table).select(table.column_x).where(table.column_x.ilike('ab%'))```

which will return
```"SELECT * FROM \"abc\" WHERE \"foo\" LIKE 'ab%'"```

coveralls: 
[![Coverage Status](https://coveralls.io/builds/16100468/badge)](https://coveralls.io/builds/16100468)

Coverage increased (+0.05%) to 97.838% when pulling **c87e96d961494f3e3a2299fa5877c89cd0d61d7a on inkmix:master** into **08c8effeba292c28476e98a4048b377a4f3a1341 on kayak:master**.


Patch:
diff --git a/pypika/enums.py b/pypika/enums.py
index 66684da..4089322 100644
--- a/pypika/enums.py
+++ b/pypika/enums.py
@@ -28,6 +28,8 @@ class Equality(Comparator):
 class Matching(Comparator):
     not_like = ' NOT LIKE '
     like = ' LIKE '
+    not_ilike = ' NOT ILIKE '
+    ilike = ' ILIKE '
     regex = ' REGEX '
     bin_regex = ' REGEX BINARY '
 
diff --git a/pypika/terms.py b/pypika/terms.py
index b0723cf..e808c11 100644
--- a/pypika/terms.py
+++ b/pypika/terms.py
@@ -102,6 +102,12 @@ class Term(object):
     def not_like(self, expr):
         return BasicCriterion(Matching.not_like, self, self._wrap(expr))
 
+    def ilike(self, expr):
+        return BasicCriterion(Matching.ilike, self, self._wrap(expr))
+
+    def not_ilike(self, expr):
+        return BasicCriterion(Matching.not_ilike, self, self._wrap(expr))
+
     def regex(self, pattern):
         return BasicCriterion(Matching.regex, self, self._wrap(pattern))
 


Test patch:
diff --git a/pypika/tests/test_criterions.py b/pypika/tests/test_criterions.py
index ef33bd8..aa2f901 100644
--- a/pypika/tests/test_criterions.py
+++ b/pypika/tests/test_criterions.py
@@ -407,6 +407,94 @@ class NotInTests(unittest.TestCase):
         self.assertEqual('COALESCE("notin"."foo",0) NOT IN (0,1)', str(c2))
 
 
+class LikeTests(unittest.TestCase):
+    t = Table('abc', alias='like')
+
+    def test_like_starts_with(self):
+        c1 = Field('foo').like('ab%')
+        c2 = Field('foo', table=self.t).like('ab%')
+
+        self.assertEqual('"foo" LIKE \'ab%\'', str(c1))
+        self.assertEqual('"like"."foo" LIKE \'ab%\'', str(c2))
+
+    def test_like_contains(self):
+        c1 = Field('foo').like('%ab%')
+        c2 = Field('foo', table=self.t).like('%ab%')
+
+        self.assertEqual('"foo" LIKE \'%ab%\'', str(c1))
+        self.assertEqual('"like"."foo" LIKE \'%ab%\'', str(c2))
+
+    def test_like_ends_with(self):
+        c1 = Field('foo').like('%ab')
+        c2 = Field('foo', table=self.t).like('%ab')
+
+        self.assertEqual('"foo" LIKE \'%ab\'', str(c1))
+        self.assertEqual('"like"."foo" LIKE \'%ab\'', str(c2))
+
+    def test_like_n_chars_long(self):
+        c1 = Field('foo').like('___')
+        c2 = Field('foo', table=self.t).like('___')
+
+        self.assertEqual('"foo" LIKE \'___\'', str(c1))
+        self.assertEqual('"like"."foo" LIKE \'___\'', str(c2))
+
+    def test_like_single_chars_and_various_chars(self):
+        c1 = Field('foo').like('a_b%c')
+        c2 = Field('foo', table=self.t).like('a_b%c')
+
+        self.assertEqual('"foo" LIKE \'a_b%c\'', str(c1))
+        self.assertEqual('"like"."foo" LIKE \'a_b%c\'', str(c2))
+
+    def test_not_like_single_chars_and_various_chars(self):
+        c1 = Field('foo').not_like('a_b%c')
+        c2 = Field('foo', table=self.t).not_like('a_b%c')
+
+        self.assertEqual('"foo" NOT LIKE \'a_b%c\'', str(c1))
+        self.assertEqual('"like"."foo" NOT LIKE \'a_b%c\'', str(c2))
+
+    def test_ilike_starts_with(self):
+        c1 = Field('foo').ilike('ab%')
+        c2 = Field('foo', table=self.t).ilike('ab%')
+
+        self.assertEqual('"foo" ILIKE \'ab%\'', str(c1))
+        self.assertEqual('"like"."foo" ILIKE \'ab%\'', str(c2))
+
+    def test_ilike_contains(self):
+        c1 = Field('foo').ilike('%ab%')
+        c2 = Field('foo', table=self.t).ilike('%ab%')
+
+        self.assertEqual('"foo" ILIKE \'%ab%\'', str(c1))
+        self.assertEqual('"like"."foo" ILIKE \'%ab%\'', str(c2))
+
+    def test_ilike_ends_with(self):
+        c1 = Field('foo').ilike('%ab')
+        c2 = Field('foo', table=self.t).ilike('%ab')
+
+        self.assertEqual('"foo" ILIKE \'%ab\'', str(c1))
+        self.assertEqual('"like"."foo" ILIKE \'%ab\'', str(c2))
+
+    def test_ilike_n_chars_long(self):
+        c1 = Field('foo').ilike('___')
+        c2 = Field('foo', table=self.t).ilike('___')
+
+        self.assertEqual('"foo" ILIKE \'___\'', str(c1))
+        self.assertEqual('"like"."foo" ILIKE \'___\'', str(c2))
+
+    def test_ilike_single_chars_and_various_chars(self):
+        c1 = Field('foo').ilike('a_b%c')
+        c2 = Field('foo', table=self.t).ilike('a_b%c')
+
+        self.assertEqual('"foo" ILIKE \'a_b%c\'', str(c1))
+        self.assertEqual('"like"."foo" ILIKE \'a_b%c\'', str(c2))
+
+    def test_not_ilike_single_chars_and_various_chars(self):
+        c1 = Field('foo').not_ilike('a_b%c')
+        c2 = Field('foo', table=self.t).not_ilike('a_b%c')
+
+        self.assertEqual('"foo" NOT ILIKE \'a_b%c\'', str(c1))
+        self.assertEqual('"like"."foo" NOT ILIKE \'a_b%c\'', str(c2))
+
+
 class ComplexCriterionTests(unittest.TestCase):
     table_abc, table_efg = Table('abc', alias='cx0'), Table('efg', alias='cx1')