diff --git a/.changes/unreleased/Features-20230922-150754.yaml b/.changes/unreleased/Features-20230922-150754.yaml new file mode 100644 index 00000000000..6492c3d934a --- /dev/null +++ b/.changes/unreleased/Features-20230922-150754.yaml @@ -0,0 +1,6 @@ +kind: Features +body: Support `fill_nulls_with` and `join_to_timespine` for metric nodes +time: 2023-09-22T15:07:54.981752-07:00 +custom: + Author: QMalcolm + Issue: "8593" diff --git a/core/dbt/contracts/graph/nodes.py b/core/dbt/contracts/graph/nodes.py index 02e2c4c9dca..3aad00901eb 100644 --- a/core/dbt/contracts/graph/nodes.py +++ b/core/dbt/contracts/graph/nodes.py @@ -1411,6 +1411,8 @@ class MetricInputMeasure(dbtClassMixin): name: str filter: Optional[WhereFilter] = None alias: Optional[str] = None + join_to_timespine: bool = False + fill_nulls_with: Optional[int] = None def measure_reference(self) -> MeasureReference: return MeasureReference(element_name=self.name) diff --git a/core/dbt/contracts/graph/unparsed.py b/core/dbt/contracts/graph/unparsed.py index 887359329d7..d06b13faa03 100644 --- a/core/dbt/contracts/graph/unparsed.py +++ b/core/dbt/contracts/graph/unparsed.py @@ -584,6 +584,8 @@ class UnparsedMetricInputMeasure(dbtClassMixin): name: str filter: Optional[str] = None alias: Optional[str] = None + join_to_timespine: bool = False + fill_nulls_with: Optional[int] = None @dataclass diff --git a/core/dbt/parser/schema_yaml_readers.py b/core/dbt/parser/schema_yaml_readers.py index 45f3cfe115b..dddad84c6db 100644 --- a/core/dbt/parser/schema_yaml_readers.py +++ b/core/dbt/parser/schema_yaml_readers.py @@ -178,6 +178,8 @@ def _get_input_measure( name=unparsed_input_measure.name, filter=filter, alias=unparsed_input_measure.alias, + join_to_timespine=unparsed_input_measure.join_to_timespine, + fill_nulls_with=unparsed_input_measure.fill_nulls_with, ) def _get_optional_input_measure( diff --git a/tests/functional/metrics/fixtures.py b/tests/functional/metrics/fixtures.py index 65d61ad74ad..89eeb930043 100644 --- a/tests/functional/metrics/fixtures.py +++ b/tests/functional/metrics/fixtures.py @@ -116,6 +116,8 @@ measure: name: years_tenure filter: "{{ Dimension('id__loves_dbt') }} is true" + join_to_timespine: true + fill_nulls_with: 0 - name: collective_window label: "Collective window" diff --git a/tests/unit/test_contracts_graph_unparsed.py b/tests/unit/test_contracts_graph_unparsed.py index 7f29937a007..fbf23a082c7 100644 --- a/tests/unit/test_contracts_graph_unparsed.py +++ b/tests/unit/test_contracts_graph_unparsed.py @@ -858,6 +858,7 @@ def get_ok_dict(self): "measure": { "name": "customers", "filter": "is_new = true", + "join_to_timespine": False, }, }, "config": {}, diff --git a/tests/unit/test_semantic_layer_nodes_satisfy_protocols.py b/tests/unit/test_semantic_layer_nodes_satisfy_protocols.py index 7325a41da19..85d24797ef1 100644 --- a/tests/unit/test_semantic_layer_nodes_satisfy_protocols.py +++ b/tests/unit/test_semantic_layer_nodes_satisfy_protocols.py @@ -216,7 +216,11 @@ def simple_metric_input_measure() -> MetricInputMeasure: @pytest.fixture(scope="session") def complex_metric_input_measure(where_filter) -> MetricInputMeasure: return MetricInputMeasure( - name="test_complex_metric_input_measure", filter=where_filter, alias="complex_alias" + name="test_complex_metric_input_measure", + filter=where_filter, + alias="complex_alias", + join_to_timespine=True, + fill_nulls_with=0, )