Repository: great-expectations/great_expectations

Issue:
Regex and like support in AthenaDialect
**Is your feature request related to a problem? Please describe.**
Like and regex based expectations are currently raising a NotImplementedError when using AthenaDialect. This limits the usability when working with text columns.

**Describe the solution you'd like**
Implementation of `_get_dialect_regex_expression` and `_get_dialect_like_pattern_expression` for `pyathena.sqlalchemy_athena.AthenaDialect`.

**Describe alternatives you've considered**
I have been using `expect_column_values_to_be_in_set` which is kind of anoying for datasets where only the begining of the string is important.


Discussion:
I am already working on this

Resolving patch:
diff --git a/great_expectations/dataset/sqlalchemy_dataset.py b/great_expectations/dataset/sqlalchemy_dataset.py
--- a/great_expectations/dataset/sqlalchemy_dataset.py
+++ b/great_expectations/dataset/sqlalchemy_dataset.py
@@ -2148,6 +2148,23 @@ def _get_dialect_regex_expression(self, column, regex, positive=True):
         except (AttributeError, TypeError):
             pass
 
+        try:
+            # Athena
+            if isinstance(
+                self.sql_engine_dialect, pyathena.sqlalchemy_athena.AthenaDialect
+            ):
+                if positive:
+                    return sa.func.REGEXP_LIKE(sa.column(column), literal(regex))
+                else:
+                    return sa.not_(
+                        sa.func.REGEXP_LIKE(sa.column(column), literal(regex))
+                    )
+        except (
+            AttributeError,
+            TypeError,
+        ):  # TypeError can occur if the driver was not installed and so is None
+            pass
+
         return None
 
     @MetaSqlAlchemyDataset.column_map_expectation
@@ -2308,6 +2325,14 @@ def _get_dialect_like_pattern_expression(self, column, like_pattern, positive=Tr
         except (AttributeError, TypeError):
             pass
 
+        try:
+            if isinstance(
+                self.sql_engine_dialect, pyathena.sqlalchemy_athena.AthenaDialect
+            ):
+                dialect_supported = True
+        except (AttributeError, TypeError):
+            pass
+
         if dialect_supported:
             try:
                 if positive:


Test patch:
diff --git a/tests/dataset/test_sqlalchemydataset.py b/tests/dataset/test_sqlalchemydataset.py
--- a/tests/dataset/test_sqlalchemydataset.py
+++ b/tests/dataset/test_sqlalchemydataset.py
@@ -368,7 +368,8 @@ def test_expect_compound_columns_to_be_unique_with_no_rows(sa):
     assert dataset.expect_compound_columns_to_be_unique(["col1", "col2"]).success
 
 
-def test_expect_column_values_to_be_of_type_string_dialect_pyathena(sa):
+@pytest.fixture
+def pyathena_dataset(sa):
     from pyathena import sqlalchemy_athena
 
     engine = sa.create_engine("sqlite://")
@@ -378,21 +379,22 @@ def test_expect_column_values_to_be_of_type_string_dialect_pyathena(sa):
     data.to_sql(name="test_sql_data", con=engine, index=False)
     dataset = SqlAlchemyDataset("test_sql_data", engine=engine)
     dataset.dialect = sqlalchemy_athena
-
-    assert dataset.expect_column_values_to_be_of_type("col", type_="STRINGTYPE").success
+    return dataset
 
 
-def test_expect_column_values_to_be_in_type_list_pyathena(sa):
-    from pyathena import sqlalchemy_athena
+def test_expect_column_values_to_be_of_type_string_dialect_pyathena(pyathena_dataset):
+    assert pyathena_dataset.expect_column_values_to_be_of_type(
+        "col", type_="STRINGTYPE"
+    ).success
 
-    engine = sa.create_engine("sqlite://")
 
-    data = pd.DataFrame({"col": ["test_val1", "test_val2"]})
+def test_expect_column_values_to_be_in_type_list_pyathena(pyathena_dataset):
+    assert pyathena_dataset.expect_column_values_to_be_in_type_list(
+        "col", type_list=["STRINGTYPE", "BOOLEAN"]
+    ).success
 
-    data.to_sql(name="test_sql_data", con=engine, index=False)
-    dataset = SqlAlchemyDataset("test_sql_data", engine=engine)
-    dataset.dialect = sqlalchemy_athena
 
-    assert dataset.expect_column_values_to_be_in_type_list(
-        "col", type_list=["STRINGTYPE", "BOOLEAN"]
+def test_expect_column_values_to_match_like_pattern_pyathena(pyathena_dataset):
+    assert pyathena_dataset.expect_column_values_to_match_like_pattern(
+        "col", like_pattern="test%"
     ).success