From d9d4b31d79d655fd15a009d3eb3ee1f881c360d2 Mon Sep 17 00:00:00 2001 From: Courtney Holcomb Date: Fri, 27 Sep 2024 12:52:55 -0700 Subject: [PATCH] Use list of where filters instead of single where filter --- dbt-metricflow/dbt_metricflow/cli/main.py | 2 +- .../v0_1/saved_query_dependency_resolver.py | 2 +- .../query/query_parser.py | 47 +++++---- .../query/test_query_parser.py | 10 +- metricflow/engine/metricflow_engine.py | 18 ++-- .../builder/test_dataflow_plan_builder.py | 42 ++++---- .../test_predicate_pushdown_optimizer.py | 16 ++-- .../query_output/test_cumulative_metrics.py | 2 +- .../query_output/test_metric_filter_output.py | 4 +- .../integration/test_configured_cases.py | 8 +- .../test_distinct_values_to_sql.py | 8 +- .../test_dataflow_to_sql_plan.py | 2 +- .../test_conversion_metric_rendering.py | 30 +++--- .../test_cumulative_metric_rendering.py | 12 ++- .../test_custom_granularity.py | 24 ++--- .../test_derived_metric_rendering.py | 38 ++++---- .../test_fill_nulls_with_rendering.py | 8 +- .../test_metric_filter_rendering.py | 96 ++++++++++++------- .../test_predicate_pushdown_rendering.py | 44 +++++---- .../query_rendering/test_query_rendering.py | 24 +++-- .../test_time_spine_join_rendering.py | 4 +- 21 files changed, 249 insertions(+), 192 deletions(-) diff --git a/dbt-metricflow/dbt_metricflow/cli/main.py b/dbt-metricflow/dbt_metricflow/cli/main.py index 969eb572ab..2b8d3300c6 100644 --- a/dbt-metricflow/dbt_metricflow/cli/main.py +++ b/dbt-metricflow/dbt_metricflow/cli/main.py @@ -281,7 +281,7 @@ def query( limit=limit, time_constraint_start=start_time, time_constraint_end=end_time, - where_constraint=where, + where_constraints=[where] if where else None, order_by_names=order, ) diff --git a/metricflow-semantics/metricflow_semantics/api/v0_1/saved_query_dependency_resolver.py b/metricflow-semantics/metricflow_semantics/api/v0_1/saved_query_dependency_resolver.py index 4367720272..55ab120c1f 100644 --- a/metricflow-semantics/metricflow_semantics/api/v0_1/saved_query_dependency_resolver.py +++ b/metricflow-semantics/metricflow_semantics/api/v0_1/saved_query_dependency_resolver.py @@ -49,7 +49,7 @@ def _resolve_dependencies(self, saved_query_name: str) -> SavedQueryDependencySe parse_result = self._query_parser.parse_and_validate_saved_query( saved_query_parameter=SavedQueryParameter(saved_query_name), - where_filter=None, + where_filters=None, limit=None, time_constraint_start=None, time_constraint_end=None, diff --git a/metricflow-semantics/metricflow_semantics/query/query_parser.py b/metricflow-semantics/metricflow_semantics/query/query_parser.py index 29d8d0b644..eacc292b5a 100644 --- a/metricflow-semantics/metricflow_semantics/query/query_parser.py +++ b/metricflow-semantics/metricflow_semantics/query/query_parser.py @@ -15,7 +15,6 @@ from dbt_semantic_interfaces.type_enums import TimeGranularity from metricflow_semantics.assert_one_arg import assert_at_most_one_arg_set -from metricflow_semantics.filters.merge_where import merge_to_single_where_filter from metricflow_semantics.filters.time_constraint import TimeRangeConstraint from metricflow_semantics.mf_logging.formatting import indent from metricflow_semantics.mf_logging.lazy_formattable import LazyFormat @@ -93,7 +92,7 @@ def __init__( # noqa: D107 def parse_and_validate_saved_query( self, saved_query_parameter: SavedQueryParameter, - where_filter: Optional[WhereFilter], + where_filters: Optional[Sequence[WhereFilter]], limit: Optional[int], time_constraint_start: Optional[datetime.datetime], time_constraint_end: Optional[datetime.datetime], @@ -107,19 +106,19 @@ def parse_and_validate_saved_query( saved_query = self._get_saved_query(saved_query_parameter) # Merge interface could streamline this. - where_filters: List[WhereFilter] = [] + parsed_where_filters: List[WhereFilter] = [] if saved_query.query_params.where is not None: - where_filters.extend(saved_query.query_params.where.where_filters) - if where_filter is not None: - where_filters.append(where_filter) + parsed_where_filters.extend(saved_query.query_params.where.where_filters) + if where_filters is not None: + parsed_where_filters.extend(where_filters) return self._parse_and_validate_query( metric_names=saved_query.query_params.metrics, metrics=None, group_by_names=saved_query.query_params.group_by, group_by=None, - where_constraint=merge_to_single_where_filter(PydanticWhereFilterIntersection(where_filters=where_filters)), - where_constraint_str=None, + where_constraints=PydanticWhereFilterIntersection(where_filters=parsed_where_filters), + where_constraint_strs=None, time_constraint_start=time_constraint_start, time_constraint_end=time_constraint_end, limit=limit, @@ -309,8 +308,8 @@ def parse_and_validate_query( limit: Optional[int] = None, time_constraint_start: Optional[datetime.datetime] = None, time_constraint_end: Optional[datetime.datetime] = None, - where_constraint: Optional[WhereFilter] = None, - where_constraint_str: Optional[str] = None, + where_constraints: Optional[Sequence[WhereFilter]] = None, + where_constraint_strs: Optional[Sequence[str]] = None, order_by_names: Optional[Sequence[str]] = None, order_by: Optional[Sequence[OrderByQueryParameter]] = None, min_max_only: bool = False, @@ -329,8 +328,8 @@ def parse_and_validate_query( limit=limit, time_constraint_start=time_constraint_start, time_constraint_end=time_constraint_end, - where_constraint=where_constraint, - where_constraint_str=where_constraint_str, + where_constraints=where_constraints, + where_constraint_strs=where_constraint_strs, order_by_names=order_by_names, order_by=order_by, min_max_only=min_max_only, @@ -346,8 +345,8 @@ def _parse_and_validate_query( limit: Optional[int], time_constraint_start: Optional[datetime.datetime], time_constraint_end: Optional[datetime.datetime], - where_constraint: Optional[WhereFilter], - where_constraint_str: Optional[str], + where_constraints: Optional[Sequence[WhereFilter]], + where_constraint_strs: Optional[Sequence[str]], order_by_names: Optional[Sequence[str]], order_by: Optional[Sequence[OrderByQueryParameter]], min_max_only: bool, @@ -357,7 +356,7 @@ def _parse_and_validate_query( assert_at_most_one_arg_set(metric_names=metric_names, metrics=metrics) assert_at_most_one_arg_set(group_by_names=group_by_names, group_by=group_by) assert_at_most_one_arg_set(order_by_names=order_by_names, order_by=order_by) - assert_at_most_one_arg_set(where_constraint=where_constraint, where_constraint_str=where_constraint_str) + assert_at_most_one_arg_set(where_constraints=where_constraints, where_constraint_strs=where_constraint_strs) metric_names = metric_names or () metrics = metrics or () @@ -455,10 +454,20 @@ def _parse_and_validate_query( where_filters: List[PydanticWhereFilter] = [] - if where_constraint is not None: - where_filters.append(PydanticWhereFilter(where_sql_template=where_constraint.where_sql_template)) - if where_constraint_str is not None: - where_filters.append(PydanticWhereFilter(where_sql_template=where_constraint_str)) + if where_constraints is not None: + where_filters.extend( + [ + PydanticWhereFilter(where_sql_template=constraint.where_sql_template) + for constraint in where_constraints + ] + ) + if where_constraint_strs is not None: + where_filters.extend( + [ + PydanticWhereFilter(where_sql_template=where_constraint_str) + for where_constraint_str in where_constraint_strs + ] + ) resolver_input_for_filter = ResolverInputForQueryLevelWhereFilterIntersection( where_filter_intersection=PydanticWhereFilterIntersection(where_filters=where_filters) 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 50c9cc6853..9b8ebbabf1 100644 --- a/metricflow-semantics/tests_metricflow_semantics/query/test_query_parser.py +++ b/metricflow-semantics/tests_metricflow_semantics/query/test_query_parser.py @@ -328,7 +328,7 @@ def test_parse_and_validate_where_constraint_dims( group_by_names=[MTD], time_constraint_start=as_datetime("2020-01-15"), time_constraint_end=as_datetime("2020-02-15"), - where_constraint_str="{{ Dimension('booking__invalid_dim') }} = '1'", + where_constraint_strs=["{{ Dimension('booking__invalid_dim') }} = '1'"], ) with pytest.raises(InvalidQueryException, match="Error parsing where filter"): @@ -337,7 +337,7 @@ def test_parse_and_validate_where_constraint_dims( group_by_names=[MTD], time_constraint_start=as_datetime("2020-01-15"), time_constraint_end=as_datetime("2020-02-15"), - where_constraint_str="{{ Dimension('invalid_format') }} = '1'", + where_constraint_strs=["{{ Dimension('invalid_format') }} = '1'"], ) result = bookings_query_parser.parse_and_validate_query( @@ -345,7 +345,7 @@ def test_parse_and_validate_where_constraint_dims( group_by_names=[MTD], time_constraint_start=as_datetime("2020-01-15"), time_constraint_end=as_datetime("2020-02-15"), - where_constraint_str="{{ Dimension('booking__is_instant') }} = '1'", + where_constraint_strs=["{{ Dimension('booking__is_instant') }} = '1'"], ) assert_object_snapshot_equal(request=request, mf_test_configuration=mf_test_configuration, obj=result) assert ( @@ -366,7 +366,7 @@ def test_parse_and_validate_where_constraint_metric_time( query_parser.parse_and_validate_query( metric_names=["revenue"], group_by_names=[MTD], - where_constraint_str="{{ TimeDimension('metric_time', 'day') }} > '2020-01-15'", + where_constraint_strs=["{{ TimeDimension('metric_time', 'day') }} > '2020-01-15'"], ) @@ -622,5 +622,5 @@ def test_invalid_group_by_metric(bookings_query_parser: MetricFlowQueryParser) - """Tests that a query for an invalid group by metric gives an appropriate group by metric suggestion.""" with pytest.raises(InvalidQueryException, match="Metric\\('bookings', group_by=\\['listing'\\]\\)"): bookings_query_parser.parse_and_validate_query( - metric_names=("bookings",), where_constraint_str="{{ Metric('listings', ['garbage']) }} > 1" + metric_names=("bookings",), where_constraint_strs=["{{ Metric('listings', ['garbage']) }} > 1"] ) diff --git a/metricflow/engine/metricflow_engine.py b/metricflow/engine/metricflow_engine.py index ac82e625a1..5dfe199670 100644 --- a/metricflow/engine/metricflow_engine.py +++ b/metricflow/engine/metricflow_engine.py @@ -90,7 +90,7 @@ class MetricFlowQueryRequest: limit: Limit the result to this many rows. time_constraint_start: Get data for the start of this time range. time_constraint_end: Get data for the end of this time range. - where_constraint: A SQL string using group by names that can be used like a where clause on the output data. + where_constraints: A sequence of SQL strings that can be used like a where clause on the output data. order_by_names: metric and group by names to order by. A "-" can be used to specify reverse order e.g. "-ds". order_by: metric, dimension, or entity objects to order by. output_table: If specified, output the result data to this table instead of a result data_table. @@ -107,7 +107,7 @@ class MetricFlowQueryRequest: limit: Optional[int] = None time_constraint_start: Optional[datetime.datetime] = None time_constraint_end: Optional[datetime.datetime] = None - where_constraint: Optional[str] = None + where_constraints: Optional[Sequence[str]] = None order_by_names: Optional[Sequence[str]] = None order_by: Optional[Sequence[OrderByQueryParameter]] = None min_max_only: bool = False @@ -125,7 +125,7 @@ def create_with_random_request_id( # noqa: D102 limit: Optional[int] = None, time_constraint_start: Optional[datetime.datetime] = None, time_constraint_end: Optional[datetime.datetime] = None, - where_constraint: Optional[str] = None, + where_constraints: Optional[Sequence[str]] = None, order_by_names: Optional[Sequence[str]] = None, order_by: Optional[Sequence[OrderByQueryParameter]] = None, sql_optimization_level: SqlQueryOptimizationLevel = SqlQueryOptimizationLevel.O4, @@ -145,7 +145,7 @@ def create_with_random_request_id( # noqa: D102 limit=limit, time_constraint_start=time_constraint_start, time_constraint_end=time_constraint_end, - where_constraint=where_constraint, + where_constraints=where_constraints, order_by_names=order_by_names, order_by=order_by, sql_optimization_level=sql_optimization_level, @@ -469,11 +469,9 @@ def _create_execution_plan(self, mf_query_request: MetricFlowQueryRequest) -> Me raise InvalidQueryException("Group by items can't be specified with a saved query.") query_spec = self._query_parser.parse_and_validate_saved_query( saved_query_parameter=SavedQueryParameter(mf_query_request.saved_query_name), - where_filter=( - PydanticWhereFilter(where_sql_template=mf_query_request.where_constraint) - if mf_query_request.where_constraint is not None - else None - ), + where_filters=[PydanticWhereFilter(where_sql_template=mf_query_request.where_constraints)] + if mf_query_request.where_constraints is not None + else None, limit=mf_query_request.limit, time_constraint_start=mf_query_request.time_constraint_start, time_constraint_end=mf_query_request.time_constraint_end, @@ -489,7 +487,7 @@ def _create_execution_plan(self, mf_query_request: MetricFlowQueryRequest) -> Me limit=mf_query_request.limit, time_constraint_start=mf_query_request.time_constraint_start, time_constraint_end=mf_query_request.time_constraint_end, - where_constraint_str=mf_query_request.where_constraint, + where_constraint_strs=mf_query_request.where_constraints, order_by_names=mf_query_request.order_by_names, order_by=mf_query_request.order_by, min_max_only=mf_query_request.min_max_only, diff --git a/tests_metricflow/dataflow/builder/test_dataflow_plan_builder.py b/tests_metricflow/dataflow/builder/test_dataflow_plan_builder.py index a349f7c019..3a965e1c6f 100644 --- a/tests_metricflow/dataflow/builder/test_dataflow_plan_builder.py +++ b/tests_metricflow/dataflow/builder/test_dataflow_plan_builder.py @@ -357,7 +357,7 @@ def test_where_constrained_plan( query_spec = query_parser.parse_and_validate_query( metric_names=("bookings",), group_by_names=("booking__is_instant",), - where_constraint_str="{{ Dimension('listing__country_latest') }} = 'us'", + where_constraint_strs=["{{ Dimension('listing__country_latest') }} = 'us'"], ).query_spec dataflow_plan = dataflow_plan_builder.build_plan(query_spec) @@ -386,7 +386,7 @@ def test_where_constrained_plan_time_dimension( query_spec = query_parser.parse_and_validate_query( metric_names=("bookings",), group_by_names=("booking__is_instant",), - where_constraint_str="{{ TimeDimension('metric_time', 'day') }} >= '2020-01-01'", + where_constraint_strs=["{{ TimeDimension('metric_time', 'day') }} >= '2020-01-01'"], ).query_spec dataflow_plan = dataflow_plan_builder.build_plan(query_spec) @@ -416,7 +416,7 @@ def test_where_constrained_with_common_linkable_plan( query_spec = query_parser.parse_and_validate_query( metric_names=("bookings",), group_by_names=("listing__country_latest",), - where_constraint_str="{{ Dimension('listing__country_latest') }} = 'us'", + where_constraint_strs=["{{ Dimension('listing__country_latest') }} = 'us'"], ).query_spec dataflow_plan = dataflow_plan_builder.build_plan(query_spec) @@ -553,7 +553,7 @@ def test_distinct_values_plan( query_spec = query_parser.parse_and_validate_query( metric_names=(), group_by_names=("listing__country_latest",), - where_constraint_str="{{ Dimension('listing__country_latest') }} = 'us'", + where_constraint_strs=["{{ Dimension('listing__country_latest') }} = 'us'"], order_by_names=("-listing__country_latest",), limit=100, ).query_spec @@ -583,7 +583,7 @@ def test_distinct_values_plan_with_join( """Tests a plan to get distinct values of 2 dimensions, where a join is required.""" query_spec = query_parser.parse_and_validate_query( group_by_names=("user__home_state_latest", "listing__is_lux_latest"), - where_constraint_str="{{ Dimension('listing__country_latest') }} = 'us'", + where_constraint_strs=["{{ Dimension('listing__country_latest') }} = 'us'"], order_by_names=("-listing__is_lux_latest",), limit=100, ).query_spec @@ -1188,9 +1188,9 @@ def test_join_to_time_spine_with_filters( query_spec = query_parser.parse_and_validate_query( metric_names=("bookings_fill_nulls_with_0",), group_by_names=("metric_time__day",), - where_constraint=PydanticWhereFilter( - where_sql_template=("{{ TimeDimension('metric_time', 'day') }} = '2020-01-01'") - ), + where_constraints=[ + PydanticWhereFilter(where_sql_template=("{{ TimeDimension('metric_time', 'day') }} = '2020-01-01'")) + ], time_constraint_start=datetime.datetime(2020, 1, 3), time_constraint_end=datetime.datetime(2020, 1, 5), ).query_spec @@ -1221,9 +1221,9 @@ def test_offset_window_metric_filter_and_query_have_different_granularities( query_spec = query_parser.parse_and_validate_query( metric_names=("booking_fees_last_week_per_booker_this_week",), group_by_names=("metric_time__month",), - where_constraint=PydanticWhereFilter( - where_sql_template=("{{ TimeDimension('metric_time', 'day') }} = '2020-01-01'") - ), + where_constraints=[ + PydanticWhereFilter(where_sql_template=("{{ TimeDimension('metric_time', 'day') }} = '2020-01-01'")) + ], ).query_spec dataflow_plan = dataflow_plan_builder.build_plan(query_spec) @@ -1252,9 +1252,9 @@ def test_offset_to_grain_metric_filter_and_query_have_different_granularities( query_spec = query_parser.parse_and_validate_query( metric_names=("bookings_at_start_of_month",), group_by_names=("metric_time__month",), - where_constraint=PydanticWhereFilter( - where_sql_template=("{{ TimeDimension('metric_time', 'day') }} = '2020-01-01'") - ), + where_constraints=[ + PydanticWhereFilter(where_sql_template=("{{ TimeDimension('metric_time', 'day') }} = '2020-01-01'")) + ], ).query_spec dataflow_plan = dataflow_plan_builder.build_plan(query_spec) @@ -1281,7 +1281,7 @@ def test_metric_in_query_where_filter( ) -> None: """Test querying a metric that has a metric in its where filter.""" query_spec = query_parser.parse_and_validate_query( - metric_names=("listings",), where_constraint_str="{{ Metric('bookings', ['listing'])}} > 2" + metric_names=("listings",), where_constraint_strs=["{{ Metric('bookings', ['listing'])}} > 2"] ).query_spec dataflow_plan = dataflow_plan_builder.build_plan(query_spec) @@ -1340,11 +1340,13 @@ def test_all_available_metric_filters( entity_spec = group_by_metric_spec.metric_subquery_entity_spec query_spec = query_parser.parse_and_validate_query( metric_names=("bookings",), - where_constraint=PydanticWhereFilter( - where_sql_template=string.Template("{{ Metric('$metric_name', ['$entity_name']) }} > 2").substitute( - metric_name=linkable_metric.element_name, entity_name=entity_spec.qualified_name - ), - ), + where_constraints=[ + PydanticWhereFilter( + where_sql_template=string.Template( + "{{ Metric('$metric_name', ['$entity_name']) }} > 2" + ).substitute(metric_name=linkable_metric.element_name, entity_name=entity_spec.qualified_name), + ) + ], ).query_spec dataflow_plan_builder.build_plan(query_spec) diff --git a/tests_metricflow/dataflow/optimizer/test_predicate_pushdown_optimizer.py b/tests_metricflow/dataflow/optimizer/test_predicate_pushdown_optimizer.py index 562d2964ec..d1851855d3 100644 --- a/tests_metricflow/dataflow/optimizer/test_predicate_pushdown_optimizer.py +++ b/tests_metricflow/dataflow/optimizer/test_predicate_pushdown_optimizer.py @@ -209,7 +209,7 @@ def test_simple_join_categorical_pushdown( query_spec = query_parser.parse_and_validate_query( metric_names=("bookings",), group_by_names=("listing__country_latest",), - where_constraint=PydanticWhereFilter(where_sql_template="{{ Dimension('booking__is_instant') }}"), + where_constraints=[PydanticWhereFilter(where_sql_template="{{ Dimension('booking__is_instant') }}")], ).query_spec _check_optimization( request=request, @@ -236,7 +236,7 @@ def test_simple_join_metric_time_pushdown_with_two_targets( query_spec = query_parser.parse_and_validate_query( metric_names=("bookings",), group_by_names=("listing__country_latest",), - where_constraint=PydanticWhereFilter(where_sql_template="{{ TimeDimension('metric_time') }} = '2024-01-01'"), + where_constraints=[PydanticWhereFilter(where_sql_template="{{ TimeDimension('metric_time') }} = '2024-01-01'")], ).query_spec _check_optimization( request=request, @@ -260,7 +260,7 @@ def test_conversion_metric_predicate_pushdown( query_spec = query_parser.parse_and_validate_query( metric_names=("visit_buy_conversion_rate_7days",), group_by_names=("metric_time", "user__home_state_latest"), - where_constraint=PydanticWhereFilter(where_sql_template="{{ Dimension('visit__referrer_id') }} = '123456'"), + where_constraints=[PydanticWhereFilter(where_sql_template="{{ Dimension('visit__referrer_id') }} = '123456'")], ).query_spec _check_optimization( request=request, @@ -290,7 +290,7 @@ def test_cumulative_metric_predicate_pushdown( query_spec = query_parser.parse_and_validate_query( metric_names=("every_two_days_bookers",), group_by_names=("listing__country_latest", "metric_time"), - where_constraint=PydanticWhereFilter(where_sql_template="{{ Dimension('booking__is_instant') }}"), + where_constraints=[PydanticWhereFilter(where_sql_template="{{ Dimension('booking__is_instant') }}")], ).query_spec _check_optimization( request=request, @@ -314,7 +314,7 @@ def test_aggregate_output_join_metric_predicate_pushdown( """ query_spec = query_parser.parse_and_validate_query( metric_names=("views_times_booking_value",), - where_constraint=PydanticWhereFilter(where_sql_template="{{ Dimension('listing__is_lux_latest') }}"), + where_constraints=[PydanticWhereFilter(where_sql_template="{{ Dimension('listing__is_lux_latest') }}")], ).query_spec _check_optimization( request=request, @@ -343,7 +343,7 @@ def test_offset_metric_predicate_pushdown( query_spec = query_parser.parse_and_validate_query( metric_names=("bookings_growth_2_weeks",), group_by_names=("listing__country_latest", "metric_time"), - where_constraint=PydanticWhereFilter(where_sql_template="{{ Dimension('booking__is_instant') }}"), + where_constraints=[PydanticWhereFilter(where_sql_template="{{ Dimension('booking__is_instant') }}")], ).query_spec _check_optimization( request=request, @@ -371,7 +371,7 @@ def test_fill_nulls_time_spine_metric_predicate_pushdown( query_spec = query_parser.parse_and_validate_query( metric_names=("bookings_growth_2_weeks_fill_nulls_with_0",), group_by_names=("listing__country_latest", "metric_time"), - where_constraint=PydanticWhereFilter(where_sql_template="{{ Dimension('booking__is_instant') }}"), + where_constraints=[PydanticWhereFilter(where_sql_template="{{ Dimension('booking__is_instant') }}")], ).query_spec _check_optimization( request=request, @@ -405,7 +405,7 @@ def test_fill_nulls_time_spine_metric_with_post_agg_join_predicate_pushdown( query_spec = query_parser.parse_and_validate_query( metric_names=("bookings_growth_2_weeks_fill_nulls_with_0",), group_by_names=("listing__country_latest", "booking__is_instant", "metric_time"), - where_constraint=PydanticWhereFilter(where_sql_template="{{ Dimension('booking__is_instant') }}"), + where_constraints=[PydanticWhereFilter(where_sql_template="{{ Dimension('booking__is_instant') }}")], ).query_spec _check_optimization( request=request, diff --git a/tests_metricflow/integration/query_output/test_cumulative_metrics.py b/tests_metricflow/integration/query_output/test_cumulative_metrics.py index 5d54d50bf7..cc719f78c5 100644 --- a/tests_metricflow/integration/query_output/test_cumulative_metrics.py +++ b/tests_metricflow/integration/query_output/test_cumulative_metrics.py @@ -144,7 +144,7 @@ def test_cumulative_metric_with_non_adjustable_filter( metric_names=["trailing_2_months_revenue"], group_by_names=["metric_time"], order_by_names=["metric_time"], - where_constraint=where_constraint, + where_constraints=[where_constraint], time_constraint_end=as_datetime("2020-12-31"), ) ) diff --git a/tests_metricflow/integration/query_output/test_metric_filter_output.py b/tests_metricflow/integration/query_output/test_metric_filter_output.py index eb51b81b16..93528434bd 100644 --- a/tests_metricflow/integration/query_output/test_metric_filter_output.py +++ b/tests_metricflow/integration/query_output/test_metric_filter_output.py @@ -22,7 +22,7 @@ def test_query_with_simple_metric_in_where_filter( # noqa: D103 metric_names=["listings", "bookings"], group_by_names=["listing"], order_by_names=["listing"], - where_constraint="{{ Metric('bookings', ['listing']) }} > 3", + where_constraints=["{{ Metric('bookings', ['listing']) }} > 3"], ) ) assert query_result.result_df is not None, "Unexpected empty result." @@ -48,7 +48,7 @@ def test_metric_with_metric_in_where_filter( # noqa: D103 metric_names=["active_listings", "bookings"], group_by_names=["listing"], order_by_names=["listing"], - where_constraint="{{ Metric('bookings', ['listing']) }} > 1", + where_constraints=["{{ Metric('bookings', ['listing']) }} > 1"], ) ) assert query_result.result_df is not None, "Unexpected empty result." diff --git a/tests_metricflow/integration/test_configured_cases.py b/tests_metricflow/integration/test_configured_cases.py index 3c387a3b3f..c7763bbb43 100644 --- a/tests_metricflow/integration/test_configured_cases.py +++ b/tests_metricflow/integration/test_configured_cases.py @@ -280,7 +280,7 @@ def test_case( limit=case.limit, time_constraint_start=parser.parse(case.time_constraint[0]) if case.time_constraint else None, time_constraint_end=parser.parse(case.time_constraint[1]) if case.time_constraint else None, - where_constraint=( + where_constraints=[ jinja2.Template( case.where_filter, undefined=jinja2.StrictUndefined, @@ -302,9 +302,9 @@ def test_case( generate_random_uuid=check_query_helpers.generate_random_uuid, cast_to_ts=check_query_helpers.cast_to_ts, ) - if case.where_filter - else None - ), + ] + if case.where_filter + else None, order_by_names=case.order_bys, min_max_only=case.min_max_only, ) diff --git a/tests_metricflow/plan_conversion/dataflow_to_sql/test_distinct_values_to_sql.py b/tests_metricflow/plan_conversion/dataflow_to_sql/test_distinct_values_to_sql.py index a7cfcd708b..4e9487a117 100644 --- a/tests_metricflow/plan_conversion/dataflow_to_sql/test_distinct_values_to_sql.py +++ b/tests_metricflow/plan_conversion/dataflow_to_sql/test_distinct_values_to_sql.py @@ -55,9 +55,11 @@ def test_dimension_values_with_a_join_and_a_filter( """Tests querying 2 dimensions that require a join and a filter.""" query_spec = query_parser.parse_and_validate_query( group_by_names=("user__home_state_latest", "listing__is_lux_latest"), - where_constraint=PydanticWhereFilter( - where_sql_template="{{ Dimension('user__home_state_latest') }} = 'us'", - ), + where_constraints=[ + PydanticWhereFilter( + where_sql_template="{{ Dimension('user__home_state_latest') }} = 'us'", + ) + ], ).query_spec dataflow_plan = dataflow_plan_builder.build_plan_for_distinct_values(query_spec) diff --git a/tests_metricflow/plan_conversion/test_dataflow_to_sql_plan.py b/tests_metricflow/plan_conversion/test_dataflow_to_sql_plan.py index 6390b1e8ec..cc75e995f7 100644 --- a/tests_metricflow/plan_conversion/test_dataflow_to_sql_plan.py +++ b/tests_metricflow/plan_conversion/test_dataflow_to_sql_plan.py @@ -1224,7 +1224,7 @@ def test_dimension_with_joined_where_constraint( """Tests querying 2 dimensions that require a join.""" query_spec = query_parser.parse_and_validate_query( group_by_names=("user__home_state_latest",), - where_constraint_str="{{ Dimension('listing__country_latest') }} = 'us'", + where_constraint_strs=["{{ Dimension('listing__country_latest') }} = 'us'"], ).query_spec dataflow_plan = dataflow_plan_builder.build_plan_for_distinct_values(query_spec) diff --git a/tests_metricflow/query_rendering/test_conversion_metric_rendering.py b/tests_metricflow/query_rendering/test_conversion_metric_rendering.py index 9dfc6f03f5..6dec9859d5 100644 --- a/tests_metricflow/query_rendering/test_conversion_metric_rendering.py +++ b/tests_metricflow/query_rendering/test_conversion_metric_rendering.py @@ -28,9 +28,9 @@ def test_conversion_metric( parsed_query = query_parser.parse_and_validate_query( metric_names=("visit_buy_conversion_rate",), group_by_names=("metric_time",), - where_constraint=PydanticWhereFilter( - where_sql_template=("{{ TimeDimension('metric_time', 'day') }} = '2020-01-01'") - ), + where_constraints=[ + PydanticWhereFilter(where_sql_template=("{{ TimeDimension('metric_time', 'day') }} = '2020-01-01'")) + ], ) render_and_check( @@ -57,9 +57,9 @@ def test_conversion_metric_with_window( parsed_query = query_parser.parse_and_validate_query( metric_names=("visit_buy_conversion_rate_7days",), group_by_names=("metric_time",), - where_constraint=PydanticWhereFilter( - where_sql_template=("{{ TimeDimension('metric_time', 'day') }} = '2020-01-01'") - ), + where_constraints=[ + PydanticWhereFilter(where_sql_template=("{{ TimeDimension('metric_time', 'day') }} = '2020-01-01'")) + ], ) render_and_check( @@ -86,9 +86,9 @@ def test_conversion_metric_with_categorical_filter( parsed_query = query_parser.parse_and_validate_query( metric_names=("visit_buy_conversion_rate",), group_by_names=("metric_time", "visit__referrer_id"), - where_constraint=PydanticWhereFilter( - where_sql_template=("{{ Dimension('visit__referrer_id') }} = 'ref_id_01'") - ), + where_constraints=[ + PydanticWhereFilter(where_sql_template=("{{ Dimension('visit__referrer_id') }} = 'ref_id_01'")) + ], ) render_and_check( @@ -115,9 +115,9 @@ def test_conversion_metric_with_time_constraint( parsed_query = query_parser.parse_and_validate_query( metric_names=("visit_buy_conversion_rate",), group_by_names=("visit__referrer_id",), - where_constraint=PydanticWhereFilter( - where_sql_template=("{{ Dimension('visit__referrer_id') }} = 'ref_id_01'") - ), + where_constraints=[ + PydanticWhereFilter(where_sql_template=("{{ Dimension('visit__referrer_id') }} = 'ref_id_01'")) + ], time_constraint_start=datetime.datetime(2020, 1, 1), time_constraint_end=datetime.datetime(2020, 1, 2), ) @@ -149,9 +149,9 @@ def test_conversion_metric_with_window_and_time_constraint( "metric_time", "visit__referrer_id", ), - where_constraint=PydanticWhereFilter( - where_sql_template=("{{ Dimension('visit__referrer_id') }} = 'ref_id_01'") - ), + where_constraints=[ + PydanticWhereFilter(where_sql_template=("{{ Dimension('visit__referrer_id') }} = 'ref_id_01'")) + ], time_constraint_start=datetime.datetime(2020, 1, 1), time_constraint_end=datetime.datetime(2020, 1, 2), ) diff --git a/tests_metricflow/query_rendering/test_cumulative_metric_rendering.py b/tests_metricflow/query_rendering/test_cumulative_metric_rendering.py index b53dfa0f4c..3e28cbdd12 100644 --- a/tests_metricflow/query_rendering/test_cumulative_metric_rendering.py +++ b/tests_metricflow/query_rendering/test_cumulative_metric_rendering.py @@ -125,12 +125,14 @@ def test_cumulative_metric_with_non_adjustable_time_filter( query_spec = query_parser.parse_and_validate_query( metric_names=("every_two_days_bookers",), group_by_names=(METRIC_TIME_ELEMENT_NAME,), - where_constraint=PydanticWhereFilter( - where_sql_template=( - "{{ TimeDimension('metric_time', 'day') }} = '2020-01-03' " - "or {{ TimeDimension('metric_time', 'day') }} = '2020-01-07'" + where_constraints=[ + PydanticWhereFilter( + where_sql_template=( + "{{ TimeDimension('metric_time', 'day') }} = '2020-01-03' " + "or {{ TimeDimension('metric_time', 'day') }} = '2020-01-07'" + ) ) - ), + ], ).query_spec render_and_check( diff --git a/tests_metricflow/query_rendering/test_custom_granularity.py b/tests_metricflow/query_rendering/test_custom_granularity.py index 5a82cb954f..97dade057b 100644 --- a/tests_metricflow/query_rendering/test_custom_granularity.py +++ b/tests_metricflow/query_rendering/test_custom_granularity.py @@ -284,9 +284,9 @@ def test_simple_metric_with_custom_granularity_filter( """Simple metric queried with a filter on a custom grain, where that grain is not used in the group by.""" query_spec = query_parser.parse_and_validate_query( metric_names=("bookings",), - where_constraint=PydanticWhereFilter( - where_sql_template=("{{ TimeDimension('metric_time', 'martian_day') }} = '2020-01-01'") - ), + where_constraints=[ + PydanticWhereFilter(where_sql_template=("{{ TimeDimension('metric_time', 'martian_day') }} = '2020-01-01'")) + ], ).query_spec render_and_check( @@ -313,9 +313,9 @@ def test_simple_metric_with_custom_granularity_in_filter_and_group_by( query_spec = query_parser.parse_and_validate_query( metric_names=("bookings",), group_by_names=("metric_time__martian_day",), - where_constraint=PydanticWhereFilter( - where_sql_template=("{{ TimeDimension('metric_time', 'martian_day') }} = '2020-01-01'") - ), + where_constraints=[ + PydanticWhereFilter(where_sql_template=("{{ TimeDimension('metric_time', 'martian_day') }} = '2020-01-01'")) + ], ).query_spec render_and_check( @@ -340,9 +340,9 @@ def test_no_metrics_with_custom_granularity_filter( """Group by items only queried with a filter on a custom grain, where that grain is not used in the group by.""" query_spec = query_parser.parse_and_validate_query( group_by_names=("listing__ds__day",), - where_constraint=PydanticWhereFilter( - where_sql_template=("{{ TimeDimension('listing__ds', 'martian_day') }} = '2020-01-01'") - ), + where_constraints=[ + PydanticWhereFilter(where_sql_template=("{{ TimeDimension('listing__ds', 'martian_day') }} = '2020-01-01'")) + ], ).query_spec render_and_check( @@ -367,9 +367,9 @@ def test_no_metrics_with_custom_granularity_in_filter_and_group_by( """Group by items only queried with a filter on a custom grain, where that grain is also used in the group by.""" query_spec = query_parser.parse_and_validate_query( group_by_names=("listing__ds__martian_day",), - where_constraint=PydanticWhereFilter( - where_sql_template=("{{ TimeDimension('listing__ds', 'martian_day') }} = '2020-01-01'") - ), + where_constraints=[ + PydanticWhereFilter(where_sql_template=("{{ TimeDimension('listing__ds', 'martian_day') }} = '2020-01-01'")) + ], ).query_spec render_and_check( diff --git a/tests_metricflow/query_rendering/test_derived_metric_rendering.py b/tests_metricflow/query_rendering/test_derived_metric_rendering.py index 83e976676d..0ba001c0c2 100644 --- a/tests_metricflow/query_rendering/test_derived_metric_rendering.py +++ b/tests_metricflow/query_rendering/test_derived_metric_rendering.py @@ -111,12 +111,14 @@ def test_derived_metric_with_offset_window_and_time_filter( # noqa: D103 query_spec = query_parser.parse_and_validate_query( metric_names=("bookings_growth_2_weeks",), group_by_names=(METRIC_TIME_ELEMENT_NAME,), - where_constraint=PydanticWhereFilter( - where_sql_template=( - "{{ TimeDimension('metric_time', 'day') }} = '2020-01-01' " - "or {{ TimeDimension('metric_time', 'day') }} = '2020-01-14'" + where_constraints=[ + PydanticWhereFilter( + where_sql_template=( + "{{ TimeDimension('metric_time', 'day') }} = '2020-01-01' " + "or {{ TimeDimension('metric_time', 'day') }} = '2020-01-14'" + ) ) - ), + ], ).query_spec render_and_check( @@ -375,12 +377,14 @@ def test_nested_offsets_with_where_constraint( # noqa: D103 query_spec = query_parser.parse_and_validate_query( metric_names=("bookings_offset_twice",), group_by_names=(METRIC_TIME_ELEMENT_NAME,), - where_constraint=PydanticWhereFilter( - where_sql_template=( - "{{ TimeDimension('metric_time', 'day') }} = '2020-01-12' " - "or {{ TimeDimension('metric_time', 'day') }} = '2020-01-13'" + where_constraints=[ + PydanticWhereFilter( + where_sql_template=( + "{{ TimeDimension('metric_time', 'day') }} = '2020-01-12' " + "or {{ TimeDimension('metric_time', 'day') }} = '2020-01-13'" + ) ) - ), + ], ).query_spec render_and_check( @@ -514,7 +518,7 @@ def test_nested_derived_metric_offset_with_joined_where_constraint_not_selected( query_spec = query_parser.parse_and_validate_query( metric_names=("bookings_offset_twice",), group_by_names=(group_by_name,), - where_constraint_str="{{ Dimension('booking__is_instant') }}", + where_constraint_strs=["{{ Dimension('booking__is_instant') }}"], ).query_spec render_and_check( @@ -749,9 +753,9 @@ def test_offset_window_metric_filter_and_query_have_different_granularities( query_spec = query_parser.parse_and_validate_query( metric_names=("booking_fees_last_week_per_booker_this_week",), group_by_names=("metric_time__month",), - where_constraint=PydanticWhereFilter( - where_sql_template=("{{ TimeDimension('metric_time', 'day') }} = '2020-01-01'") - ), + where_constraints=[ + PydanticWhereFilter(where_sql_template=("{{ TimeDimension('metric_time', 'day') }} = '2020-01-01'")) + ], ).query_spec render_and_check( @@ -778,9 +782,9 @@ def test_offset_to_grain_metric_filter_and_query_have_different_granularities( query_spec = query_parser.parse_and_validate_query( metric_names=("bookings_at_start_of_month",), group_by_names=("metric_time__month",), - where_constraint=PydanticWhereFilter( - where_sql_template=("{{ TimeDimension('metric_time', 'day') }} = '2020-01-01'") - ), + where_constraints=[ + PydanticWhereFilter(where_sql_template=("{{ TimeDimension('metric_time', 'day') }} = '2020-01-01'")) + ], ).query_spec render_and_check( diff --git a/tests_metricflow/query_rendering/test_fill_nulls_with_rendering.py b/tests_metricflow/query_rendering/test_fill_nulls_with_rendering.py index 3189d6cb21..a90c3e14c7 100644 --- a/tests_metricflow/query_rendering/test_fill_nulls_with_rendering.py +++ b/tests_metricflow/query_rendering/test_fill_nulls_with_rendering.py @@ -197,9 +197,11 @@ def test_join_to_time_spine_with_filters( # noqa: D103 query_spec = query_parser.parse_and_validate_query( metric_names=("bookings_fill_nulls_with_0",), group_by_names=("metric_time__day",), - where_constraint=PydanticWhereFilter( - where_sql_template="{{ TimeDimension('metric_time') }} > '2020-01-01'", - ), + where_constraints=[ + PydanticWhereFilter( + where_sql_template="{{ TimeDimension('metric_time') }} > '2020-01-01'", + ) + ], time_constraint_start=datetime.datetime(2020, 1, 3), time_constraint_end=datetime.datetime(2020, 1, 5), ).query_spec diff --git a/tests_metricflow/query_rendering/test_metric_filter_rendering.py b/tests_metricflow/query_rendering/test_metric_filter_rendering.py index a2ce2e2e6d..1d1fc1af4f 100644 --- a/tests_metricflow/query_rendering/test_metric_filter_rendering.py +++ b/tests_metricflow/query_rendering/test_metric_filter_rendering.py @@ -24,9 +24,11 @@ def test_query_with_simple_metric_in_where_filter( """Tests a query with a simple metric in the query-level where filter.""" query_spec = query_parser.parse_and_validate_query( metric_names=("listings",), - where_constraint=PydanticWhereFilter( - where_sql_template="{{ Metric('bookings', ['listing']) }} > 2", - ), + where_constraints=[ + PydanticWhereFilter( + where_sql_template="{{ Metric('bookings', ['listing']) }} > 2", + ) + ], ).query_spec render_and_check( @@ -76,9 +78,11 @@ def test_query_with_derived_metric_in_where_filter( """Tests a query with a derived metric in the query-level where filter.""" query_spec = query_parser.parse_and_validate_query( metric_names=("listings",), - where_constraint=PydanticWhereFilter( - where_sql_template="{{ Metric('views_times_booking_value', ['listing']) }} > 1", - ), + where_constraints=[ + PydanticWhereFilter( + where_sql_template="{{ Metric('views_times_booking_value', ['listing']) }} > 1", + ) + ], ).query_spec render_and_check( @@ -103,9 +107,11 @@ def test_query_with_ratio_metric_in_where_filter( """Tests a query with a ratio metric in the query-level where filter.""" query_spec = query_parser.parse_and_validate_query( metric_names=("listings",), - where_constraint=PydanticWhereFilter( - where_sql_template="{{ Metric('bookings_per_booker', ['listing']) }} > 1", - ), + where_constraints=[ + PydanticWhereFilter( + where_sql_template="{{ Metric('bookings_per_booker', ['listing']) }} > 1", + ) + ], ).query_spec render_and_check( @@ -133,9 +139,11 @@ def test_query_with_cumulative_metric_in_where_filter( """ query_spec = query_parser.parse_and_validate_query( metric_names=("listings",), - where_constraint=PydanticWhereFilter( - where_sql_template="{{ Metric('revenue_all_time', ['user']) }} > 1", - ), + where_constraints=[ + PydanticWhereFilter( + where_sql_template="{{ Metric('revenue_all_time', ['user']) }} > 1", + ) + ], ).query_spec render_and_check( @@ -160,9 +168,11 @@ def test_query_with_multiple_metrics_in_filter( """Tests a query with 2 simple metrics in the query-level where filter.""" query_spec = query_parser.parse_and_validate_query( metric_names=("listings",), - where_constraint=PydanticWhereFilter( - where_sql_template="{{ Metric('bookings', ['listing']) }} > 2 AND {{ Metric('bookers', ['listing']) }} > 1", - ), + where_constraints=[ + PydanticWhereFilter( + where_sql_template="{{ Metric('bookings', ['listing']) }} > 2 AND {{ Metric('bookers', ['listing']) }} > 1", + ) + ], ).query_spec render_and_check( @@ -187,9 +197,11 @@ def test_filter_by_metric_in_same_semantic_model_as_queried_metric( """Tests a query with a simple metric in the query-level where filter.""" query_spec = query_parser.parse_and_validate_query( metric_names=("bookers",), - where_constraint=PydanticWhereFilter( - where_sql_template="{{ Metric('booking_value', ['guest']) }} > 1.00", - ), + where_constraints=[ + PydanticWhereFilter( + where_sql_template="{{ Metric('booking_value', ['guest']) }} > 1.00", + ) + ], ).query_spec render_and_check( @@ -214,9 +226,11 @@ def test_distinct_values_query_with_metric_filter( """Tests a distinct values query with a metric in the query-level where filter.""" query_spec = query_parser.parse_and_validate_query( group_by_names=("listing",), - where_constraint=PydanticWhereFilter( - where_sql_template="{{ Metric('bookings', ['listing']) }} > 2", - ), + where_constraints=[ + PydanticWhereFilter( + where_sql_template="{{ Metric('bookings', ['listing']) }} > 2", + ) + ], ).query_spec render_and_check( @@ -241,9 +255,11 @@ def test_metric_filtered_by_itself( """Tests a query for a metric that filters by the same metric.""" query_spec = query_parser.parse_and_validate_query( metric_names=("bookers",), - where_constraint=PydanticWhereFilter( - where_sql_template="{{ Metric('bookers', ['listing']) }} > 1.00", - ), + where_constraints=[ + PydanticWhereFilter( + where_sql_template="{{ Metric('bookers', ['listing']) }} > 1.00", + ) + ], ).query_spec render_and_check( @@ -267,9 +283,11 @@ def test_group_by_has_local_entity_prefix( # noqa: D103 ) -> None: query_spec = query_parser.parse_and_validate_query( metric_names=("listings",), - where_constraint=PydanticWhereFilter( - where_sql_template="{{ Metric('average_booking_value', ['listing__user']) }} > 1", - ), + where_constraints=[ + PydanticWhereFilter( + where_sql_template="{{ Metric('average_booking_value', ['listing__user']) }} > 1", + ) + ], ).query_spec render_and_check( @@ -293,9 +311,11 @@ def test_filter_with_conversion_metric( # noqa: D103 ) -> None: query_spec = query_parser.parse_and_validate_query( metric_names=("listings",), - where_constraint=PydanticWhereFilter( - where_sql_template="{{ Metric('visit_buy_conversion_rate', ['user']) }} > 2", - ), + where_constraints=[ + PydanticWhereFilter( + where_sql_template="{{ Metric('visit_buy_conversion_rate', ['user']) }} > 2", + ) + ], ).query_spec render_and_check( @@ -320,9 +340,11 @@ def test_inner_query_single_hop( """Tests rendering for a metric filter using a one-hop join in the inner query.""" query_spec = multihop_query_parser.parse_and_validate_query( metric_names=("third_hop_count",), - where_constraint=PydanticWhereFilter( - where_sql_template="{{ Metric('paraguayan_customers', ['customer_id__customer_third_hop_id']) }} > 0", - ), + where_constraints=[ + PydanticWhereFilter( + where_sql_template="{{ Metric('paraguayan_customers', ['customer_id__customer_third_hop_id']) }} > 0", + ) + ], ).query_spec render_and_check( @@ -347,9 +369,11 @@ def test_inner_query_multi_hop( """Tests rendering for a metric filter using a two-hop join in the inner query.""" query_spec = multihop_query_parser.parse_and_validate_query( metric_names=("third_hop_count",), - where_constraint=PydanticWhereFilter( - where_sql_template="{{ Metric('txn_count', ['account_id__customer_id__customer_third_hop_id']) }} > 2", - ), + where_constraints=[ + PydanticWhereFilter( + where_sql_template="{{ Metric('txn_count', ['account_id__customer_id__customer_third_hop_id']) }} > 2", + ) + ], ).query_spec render_and_check( diff --git a/tests_metricflow/query_rendering/test_predicate_pushdown_rendering.py b/tests_metricflow/query_rendering/test_predicate_pushdown_rendering.py index 337b201a2b..d16ab8aecd 100644 --- a/tests_metricflow/query_rendering/test_predicate_pushdown_rendering.py +++ b/tests_metricflow/query_rendering/test_predicate_pushdown_rendering.py @@ -26,9 +26,11 @@ def test_single_categorical_dimension_pushdown( parsed_query = query_parser.parse_and_validate_query( metric_names=("bookings",), group_by_names=("listing__country_latest",), - where_constraint=PydanticWhereFilter( - where_sql_template="{{ Dimension('booking__is_instant') }}", - ), + where_constraints=[ + PydanticWhereFilter( + where_sql_template="{{ Dimension('booking__is_instant') }}", + ) + ], ) render_and_check( @@ -54,9 +56,11 @@ def test_multiple_categorical_dimension_pushdown( parsed_query = query_parser.parse_and_validate_query( metric_names=("listings",), group_by_names=("user__home_state_latest",), - where_constraint=PydanticWhereFilter( - where_sql_template="{{ Dimension('listing__is_lux_latest') }} OR {{ Dimension('listing__capacity_latest') }} > 4", - ), + where_constraints=[ + PydanticWhereFilter( + where_sql_template="{{ Dimension('listing__is_lux_latest') }} OR {{ Dimension('listing__capacity_latest') }} > 4", + ) + ], ) render_and_check( @@ -122,9 +126,11 @@ def test_skipped_pushdown( parsed_query = query_parser.parse_and_validate_query( metric_names=("bookings",), group_by_names=("listing__country_latest",), - where_constraint=PydanticWhereFilter( - where_sql_template="{{ Dimension('booking__is_instant') }} OR {{ Dimension('listing__is_lux_latest') }}", - ), + where_constraints=[ + PydanticWhereFilter( + where_sql_template="{{ Dimension('booking__is_instant') }} OR {{ Dimension('listing__is_lux_latest') }}", + ) + ], ) render_and_check( @@ -155,7 +161,7 @@ def test_metric_time_filter_with_two_targets( parsed_query = query_parser.parse_and_validate_query( metric_names=("bookings",), group_by_names=("listing__country_latest",), - where_constraint=PydanticWhereFilter(where_sql_template="{{ TimeDimension('metric_time') }} = '2024-01-01'"), + where_constraints=[PydanticWhereFilter(where_sql_template="{{ TimeDimension('metric_time') }} = '2024-01-01'")], ) render_and_check( @@ -181,7 +187,7 @@ def test_conversion_metric_query_filters( parsed_query = query_parser.parse_and_validate_query( metric_names=("visit_buy_conversion_rate_7days",), group_by_names=("metric_time", "user__home_state_latest"), - where_constraint=PydanticWhereFilter(where_sql_template="{{ Dimension('visit__referrer_id') }} = '123456'"), + where_constraints=[PydanticWhereFilter(where_sql_template="{{ Dimension('visit__referrer_id') }} = '123456'")], ) render_and_check( @@ -210,7 +216,7 @@ def test_cumulative_metric_with_query_time_filters( parsed_query = query_parser.parse_and_validate_query( metric_names=("every_two_days_bookers",), group_by_names=("listing__country_latest", "metric_time"), - where_constraint=PydanticWhereFilter(where_sql_template="{{ Dimension('booking__is_instant') }}"), + where_constraints=[PydanticWhereFilter(where_sql_template="{{ Dimension('booking__is_instant') }}")], ) render_and_check( @@ -239,7 +245,7 @@ def test_offset_metric_with_query_time_filters( parsed_query = query_parser.parse_and_validate_query( metric_names=("bookings_growth_2_weeks",), group_by_names=("listing__country_latest", "metric_time"), - where_constraint=PydanticWhereFilter(where_sql_template="{{ Dimension('booking__is_instant') }}"), + where_constraints=[PydanticWhereFilter(where_sql_template="{{ Dimension('booking__is_instant') }}")], ) render_and_check( @@ -268,7 +274,7 @@ def test_fill_nulls_time_spine_metric_predicate_pushdown( parsed_query = query_parser.parse_and_validate_query( metric_names=("bookings_growth_2_weeks_fill_nulls_with_0",), group_by_names=("listing__country_latest", "metric_time"), - where_constraint=PydanticWhereFilter(where_sql_template="{{ Dimension('booking__is_instant') }}"), + where_constraints=[PydanticWhereFilter(where_sql_template="{{ Dimension('booking__is_instant') }}")], ) render_and_check( @@ -297,9 +303,11 @@ def test_simple_join_to_time_spine_pushdown_filter_application( parsed_query = query_parser.parse_and_validate_query( metric_names=("bookings_join_to_time_spine",), group_by_names=("booking__is_instant", "metric_time"), - where_constraint=PydanticWhereFilter( - where_sql_template="{{ Dimension('booking__is_instant') }}", - ), + where_constraints=[ + PydanticWhereFilter( + where_sql_template="{{ Dimension('booking__is_instant') }}", + ) + ], ) render_and_check( @@ -327,7 +335,7 @@ def test_saved_query_with_metric_joins_and_filter( """ parsed_query = query_parser.parse_and_validate_saved_query( saved_query_parameter=SavedQueryParameter("saved_query_with_metric_joins_and_filter"), - where_filter=None, + where_filters=None, limit=None, time_constraint_start=None, time_constraint_end=None, diff --git a/tests_metricflow/query_rendering/test_query_rendering.py b/tests_metricflow/query_rendering/test_query_rendering.py index c40179cbfc..8bc4096426 100644 --- a/tests_metricflow/query_rendering/test_query_rendering.py +++ b/tests_metricflow/query_rendering/test_query_rendering.py @@ -77,9 +77,11 @@ def test_filter_with_where_constraint_on_join_dim( query_spec = query_parser.parse_and_validate_query( metric_names=("bookings",), group_by_names=("booking__is_instant",), - where_constraint=PydanticWhereFilter( - where_sql_template="{{ Dimension('listing__country_latest') }} = 'us'", - ), + where_constraints=[ + PydanticWhereFilter( + where_sql_template="{{ Dimension('listing__country_latest') }} = 'us'", + ) + ], ).query_spec render_and_check( @@ -165,9 +167,11 @@ def test_distinct_values( query_spec = query_parser.parse_and_validate_query( group_by_names=("listing__country_latest",), order_by_names=("-listing__country_latest",), - where_constraint=PydanticWhereFilter( - where_sql_template="{{ Dimension('listing__country_latest') }} = 'us'", - ), + where_constraints=[ + PydanticWhereFilter( + where_sql_template="{{ Dimension('listing__country_latest') }} = 'us'", + ) + ], limit=100, ).query_spec @@ -295,9 +299,11 @@ def test_join_to_scd_dimension( query_spec = scd_query_parser.parse_and_validate_query( metric_names=("family_bookings",), group_by_names=(METRIC_TIME_ELEMENT_NAME,), - where_constraint=PydanticWhereFilter( - where_sql_template="{{ Dimension('listing__capacity') }} > 2", - ), + where_constraints=[ + PydanticWhereFilter( + where_sql_template="{{ Dimension('listing__capacity') }} > 2", + ) + ], ).query_spec render_and_check( diff --git a/tests_metricflow/query_rendering/test_time_spine_join_rendering.py b/tests_metricflow/query_rendering/test_time_spine_join_rendering.py index 937420c8f8..261b644677 100644 --- a/tests_metricflow/query_rendering/test_time_spine_join_rendering.py +++ b/tests_metricflow/query_rendering/test_time_spine_join_rendering.py @@ -61,7 +61,7 @@ def test_simple_join_to_time_spine_with_filter( query_spec = query_parser.parse_and_validate_query( metric_names=("bookings_fill_nulls_with_0",), group_by_names=("metric_time__day",), - where_constraint=PydanticWhereFilter(where_sql_template="{{ Dimension('booking__is_instant') }}"), + where_constraints=[PydanticWhereFilter(where_sql_template="{{ Dimension('booking__is_instant') }}")], ).query_spec render_and_check( @@ -87,7 +87,7 @@ def test_simple_join_to_time_spine_with_queried_filter( query_spec = query_parser.parse_and_validate_query( metric_names=("bookings_fill_nulls_with_0",), group_by_names=("metric_time__day", "booking__is_instant"), - where_constraint=PydanticWhereFilter(where_sql_template="{{ Dimension('booking__is_instant') }}"), + where_constraints=[PydanticWhereFilter(where_sql_template="{{ Dimension('booking__is_instant') }}")], ).query_spec render_and_check(