Skip to content

Commit

Permalink
implemented date_part in where filter
Browse files Browse the repository at this point in the history
  • Loading branch information
DevonFulcher committed Nov 8, 2023
1 parent 043bbbb commit 8d9c031
Show file tree
Hide file tree
Showing 31 changed files with 230 additions and 107 deletions.
6 changes: 6 additions & 0 deletions .changes/unreleased/Features-20231107-180843.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
kind: Features
body: Implemented date_part in where filter.
time: 2023-11-07T18:08:43.67846-06:00
custom:
Author: DevonFulcher
Issue: None
6 changes: 6 additions & 0 deletions .changes/unreleased/Under the Hood-20231107-184138.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
kind: Under the Hood
body: Removed DatePart Enum and change imports to depend on DSI version instead.
time: 2023-11-07T18:41:38.606807-06:00
custom:
Author: DevonFulcher
Issue: None
5 changes: 5 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ postgresql postgres:
regenerate-test-snapshots:
hatch -v run dev-env:python metricflow/test/generate_snapshots.py

# Populate persistent source schemas for all relevant SQL engines.
.PHONY: populate-persistent-source-schemas
populate-persistent-source-schemas:
hatch -v run dev-env:python metricflow/test/populate_persistent_source_schemas.py

# Re-generate snapshots for the default SQL engine.
.PHONY: test-snap
test-snap:
Expand Down
2 changes: 1 addition & 1 deletion metricflow/dataset/convert_semantic_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from dbt_semantic_interfaces.protocols.measure import Measure
from dbt_semantic_interfaces.protocols.semantic_model import SemanticModel
from dbt_semantic_interfaces.references import SemanticModelElementReference, SemanticModelReference
from dbt_semantic_interfaces.type_enums.date_part import DatePart
from dbt_semantic_interfaces.type_enums.time_granularity import TimeGranularity

from metricflow.aggregation_properties import AggregationState
Expand Down Expand Up @@ -47,7 +48,6 @@
SqlSelectStatementNode,
SqlTableFromClauseNode,
)
from metricflow.time.date_part import DatePart

logger = logging.getLogger(__name__)

Expand Down
2 changes: 1 addition & 1 deletion metricflow/dataset/dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
from typing import Optional, Sequence

from dbt_semantic_interfaces.references import TimeDimensionReference
from dbt_semantic_interfaces.type_enums.date_part import DatePart
from dbt_semantic_interfaces.type_enums.time_granularity import TimeGranularity
from dbt_semantic_interfaces.validations.unique_valid_name import MetricFlowReservedKeywords

from metricflow.instances import InstanceSet, TimeDimensionInstance
from metricflow.specs.specs import TimeDimensionSpec
from metricflow.time.date_part import DatePart

logger = logging.getLogger(__name__)

Expand Down
3 changes: 1 addition & 2 deletions metricflow/naming/linkable_spec_name.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@
from dataclasses import dataclass
from typing import Optional, Tuple

from dbt_semantic_interfaces.type_enums.date_part import DatePart
from dbt_semantic_interfaces.type_enums.time_granularity import TimeGranularity

from metricflow.time.date_part import DatePart

DUNDER = "__"

logger = logging.getLogger(__name__)
Expand Down
2 changes: 1 addition & 1 deletion metricflow/plan_conversion/instance_converters.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from typing import Dict, List, Optional, Sequence, Tuple

from dbt_semantic_interfaces.references import SemanticModelReference
from dbt_semantic_interfaces.type_enums.date_part import DatePart
from dbt_semantic_interfaces.type_enums.time_granularity import TimeGranularity
from more_itertools import bucket

Expand Down Expand Up @@ -47,7 +48,6 @@
SqlFunctionExpression,
)
from metricflow.sql.sql_plan import SqlSelectColumn
from metricflow.time.date_part import DatePart

logger = logging.getLogger(__name__)

Expand Down
3 changes: 1 addition & 2 deletions metricflow/protocols/query_parameter.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
from typing import Optional, Protocol, Union, runtime_checkable

from dbt_semantic_interfaces.type_enums import TimeGranularity

from metricflow.time.date_part import DatePart
from dbt_semantic_interfaces.type_enums.date_part import DatePart


@runtime_checkable
Expand Down
2 changes: 1 addition & 1 deletion metricflow/query/query_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
MetricReference,
TimeDimensionReference,
)
from dbt_semantic_interfaces.type_enums.date_part import DatePart
from dbt_semantic_interfaces.type_enums.time_granularity import TimeGranularity

