From a46495be452cde9c9703e7c67b8c85ef963f7774 Mon Sep 17 00:00:00 2001 From: Courtney Holcomb Date: Mon, 16 Sep 2024 16:08:08 -0700 Subject: [PATCH] wip - allow grain in where filter --- .../requirements-cli.txt | 2 +- .../specs/patterns/typed_patterns.py | 16 +++-- .../query/test_query_parser.py | 58 ++++++++++++++++++- 3 files changed, 69 insertions(+), 7 deletions(-) diff --git a/dbt-metricflow/extra-hatch-configuration/requirements-cli.txt b/dbt-metricflow/extra-hatch-configuration/requirements-cli.txt index ead6c13150..5f59cb9a84 100644 --- a/dbt-metricflow/extra-hatch-configuration/requirements-cli.txt +++ b/dbt-metricflow/extra-hatch-configuration/requirements-cli.txt @@ -1,5 +1,5 @@ # Internal dependencies -dbt-core @ git+https://github.com/dbt-labs/dbt-core@e53420c1d073dc81609ae7aa84cef6ee09650576#subdirectory=core +dbt-core @ git+https://github.com/dbt-labs/dbt-core@ab500a9709e596e6d762855470932eed31267f36#subdirectory=core # dsi version should be fixed by MetricFlow/dbt-core, not set here dbt-semantic-interfaces diff --git a/metricflow-semantics/metricflow_semantics/specs/patterns/typed_patterns.py b/metricflow-semantics/metricflow_semantics/specs/patterns/typed_patterns.py index 22d46f3170..ef05e1f42c 100644 --- a/metricflow-semantics/metricflow_semantics/specs/patterns/typed_patterns.py +++ b/metricflow-semantics/metricflow_semantics/specs/patterns/typed_patterns.py @@ -1,7 +1,7 @@ from __future__ import annotations from dataclasses import dataclass -from typing import List, Sequence +from typing import List, Sequence, Tuple from dbt_semantic_interfaces.call_parameter_sets import ( DimensionCallParameterSet, @@ -39,12 +39,18 @@ def match(self, candidate_specs: Sequence[InstanceSpec]) -> Sequence[LinkableIns def from_call_parameter_set( # noqa: D102 dimension_call_parameter_set: DimensionCallParameterSet, ) -> DimensionPattern: + fields_to_compare: Tuple[ParameterSetField, ...] = ( + ParameterSetField.ELEMENT_NAME, + ParameterSetField.ENTITY_LINKS, + ParameterSetField.DATE_PART, + ) + + if dimension_call_parameter_set.time_granularity is not None: + fields_to_compare += (ParameterSetField.TIME_GRANULARITY,) + return DimensionPattern( parameter_set=EntityLinkPatternParameterSet.from_parameters( - fields_to_compare=( - ParameterSetField.ELEMENT_NAME, - ParameterSetField.ENTITY_LINKS, - ), + fields_to_compare=fields_to_compare, element_name=dimension_call_parameter_set.dimension_reference.element_name, entity_links=dimension_call_parameter_set.entity_path, ) diff --git a/metricflow-semantics/tests_metricflow_semantics/query/test_query_parser.py b/metricflow-semantics/tests_metricflow_semantics/query/test_query_parser.py index 0f30cb2537..262e91b277 100644 --- a/metricflow-semantics/tests_metricflow_semantics/query/test_query_parser.py +++ b/metricflow-semantics/tests_metricflow_semantics/query/test_query_parser.py @@ -28,7 +28,13 @@ from metricflow_semantics.test_helpers.example_project_configuration import ( EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE, ) -from metricflow_semantics.test_helpers.metric_time_dimension import MTD +from metricflow_semantics.test_helpers.metric_time_dimension import ( + MTD, + MTD_SPEC_MONTH, + MTD_SPEC_QUARTER, + MTD_SPEC_WEEK, + MTD_SPEC_YEAR, +) from metricflow_semantics.test_helpers.snapshot_helpers import assert_object_snapshot_equal logger = logging.getLogger(__name__) @@ -624,3 +630,53 @@ def test_invalid_group_by_metric(bookings_query_parser: MetricFlowQueryParser) - bookings_query_parser.parse_and_validate_query( metric_names=("bookings",), where_constraint_str="{{ Metric('listings', ['garbage']) }} > 1" ) + + +def test_where_filter_with_grain(bookings_query_parser: MetricFlowQueryParser) -> None: # noqa: D103 + # Can pass granularity into TimeDimension object via time dimension name + query_spec = bookings_query_parser.parse_and_validate_query( + metric_names=["bookings"], + group_by_names=["metric_time"], + where_constraint_str="{{ TimeDimension('metric_time__quarter') }} > '2020-01-15'", + ).query_spec + filter_spec_resolutions = [ + resolution.resolved_spec for resolution in query_spec.filter_spec_resolution_lookup.spec_resolutions + ] + assert len(filter_spec_resolutions) == 1 + assert filter_spec_resolutions[0] == MTD_SPEC_QUARTER + + # Can pass granularity into TimeDimension object via parameter + query_spec = bookings_query_parser.parse_and_validate_query( + metric_names=["bookings"], + group_by_names=["metric_time"], + where_constraint_str="{{ TimeDimension('metric_time', time_granularity_name='year') }} > '2020-01-15'", + ).query_spec + filter_spec_resolutions = [ + resolution.resolved_spec for resolution in query_spec.filter_spec_resolution_lookup.spec_resolutions + ] + assert len(filter_spec_resolutions) == 1 + assert filter_spec_resolutions[0] == MTD_SPEC_YEAR + + # Can pass granularity into Dimension object via time dimension name + query_spec = bookings_query_parser.parse_and_validate_query( + metric_names=["bookings"], + group_by_names=["metric_time"], + where_constraint_str="{{ Dimension('metric_time__week') }} > '2020-01-15'", + ).query_spec + filter_spec_resolutions = [ + resolution.resolved_spec for resolution in query_spec.filter_spec_resolution_lookup.spec_resolutions + ] + assert len(filter_spec_resolutions) == 1 + assert filter_spec_resolutions[0] == MTD_SPEC_WEEK + + # Can pass granularity into Dimension object via parameter + query_spec = bookings_query_parser.parse_and_validate_query( + metric_names=["bookings"], + group_by_names=["metric_time"], + where_constraint_str="{{ Dimension('metric_time', time_granularity='month') }} > '2020-01-15'", + ).query_spec + filter_spec_resolutions = [ + resolution.resolved_spec for resolution in query_spec.filter_spec_resolution_lookup.spec_resolutions + ] + assert len(filter_spec_resolutions) == 1 + assert filter_spec_resolutions[0] == MTD_SPEC_MONTH