Skip to content

Commit

Permalink
Support null coalescing properties for metric nodes (#8700)
Browse files Browse the repository at this point in the history
* Include 'join_to_timespine` and `fill_nulls_with` in metric fixture

* Support `join_to_timespine` and `fill_nulls_with` properties on measure inputs to metrics

* Assert new `fill_nulls_with` and `join_to_timespine` properties don't break associated DSI protocol

* Add doc for metric null coalescing improvements

* Fix unit test for unparsed metric objects

The `assert_symmetric` function asserts that dictionaries are mostly
equivalent. I say mostly equivalent because it drops keys that are
`None`. The issue is that that `join_to_timespine` gets defaulted
to `False`, so we have to specify it in the `get_ok_dict` so that
they match.
  • Loading branch information
QMalcolm committed Oct 6, 2023
1 parent 7ab6e2b commit 519a3fd
Show file tree
Hide file tree
Showing 7 changed files with 20 additions and 1 deletion.
6 changes: 6 additions & 0 deletions .changes/unreleased/Features-20230922-150754.yaml
Original file line number Diff line number Diff line change
@@ -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"
2 changes: 2 additions & 0 deletions core/dbt/contracts/graph/nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 2 additions & 0 deletions core/dbt/contracts/graph/unparsed.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions core/dbt/parser/schema_yaml_readers.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
2 changes: 2 additions & 0 deletions tests/functional/metrics/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
1 change: 1 addition & 0 deletions tests/unit/test_contracts_graph_unparsed.py
Original file line number Diff line number Diff line change
Expand Up @@ -858,6 +858,7 @@ def get_ok_dict(self):
"measure": {
"name": "customers",
"filter": "is_new = true",
"join_to_timespine": False,
},
},
"config": {},
Expand Down
6 changes: 5 additions & 1 deletion tests/unit/test_semantic_layer_nodes_satisfy_protocols.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
)


Expand Down

0 comments on commit 519a3fd

Please sign in to comment.