from metricflow.assert_one_arg import assert_exactly_one_arg_set
Expand Down Expand Up @@ -55,7 +56,6 @@
WhereFilterSpec,
)
from metricflow.specs.where_filter_transform import WhereSpecFactory
from metricflow.time.date_part import DatePart
from metricflow.time.time_granularity_solver import (
PartialTimeDimensionSpec,
RequestTimeGranularityException,
Expand Down
13 changes: 10 additions & 3 deletions metricflow/specs/dimension_spec_resolver.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from __future__ import annotations

from typing import Sequence
from typing import Optional, Sequence

from dbt_semantic_interfaces.call_parameter_sets import (
DimensionCallParameterSet,
Expand All @@ -10,6 +10,7 @@
from dbt_semantic_interfaces.naming.dundered import DunderedNameFormatter
from dbt_semantic_interfaces.references import DimensionReference, EntityReference, TimeDimensionReference
from dbt_semantic_interfaces.type_enums import TimeGranularity
from dbt_semantic_interfaces.type_enums.date_part import DatePart

from metricflow.specs.specs import DEFAULT_TIME_GRANULARITY, DimensionSpec, TimeDimensionSpec

Expand All @@ -35,16 +36,21 @@ def resolve_dimension_spec(self, name: str, entity_path: Sequence[str]) -> Dimen
)

def resolve_time_dimension_spec(
self, name: str, time_granularity_name: TimeGranularity, entity_path: Sequence[str]
self,
name: str,
time_granularity: Optional[TimeGranularity],
entity_path: Sequence[str],
date_part: Optional[DatePart],
) -> TimeDimensionSpec:
"""Resolve TimeDimension spec with the call_parameter_sets."""
structured_name = DunderedNameFormatter.parse_name(name)
call_parameter_set = TimeDimensionCallParameterSet(
time_dimension_reference=TimeDimensionReference(element_name=structured_name.element_name),
time_granularity=time_granularity_name,
time_granularity=time_granularity,
entity_path=(
tuple(EntityReference(element_name=arg) for arg in entity_path) + structured_name.entity_links
),
date_part=date_part,
)
assert call_parameter_set in self._call_parameter_sets.time_dimension_call_parameter_sets
return TimeDimensionSpec(
Expand All @@ -56,4 +62,5 @@ def resolve_time_dimension_spec(
if call_parameter_set.time_granularity is not None
else DEFAULT_TIME_GRANULARITY
),
date_part=call_parameter_set.date_part,
)
2 changes: 1 addition & 1 deletion metricflow/specs/query_param_implementations.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
from typing import Optional

from dbt_semantic_interfaces.protocols import ProtocolHint
from dbt_semantic_interfaces.type_enums.date_part import DatePart
from dbt_semantic_interfaces.type_enums.time_granularity import TimeGranularity
from typing_extensions import override

from metricflow.naming.linkable_spec_name import StructuredLinkableSpecName
from metricflow.protocols.query_parameter import InputOrderByParameter
from metricflow.protocols.query_parameter import SavedQueryParameter as SavedQueryParameterProtocol
from metricflow.time.date_part import DatePart


@dataclass(frozen=True)
Expand Down
2 changes: 1 addition & 1 deletion metricflow/specs/specs.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@
TimeDimensionReference,
)
from dbt_semantic_interfaces.type_enums.aggregation_type import AggregationType
from dbt_semantic_interfaces.type_enums.date_part import DatePart
from dbt_semantic_interfaces.type_enums.time_granularity import TimeGranularity

from metricflow.aggregation_properties import AggregationState
from metricflow.filters.time_constraint import TimeRangeConstraint
from metricflow.naming.linkable_spec_name import StructuredLinkableSpecName
from metricflow.sql.sql_bind_parameters import SqlBindParameters
from metricflow.sql.sql_column_type import SqlColumnType
from metricflow.time.date_part import DatePart
from metricflow.visitor import VisitorOutputT


Expand Down
39 changes: 28 additions & 11 deletions metricflow/specs/where_filter_dimension.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@
QueryInterfaceDimensionFactory,
)
from dbt_semantic_interfaces.type_enums import TimeGranularity
from dbt_semantic_interfaces.type_enums.date_part import DatePart
from typing_extensions import override

from metricflow.errors.errors import InvalidQuerySyntax
from metricflow.specs.column_assoc import ColumnAssociationResolver
from metricflow.specs.dimension_spec_resolver import DimensionSpecResolver
from metricflow.specs.specs import TimeDimensionSpec
from metricflow.specs.specs import DimensionSpec, InstanceSpec, TimeDimensionSpec


