Skip to content

Commit

Permalink
[Backport 1.6.latest] Support null coalescing properties for metric n…
Browse files Browse the repository at this point in the history
…odes (#8700) (#8773)

* Support null coalescing properties for metric nodes (#8700)

* 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.

* Regenerate v10 schema to include null coalescing options
  • Loading branch information
QMalcolm authored Oct 5, 2023
1 parent 6946a20 commit 0a78a96
Show file tree
Hide file tree
Showing 8 changed files with 51 additions and 185 deletions.
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 @@ -1342,6 +1342,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 @@ -597,6 +597,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
215 changes: 31 additions & 184 deletions schemas/dbt/manifest/v10.json
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@
"generated_at": {
"type": "string",
"format": "date-time",
"default": "2023-10-04T12:51:08.278576Z"
"default": "2023-10-05T00:33:14.410024Z"
},
"invocation_id": {
"oneOf": [
Expand All @@ -243,7 +243,7 @@
"type": "null"
}
],
"default": "91c3fe8c-af16-45af-addf-bad2baaac57b"
"default": "603e2fae-9c7d-4d17-8530-7d28c9875263"
},
"env": {
"type": "object",
Expand Down Expand Up @@ -474,7 +474,7 @@
},
"created_at": {
"type": "number",
"default": 1696423868.282719
"default": 1696465994.411958
},
"config_call_dict": {
"type": "object",
Expand Down Expand Up @@ -1187,7 +1187,7 @@
},
"created_at": {
"type": "number",
"default": 1696423868.286342
"default": 1696465994.413604
},
"config_call_dict": {
"type": "object",
Expand Down Expand Up @@ -1575,7 +1575,7 @@
},
"created_at": {
"type": "number",
"default": 1696423868.2879858
"default": 1696465994.414359
},
"config_call_dict": {
"type": "object",
Expand Down Expand Up @@ -1851,7 +1851,7 @@
},
"created_at": {
"type": "number",
"default": 1696423868.2906518
"default": 1696465994.4150689
},
"config_call_dict": {
"type": "object",
Expand Down Expand Up @@ -2273,7 +2273,7 @@
},
"created_at": {
"type": "number",
"default": 1696423868.293976
"default": 1696465994.416128
},
"config_call_dict": {
"type": "object",
Expand Down Expand Up @@ -2539,7 +2539,7 @@
},
"created_at": {
"type": "number",
"default": 1696423868.29565
"default": 1696465994.41679
},
"config_call_dict": {
"type": "object",
Expand Down Expand Up @@ -2797,7 +2797,7 @@
},
"created_at": {
"type": "number",
"default": 1696423868.2974122
"default": 1696465994.4175282
},
"config_call_dict": {
"type": "object",
Expand Down Expand Up @@ -3092,7 +3092,7 @@
},
"created_at": {
"type": "number",
"default": 1696423868.3007638
"default": 1696465994.418854
},
"config_call_dict": {
"type": "object",
Expand Down Expand Up @@ -3599,7 +3599,7 @@
},
"created_at": {
"type": "number",
"default": 1696423868.3035781
"default": 1696465994.420199
},
"config_call_dict": {
"type": "object",
Expand Down Expand Up @@ -4020,7 +4020,7 @@
},
"created_at": {
"type": "number",
"default": 1696423868.3070972
"default": 1696465994.421661
}
},
"additionalProperties": false,
Expand Down Expand Up @@ -4120,138 +4120,6 @@
"additionalProperties": false,
"description": "FreshnessThreshold(warn_after: Union[dbt.contracts.graph.unparsed.Time, NoneType] = <factory>, error_after: Union[dbt.contracts.graph.unparsed.Time, NoneType] = <factory>, filter: Union[str, NoneType] = None)"
},
"FreshnessMetadata": {
"type": "object",
"required": [],
"properties": {
"dbt_schema_version": {
"type": "string",
"default": "https://schemas.getdbt.com/dbt/sources/v3.json"
},
"dbt_version": {
"type": "string",
"default": "1.6.5"
},
"generated_at": {
"type": "string",
"format": "date-time",
"default": "2023-10-04T12:51:08.273991Z"
},
"invocation_id": {
"oneOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": "91c3fe8c-af16-45af-addf-bad2baaac57b"
},
"env": {
"type": "object",
"additionalProperties": {
"type": "string"
},
"default": {}
}
},
"additionalProperties": false,
"description": "FreshnessMetadata(dbt_schema_version: str = <factory>, dbt_version: str = '1.6.5', generated_at: datetime.datetime = <factory>, invocation_id: Union[str, NoneType] = <factory>, env: Dict[str, str] = <factory>)"
},
"SourceFreshnessRuntimeError": {
"type": "object",
"required": [
"unique_id",
"status"
],
"properties": {
"unique_id": {
"type": "string"
},
"error": {
"oneOf": [
{
"type": "string"
},
{
"type": "integer"
},
{
"type": "null"
}
]
},
"status": {
"type": "string",
"enum": [
"runtime error"
]
}
},
"additionalProperties": false,
"description": "SourceFreshnessRuntimeError(unique_id: str, error: Union[str, int, NoneType], status: dbt.contracts.results.FreshnessErrorEnum)"
},
"SourceFreshnessOutput": {
"type": "object",
"required": [
"unique_id",
"max_loaded_at",
"snapshotted_at",
"max_loaded_at_time_ago_in_s",
"status",
"criteria",
"adapter_response",
"timing",
"thread_id",
"execution_time"
],
"properties": {
"unique_id": {
"type": "string"
},
"max_loaded_at": {
"type": "string",
"format": "date-time"
},
"snapshotted_at": {
"type": "string",
"format": "date-time"
},
"max_loaded_at_time_ago_in_s": {
"type": "number"
},
"status": {
"type": "string",
"enum": [
"pass",
"warn",
"error",
"runtime error"
]
},
"criteria": {
"$ref": "#/definitions/FreshnessThreshold"
},
"adapter_response": {
"type": "object"
},
"timing": {
"type": "array",
"items": {
"$ref": "#/definitions/TimingInfo"
}
},
"thread_id": {
"type": "string"
},
"execution_time": {
"type": "number"
}
},
"additionalProperties": false,
"description": "SourceFreshnessOutput(unique_id: str, max_loaded_at: datetime.datetime, snapshotted_at: datetime.datetime, max_loaded_at_time_ago_in_s: float, status: dbt.contracts.results.FreshnessStatus, criteria: dbt.contracts.graph.unparsed.FreshnessThreshold, adapter_response: Dict[str, Any], timing: List[dbt.contracts.results.TimingInfo], thread_id: str, execution_time: float)"
},
"Time": {
"type": "object",
"required": [],
Expand Down Expand Up @@ -4285,41 +4153,6 @@
"additionalProperties": false,
"description": "Time(count: Union[int, NoneType] = None, period: Union[dbt.contracts.graph.unparsed.TimePeriod, NoneType] = None)"
},
"TimingInfo": {
"type": "object",
"required": [
"name"
],
"properties": {
"name": {
"type": "string"
},
"started_at": {
"oneOf": [
{
"type": "string",
"format": "date-time"
},
{
"type": "null"
}
]
},
"completed_at": {
"oneOf": [
{
"type": "string",
"format": "date-time"
},
{
"type": "null"
}
]
}
},
"additionalProperties": false,
"description": "TimingInfo(name: str, started_at: Union[datetime.datetime, NoneType] = None, completed_at: Union[datetime.datetime, NoneType] = None)"
},
"ExternalTable": {
"type": "object",
"required": [],
Expand Down Expand Up @@ -4499,7 +4332,7 @@
},
"created_at": {
"type": "number",
"default": 1696423868.3079429
"default": 1696465994.421958
},
"supported_languages": {
"oneOf": [
Expand Down Expand Up @@ -4739,7 +4572,7 @@
},
"created_at": {
"type": "number",
"default": 1696423868.309657
"default": 1696465994.422623
}
},
"additionalProperties": false,
Expand Down Expand Up @@ -4924,7 +4757,7 @@
},
"created_at": {
"type": "number",
"default": 1696423868.3126311
"default": 1696465994.4238322
},
"group": {
"oneOf": [
Expand Down Expand Up @@ -5063,10 +4896,24 @@
"type": "null"
}
]
},
"join_to_timespine": {
"type": "boolean",
"default": false
},
"fill_nulls_with": {
"oneOf": [
{
"type": "integer"
},
{
"type": "null"
}
]
}
},
"additionalProperties": false,
"description": "MetricInputMeasure(name: str, filter: Union[dbt.contracts.graph.nodes.WhereFilter, NoneType] = None, alias: Union[str, NoneType] = None)"
"description": "MetricInputMeasure(name: str, filter: Union[dbt.contracts.graph.nodes.WhereFilter, NoneType] = None, alias: Union[str, NoneType] = None, join_to_timespine: bool = False, fill_nulls_with: Union[int, NoneType] = None)"
},
"WhereFilter": {
"type": "object",
Expand Down Expand Up @@ -5413,7 +5260,7 @@
},
"created_at": {
"type": "number",
"default": 1696423868.316482
"default": 1696465994.425479
},
"config": {
"$ref": "#/definitions/SemanticModelConfig",
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
Loading

0 comments on commit 0a78a96

Please sign in to comment.