diff --git a/.changes/unreleased/Features-20231024-162842.yaml b/.changes/unreleased/Features-20231024-162842.yaml new file mode 100644 index 00000000..d567e0e3 --- /dev/null +++ b/.changes/unreleased/Features-20231024-162842.yaml @@ -0,0 +1,6 @@ +kind: Features +body: Add exports configuration to YAML spec. +time: 2023-10-24T16:28:42.013032-07:00 +custom: + Author: courtneyholcomb + Issue: "189" diff --git a/dbt_semantic_interfaces/implementations/export.py b/dbt_semantic_interfaces/implementations/export.py new file mode 100644 index 00000000..d3626ef9 --- /dev/null +++ b/dbt_semantic_interfaces/implementations/export.py @@ -0,0 +1,29 @@ +from __future__ import annotations + +from typing import Optional + +from typing_extensions import override + +from dbt_semantic_interfaces.implementations.base import HashableBaseModel +from dbt_semantic_interfaces.protocols import ProtocolHint +from dbt_semantic_interfaces.protocols.export import Export, ExportConfig +from dbt_semantic_interfaces.type_enums.export_destination_type import ExportDestinationType + + +class PydanticExport(HashableBaseModel, ProtocolHint[Export]): + """Pydantic implementation of Export.""" + + @override + def _implements_protocol(self) -> Export: + return self + + name: str + config: PydanticExportConfig + + +class PydanticExportConfig(HashableBaseModel, ProtocolHint[ExportConfig]): + """Pydantic implementation of ExportConfig.""" + + export_as: ExportDestinationType + schema: Optional[str] = None + alias: Optional[str] = None diff --git a/dbt_semantic_interfaces/implementations/saved_query.py b/dbt_semantic_interfaces/implementations/saved_query.py index 53de5038..1258b1be 100644 --- a/dbt_semantic_interfaces/implementations/saved_query.py +++ b/dbt_semantic_interfaces/implementations/saved_query.py @@ -12,6 +12,7 @@ PydanticWhereFilterIntersection, ) from dbt_semantic_interfaces.implementations.metadata import PydanticMetadata +from dbt_semantic_interfaces.implementations.export import PydanticExport from dbt_semantic_interfaces.protocols import ProtocolHint from dbt_semantic_interfaces.protocols.saved_query import SavedQuery @@ -31,3 +32,4 @@ def _implements_protocol(self) -> SavedQuery: description: Optional[str] = None metadata: Optional[PydanticMetadata] = None label: Optional[str] = None + exports: Optional[List[PydanticExport]] = None diff --git a/dbt_semantic_interfaces/protocols/export.py b/dbt_semantic_interfaces/protocols/export.py new file mode 100644 index 00000000..4bf163a9 --- /dev/null +++ b/dbt_semantic_interfaces/protocols/export.py @@ -0,0 +1,40 @@ +from __future__ import annotations +from typing import Protocol, Optional +from abc import abstractmethod +from dbt_semantic_interfaces.type_enums.export_destination_type import ExportDestinationType + + +class Export(Protocol): + """Configuration for writing query results to a table.""" + + @property + @abstractmethod + def name(self) -> str: # noqa: D + pass + + @property + @abstractmethod + def config(self) -> ExportConfig: # noqa: D + pass + + +class ExportConfig(Protocol): + """Nested configuration attributes for exports.""" + + @property + @abstractmethod + def export_as(self) -> ExportDestinationType: + """Type of destination to write export to.""" + pass + + @property + @abstractmethod + def schema(self) -> Optional[str]: + """Schema to write export to. Defaults to deployment schema.""" + pass + + @property + @abstractmethod + def alias(self) -> Optional[str]: + """Name for table/filte export is written to. Defaults to export name.""" + pass diff --git a/dbt_semantic_interfaces/protocols/saved_query.py b/dbt_semantic_interfaces/protocols/saved_query.py index 3bd739d9..916bcf01 100644 --- a/dbt_semantic_interfaces/protocols/saved_query.py +++ b/dbt_semantic_interfaces/protocols/saved_query.py @@ -1,7 +1,8 @@ from abc import abstractmethod -from typing import Optional, Protocol, Sequence +from typing import Optional, Protocol, Sequence, List from dbt_semantic_interfaces.protocols.metadata import Metadata +from dbt_semantic_interfaces.protocols.export import Export from dbt_semantic_interfaces.protocols.where_filter import WhereFilterIntersection @@ -44,3 +45,9 @@ def where(self) -> Optional[WhereFilterIntersection]: def label(self) -> Optional[str]: """Returns a string representing a human readable label for the saved query.""" pass + + @property + @abstractmethod + def exports(self) -> Optional[List[Export]]: + """Exports that can run using this saved query.""" + pass diff --git a/dbt_semantic_interfaces/type_enums/export_destination_type.py b/dbt_semantic_interfaces/type_enums/export_destination_type.py new file mode 100644 index 00000000..2db47b7f --- /dev/null +++ b/dbt_semantic_interfaces/type_enums/export_destination_type.py @@ -0,0 +1,8 @@ +from dbt_semantic_interfaces.enum_extension import ExtendedEnum + + +class ExportDestinationType(ExtendedEnum): + """Types of destinations that exports can be written to.""" + + TABLE = "table" + VIEW = "view"