class WhereFilterDimension(ProtocolHint[QueryInterfaceDimension]):
Expand All @@ -37,32 +38,48 @@ def __init__( # noqa
self._column_association_resolver = column_association_resolver
self._name = name
self._entity_path = entity_path
self.dimension_spec = self._dimension_spec_resolver.resolve_dimension_spec(name, entity_path)
self.time_dimension_spec: Optional[TimeDimensionSpec] = None
self.dimension_spec: DimensionSpec = self._dimension_spec_resolver.resolve_dimension_spec(
self._name, self._entity_path
)
self.date_part_name: Optional[str] = None
self.time_granularity_name: Optional[str] = None

@property
def time_dimension_spec(self) -> TimeDimensionSpec:
"""TimeDimensionSpec that results from the builder-pattern configuration."""
return self._dimension_spec_resolver.resolve_time_dimension_spec(
self._name,
TimeGranularity(self.time_granularity_name) if self.time_granularity_name else None,
self._entity_path,
DatePart(self.date_part_name) if self.date_part_name else None,
)

def grain(self, time_granularity_name: str) -> QueryInterfaceDimension:
"""The time granularity."""
self.time_dimension_spec = self._dimension_spec_resolver.resolve_time_dimension_spec(
self._name, TimeGranularity(time_granularity_name), self._entity_path
)
self.time_granularity_name = time_granularity_name
return self

def date_part(self, _date_part: str) -> QueryInterfaceDimension:
def date_part(self, date_part_name: str) -> QueryInterfaceDimension:
"""The date_part requested to extract."""
raise InvalidQuerySyntax("date_part isn't currently supported in the where parameter")
self.date_part_name = date_part_name
return self

def descending(self, _is_descending: bool) -> QueryInterfaceDimension:
"""Set the sort order for order-by."""
raise InvalidQuerySyntax("descending is invalid in the where parameter")

def _get_spec(self) -> InstanceSpec:
"""Get either the TimeDimensionSpec or DimensionSpec."""
if self.time_granularity_name or self.date_part_name:
return self.time_dimension_spec
return self.dimension_spec

def __str__(self) -> str:
"""Returns the column name.
Important in the Jinja sandbox.
"""
return self._column_association_resolver.resolve_spec(
self.time_dimension_spec or self.dimension_spec
).column_name
return self._column_association_resolver.resolve_spec(self._get_spec()).column_name


class WhereFilterDimensionFactory(ProtocolHint[QueryInterfaceDimensionFactory]):
Expand Down
8 changes: 5 additions & 3 deletions metricflow/specs/where_filter_time_dimension.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
QueryInterfaceTimeDimensionFactory,
)
from dbt_semantic_interfaces.type_enums import TimeGranularity
from dbt_semantic_interfaces.type_enums.date_part import DatePart
from typing_extensions import override

from metricflow.errors.errors import InvalidQuerySyntax
Expand Down Expand Up @@ -68,10 +69,11 @@ def create(
raise InvalidQuerySyntax(
"Can't set descending in the where clause. Try setting descending in the order_by clause instead"
)
if date_part_name:
raise InvalidQuerySyntax("date_part_name isn't currently supported in the where parameter")
time_dimension_spec = self._dimension_spec_resolver.resolve_time_dimension_spec(
time_dimension_name, TimeGranularity(time_granularity_name), entity_path
time_dimension_name,
TimeGranularity(time_granularity_name) if time_dimension_name else None,
entity_path,
DatePart(date_part_name) if date_part_name else None,
)
self.time_dimension_specs.append(time_dimension_spec)
column_name = self._column_association_resolver.resolve_spec(time_dimension_spec).column_name
Expand Down
6 changes: 3 additions & 3 deletions metricflow/specs/where_filter_transform.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,12 @@ def create_from_where_filter(self, where_filter: WhereFilter) -> WhereFilterSpec
)

"""
Dimensions that are created with a grain parameter, Dimension(...).grain(...), are
added to dimension_specs otherwise they are add to time_dimension_factory.time_dimension_specs
Dimensions that are created with a grain or date_part parameter, Dimension(...).grain(...), are
added to time_dimension_factory.time_dimension_specs otherwise they are add to dimension_specs
"""
dimension_specs = []
for dimension in dimension_factory.created:
if dimension.time_dimension_spec:
if dimension.time_granularity_name or dimension.date_part_name:
time_dimension_factory.time_dimension_specs.append(dimension.time_dimension_spec)
else:
dimension_specs.append(dimension.dimension_spec)
Expand Down
2 changes: 1 addition & 1 deletion metricflow/sql/render/big_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from typing import Collection

