Repository: great-expectations/great_expectations

Issue:
Use cleaner solution for non-truncating division in python 2
Prefer `from __future__ import division` to `1.*x/y`


Discussion:
Done inline during improve_partitions push.

Resolving patch:
diff --git a/great_expectations/execution_engine/sqlalchemy_execution_engine.py b/great_expectations/execution_engine/sqlalchemy_execution_engine.py
--- a/great_expectations/execution_engine/sqlalchemy_execution_engine.py
+++ b/great_expectations/execution_engine/sqlalchemy_execution_engine.py
@@ -50,12 +50,12 @@
     from sqlalchemy.engine.default import DefaultDialect
     from sqlalchemy.engine.url import URL
     from sqlalchemy.exc import OperationalError
-    from sqlalchemy.sql import Select
+    from sqlalchemy.sql import Selectable
     from sqlalchemy.sql.elements import TextClause, quoted_name
 except ImportError:
     reflection = None
     DefaultDialect = None
-    Select = None
+    Selectable = None
     TextClause = None
     quoted_name = None
     OperationalError = None
@@ -372,28 +372,21 @@ def _get_sqlalchemy_key_pair_auth_url(
             create_engine_kwargs,
         )
 
-    def get_compute_domain(
+    def get_domain_records(
         self,
         domain_kwargs: Dict,
-        domain_type: Union[str, MetricDomainTypes],
-        accessor_keys: Optional[Iterable[str]] = None,
-    ) -> Tuple[Select, dict, dict]:
-        """Uses a given batch dictionary and domain kwargs to obtain a SqlAlchemy column object.
+    ) -> Selectable:
+        """
+        Uses the given domain kwargs (which include row_condition, condition_parser, and ignore_row_if directives) to
+        obtain and/or query a batch. Returns in the format of an SqlAlchemy table/column(s) object.
 
         Args:
             domain_kwargs (dict) - A dictionary consisting of the domain kwargs specifying which data to obtain
-            domain_type (str or MetricDomainTypes) - an Enum value indicating which metric domain the user would
-            like to be using, or a corresponding string value representing it. String types include "identity",
-            "column", "column_pair", "table" and "other". Enum types include capitalized versions of these from the
-            class MetricDomainTypes.
-            accessor_keys (str iterable) - keys that are part of the compute domain but should be ignored when
-            describing the domain and simply transferred with their associated values into accessor_domain_kwargs.
 
         Returns:
-            SqlAlchemy column
+            An SqlAlchemy table/column(s) (the selectable object for obtaining data on which to compute)
         """
         # Extracting value from enum if it is given for future computation
-        domain_type = MetricDomainTypes(domain_type)
         batch_id = domain_kwargs.get("batch_id")
         if batch_id is None:
             # We allow no batch id specified if there is only one batch
@@ -411,8 +404,6 @@ class MetricDomainTypes.
                     f"Unable to find batch with batch_id {batch_id}"
                 )
 
-        compute_domain_kwargs = copy.deepcopy(domain_kwargs)
-        accessor_domain_kwargs = dict()
         if "table" in domain_kwargs and domain_kwargs["table"] is not None:
             # TODO: Add logic to handle record_set_name once implemented
             # (i.e. multiple record sets (tables) in one batch
@@ -431,6 +422,7 @@ class MetricDomainTypes.
         else:
             selectable = data_object.selectable
 
+        # Filtering by row condition.
         if (
             "row_condition" in domain_kwargs
             and domain_kwargs["row_condition"] is not None
@@ -449,6 +441,136 @@ class MetricDomainTypes.
                     "SqlAlchemyExecutionEngine only supports the great_expectations condition_parser."
                 )
 
+        if "column" in domain_kwargs:
+            return selectable
+
+        if "column_A" in domain_kwargs and "column_B" in domain_kwargs:
+            if "ignore_row_if" in domain_kwargs:
+                if self.active_batch_data.use_quoted_name:
+                    # If case matters...
+                    # noinspection PyPep8Naming
+                    column_A_name = quoted_name(domain_kwargs["column_A"])
+                    # noinspection PyPep8Naming
+                    column_B_name = quoted_name(domain_kwargs["column_B"])
+                else:
+                    # noinspection PyPep8Naming
+                    column_A_name = domain_kwargs["column_A"]
+                    # noinspection PyPep8Naming
+                    column_B_name = domain_kwargs["column_B"]
+
+                ignore_row_if = domain_kwargs["ignore_row_if"]
+                if ignore_row_if == "both_values_are_missing":
+                    selectable = (
+                        sa.select([sa.text("*")])
+                        .select_from(selectable)
+                        .where(
+                            sa.not_(
+                                sa.and_(
+                                    sa.column(column_A_name) == None,
+                                    sa.column(column_B_name) == None,
+                                )
+                            )
+                        )
+                    )
+                elif ignore_row_if == "either_value_is_missing":
+                    selectable = (
+                        sa.select([sa.text("*")])
+                        .select_from(selectable)
+                        .where(
+                            sa.not_(
+                                sa.or_(
+                                    sa.column(column_A_name) == None,
+                                    sa.column(column_B_name) == None,
+                                )
+                            )
+                        )
+                    )
+                else:
+                    if ignore_row_if != "never":
+                        raise ValueError(
+                            f'Unrecognized value of ignore_row_if ("{ignore_row_if}").'
+                        )
+
+                return selectable
+
+        if "column_list" in domain_kwargs:
+            if "ignore_row_if" in domain_kwargs:
+                if self.active_batch_data.use_quoted_name:
+                    # If case matters...
+                    column_list = [
+                        quoted_name(domain_kwargs[column_name])
+                        for column_name in domain_kwargs["column_list"]
+                    ]
+                else:
+                    column_list = domain_kwargs["column_list"]
+
+                ignore_row_if = domain_kwargs["ignore_row_if"]
+                if ignore_row_if == "all_values_are_missing":
+                    selectable = (
+                        sa.select([sa.text("*")])
+                        .select_from(selectable)
+                        .where(
+                            sa.not_(
+                                sa.and_(
+                                    *(
+                                        sa.column(column_name) == None
+                                        for column_name in column_list
+                                    )
+                                )
+                            )
+                        )
+                    )
+                elif ignore_row_if == "any_value_is_missing":
+                    selectable = (
+                        sa.select([sa.text("*")])
+                        .select_from(selectable)
+                        .where(
+                            sa.not_(
+                                sa.or_(
+                                    *(
+                                        sa.column(column_name) == None
+                                        for column_name in column_list
+                                    )
+                                )
+                            )
+                        )
+                    )
+                else:
+                    if ignore_row_if != "never":
+                        raise ValueError(
+                            f'Unrecognized value of ignore_row_if ("{ignore_row_if}").'
+                        )
+
+                return selectable
+
+        return selectable
+
+    def get_compute_domain(
+        self,
+        domain_kwargs: Dict,
+        domain_type: Union[str, MetricDomainTypes],
+        accessor_keys: Optional[Iterable[str]] = None,
+    ) -> Tuple[Selectable, dict, dict]:
+        """Uses a given batch dictionary and domain kwargs to obtain a SqlAlchemy column object.
+
+        Args:
+            domain_kwargs (dict) - A dictionary consisting of the domain kwargs specifying which data to obtain
+            domain_type (str or MetricDomainTypes) - an Enum value indicating which metric domain the user would
+            like to be using, or a corresponding string value representing it. String types include "identity",
+            "column", "column_pair", "table" and "other". Enum types include capitalized versions of these from the
+            class MetricDomainTypes.
+            accessor_keys (str iterable) - keys that are part of the compute domain but should be ignored when
+            describing the domain and simply transferred with their associated values into accessor_domain_kwargs.
+
+        Returns:
+            SqlAlchemy column
+        """
+        selectable = self.get_domain_records(
+            domain_kwargs=domain_kwargs,
+        )
+        # Extracting value from enum if it is given for future computation
+        domain_type = MetricDomainTypes(domain_type)
+
         # Warning user if accessor keys are in any domain that is not of type table, will be ignored
         if (
             domain_type != MetricDomainTypes.TABLE
@@ -459,6 +581,8 @@ class MetricDomainTypes.
                 'Accessor keys ignored since Metric Domain Type is not "table"'
             )
 
+        compute_domain_kwargs = copy.deepcopy(domain_kwargs)
+        accessor_domain_kwargs = dict()
         if domain_type == MetricDomainTypes.TABLE:
             if accessor_keys is not None and len(list(accessor_keys)) > 0:
                 for key in accessor_keys:
@@ -499,6 +623,7 @@ class MetricDomainTypes.
                 raise GreatExpectationsError(
                     "Column not provided in compute_domain_kwargs"
                 )
+            return selectable, compute_domain_kwargs, accessor_domain_kwargs
 
         # Else, if column pair values requested
         elif domain_type == MetricDomainTypes.COLUMN_PAIR:
@@ -526,62 +651,21 @@ class MetricDomainTypes.
                 raise GreatExpectationsError(
                     "column_A or column_B not found within compute_domain_kwargs"
                 )
+            return selectable, compute_domain_kwargs, accessor_domain_kwargs
 
         # Checking if table or identity or other provided, column is not specified. If it is, warning the user
         elif domain_type == MetricDomainTypes.MULTICOLUMN:
-            if "column_list" in compute_domain_kwargs:
-                # If column_list exists
-                accessor_domain_kwargs["column_list"] = compute_domain_kwargs.pop(
-                    "column_list"
+            # Ensuring column_list parameter is provided
+            if "column_list" not in domain_kwargs:
+                raise GreatExpectationsError(
+                    "column_list not found within domain_kwargs"
                 )
 
-        # Filtering if identity
-        elif domain_type == MetricDomainTypes.IDENTITY:
-            # If we would like our data to become a single column
-            if "column" in compute_domain_kwargs:
-                if self.active_batch_data.use_quoted_name:
-                    selectable = sa.select(
-                        [sa.column(quoted_name(compute_domain_kwargs["column"]))]
-                    ).select_from(selectable)
-                else:
-                    selectable = sa.select(
-                        [sa.column(compute_domain_kwargs["column"])]
-                    ).select_from(selectable)
-
-            # If we would like our data to now become a column pair
-            elif ("column_A" in compute_domain_kwargs) and (
-                "column_B" in compute_domain_kwargs
-            ):
-                if self.active_batch_data.use_quoted_name:
-                    selectable = sa.select(
-                        [
-                            sa.column(quoted_name(compute_domain_kwargs["column_A"])),
-                            sa.column(quoted_name(compute_domain_kwargs["column_B"])),
-                        ]
-                    ).select_from(selectable)
-                else:
-                    selectable = sa.select(
-                        [
-                            sa.column(compute_domain_kwargs["column_A"]),
-                            sa.column(compute_domain_kwargs["column_B"]),
-                        ]
-                    ).select_from(selectable)
-            else:
-                # If we would like our data to become a multicolumn
-                if "column_list" in compute_domain_kwargs:
-                    if self.active_batch_data.use_quoted_name:
-                        # Building a list of column objects used for sql alchemy selection
-                        to_select = [
-                            sa.column(quoted_name(col))
-                            for col in compute_domain_kwargs["column_list"]
-                        ]
-                        selectable = sa.select(to_select).select_from(selectable)
-                    else:
-                        to_select = [
-                            sa.column(col)
-                            for col in compute_domain_kwargs["column_list"]
-                        ]
-                        selectable = sa.select(to_select).select_from(selectable)
+            accessor_domain_kwargs["column_list"] = compute_domain_kwargs.pop(
+                "column_list"
+            )
+            # Checking if table or identity or other provided, column is not specified. If it is, warning the user
+            return selectable, compute_domain_kwargs, accessor_domain_kwargs
 
         # Letting selectable fall through
         return selectable, compute_domain_kwargs, accessor_domain_kwargs
@@ -805,7 +889,7 @@ def _sample_using_md5(
             == hash_value
         )
 
-    def _build_selectable_from_batch_spec(self, batch_spec) -> Union[Select, str]:
+    def _build_selectable_from_batch_spec(self, batch_spec) -> Union[Selectable, str]:
         table_name: str = batch_spec["table_name"]
         if "splitter_method" in batch_spec:
             splitter_fn = getattr(self, batch_spec["splitter_method"])
@@ -924,7 +1008,7 @@ def get_batch_data_and_markers(
                     batch_spec=batch_spec
                 )
             else:
-                selectable: Select = self._build_selectable_from_batch_spec(
+                selectable: Selectable = self._build_selectable_from_batch_spec(
                     batch_spec=batch_spec
                 )
 
diff --git a/great_expectations/expectations/metrics/map_metric_provider.py b/great_expectations/expectations/metrics/map_metric_provider.py
--- a/great_expectations/expectations/metrics/map_metric_provider.py
+++ b/great_expectations/expectations/metrics/map_metric_provider.py
@@ -748,8 +748,7 @@ def _pandas_multicolumn_map_condition_values(
     In order to invoke the "ignore_row_if" filtering logic, "execution_engine.get_domain_records()" must be supplied
     with all of the available "domain_kwargs" keys.
     """
-    domain_kwargs = copy.deepcopy(compute_domain_kwargs)
-    domain_kwargs.update(accessor_domain_kwargs)
+    domain_kwargs = dict(**compute_domain_kwargs, **accessor_domain_kwargs)
     df = execution_engine.get_domain_records(
         domain_kwargs=domain_kwargs,
     )
@@ -797,8 +796,7 @@ def _pandas_multicolumn_map_condition_filtered_row_count(
     In order to invoke the "ignore_row_if" filtering logic, "execution_engine.get_domain_records()" must be supplied
     with all of the available "domain_kwargs" keys.
     """
-    domain_kwargs = copy.deepcopy(compute_domain_kwargs)
-    domain_kwargs.update(accessor_domain_kwargs)
+    domain_kwargs = dict(**compute_domain_kwargs, **accessor_domain_kwargs)
     df = execution_engine.get_domain_records(
         domain_kwargs=domain_kwargs,
     )
@@ -912,8 +910,7 @@ def _pandas_map_condition_index(
     In order to invoke the "ignore_row_if" filtering logic, "execution_engine.get_domain_records()" must be supplied
     with all of the available "domain_kwargs" keys.
     """
-    domain_kwargs = copy.deepcopy(compute_domain_kwargs)
-    domain_kwargs.update(accessor_domain_kwargs)
+    domain_kwargs = dict(**compute_domain_kwargs, **accessor_domain_kwargs)
     df = execution_engine.get_domain_records(
         domain_kwargs=domain_kwargs,
     )
@@ -1044,8 +1041,7 @@ def _pandas_map_condition_rows(
     In order to invoke the "ignore_row_if" filtering logic, "execution_engine.get_domain_records()" must be supplied
     with all of the available "domain_kwargs" keys.
     """
-    domain_kwargs = copy.deepcopy(compute_domain_kwargs)
-    domain_kwargs.update(accessor_domain_kwargs)
+    domain_kwargs = dict(**compute_domain_kwargs, **accessor_domain_kwargs)
     df = execution_engine.get_domain_records(
         domain_kwargs=domain_kwargs,
     )
@@ -1127,8 +1123,8 @@ def _sqlalchemy_map_condition_unexpected_count_value(
     unexpected_condition, compute_domain_kwargs, accessor_domain_kwargs = metrics.get(
         "unexpected_condition"
     )
-    (selectable, _, _,) = execution_engine.get_compute_domain(
-        compute_domain_kwargs, domain_type=MetricDomainTypes.IDENTITY
+    selectable = execution_engine.get_domain_records(
+        domain_kwargs=compute_domain_kwargs,
     )
 
     count_case_statement: List[sa.sql.elements.Label] = [
@@ -1209,8 +1205,8 @@ def _sqlalchemy_column_map_condition_values(
     unexpected_condition, compute_domain_kwargs, accessor_domain_kwargs = metrics.get(
         "unexpected_condition"
     )
-    (selectable, _, _,) = execution_engine.get_compute_domain(
-        compute_domain_kwargs, domain_type=MetricDomainTypes.IDENTITY
+    selectable = execution_engine.get_domain_records(
+        domain_kwargs=compute_domain_kwargs,
     )
 
     if "column" not in accessor_domain_kwargs:
@@ -1258,8 +1254,8 @@ def _sqlalchemy_column_map_condition_value_counts(
     unexpected_condition, compute_domain_kwargs, accessor_domain_kwargs = metrics.get(
         "unexpected_condition"
     )
-    (selectable, _, _,) = execution_engine.get_compute_domain(
-        compute_domain_kwargs, domain_type=MetricDomainTypes.IDENTITY
+    selectable = execution_engine.get_domain_records(
+        domain_kwargs=compute_domain_kwargs,
     )
 
     if "column" not in accessor_domain_kwargs:
@@ -1301,8 +1297,13 @@ def _sqlalchemy_map_condition_rows(
     unexpected_condition, compute_domain_kwargs, accessor_domain_kwargs = metrics.get(
         "unexpected_condition"
     )
-    (selectable, _, _,) = execution_engine.get_compute_domain(
-        compute_domain_kwargs, domain_type=MetricDomainTypes.IDENTITY
+    """
+    In order to invoke the "ignore_row_if" filtering logic, "execution_engine.get_domain_records()" must be supplied
+    with all of the available "domain_kwargs" keys.
+    """
+    domain_kwargs = dict(**compute_domain_kwargs, **accessor_domain_kwargs)
+    selectable = execution_engine.get_domain_records(
+        domain_kwargs=domain_kwargs,
     )
 
     query = (
@@ -1609,6 +1610,15 @@ def _register_metric_functions(cls):
                         metric_provider=condition_provider,
                         metric_fn_type=metric_fn_type,
                     )
+                    register_metric(
+                        metric_name=metric_name + ".unexpected_rows",
+                        metric_domain_keys=metric_domain_keys,
+                        metric_value_keys=(*metric_value_keys, "result_format"),
+                        execution_engine=engine,
+                        metric_class=cls,
+                        metric_provider=_sqlalchemy_map_condition_rows,
+                        metric_fn_type=MetricFunctionTypes.VALUE,
+                    )
                     if metric_fn_type == MetricPartialFunctionTypes.MAP_CONDITION_FN:
                         register_metric(
                             metric_name=metric_name + ".unexpected_count.aggregate_fn",
@@ -1640,15 +1650,6 @@ def _register_metric_functions(cls):
                             metric_provider=_sqlalchemy_map_condition_unexpected_count_value,
                             metric_fn_type=MetricFunctionTypes.VALUE,
                         )
-                    register_metric(
-                        metric_name=metric_name + ".unexpected_rows",
-                        metric_domain_keys=metric_domain_keys,
-                        metric_value_keys=(*metric_value_keys, "result_format"),
-                        execution_engine=engine,
-                        metric_class=cls,
-                        metric_provider=_sqlalchemy_map_condition_rows,
-                        metric_fn_type=MetricFunctionTypes.VALUE,
-                    )
                     if domain_type == MetricDomainTypes.COLUMN:
                         register_metric(
                             metric_name=metric_name + ".unexpected_values",
@@ -1678,6 +1679,15 @@ def _register_metric_functions(cls):
                         metric_provider=condition_provider,
                         metric_fn_type=metric_fn_type,
                     )
+                    register_metric(
+                        metric_name=metric_name + ".unexpected_rows",
+                        metric_domain_keys=metric_domain_keys,
+                        metric_value_keys=(*metric_value_keys, "result_format"),
+                        execution_engine=engine,
+                        metric_class=cls,
+                        metric_provider=_spark_map_condition_rows,
+                        metric_fn_type=MetricFunctionTypes.VALUE,
+                    )
                     if metric_fn_type == MetricPartialFunctionTypes.MAP_CONDITION_FN:
                         register_metric(
                             metric_name=metric_name + ".unexpected_count.aggregate_fn",
@@ -1709,15 +1719,6 @@ def _register_metric_functions(cls):
                             metric_provider=_spark_map_condition_unexpected_count_value,
                             metric_fn_type=MetricFunctionTypes.VALUE,
                         )
-                    register_metric(
-                        metric_name=metric_name + ".unexpected_rows",
-                        metric_domain_keys=metric_domain_keys,
-                        metric_value_keys=(*metric_value_keys, "result_format"),
-                        execution_engine=engine,
-                        metric_class=cls,
-                        metric_provider=_spark_map_condition_rows,
-                        metric_fn_type=MetricFunctionTypes.VALUE,
-                    )
                     if domain_type == MetricDomainTypes.COLUMN:
                         register_metric(
                             metric_name=metric_name + ".unexpected_values",


Test patch:
diff --git a/tests/execution_engine/test_sqlalchemy_execution_engine.py b/tests/execution_engine/test_sqlalchemy_execution_engine.py
--- a/tests/execution_engine/test_sqlalchemy_execution_engine.py
+++ b/tests/execution_engine/test_sqlalchemy_execution_engine.py
@@ -231,6 +231,150 @@ def test_sa_batch_aggregate_metrics(caplog, sa):
     assert found_message
 
 
+def test_get_domain_records_with_column_domain(sa):
+    df = pd.DataFrame(
+        {"a": [1, 2, 3, 4, 5], "b": [2, 3, 4, 5, None], "c": [1, 2, 3, 4, None]}
+    )
+    engine = build_sa_engine(df, sa)
+    data = engine.get_domain_records(
+        domain_kwargs={
+            "column": "a",
+            "row_condition": 'col("b")<5',
+            "condition_parser": "great_expectations__experimental__",
+        }
+    )
+    domain_data = engine.engine.execute(sa.select(["*"]).select_from(data)).fetchall()
+
+    expected_column_df = df.iloc[:3]
+    engine = build_sa_engine(expected_column_df, sa)
+    expected_data = engine.engine.execute(
+        sa.select(["*"]).select_from(engine.active_batch_data.selectable)
+    ).fetchall()
+
+    assert (
+        domain_data == expected_data
+    ), "Data does not match after getting full access compute domain"
+
+
+def test_get_domain_records_with_column_pair_domain(sa):
+    df = pd.DataFrame(
+        {
+            "a": [1, 2, 3, 4, 5, 6],
+            "b": [2, 3, 4, 5, None, 6],
+            "c": [1, 2, 3, 4, 5, None],
+        }
+    )
+    engine = build_sa_engine(df, sa)
+    data = engine.get_domain_records(
+        domain_kwargs={
+            "column_A": "a",
+            "column_B": "b",
+            "row_condition": 'col("b")>2',
+            "condition_parser": "great_expectations__experimental__",
+            "ignore_row_if": "either_value_is_missing",
+        }
+    )
+    domain_data = engine.engine.execute(sa.select(["*"]).select_from(data)).fetchall()
+
+    expected_column_pair_df = pd.DataFrame(
+        {"a": [2, 3, 4, 6], "b": [3.0, 4.0, 5.0, 6.0], "c": [2.0, 3.0, 4.0, None]}
+    )
+    engine = build_sa_engine(expected_column_pair_df, sa)
+    expected_data = engine.engine.execute(
+        sa.select(["*"]).select_from(engine.active_batch_data.selectable)
+    ).fetchall()
+
+    assert (
+        domain_data == expected_data
+    ), "Data does not match after getting full access compute domain"
+
+    engine = build_sa_engine(df, sa)
+    data = engine.get_domain_records(
+        domain_kwargs={
+            "column_A": "b",
+            "column_B": "c",
+            "row_condition": 'col("a")<6',
+            "condition_parser": "great_expectations__experimental__",
+            "ignore_row_if": "either_value_is_missing",
+        }
+    )
+    domain_data = engine.engine.execute(sa.select(["*"]).select_from(data)).fetchall()
+
+    expected_column_pair_df = pd.DataFrame(
+        {"a": [1, 2, 3, 4], "b": [2, 3, 4, 5], "c": [1, 2, 3, 4]}
+    )
+    engine = build_sa_engine(expected_column_pair_df, sa)
+    expected_data = engine.engine.execute(
+        sa.select(["*"]).select_from(engine.active_batch_data.selectable)
+    ).fetchall()
+
+    assert (
+        domain_data == expected_data
+    ), "Data does not match after getting full access compute domain"
+
+
+def test_get_domain_records_with_multicolumn_domain(sa):
+    df = pd.DataFrame(
+        {
+            "a": [1, 2, 3, 4, None, 5],
+            "b": [2, 3, 4, 5, 6, 7],
+            "c": [1, 2, 3, 4, None, 6],
+        }
+    )
+    engine = build_sa_engine(df, sa)
+    data = engine.get_domain_records(
+        domain_kwargs={
+            "column_list": ["a", "c"],
+            "row_condition": 'col("b")>2',
+            "condition_parser": "great_expectations__experimental__",
+            "ignore_row_if": "all_values_are_missing",
+        }
+    )
+    domain_data = engine.engine.execute(sa.select(["*"]).select_from(data)).fetchall()
+
+    expected_multicolumn_df = pd.DataFrame(
+        {"a": [2, 3, 4, 5], "b": [3, 4, 5, 7], "c": [2, 3, 4, 6]}, index=[0, 1, 2, 4]
+    )
+    engine = build_sa_engine(expected_multicolumn_df, sa)
+    expected_data = engine.engine.execute(
+        sa.select(["*"]).select_from(engine.active_batch_data.selectable)
+    ).fetchall()
+
+    assert (
+        domain_data == expected_data
+    ), "Data does not match after getting full access compute domain"
+
+    df = pd.DataFrame(
+        {
+            "a": [1, 2, 3, 4, 5, 6],
+            "b": [2, 3, 4, 5, None, 6],
+            "c": [1, 2, 3, 4, 5, None],
+        }
+    )
+    engine = build_sa_engine(df, sa)
+    data = engine.get_domain_records(
+        domain_kwargs={
+            "column_list": ["b", "c"],
+            "row_condition": 'col("a")<6',
+            "condition_parser": "great_expectations__experimental__",
+            "ignore_row_if": "any_value_is_missing",
+        }
+    )
+    domain_data = engine.engine.execute(sa.select(["*"]).select_from(data)).fetchall()
+
+    expected_multicolumn_df = pd.DataFrame(
+        {"a": [1, 2, 3, 4], "b": [2, 3, 4, 5], "c": [1, 2, 3, 4]}
+    )
+    engine = build_sa_engine(expected_multicolumn_df, sa)
+    expected_data = engine.engine.execute(
+        sa.select(["*"]).select_from(engine.active_batch_data.selectable)
+    ).fetchall()
+
+    assert (
+        domain_data == expected_data
+    ), "Data does not match after getting full access compute domain"
+
+
 # Ensuring functionality of compute_domain when no domain kwargs are given
 def test_get_compute_domain_with_no_domain_kwargs(sa):
     engine = build_sa_engine(
@@ -281,30 +425,6 @@ def test_get_compute_domain_with_column_pair(sa):
         "column_B": "b",
     }, "Accessor kwargs have been modified"
 
-    # Building new engine so that values still found
-    engine = build_sa_engine(
-        pd.DataFrame({"a": [1, 2, 3, 4], "b": [2, 3, 4, None]}), sa
-    )
-    data2, compute_kwargs, accessor_kwargs = engine.get_compute_domain(
-        domain_kwargs={"column_A": "a", "column_B": "b"}, domain_type="identity"
-    )
-
-    # Seeing if raw data is the same as the data after condition has been applied - checking post computation data
-    raw_data = engine.engine.execute(
-        sa.select([sa.column("a"), sa.column("b")]).select_from(
-            engine.active_batch_data.selectable
-        )
-    ).fetchall()
-    domain_data = engine.engine.execute(sa.select(["*"]).select_from(data2)).fetchall()
-
-    # Ensuring that with no domain nothing happens to the data itself
-    assert raw_data == domain_data, "Data does not match after getting compute domain"
-    assert compute_kwargs == {
-        "column_A": "a",
-        "column_B": "b",
-    }, "Compute domain kwargs should be existent"
-    assert accessor_kwargs == {}, "Accessor kwargs have been modified"
-
 
 # Testing for only untested use case - multicolumn
 def test_get_compute_domain_with_multicolumn(sa):
@@ -331,26 +451,6 @@ def test_get_compute_domain_with_multicolumn(sa):
         "column_list": ["a", "b", "c"]
     }, "Accessor kwargs have been modified"
 
-    # Checking for identity
-    data, compute_kwargs, accessor_kwargs = engine.get_compute_domain(
-        domain_kwargs={"column_list": ["a", "b", "c"]}, domain_type="identity"
-    )
-
-    # Seeing if raw data is the same as the data after condition has been applied - checking post computation data
-    raw_data = engine.engine.execute(
-        sa.select([sa.column("a"), sa.column("b"), sa.column("c")]).select_from(
-            engine.active_batch_data.selectable
-        )
-    ).fetchall()
-    domain_data = engine.engine.execute(sa.select(["*"]).select_from(data)).fetchall()
-
-    # Ensuring that with no domain nothing happens to the data itself
-    assert raw_data == domain_data, "Data does not match after getting compute domain"
-    assert compute_kwargs == {
-        "column_list": ["a", "b", "c"]
-    }, "Compute domain kwargs should be existent"
-    assert accessor_kwargs == {}, "Accessor kwargs have been modified"
-
 
 # Testing whether compute domain is properly calculated, but this time obtaining a column
 def test_get_compute_domain_with_column_domain(sa):
@@ -374,27 +474,6 @@ def test_get_compute_domain_with_column_domain(sa):
     assert compute_kwargs == {}, "Compute domain kwargs should be existent"
     assert accessor_kwargs == {"column": "a"}, "Accessor kwargs have been modified"
 
-    # Testing for identity
-    engine = build_sa_engine(
-        pd.DataFrame({"a": [1, 2, 3, 4], "b": [2, 3, 4, None]}), sa
-    )
-
-    # Loading batch data
-    data, compute_kwargs, accessor_kwargs = engine.get_compute_domain(
-        domain_kwargs={"column": "a"}, domain_type=MetricDomainTypes.IDENTITY
-    )
-
-    # Seeing if raw data is the same as the data after condition has been applied - checking post computation data
-    raw_data = engine.engine.execute(
-        sa.select([sa.column("a")]).select_from(engine.active_batch_data.selectable)
-    ).fetchall()
-    domain_data = engine.engine.execute(sa.select(["*"]).select_from(data)).fetchall()
-
-    # Ensuring that column domain is now an accessor kwarg, and data remains unmodified
-    assert raw_data == domain_data, "Data does not match after getting compute domain"
-    assert compute_kwargs == {"column": "a"}, "Compute domain kwargs should be existent"
-    assert accessor_kwargs == {}, "Accessor kwargs have been modified"
-
 
 # What happens when we filter such that no value meets the condition?
 def test_get_compute_domain_with_unmeetable_row_condition(sa):
@@ -404,10 +483,11 @@ def test_get_compute_domain_with_unmeetable_row_condition(sa):
 
     data, compute_kwargs, accessor_kwargs = engine.get_compute_domain(
         domain_kwargs={
+            "column": "a",
             "row_condition": 'col("b") > 24',
             "condition_parser": "great_expectations__experimental__",
         },
-        domain_type="identity",
+        domain_type="column",
     )
 
     # Seeing if raw data is the same as the data after condition has been applied - checking post computation data
@@ -424,7 +504,7 @@ def test_get_compute_domain_with_unmeetable_row_condition(sa):
     assert (
         "row_condition" in compute_kwargs.keys()
     ), "Row condition should be located within compute kwargs"
-    assert accessor_kwargs == {}, "Accessor kwargs have been modified"
+    assert accessor_kwargs == {"column": "a"}, "Accessor kwargs have been modified"
 
 
 # Testing to ensure that great expectation experimental parser also works in terms of defining a compute domain
@@ -460,34 +540,6 @@ def test_get_compute_domain_with_ge_experimental_condition_parser(sa):
     ), "Row condition should be located within compute kwargs"
     assert accessor_kwargs == {"column": "b"}, "Accessor kwargs have been modified"
 
-    # Should react differently for domain type identity
-    data, compute_kwargs, accessor_kwargs = engine.get_compute_domain(
-        domain_kwargs={
-            "column": "b",
-            "row_condition": 'col("b") == 2',
-            "condition_parser": "great_expectations__experimental__",
-        },
-        domain_type="identity",
-    )
-
-    # Ensuring data has been properly queried
-    # Seeing if raw data is the same as the data after condition has been applied - checking post computation data
-    engine = build_sa_engine(
-        pd.DataFrame({"a": [1, 2, 3, 4], "b": [2, 3, 4, None]}), sa
-    )
-    raw_data = engine.engine.execute(
-        sa.select(["*"])
-        .select_from(engine.active_batch_data.selectable)
-        .where(sa.column("b") == 2)
-    ).fetchall()
-    domain_data = engine.engine.execute(sa.select(["*"]).select_from(data)).fetchall()
-
-    # Ensuring compute kwargs have not been modified
-    assert (
-        "row_condition" in compute_kwargs.keys()
-    ), "Row condition should be located within compute kwargs"
-    assert accessor_kwargs == {}, "Accessor kwargs have been modified"
-
 
 def test_get_compute_domain_with_nonexistent_condition_parser(sa):
     engine = build_sa_engine(