diff --git a/.changes/unreleased/Under the Hood-20230921-161752.yaml b/.changes/unreleased/Under the Hood-20230921-161752.yaml new file mode 100644 index 00000000..6f8b8495 --- /dev/null +++ b/.changes/unreleased/Under the Hood-20230921-161752.yaml @@ -0,0 +1,6 @@ +kind: Under the Hood +body: Support for descending & date_part in the query interface +time: 2023-09-21T16:17:52.090209-05:00 +custom: + Author: DevonFulcher + Issue: None diff --git a/dbt_semantic_interfaces/errors.py b/dbt_semantic_interfaces/errors.py index 322e60ab..5cc9e631 100644 --- a/dbt_semantic_interfaces/errors.py +++ b/dbt_semantic_interfaces/errors.py @@ -22,3 +22,10 @@ class ModelTransformError(Exception): """Exception to represent errors related to model transformations.""" pass + + +class InvalidQuerySyntax(Exception): + """Raised when query syntax is invalid.""" + + def __init__(self, msg: str) -> None: # noqa: D + super().__init__(msg) diff --git a/dbt_semantic_interfaces/parsing/where_filter/where_filter_dimension.py b/dbt_semantic_interfaces/parsing/where_filter/where_filter_dimension.py index 4a873cca..fbd884d4 100644 --- a/dbt_semantic_interfaces/parsing/where_filter/where_filter_dimension.py +++ b/dbt_semantic_interfaces/parsing/where_filter/where_filter_dimension.py @@ -4,6 +4,7 @@ from typing_extensions import override +from dbt_semantic_interfaces.errors import InvalidQuerySyntax from dbt_semantic_interfaces.protocols.protocol_hint import ProtocolHint from dbt_semantic_interfaces.protocols.query_interface import ( QueryInterfaceDimension, @@ -32,6 +33,14 @@ def grain(self, time_granularity: str) -> QueryInterfaceDimension: self.time_granularity_name = time_granularity 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 and filter spec") + + def date_part(self, _date_part: str) -> QueryInterfaceDimension: + """Date part to extract from the dimension.""" + raise InvalidQuerySyntax("date_part isn't currently supported in the where parameter and filter spec") + class WhereFilterDimensionFactory(ProtocolHint[QueryInterfaceDimensionFactory]): """Creates a WhereFilterDimension. diff --git a/dbt_semantic_interfaces/parsing/where_filter/where_filter_time_dimension.py b/dbt_semantic_interfaces/parsing/where_filter/where_filter_time_dimension.py index 3da96607..7ba7dc36 100644 --- a/dbt_semantic_interfaces/parsing/where_filter/where_filter_time_dimension.py +++ b/dbt_semantic_interfaces/parsing/where_filter/where_filter_time_dimension.py @@ -1,10 +1,11 @@ from __future__ import annotations -from typing import List, Sequence +from typing import List, Optional, Sequence from typing_extensions import override from dbt_semantic_interfaces.call_parameter_sets import TimeDimensionCallParameterSet +from dbt_semantic_interfaces.errors import InvalidQuerySyntax from dbt_semantic_interfaces.parsing.where_filter.parameter_set_factory import ( ParameterSetFactory, ) @@ -38,9 +39,18 @@ def __init__(self) -> None: # noqa self.time_dimension_call_parameter_sets: List[TimeDimensionCallParameterSet] = [] def create( - self, time_dimension_name: str, time_granularity_name: str, entity_path: Sequence[str] = () + self, + time_dimension_name: str, + time_granularity_name: str, + descending: Optional[bool] = None, + date_part_name: Optional[str] = None, + entity_path: Sequence[str] = (), ) -> TimeDimensionStub: """Gets called by Jinja when rendering {{ TimeDimension(...) }}.""" + if descending is not None: + raise InvalidQuerySyntax("descending is invalid in the where parameter and filter spec") + if date_part_name is not None: + raise InvalidQuerySyntax("date_part isn't currently supported in the where parameter and filter spec") self.time_dimension_call_parameter_sets.append( ParameterSetFactory.create_time_dimension(time_dimension_name, time_granularity_name, entity_path) ) diff --git a/dbt_semantic_interfaces/protocols/query_interface.py b/dbt_semantic_interfaces/protocols/query_interface.py index 8cc6db4a..32ea87d7 100644 --- a/dbt_semantic_interfaces/protocols/query_interface.py +++ b/dbt_semantic_interfaces/protocols/query_interface.py @@ -1,7 +1,16 @@ from __future__ import annotations from abc import abstractmethod -from typing import Protocol, Sequence +from typing import Optional, Protocol, Sequence + + +class QueryInterfaceMetric(Protocol): + """Represents the interface for Metric in the query interface.""" + + @abstractmethod + def descending(self, _is_descending: bool) -> QueryInterfaceMetric: + """Set the sort order for order-by.""" + pass class QueryInterfaceDimension(Protocol): @@ -12,6 +21,16 @@ def grain(self, _grain: str) -> QueryInterfaceDimension: """The time granularity.""" pass + @abstractmethod + def descending(self, _is_descending: bool) -> QueryInterfaceDimension: + """Set the sort order for order-by.""" + pass + + @abstractmethod + def date_part(self, _date_part: str) -> QueryInterfaceDimension: + """Date part to extract from the dimension.""" + pass + class QueryInterfaceDimensionFactory(Protocol): """Creates a Dimension for the query interface. @@ -42,6 +61,8 @@ def create( self, time_dimension_name: str, time_granularity_name: str, + descending: Optional[bool] = None, + date_part_name: Optional[str] = None, entity_path: Sequence[str] = (), ) -> QueryInterfaceTimeDimension: """Create a TimeDimension."""