from dbt_semantic_interfaces.enum_extension import assert_values_exhausted
from dbt_semantic_interfaces.type_enums.date_part import DatePart
from dbt_semantic_interfaces.type_enums.time_granularity import TimeGranularity
from typing_extensions import override

Expand All @@ -25,7 +26,6 @@
SqlSubtractTimeIntervalExpression,
)
from metricflow.sql.sql_plan import SqlSelectColumn
from metricflow.time.date_part import DatePart


class BigQuerySqlExpressionRenderer(DefaultSqlExpressionRenderer):
Expand Down
2 changes: 1 addition & 1 deletion metricflow/sql/render/databricks.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from typing import Collection

from dbt_semantic_interfaces.enum_extension import assert_values_exhausted
from dbt_semantic_interfaces.type_enums.date_part import DatePart
from typing_extensions import override

from metricflow.errors.errors import UnsupportedEngineFeatureError
Expand All @@ -13,7 +14,6 @@
)
from metricflow.sql.render.sql_plan_renderer import DefaultSqlQueryPlanRenderer
from metricflow.sql.sql_exprs import SqlPercentileExpression, SqlPercentileFunctionType
from metricflow.time.date_part import DatePart


class DatabricksSqlExpressionRenderer(DefaultSqlExpressionRenderer):
Expand Down
2 changes: 1 addition & 1 deletion metricflow/sql/render/expr_renderer.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from typing import Collection, List

import jinja2
from dbt_semantic_interfaces.type_enums.date_part import DatePart
from dbt_semantic_interfaces.type_enums.time_granularity import TimeGranularity
from typing_extensions import override

Expand Down Expand Up @@ -37,7 +38,6 @@
SqlWindowFunctionExpression,
)
from metricflow.sql.sql_plan import SqlSelectColumn
from metricflow.time.date_part import DatePart

logger = logging.getLogger(__name__)

Expand Down
2 changes: 1 addition & 1 deletion metricflow/sql/render/redshift.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from typing import Collection

from dbt_semantic_interfaces.enum_extension import assert_values_exhausted
from dbt_semantic_interfaces.type_enums.date_part import DatePart
from typing_extensions import override

from metricflow.errors.errors import UnsupportedEngineFeatureError
Expand All @@ -19,7 +20,6 @@
SqlPercentileExpression,
SqlPercentileFunctionType,
)
from metricflow.time.date_part import DatePart


class RedshiftSqlExpressionRenderer(DefaultSqlExpressionRenderer):
Expand Down
2 changes: 1 addition & 1 deletion metricflow/sql/render/snowflake.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from typing import Collection

from dbt_semantic_interfaces.enum_extension import assert_values_exhausted
from dbt_semantic_interfaces.type_enums.date_part import DatePart
from typing_extensions import override

from metricflow.errors.errors import UnsupportedEngineFeatureError
Expand All @@ -14,7 +15,6 @@
from metricflow.sql.render.sql_plan_renderer import DefaultSqlQueryPlanRenderer
from metricflow.sql.sql_bind_parameters import SqlBindParameters
from metricflow.sql.sql_exprs import SqlGenerateUuidExpression, SqlPercentileExpression, SqlPercentileFunctionType
from metricflow.time.date_part import DatePart


class SnowflakeSqlExpressionRenderer(DefaultSqlExpressionRenderer):
Expand Down
2 changes: 1 addition & 1 deletion metricflow/sql/sql_exprs.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from dbt_semantic_interfaces.enum_extension import assert_values_exhausted
from dbt_semantic_interfaces.protocols.measure import MeasureAggregationParameters
from dbt_semantic_interfaces.type_enums.aggregation_type import AggregationType
from dbt_semantic_interfaces.type_enums.date_part import DatePart
from dbt_semantic_interfaces.type_enums.time_granularity import TimeGranularity

from metricflow.dag.id_generation import (
Expand All @@ -35,7 +36,6 @@
)
from metricflow.dag.mf_dag import DagNode, DisplayedProperty, NodeId
from metricflow.sql.sql_bind_parameters import SqlBindParameters
from metricflow.time.date_part import DatePart
from metricflow.visitor import Visitable, VisitorOutputT


Expand Down
Loading

0 comments on commit 8d9c031

Please sign in to comment.