From e3ff212bf57b24249e63ca8e6c1a575435c65a2f Mon Sep 17 00:00:00 2001 From: Quigley Malcolm Date: Fri, 30 Jun 2023 13:41:54 -0700 Subject: [PATCH 01/17] Add metrics from metric type params to a metric's depends_on --- core/dbt/parser/manifest.py | 1 + 1 file changed, 1 insertion(+) diff --git a/core/dbt/parser/manifest.py b/core/dbt/parser/manifest.py index 1765cfb1698..032b502a654 100644 --- a/core/dbt/parser/manifest.py +++ b/core/dbt/parser/manifest.py @@ -1495,6 +1495,7 @@ def _process_metric_node( manifest=manifest, current_project=current_project, metric=target_metric ) metric.type_params.input_measures.extend(target_metric.type_params.input_measures) + metric.depends_on.add_node(target_metric.unique_id) else: assert_values_exhausted(metric.type) From 38127380e89e6a249f86edcbb078deabe1d72f70 Mon Sep 17 00:00:00 2001 From: Quigley Malcolm Date: Fri, 30 Jun 2023 17:40:53 -0700 Subject: [PATCH 02/17] Add Lookup utility for finding `SemanticModel`s by measure names --- core/dbt/contracts/graph/manifest.py | 75 ++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/core/dbt/contracts/graph/manifest.py b/core/dbt/contracts/graph/manifest.py index b278970c154..20d2dc5f394 100644 --- a/core/dbt/contracts/graph/manifest.py +++ b/core/dbt/contracts/graph/manifest.py @@ -1,9 +1,11 @@ import enum +from collections import defaultdict from dataclasses import dataclass, field from itertools import chain, islice from mashumaro.mixins.msgpack import DataClassMessagePackMixin from multiprocessing.synchronize import Lock from typing import ( + DefaultDict, Dict, List, Optional, @@ -297,6 +299,49 @@ def perform_lookup(self, unique_id: UniqueID, manifest: "Manifest") -> Metric: return manifest.metrics[unique_id] +class SemanticModelByMeasureLookup(dbtClassMixin): + """Lookup utility for finding SemanticModel by measure + + This is possible because measure names are supposed to be unique across + the semantic models in a manifest. + """ + + def __init__(self, manifest: "Manifest"): + self.storage: DefaultDict[str, Dict[PackageName, UniqueID]] = defaultdict(dict) + self.populate(manifest) + + def get_unique_id(self, search_name: str, package: Optional[PackageName]): + return find_unique_id_for_package(self.storage, search_name, package) + + def find( + self, search_name: str, package: Optional[PackageName], manifest: "Manifest" + ) -> Optional[SemanticModel]: + """Tries to find a SemanticModel based on a measure name""" + unique_id = self.get_unique_id(search_name, package) + if unique_id is not None: + return self.perform_lookup(unique_id, manifest) + return None + + def add(self, semantic_model: SemanticModel): + """Sets all measures for a SemanticModel as paths to the SemanticModel's `unique_id`""" + for measure in semantic_model.measures: + self.storage[measure.name][semantic_model.package_name] = semantic_model.unique_id + + def populate(self, manifest: "Manifest"): + """Populate storage with all the measure + package paths to the Manifest's SemanticModels""" + for semantic_model in manifest.semantic_models.values(): + self.add(semantic_model=semantic_model) + + def perform_lookup(self, unique_id: UniqueID, manifest: "Manifest") -> SemanticModel: + """Tries to get a SemanticModel from the Manifest""" + semantic_model = manifest.semantic_models.get(unique_id) + if semantic_model is None: + raise dbt.exceptions.DbtInternalError( + f"Semantic model `{unique_id}` found in cache but not found in manifest" + ) + return semantic_model + + # This handles both models/seeds/snapshots and sources/metrics/exposures class DisabledLookup(dbtClassMixin): def __init__(self, manifest: "Manifest"): @@ -710,6 +755,9 @@ class Manifest(MacroMethods, DataClassMessagePackMixin, dbtClassMixin): _metric_lookup: Optional[MetricLookup] = field( default=None, metadata={"serialize": lambda x: None, "deserialize": lambda x: None} ) + _semantic_model_by_measure_lookup: Optional[SemanticModelByMeasureLookup] = field( + default=None, metadata={"serialize": lambda x: None, "deserialize": lambda x: None} + ) _disabled_lookup: Optional[DisabledLookup] = field( default=None, metadata={"serialize": lambda x: None, "deserialize": lambda x: None} ) @@ -960,6 +1008,13 @@ def metric_lookup(self) -> MetricLookup: self._metric_lookup = MetricLookup(self) return self._metric_lookup + @property + def semantic_model_by_measure_lookup(self) -> SemanticModelByMeasureLookup: + """Gets (and creates if necessary) the lookup utility for getting SemanticModels by measures""" + if self._semantic_model_by_measure_lookup is None: + self._semantic_model_by_measure_lookup = SemanticModelByMeasureLookup(self) + return self._semantic_model_by_measure_lookup + def rebuild_ref_lookup(self): self._ref_lookup = RefableLookup(self) @@ -1087,6 +1142,25 @@ def resolve_metric( return Disabled(disabled[0]) return None + def resolve_semantic_model_for_measure( + self, + target_measure_name: str, + current_project: str, + node_package: str, + target_package: Optional[str] = None, + ) -> Optional[SemanticModel]: + """Tries to find the SemanticModel that a measure belongs to""" + candidates = _packages_to_search(current_project, node_package, target_package) + + for pkg in candidates: + semantic_model = self.semantic_model_by_measure_lookup.find( + target_measure_name, pkg, self + ) + if semantic_model is not None: + return semantic_model + + return None + # Called by DocsRuntimeContext.doc def resolve_doc( self, @@ -1328,6 +1402,7 @@ def __reduce_ex__(self, protocol): self._source_lookup, self._ref_lookup, self._metric_lookup, + self._semantic_model_by_measure_lookup, self._disabled_lookup, self._analysis_lookup, ) From 62b7ce4f15f97b3ccce55504b266134e861f77b1 Mon Sep 17 00:00:00 2001 From: Quigley Malcolm Date: Fri, 30 Jun 2023 17:41:53 -0700 Subject: [PATCH 03/17] Add the `SemanticModel` of a `Metric`'s measure property to the `Metric`'s `depends_on` --- core/dbt/parser/manifest.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/core/dbt/parser/manifest.py b/core/dbt/parser/manifest.py index 032b502a654..badc20ce09e 100644 --- a/core/dbt/parser/manifest.py +++ b/core/dbt/parser/manifest.py @@ -1447,7 +1447,7 @@ def _process_metric_node( current_project: str, metric: Metric, ) -> None: - """Sets a metric's input_measures""" + """Sets a metric's `input_measures` and `depends_on` properties""" # This ensures that if this metrics input_measures have already been set # we skip the work. This could happen either due to recursion or if multiple @@ -1461,6 +1461,18 @@ def _process_metric_node( metric.type_params.measure is not None ), f"{metric} should have a measure defined, but it does not." metric.type_params.input_measures.append(metric.type_params.measure) + target_semantic_model = manifest.resolve_semantic_model_for_measure( + target_measure_name=metric.type_params.measure.name, + current_project=current_project, + node_package=metric.package_name, + ) + if target_semantic_model is None: + raise dbt.exceptions.ParsingError( + f"A semantic model having a measure `{metric.type_params.measure.name}` does not exist but was referenced.", + node=metric, + ) + + metric.depends_on.add_node(target_semantic_model.unique_id) elif metric.type is MetricType.DERIVED or metric.type is MetricType.RATIO: input_metrics = metric.input_metrics From 19ba6161ecae6fea9c373398365b87dad5393fa4 Mon Sep 17 00:00:00 2001 From: Quigley Malcolm Date: Mon, 10 Jul 2023 15:25:45 -0700 Subject: [PATCH 04/17] Add `SemanticModelConfig` to `SemanticModel` Some tests were failing due to `Metric`'s referencing `SemanticModels`. Specifically there was a check to see if a referenced node was disabled, and because `SemanticModel`'s didn't have a `config` holding the `enabled` boolean attr, core would blow up. --- core/dbt/contracts/graph/model_config.py | 5 +++++ core/dbt/contracts/graph/nodes.py | 2 ++ 2 files changed, 7 insertions(+) diff --git a/core/dbt/contracts/graph/model_config.py b/core/dbt/contracts/graph/model_config.py index fbcfb6d3c56..62664664ae9 100644 --- a/core/dbt/contracts/graph/model_config.py +++ b/core/dbt/contracts/graph/model_config.py @@ -386,6 +386,11 @@ def replace(self, **kwargs): return self.from_dict(dct) +@dataclass +class SemanticModelConfig(BaseConfig): + enabled: bool = True + + @dataclass class MetricConfig(BaseConfig): enabled: bool = True diff --git a/core/dbt/contracts/graph/nodes.py b/core/dbt/contracts/graph/nodes.py index 3fa2e098f45..4c76b90827e 100644 --- a/core/dbt/contracts/graph/nodes.py +++ b/core/dbt/contracts/graph/nodes.py @@ -65,6 +65,7 @@ ExposureConfig, EmptySnapshotConfig, SnapshotConfig, + SemanticModelConfig, ) @@ -1482,6 +1483,7 @@ class SemanticModel(GraphNode): depends_on: DependsOn = field(default_factory=DependsOn) refs: List[RefArgs] = field(default_factory=list) created_at: float = field(default_factory=lambda: time.time()) + config: SemanticModelConfig = field(default_factory=SemanticModelConfig) @property def entity_references(self) -> List[LinkableElementReference]: From dbe943b2611d98de4282f8412d06f540d6c9ecc1 Mon Sep 17 00:00:00 2001 From: Quigley Malcolm Date: Tue, 11 Jul 2023 12:42:00 -0700 Subject: [PATCH 05/17] Checkpoint on test fixing --- tests/functional/access/test_access.py | 26 +++++++++ .../artifacts/test_previous_version_state.py | 23 ++++++++ tests/functional/exposures/fixtures.py | 24 +++++++++ .../exposures/test_exposure_configs.py | 4 ++ tests/functional/exposures/test_exposures.py | 4 ++ tests/functional/metrics/fixtures.py | 35 +++++++++++- .../functional/metrics/test_metric_configs.py | 6 +++ tests/functional/partial_parsing/fixtures.py | 31 +++++++++++ .../test_pp_disabled_config.py | 54 +++++++++++++++++++ .../partial_parsing/test_pp_metrics.py | 9 +++- .../partial_parsing/test_pp_vars.py | 8 +++ 11 files changed, 221 insertions(+), 3 deletions(-) diff --git a/tests/functional/access/test_access.py b/tests/functional/access/test_access.py index 4e9551d08a3..df7c744284b 100644 --- a/tests/functional/access/test_access.py +++ b/tests/functional/access/test_access.py @@ -124,6 +124,31 @@ select 1 as id, 'Callum' as first_name, 'McCann' as last_name, 'emerald' as favorite_color, true as loves_dbt, 0 as tenure, current_timestamp as created_at """ +people_semantic_model_yml = """ +semantic_models: + - name: semantic_people + model: ref('people') + dimensions: + - name: favorite_color + type: categorical + - name: created_at + type: TIME + type_params: + time_granularity: day + measures: + - name: years_tenure + agg: SUM + expr: tenure + - name: people + agg: count + expr: id + entities: + - name: id + type: primary + defaults: + agg_time_dimension: created_at +""" + people_metric_yml = """ metrics: @@ -278,6 +303,7 @@ def test_access_attribute(self, project): write_file(v5_schema_yml, project.project_root, "models", "schema.yml") rm_file(project.project_root, "models", "simple_exposure.yml") write_file(people_model_sql, "models", "people_model.sql") + write_file(people_semantic_model_yml, "models", "people_semantic_model.yml") write_file(people_metric_yml, "models", "people_metric.yml") # Should succeed manifest = run_dbt(["parse"]) diff --git a/tests/functional/artifacts/test_previous_version_state.py b/tests/functional/artifacts/test_previous_version_state.py index 401ff2b4dc1..8ba2f83efb8 100644 --- a/tests/functional/artifacts/test_previous_version_state.py +++ b/tests/functional/artifacts/test_previous_version_state.py @@ -127,6 +127,29 @@ tests: - not_null +semantic_models: + - name: semantic_people + model: ref('people') + dimensions: + - name: favorite_color + type: categorical + - name: created_at + type: TIME + type_params: + time_granularity: day + measures: + - name: years_tenure + agg: SUM + expr: tenure + - name: people + agg: count + expr: id + entities: + - name: id + type: primary + defaults: + agg_time_dimension: created_at + metrics: - name: my_metric label: Count records diff --git a/tests/functional/exposures/fixtures.py b/tests/functional/exposures/fixtures.py index 8b97c657aff..489daa29b1e 100644 --- a/tests/functional/exposures/fixtures.py +++ b/tests/functional/exposures/fixtures.py @@ -7,6 +7,11 @@ """ +metricflow_time_spine_sql = """ +SELECT to_date('02/20/2023, 'mm/dd/yyyy') as date_day +""" + + source_schema_yml = """version: 2 sources: @@ -15,6 +20,25 @@ - name: test_table """ + +semantic_models_schema_yml = """version: 2 + +semantic_models: + - name: semantic_model + model: ref('model') + measures: + - name: distinct_metrics + agg: count_distinct + expr: id + entities: + - name: model + type: primary + expr: id + defaults: + agg_time_dimension: created_at +""" + + metrics_schema_yml = """version: 2 metrics: diff --git a/tests/functional/exposures/test_exposure_configs.py b/tests/functional/exposures/test_exposure_configs.py index 199a6368a4a..34c5570a84e 100644 --- a/tests/functional/exposures/test_exposure_configs.py +++ b/tests/functional/exposures/test_exposure_configs.py @@ -12,6 +12,8 @@ enabled_yaml_level_exposure_yml, invalid_config_exposure_yml, source_schema_yml, + metricflow_time_spine_sql, + semantic_models_schema_yml, metrics_schema_yml, ) @@ -30,9 +32,11 @@ class TestExposureEnabledConfigProjectLevel(ExposureConfigTests): def models(self): return { "model.sql": models_sql, + "metricflow_time_spine.sql": metricflow_time_spine_sql, "second_model.sql": second_model_sql, "exposure.yml": simple_exposure_yml, "schema.yml": source_schema_yml, + "semantic_models.yml": semantic_models_schema_yml, "metrics.yml": metrics_schema_yml, } diff --git a/tests/functional/exposures/test_exposures.py b/tests/functional/exposures/test_exposures.py index 97849fa0835..1988dd976b3 100644 --- a/tests/functional/exposures/test_exposures.py +++ b/tests/functional/exposures/test_exposures.py @@ -7,6 +7,8 @@ simple_exposure_yml, source_schema_yml, metrics_schema_yml, + semantic_models_schema_yml, + metricflow_time_spine_sql, ) @@ -16,8 +18,10 @@ def models(self): return { "exposure.yml": simple_exposure_yml, "model.sql": models_sql, + "metricflow_time_spine.sql": metricflow_time_spine_sql, "second_model.sql": second_model_sql, "schema.yml": source_schema_yml, + "semantic_models.yml": semantic_models_schema_yml, "metrics.yml": metrics_schema_yml, } diff --git a/tests/functional/metrics/fixtures.py b/tests/functional/metrics/fixtures.py index 9f5b4a37ae5..4647f64e1e3 100644 --- a/tests/functional/metrics/fixtures.py +++ b/tests/functional/metrics/fixtures.py @@ -17,9 +17,36 @@ models_people_sql = """ select 1 as id, 'Drew' as first_name, 'Banin' as last_name, 'yellow' as favorite_color, true as loves_dbt, 5 as tenure, current_timestamp as created_at union all -select 1 as id, 'Jeremy' as first_name, 'Cohen' as last_name, 'indigo' as favorite_color, true as loves_dbt, 4 as tenure, current_timestamp as created_at +select 2 as id, 'Jeremy' as first_name, 'Cohen' as last_name, 'indigo' as favorite_color, true as loves_dbt, 4 as tenure, current_timestamp as created_at union all -select 1 as id, 'Callum' as first_name, 'McCann' as last_name, 'emerald' as favorite_color, true as loves_dbt, 0 as tenure, current_timestamp as created_at +select 3 as id, 'Callum' as first_name, 'McCann' as last_name, 'emerald' as favorite_color, true as loves_dbt, 0 as tenure, current_timestamp as created_at +""" + +semantic_model_people_yml = """ +version: 2 + +semantic_models: + - name: semantic_people + model: ref('people') + dimensions: + - name: favorite_color + type: categorical + - name: created_at + type: TIME + type_params: + time_granularity: day + measures: + - name: years_tenure + agg: SUM + expr: tenure + - name: people + agg: count + expr: id + entities: + - name: id + type: primary + defaults: + agg_time_dimension: created_at """ basic_metrics_yml = """ @@ -63,6 +90,10 @@ expr: "average_tenure + 1" """ +metricflow_time_spine_sql = """ +SELECT to_date('02/20/2023, 'mm/dd/yyyy') as date_day +""" + models_people_metrics_yml = """ version: 2 diff --git a/tests/functional/metrics/test_metric_configs.py b/tests/functional/metrics/test_metric_configs.py index efc3f37b26a..cc6f3fcf760 100644 --- a/tests/functional/metrics/test_metric_configs.py +++ b/tests/functional/metrics/test_metric_configs.py @@ -8,10 +8,12 @@ from tests.functional.metrics.fixtures import ( models_people_sql, models_people_metrics_yml, + metricflow_time_spine_sql, disabled_metric_level_schema_yml, enabled_metric_level_schema_yml, models_people_metrics_sql, invalid_config_metric_yml, + semantic_model_people_yml, ) @@ -29,6 +31,7 @@ class TestMetricEnabledConfigProjectLevel(MetricConfigTests): def models(self): return { "people.sql": models_people_sql, + "semantic_model_people.yml": semantic_model_people_yml, "schema.yml": models_people_metrics_yml, } @@ -69,6 +72,7 @@ class TestConfigYamlMetricLevel(MetricConfigTests): def models(self): return { "people.sql": models_people_sql, + "semantic_model_people.yml": semantic_model_people_yml, "schema.yml": disabled_metric_level_schema_yml, } @@ -85,6 +89,7 @@ class TestMetricConfigsInheritence(MetricConfigTests): def models(self): return { "people.sql": models_people_sql, + "semantic_model_people.yml": semantic_model_people_yml, "schema.yml": enabled_metric_level_schema_yml, } @@ -112,6 +117,7 @@ class TestDisabledMetricRef(MetricConfigTests): def models(self): return { "people.sql": models_people_sql, + "metricflow_time_spine.sql": metricflow_time_spine_sql, "people_metrics.sql": models_people_metrics_sql, "schema.yml": models_people_metrics_yml, } diff --git a/tests/functional/partial_parsing/fixtures.py b/tests/functional/partial_parsing/fixtures.py index 12ec77b178e..e94e1f554eb 100644 --- a/tests/functional/partial_parsing/fixtures.py +++ b/tests/functional/partial_parsing/fixtures.py @@ -397,6 +397,10 @@ """ +metricflow_time_spine_sql = """ +SELECT to_date('02/20/2023, 'mm/dd/yyyy') as date_day +""" + env_var_schema3_yml = """ models: @@ -421,6 +425,33 @@ """ +people_semantic_models_yml = """ +version: 2 + +semantic_models: + - name: semantic_people + model: ref('people') + dimensions: + - name: favorite_color + type: categorical + - name: created_at + type: TIME + type_params: + time_granularity: day + measures: + - name: years_tenure + agg: SUM + expr: tenure + - name: people + agg: count + expr: id + entities: + - name: id + type: primary + defaults: + agg_time_dimension: created_at +""" + env_var_metrics_yml = """ metrics: diff --git a/tests/functional/partial_parsing/test_pp_disabled_config.py b/tests/functional/partial_parsing/test_pp_disabled_config.py index 01df216d758..2501e31d05a 100644 --- a/tests/functional/partial_parsing/test_pp_disabled_config.py +++ b/tests/functional/partial_parsing/test_pp_disabled_config.py @@ -11,6 +11,24 @@ models: - name: model_one +semantic_models: + - name: semantic_people + model: ref('people') + dimensions: + - name: created_at + type: TIME + type_params: + time_granularity: day + measures: + - name: people + agg: count + expr: fun + entities: + - name: fun + type: primary + defaults: + agg_time_dimension: created_at + metrics: - name: number_of_people @@ -39,6 +57,24 @@ models: - name: model_one +semantic_models: + - name: semantic_people + model: ref('people') + dimensions: + - name: created_at + type: TIME + type_params: + time_granularity: day + measures: + - name: people + agg: count + expr: fun + entities: + - name: fun + type: primary + defaults: + agg_time_dimension: created_at + metrics: - name: number_of_people @@ -71,6 +107,24 @@ models: - name: model_one +semantic_models: + - name: semantic_people + model: ref('people') + dimensions: + - name: created_at + type: TIME + type_params: + time_granularity: day + measures: + - name: people + agg: count + expr: fun + entities: + - name: fun + type: primary + defaults: + agg_time_dimension: created_at + metrics: - name: number_of_people diff --git a/tests/functional/partial_parsing/test_pp_metrics.py b/tests/functional/partial_parsing/test_pp_metrics.py index d6e837f7b55..1652d9c02b8 100644 --- a/tests/functional/partial_parsing/test_pp_metrics.py +++ b/tests/functional/partial_parsing/test_pp_metrics.py @@ -3,6 +3,7 @@ from dbt.tests.util import run_dbt, write_file, get_manifest from tests.functional.partial_parsing.fixtures import ( people_sql, + people_semantic_models_yml, people_metrics_yml, people_metrics2_yml, metric_model_a_sql, @@ -26,7 +27,13 @@ def test_metrics(self, project): manifest = get_manifest(project.project_root) assert len(manifest.nodes) == 1 - # Add metrics yaml file + # Add metrics yaml file (and necessary semantic models yaml) + write_file( + people_semantic_models_yml, + project.project_root, + "models", + "people_semantic_models.yml", + ) write_file(people_metrics_yml, project.project_root, "models", "people_metrics.yml") results = run_dbt(["run"]) assert len(results) == 1 diff --git a/tests/functional/partial_parsing/test_pp_vars.py b/tests/functional/partial_parsing/test_pp_vars.py index a73d250eb30..f57fca06b1e 100644 --- a/tests/functional/partial_parsing/test_pp_vars.py +++ b/tests/functional/partial_parsing/test_pp_vars.py @@ -17,8 +17,10 @@ env_var_schema3_yml, env_var_schema_yml, env_var_sources_yml, + metricflow_time_spine_sql, model_color_sql, model_one_sql, + people_semantic_models_yml, people_sql, raw_customers_csv, test_color_sql, @@ -228,6 +230,12 @@ def test_env_vars_models(self, project): # Add a metrics file with env_vars os.environ["ENV_VAR_METRICS"] = "TeStInG" write_file(people_sql, project.project_root, "models", "people.sql") + write_file( + metricflow_time_spine_sql, project.project_root, "models", "metricflow_time_spine.sql" + ) + write_file( + people_semantic_models_yml, project.project_root, "models", "semantic_models.yml" + ) write_file(env_var_metrics_yml, project.project_root, "models", "metrics.yml") results = run_dbt(["run"]) manifest = get_manifest(project.project_root) From 63a7acaa0619641e3ac235b8027e30086fb2e14a Mon Sep 17 00:00:00 2001 From: Quigley Malcolm Date: Tue, 11 Jul 2023 13:05:26 -0700 Subject: [PATCH 06/17] Correct metricflow_time_spine_sql in test fixtures --- tests/functional/exposures/fixtures.py | 2 +- tests/functional/partial_parsing/fixtures.py | 2 +- .../test_pp_disabled_config.py | 23 +++++++++++-------- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/tests/functional/exposures/fixtures.py b/tests/functional/exposures/fixtures.py index 489daa29b1e..cae884b534e 100644 --- a/tests/functional/exposures/fixtures.py +++ b/tests/functional/exposures/fixtures.py @@ -8,7 +8,7 @@ metricflow_time_spine_sql = """ -SELECT to_date('02/20/2023, 'mm/dd/yyyy') as date_day +SELECT to_date('02/20/2023', 'mm/dd/yyyy') as date_day """ diff --git a/tests/functional/partial_parsing/fixtures.py b/tests/functional/partial_parsing/fixtures.py index e94e1f554eb..9da5a6f5025 100644 --- a/tests/functional/partial_parsing/fixtures.py +++ b/tests/functional/partial_parsing/fixtures.py @@ -398,7 +398,7 @@ """ metricflow_time_spine_sql = """ -SELECT to_date('02/20/2023, 'mm/dd/yyyy') as date_day +SELECT to_date('02/20/2023', 'mm/dd/yyyy') as date_day """ env_var_schema3_yml = """ diff --git a/tests/functional/partial_parsing/test_pp_disabled_config.py b/tests/functional/partial_parsing/test_pp_disabled_config.py index 2501e31d05a..03d2e8a728b 100644 --- a/tests/functional/partial_parsing/test_pp_disabled_config.py +++ b/tests/functional/partial_parsing/test_pp_disabled_config.py @@ -5,6 +5,10 @@ select 1 as fun """ +metricflow_time_spine_sql = """ +SELECT to_date('02/20/2023', 'mm/dd/yyyy') as date_day +""" + schema1_yml = """ version: 2 @@ -13,7 +17,7 @@ semantic_models: - name: semantic_people - model: ref('people') + model: ref('model_one') dimensions: - name: created_at type: TIME @@ -59,7 +63,7 @@ semantic_models: - name: semantic_people - model: ref('people') + model: ref('model_one') dimensions: - name: created_at type: TIME @@ -109,7 +113,7 @@ semantic_models: - name: semantic_people - model: ref('people') + model: ref('model_one') dimensions: - name: created_at type: TIME @@ -162,6 +166,7 @@ class TestDisabled: def models(self): return { "model_one.sql": model_one_sql, + "metricflow_time_spine.sql": metricflow_time_spine_sql, "schema.yml": schema1_yml, } @@ -170,10 +175,8 @@ def test_pp_disabled(self, project): expected_metric = "metric.test.number_of_people" run_dbt(["seed"]) - results = run_dbt(["run"]) - assert len(results) == 1 + manifest = run_dbt(["parse"]) - manifest = get_manifest(project.project_root) assert expected_exposure in manifest.exposures assert expected_metric in manifest.metrics assert expected_exposure not in manifest.disabled @@ -182,7 +185,7 @@ def test_pp_disabled(self, project): # Update schema file with disabled metric and exposure write_file(schema2_yml, project.project_root, "models", "schema.yml") results = run_dbt(["--partial-parse", "run"]) - assert len(results) == 1 + assert len(results) == 2 manifest = get_manifest(project.project_root) assert expected_exposure not in manifest.exposures assert expected_metric not in manifest.metrics @@ -192,7 +195,7 @@ def test_pp_disabled(self, project): # Update schema file with enabled metric and exposure write_file(schema1_yml, project.project_root, "models", "schema.yml") results = run_dbt(["--partial-parse", "run"]) - assert len(results) == 1 + assert len(results) == 2 manifest = get_manifest(project.project_root) assert expected_exposure in manifest.exposures assert expected_metric in manifest.metrics @@ -202,7 +205,7 @@ def test_pp_disabled(self, project): # Update schema file - remove exposure, enable metric write_file(schema3_yml, project.project_root, "models", "schema.yml") results = run_dbt(["--partial-parse", "run"]) - assert len(results) == 1 + assert len(results) == 2 manifest = get_manifest(project.project_root) assert expected_exposure not in manifest.exposures assert expected_metric in manifest.metrics @@ -212,7 +215,7 @@ def test_pp_disabled(self, project): # Update schema file - add back exposure, remove metric write_file(schema4_yml, project.project_root, "models", "schema.yml") results = run_dbt(["--partial-parse", "run"]) - assert len(results) == 1 + assert len(results) == 2 manifest = get_manifest(project.project_root) assert expected_exposure not in manifest.exposures assert expected_metric not in manifest.metrics From 7e1cffaaf39fb7330c3d103298feb7c7d2471a58 Mon Sep 17 00:00:00 2001 From: Quigley Malcolm Date: Tue, 11 Jul 2023 13:06:03 -0700 Subject: [PATCH 07/17] Add check for `SemanticModel` nodes in `Linker.link_node` Now that `Metrics` depend on `SemanticModels` and `SemanticModels` have their own dependencies on `Models` they need to be checked for in the `Linker.link_node`. I forget the details but things blow up without it. Basically it adds the SemanticModels to the dependency graph. --- core/dbt/compilation.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/dbt/compilation.py b/core/dbt/compilation.py index 125fe8abf8a..d9a52865460 100644 --- a/core/dbt/compilation.py +++ b/core/dbt/compilation.py @@ -173,6 +173,8 @@ def link_node(self, node: GraphMemberNode, manifest: Manifest): self.dependency(node.unique_id, (manifest.sources[dependency].unique_id)) elif dependency in manifest.metrics: self.dependency(node.unique_id, (manifest.metrics[dependency].unique_id)) + elif dependency in manifest.semantic_models: + self.dependency(node.unique_id, (manifest.semantic_models[dependency].unique_id)) else: raise GraphDependencyNotFoundError(node, dependency) From a0641463d61a65aa9502a91241cd8a81a425c3f3 Mon Sep 17 00:00:00 2001 From: Gerda Shank Date: Tue, 11 Jul 2023 16:21:46 -0400 Subject: [PATCH 08/17] Fix artifacts/test_previous_version_state.py tests --- .../artifacts/test_previous_version_state.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/tests/functional/artifacts/test_previous_version_state.py b/tests/functional/artifacts/test_previous_version_state.py index 8ba2f83efb8..7ed5fb61310 100644 --- a/tests/functional/artifacts/test_previous_version_state.py +++ b/tests/functional/artifacts/test_previous_version_state.py @@ -113,6 +113,10 @@ select 9 as id """ +metricflow_time_spine_sql = """ +SELECT to_date('02/20/2023', 'mm/dd/yyyy') as date_day +""" + # Use old attribute names (v1.0-1.2) to test forward/backward compatibility with the rename in v1.3 models__schema_yml = """ version: 2 @@ -129,7 +133,7 @@ semantic_models: - name: semantic_people - model: ref('people') + model: ref('my_model') dimensions: - name: favorite_color type: categorical @@ -144,6 +148,9 @@ - name: people agg: count expr: id + - name: customers + agg: count + expr: id entities: - name: id type: primary @@ -231,6 +238,7 @@ def models(self): "schema.yml": models__schema_yml, "somedoc.md": docs__somedoc_md, "disabled_model.sql": models__disabled_model_sql, + "metricflow_time_spine.sql": metricflow_time_spine_sql, } @pytest.fixture(scope="class") @@ -273,10 +281,10 @@ def test_project(self, project): # This is mainly used to test changes to the test project in isolation from # the other noise. results = run_dbt(["run"]) - assert len(results) == 1 + assert len(results) == 2 manifest = get_manifest(project.project_root) # model, snapshot, seed, singular test, generic test, analysis - assert len(manifest.nodes) == 7 + assert len(manifest.nodes) == 8 assert len(manifest.sources) == 1 assert len(manifest.exposures) == 1 assert len(manifest.metrics) == 1 @@ -320,7 +328,7 @@ def compare_previous_state( ] if expect_pass: results = run_dbt(cli_args, expect_pass=expect_pass) - assert len(results) == 0 + assert len(results) == 1 else: with pytest.raises(IncompatibleSchemaError): run_dbt(cli_args, expect_pass=expect_pass) From 087b6276677fada7c1c57b92f4eb9febc968ac82 Mon Sep 17 00:00:00 2001 From: Gerda Shank Date: Tue, 11 Jul 2023 16:32:11 -0400 Subject: [PATCH 09/17] fix access/test_access.py tests --- tests/functional/access/test_access.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tests/functional/access/test_access.py b/tests/functional/access/test_access.py index df7c744284b..424616970f7 100644 --- a/tests/functional/access/test_access.py +++ b/tests/functional/access/test_access.py @@ -112,7 +112,7 @@ group: analytics - name: people_model description: "some people" - access: private + access: public group: analytics """ @@ -127,7 +127,7 @@ people_semantic_model_yml = """ semantic_models: - name: semantic_people - model: ref('people') + model: ref('people_model') dimensions: - name: favorite_color type: categorical @@ -228,6 +228,10 @@ group: package """ +metricflow_time_spine_sql = """ +SELECT to_date('02/20/2023', 'mm/dd/yyyy') as date_day +""" + class TestAccess: @pytest.fixture(scope="class") @@ -305,9 +309,10 @@ def test_access_attribute(self, project): write_file(people_model_sql, "models", "people_model.sql") write_file(people_semantic_model_yml, "models", "people_semantic_model.yml") write_file(people_metric_yml, "models", "people_metric.yml") + write_file(metricflow_time_spine_sql, "models", "metricflow_time_spine.sql") # Should succeed manifest = run_dbt(["parse"]) - assert len(manifest.nodes) == 4 + assert len(manifest.nodes) == 5 manifest = get_manifest(project.project_root) metric_id = "metric.test.number_of_people" assert manifest.metrics[metric_id].group == "analytics" From 1ae97630b8c1d2103584362226b37bcab65f4dba Mon Sep 17 00:00:00 2001 From: Quigley Malcolm Date: Tue, 11 Jul 2023 13:34:05 -0700 Subject: [PATCH 10/17] Fix function metric tests --- tests/functional/metrics/test_metric_configs.py | 8 ++++++++ tests/functional/metrics/test_metrics.py | 4 ++++ 2 files changed, 12 insertions(+) diff --git a/tests/functional/metrics/test_metric_configs.py b/tests/functional/metrics/test_metric_configs.py index cc6f3fcf760..03b8fe2275c 100644 --- a/tests/functional/metrics/test_metric_configs.py +++ b/tests/functional/metrics/test_metric_configs.py @@ -31,6 +31,7 @@ class TestMetricEnabledConfigProjectLevel(MetricConfigTests): def models(self): return { "people.sql": models_people_sql, + "metricflow_time_spine.sql": metricflow_time_spine_sql, "semantic_model_people.yml": semantic_model_people_yml, "schema.yml": models_people_metrics_yml, } @@ -72,6 +73,7 @@ class TestConfigYamlMetricLevel(MetricConfigTests): def models(self): return { "people.sql": models_people_sql, + "metricflow_time_spine.sql": metricflow_time_spine_sql, "semantic_model_people.yml": semantic_model_people_yml, "schema.yml": disabled_metric_level_schema_yml, } @@ -89,6 +91,7 @@ class TestMetricConfigsInheritence(MetricConfigTests): def models(self): return { "people.sql": models_people_sql, + "metricflow_time_spine.sql": metricflow_time_spine_sql, "semantic_model_people.yml": semantic_model_people_yml, "schema.yml": enabled_metric_level_schema_yml, } @@ -118,6 +121,7 @@ def models(self): return { "people.sql": models_people_sql, "metricflow_time_spine.sql": metricflow_time_spine_sql, + "semantic_model_people.yml": semantic_model_people_yml, "people_metrics.sql": models_people_metrics_sql, "schema.yml": models_people_metrics_yml, } @@ -158,6 +162,8 @@ class TestInvalidMetric(MetricConfigTests): def models(self): return { "people.sql": models_people_sql, + "metricflow_time_spine.sql": metricflow_time_spine_sql, + "semantic_model_people.yml": semantic_model_people_yml, "schema.yml": invalid_config_metric_yml, } @@ -173,6 +179,8 @@ class TestDisabledMetric(MetricConfigTests): def models(self): return { "people.sql": models_people_sql, + "metricflow_time_spine.sql": metricflow_time_spine_sql, + "semantic_model_people.yml": semantic_model_people_yml, "schema.yml": models_people_metrics_yml, } diff --git a/tests/functional/metrics/test_metrics.py b/tests/functional/metrics/test_metrics.py index 0f1ebe67fdf..82182a94749 100644 --- a/tests/functional/metrics/test_metrics.py +++ b/tests/functional/metrics/test_metrics.py @@ -22,6 +22,8 @@ derived_metric_yml, invalid_metric_without_timestamp_with_time_grains_yml, invalid_metric_without_timestamp_with_window_yml, + metricflow_time_spine_sql, + semantic_model_people_yml, ) @@ -30,6 +32,8 @@ class TestSimpleMetrics: def models(self): return { "people_metrics.yml": models_people_metrics_yml, + "metricflow_time_spine.sql": metricflow_time_spine_sql, + "semantic_model_people.yml": semantic_model_people_yml, "people.sql": models_people_sql, } From 10f1c269c0df2c0b7bd1b1a2de33c9737dac1c34 Mon Sep 17 00:00:00 2001 From: Quigley Malcolm Date: Tue, 11 Jul 2023 13:54:00 -0700 Subject: [PATCH 11/17] Fix functional partial_parsing tests --- tests/functional/partial_parsing/test_pp_metrics.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/functional/partial_parsing/test_pp_metrics.py b/tests/functional/partial_parsing/test_pp_metrics.py index 1652d9c02b8..da994e09808 100644 --- a/tests/functional/partial_parsing/test_pp_metrics.py +++ b/tests/functional/partial_parsing/test_pp_metrics.py @@ -3,6 +3,7 @@ from dbt.tests.util import run_dbt, write_file, get_manifest from tests.functional.partial_parsing.fixtures import ( people_sql, + metricflow_time_spine_sql, people_semantic_models_yml, people_metrics_yml, people_metrics2_yml, @@ -18,14 +19,15 @@ class TestMetrics: def models(self): return { "people.sql": people_sql, + "metricflow_time_spine.sql": metricflow_time_spine_sql, } def test_metrics(self, project): # initial run results = run_dbt(["run"]) - assert len(results) == 1 + assert len(results) == 2 manifest = get_manifest(project.project_root) - assert len(manifest.nodes) == 1 + assert len(manifest.nodes) == 2 # Add metrics yaml file (and necessary semantic models yaml) write_file( @@ -36,7 +38,7 @@ def test_metrics(self, project): ) write_file(people_metrics_yml, project.project_root, "models", "people_metrics.yml") results = run_dbt(["run"]) - assert len(results) == 1 + assert len(results) == 2 manifest = get_manifest(project.project_root) assert len(manifest.metrics) == 2 metric_people_id = "metric.test.number_of_people" @@ -55,7 +57,7 @@ def test_metrics(self, project): # Change metrics yaml files write_file(people_metrics2_yml, project.project_root, "models", "people_metrics.yml") results = run_dbt(["run"]) - assert len(results) == 1 + assert len(results) == 2 manifest = get_manifest(project.project_root) metric_people = manifest.metrics[metric_people_id] expected_meta = {"my_meta": "replaced"} From fb67d0a28a5899fd1c987b5fd512224d11c454a1 Mon Sep 17 00:00:00 2001 From: Quigley Malcolm Date: Wed, 12 Jul 2023 10:07:28 -0700 Subject: [PATCH 12/17] Add time dimension to semantic model in exposures fixture --- tests/functional/exposures/fixtures.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/functional/exposures/fixtures.py b/tests/functional/exposures/fixtures.py index cae884b534e..809df9e901c 100644 --- a/tests/functional/exposures/fixtures.py +++ b/tests/functional/exposures/fixtures.py @@ -26,6 +26,9 @@ semantic_models: - name: semantic_model model: ref('model') + dimensions: + - name: created_at + type: time measures: - name: distinct_metrics agg: count_distinct From ba230f1b60cf4f4f77f70a273f4a1fce5e64839a Mon Sep 17 00:00:00 2001 From: Quigley Malcolm Date: Wed, 12 Jul 2023 10:07:54 -0700 Subject: [PATCH 13/17] Bump DSI version to a minimum of 0.1.0dev10 DSI 0.1.0dev10 fixes an incoherence issue in DSI around `agg_time_dimension` setting. This incoherence was that `measure.agg_time_dimension` was being required, even though it was no longer supposed to be a required attribute (it's specificially typed as optional in the protocol). This was causing a handful of tests to fail because the `semantic_model.defaults.agg_time_dimension` value wasn't being respected. Pulling in the fix from DSI 0.1.0dev10 fixes the issue. Interestingly after bumping the DSI version, the integration tests were still failing. If I ran the tests individually they passed though. To get `make integration` to run properly I ended up having to clear my `.tox` cache, as it seems some outdated state was being persisted. --- core/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/setup.py b/core/setup.py index c56315997be..ea8332a6102 100644 --- a/core/setup.py +++ b/core/setup.py @@ -78,7 +78,7 @@ "minimal-snowplow-tracker~=0.0.2", # DSI is under active development, so we're pinning to specific dev versions for now. # TODO: Before RC/final release, update to use ~= pinning. - "dbt-semantic-interfaces==0.1.0.dev8", + "dbt-semantic-interfaces~=0.1.0.dev10", # ---- # Expect compatibility with all new versions of these packages, so lower bounds only. "packaging>20.9", From d476e5452a6030499cdaf7347385d1038c31b7bf Mon Sep 17 00:00:00 2001 From: Quigley Malcolm Date: Wed, 12 Jul 2023 11:46:35 -0700 Subject: [PATCH 14/17] Add test specifically for checking the `depends_on` of `Metric` nodes --- tests/functional/metrics/test_metrics.py | 27 ++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tests/functional/metrics/test_metrics.py b/tests/functional/metrics/test_metrics.py index 82182a94749..0e1b8744893 100644 --- a/tests/functional/metrics/test_metrics.py +++ b/tests/functional/metrics/test_metrics.py @@ -201,6 +201,33 @@ def test_invalid_derived_metrics(self, project): run_dbt(["run"]) +class TestMetricDependsOn: + @pytest.fixture(scope="class") + def models(self): + return { + "people.sql": models_people_sql, + "metricflow_time_spine.sql": metricflow_time_spine_sql, + "semantic_models.yml": semantic_model_people_yml, + "people_metrics.yml": models_people_metrics_yml, + } + + def test_metric_depends_on(self, project): + manifest = run_dbt(["parse"]) + assert isinstance(manifest, Manifest) + + expected_depends_on_for_number_of_people = ["semantic_model.test.semantic_people"] + expected_depends_on_for_average_tenure = [ + "metric.test.collective_tenure", + "metric.test.number_of_people", + ] + + number_of_people_metric = manifest.metrics["metric.test.number_of_people"] + assert number_of_people_metric.depends_on.nodes == expected_depends_on_for_number_of_people + + average_tenure_metric = manifest.metrics["metric.test.average_tenure"] + assert average_tenure_metric.depends_on.nodes == expected_depends_on_for_average_tenure + + class TestDerivedMetric: @pytest.fixture(scope="class") def models(self): From 2caf63d13f6ac56ec9f814e172d31c2cf8b3e161 Mon Sep 17 00:00:00 2001 From: Quigley Malcolm Date: Wed, 12 Jul 2023 11:47:17 -0700 Subject: [PATCH 15/17] Re-enable test asserting calling metric nodes in models --- tests/functional/metrics/fixtures.py | 32 ++++++++++++++++++++++-- tests/functional/metrics/test_metrics.py | 10 +++++--- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/tests/functional/metrics/fixtures.py b/tests/functional/metrics/fixtures.py index 4647f64e1e3..87fc67c10c6 100644 --- a/tests/functional/metrics/fixtures.py +++ b/tests/functional/metrics/fixtures.py @@ -327,8 +327,7 @@ label: {{ m.label }} type: {{ m.type }} type_params: {{ m.type_params }} - filters {{ m.filter }} - window: {{ m.window }} + filter: {{ m.filter }} {% endfor %} {% endif %} @@ -376,6 +375,35 @@ - payment_type """ +purchasing_model_sql = """ +select purchased_at, payment_type, payment_total from {{ ref('mock_purchase_data') }} +""" + +semantic_model_purchasing_yml = """ +version: 2 + +semantic_models: + - name: semantic_purchasing + model: ref('purchasing') + measures: + - name: num_orders + agg: COUNT + expr: purchased_at + - name: order_revenue + agg: SUM + expr: payment_total + dimensions: + - name: purchased_at + type: TIME + entities: + - name: purchase + type: primary + expr: '1' + defaults: + agg_time_dimension: purchased_at + +""" + derived_metric_yml = """ version: 2 metrics: diff --git a/tests/functional/metrics/test_metrics.py b/tests/functional/metrics/test_metrics.py index 0e1b8744893..3cc0ea412b7 100644 --- a/tests/functional/metrics/test_metrics.py +++ b/tests/functional/metrics/test_metrics.py @@ -24,6 +24,8 @@ invalid_metric_without_timestamp_with_window_yml, metricflow_time_spine_sql, semantic_model_people_yml, + semantic_model_purchasing_yml, + purchasing_model_sql, ) @@ -232,8 +234,11 @@ class TestDerivedMetric: @pytest.fixture(scope="class") def models(self): return { - "derived_metric.yml": derived_metric_yml, "downstream_model.sql": downstream_model_sql, + "purchasing.sql": purchasing_model_sql, + "metricflow_time_spine.sql": metricflow_time_spine_sql, + "semantic_models.yml": semantic_model_purchasing_yml, + "derived_metric.yml": derived_metric_yml, } # not strictly necessary to use "real" mock data for this test @@ -245,7 +250,6 @@ def seeds(self): "mock_purchase_data.csv": mock_purchase_data_csv, } - @pytest.mark.skip("TODO bring back once we start populating metric `depends_on`") def test_derived_metric( self, project, @@ -276,7 +280,6 @@ def test_derived_metric( # make sure the 'expression' metric depends on the two upstream metrics derived_metric = manifest.metrics["metric.test.average_order_value"] - assert sorted(derived_metric.metrics) == [["count_orders"], ["sum_order_revenue"]] assert sorted(derived_metric.depends_on.nodes) == [ "metric.test.count_orders", "metric.test.sum_order_revenue", @@ -295,7 +298,6 @@ def test_derived_metric( "type", "type_params", "filter", - "window", ]: expected_value = getattr(parsed_metric_node, property) assert f"{property}: {expected_value}" in compiled_code From 6a0af562c4a2bac70974b4c73b0814cb2a2d80df Mon Sep 17 00:00:00 2001 From: Quigley Malcolm Date: Wed, 12 Jul 2023 12:17:59 -0700 Subject: [PATCH 16/17] Migrate `checked_agg_time_dimension` to `checked_agg_time_dimension_for_measure` DSI 0.1.0dev10 moved `checked_agg_time_dimension` from the `Measure` protocol to the `SemanticModel` protocol as `checked_agg_time_dimension_for_measure`. This finishes a change where for a given measure either the `Measure.agg_time_dimension` or the measure's parent `SemanticModel.defaults.agg_time_dimension` needs to be set, instead of always require the measure's `Measure.agg_time_dimension`. --- core/dbt/contracts/graph/nodes.py | 24 +++++++++++++++++++++ core/dbt/contracts/graph/semantic_models.py | 7 ------ 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/core/dbt/contracts/graph/nodes.py b/core/dbt/contracts/graph/nodes.py index 4c76b90827e..94710a4cfb7 100644 --- a/core/dbt/contracts/graph/nodes.py +++ b/core/dbt/contracts/graph/nodes.py @@ -52,6 +52,7 @@ MeasureReference, LinkableElementReference, SemanticModelReference, + TimeDimensionReference, ) from dbt_semantic_interfaces.references import MetricReference as DSIMetricReference from dbt_semantic_interfaces.type_enums import MetricType, TimeGranularity @@ -1542,6 +1543,29 @@ def depends_on_nodes(self): def depends_on_macros(self): return self.depends_on.macros + def checked_agg_time_dimension_for_measure( + self, measure_reference: MeasureReference + ) -> TimeDimensionReference: + measure: Optional[Measure] = None + for measure in self.measures: + if measure.reference == measure_reference: + measure = measure + + assert ( + measure is not None + ), f"No measure with name ({measure_reference.element_name}) in semantic_model with name ({self.name})" + + if self.defaults is not None: + default_agg_time_dimesion = self.defaults.agg_time_dimension + + agg_time_dimension_name = measure.agg_time_dimension or default_agg_time_dimesion + assert agg_time_dimension_name is not None, ( + f"Aggregation time dimension for measure {measure.name} is not set! This should either be set directly on " + f"the measure specification in the model, or else defaulted to the primary time dimension in the data " + f"source containing the measure." + ) + return TimeDimensionReference(element_name=agg_time_dimension_name) + # ==================================== # Patches diff --git a/core/dbt/contracts/graph/semantic_models.py b/core/dbt/contracts/graph/semantic_models.py index 492c3188808..3ccf705ed85 100644 --- a/core/dbt/contracts/graph/semantic_models.py +++ b/core/dbt/contracts/graph/semantic_models.py @@ -142,13 +142,6 @@ class Measure(dbtClassMixin): non_additive_dimension: Optional[NonAdditiveDimension] = None agg_time_dimension: Optional[str] = None - @property - def checked_agg_time_dimension(self) -> TimeDimensionReference: - if self.agg_time_dimension is not None: - return TimeDimensionReference(element_name=self.agg_time_dimension) - else: - raise Exception("Measure is missing agg_time_dimension!") - @property def reference(self) -> MeasureReference: return MeasureReference(element_name=self.name) From 0080a211ffa83e2b9ca91cc00b46f58c2b2af7ae Mon Sep 17 00:00:00 2001 From: Quigley Malcolm Date: Wed, 12 Jul 2023 13:06:29 -0700 Subject: [PATCH 17/17] Add changie doc for populating metric --- .changes/unreleased/Features-20230712-123724.yaml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changes/unreleased/Features-20230712-123724.yaml diff --git a/.changes/unreleased/Features-20230712-123724.yaml b/.changes/unreleased/Features-20230712-123724.yaml new file mode 100644 index 00000000000..635b56715ca --- /dev/null +++ b/.changes/unreleased/Features-20230712-123724.yaml @@ -0,0 +1,6 @@ +kind: Features +body: Begin populating `depends_on` of metric nodes +time: 2023-07-12T12:37:24.01449-07:00 +custom: + Author: QMalcolm gshank + Issue: "7854"