Repository: kayak/pypika (python)

Issue:
Add support for Vertica labels
Please add support for Vertica labels https://my.vertica.com/docs/7.1.x/HTML/Content/Authoring/AdministratorsGuide/Profiling/HowToLabelQueriesForProfiling.htm
something like:
```
customers = Table('customers')
q = Query.from_(customers).select(customers.id, customers.fname, customers.lname, customers.phone).label('my custom label')
```
output: 
`SELECT /* + label(my custom label)*/ id,fname,lname,phone FROM customers`

Pull request description:
Fixes #105 Added a VerticaQueryBuilder class with support for a query hint
This adds a vendor specific query class which allows vertica queries to set a hint

Patch:
diff --git a/pypika/__init__.py b/pypika/__init__.py
index 33cb35c..c68b010 100644
--- a/pypika/__init__.py
+++ b/pypika/__init__.py
@@ -72,4 +72,4 @@ from .utils import (
 
 __author__ = "Timothy Heys"
 __email__ = "theys@kayak.com"
-__version__ = "0.11.0"
+__version__ = "0.10.7"
diff --git a/pypika/dialects.py b/pypika/dialects.py
index 3d72605..c5aa0be 100644
--- a/pypika/dialects.py
+++ b/pypika/dialects.py
@@ -1,3 +1,4 @@
+from .utils import builder
 from .enums import Dialects
 from .queries import (
     Query,
@@ -15,6 +16,26 @@ class MySQLQuery(Query):
         return QueryBuilder(quote_char='`', dialect=Dialects.MYSQL, wrap_union_queries=False)
 
 
+class VerticaQueryBuilder(QueryBuilder):
+    def __init__(self):
+        super(VerticaQueryBuilder, self).__init__(dialect=Dialects.VERTICA)
+        self._hint = None
+
+    @builder
+    def hint(self, label):
+        self._hint = label
+
+    def get_sql(self, *args, **kwargs):
+        sql = super(VerticaQueryBuilder, self).get_sql(*args, **kwargs)
+
+        if self._hint is not None:
+            sql = ''.join([sql[:7],
+                           '/*+label({hint})*/'.format(hint=self._hint),
+                           sql[6:]])
+
+        return sql
+
+
 class VerticaQuery(Query):
     """
     Defines a query class for use with Vertica.
@@ -22,7 +43,7 @@ class VerticaQuery(Query):
 
     @classmethod
     def _builder(cls):
-        return QueryBuilder(dialect=Dialects.VERTICA)
+        return VerticaQueryBuilder()
 
 
 class OracleQuery(Query):
diff --git a/pypika/enums.py b/pypika/enums.py
index 4089322..e96a283 100644
--- a/pypika/enums.py
+++ b/pypika/enums.py
@@ -26,10 +26,7 @@ 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 e808c11..795caaf 100644
--- a/pypika/terms.py
+++ b/pypika/terms.py
@@ -99,15 +99,6 @@ class Term(object):
     def like(self, expr):
         return BasicCriterion(Matching.like, self, self._wrap(expr))
 
-    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 aa2f901..ef33bd8 100644
--- a/pypika/tests/test_criterions.py
+++ b/pypika/tests/test_criterions.py
@@ -407,94 +407,6 @@ 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')
 
diff --git a/pypika/tests/test_selects.py b/pypika/tests/test_selects.py
index f3e926f..73fe402 100644
--- a/pypika/tests/test_selects.py
+++ b/pypika/tests/test_selects.py
@@ -223,26 +223,6 @@ class WhereTests(unittest.TestCase):
 
         self.assertEqual("SELECT * FROM \"abc\" WHERE \"foo\" LIKE '___'", str(q))
 
-    def test_where_field_does_not_start_with(self):
-        q = Query.from_(self.t).select(self.t.star).where(self.t.foo.not_like('ab%'))
-
-        self.assertEqual("SELECT * FROM \"abc\" WHERE \"foo\" NOT LIKE 'ab%'", str(q))
-
-    def test_where_field_does_not_contain(self):
-        q = Query.from_(self.t).select(self.t.star).where(self.t.foo.not_like('%fg%'))
-
-        self.assertEqual("SELECT * FROM \"abc\" WHERE \"foo\" NOT LIKE '%fg%'", str(q))
-
-    def test_where_field_does_not_end_with(self):
-        q = Query.from_(self.t).select(self.t.star).where(self.t.foo.not_like('%yz'))
-
-        self.assertEqual("SELECT * FROM \"abc\" WHERE \"foo\" NOT LIKE '%yz'", str(q))
-
-    def test_where_field_is_not_n_chars_long(self):
-        q = Query.from_(self.t).select(self.t.star).where(self.t.foo.not_like('___'))
-
-        self.assertEqual("SELECT * FROM \"abc\" WHERE \"foo\" NOT LIKE '___'", str(q))
-
     def test_where_field_matches_regex(self):
         q = Query.from_(self.t).select(self.t.star).where(self.t.foo.regex(r'^b'))
 
diff --git a/pypika/tests/test_vertica_queries.py b/pypika/tests/test_vertica_queries.py
new file mode 100644
index 0000000..8b06812
--- /dev/null
+++ b/pypika/tests/test_vertica_queries.py
@@ -0,0 +1,45 @@
+import unittest
+
+from pypika import (
+    Table,
+    VerticaQuery,
+)
+
+__author__ = "Timothy Heys"
+__email__ = "theys@kayak.com"
+
+
+class VerticaQueryTests(unittest.TestCase):
+    table_abc = Table('abc')
+
+    def test_select_query_with_hint(self):
+        q = VerticaQuery \
+            .from_('abc') \
+            .select('*') \
+            .hint('test_hint')
+
+        self.assertEqual('SELECT /*+label(test_hint)*/ * FROM "abc"', str(q))
+
+    def test_insert_query_with_hint(self):
+        query = VerticaQuery \
+            .into(self.table_abc) \
+            .insert(1) \
+            .hint('test_hint')
+
+        self.assertEqual('INSERT /*+label(test_hint)*/ INTO "abc" VALUES (1)', str(query))
+
+    def test_update_query_with_hint(self):
+        q = VerticaQuery \
+            .update(self.table_abc) \
+            .set('foo', 'bar') \
+            .hint('test_hint')
+
+        self.assertEqual('UPDATE /*+label(test_hint)*/ "abc" SET "foo"=\'bar\'', str(q))
+
+    def test_delete_query_with_hint(self):
+        q = VerticaQuery \
+            .from_('abc') \
+            .delete() \
+            .hint('test_hint')
+
+        self.assertEqual('DELETE /*+label(test_hint)*/ FROM "abc"', str(q))