Skip to content

Commit fccc1e5

Browse files
eddowhfa-assistant
authored andcommitted
Hydrate metrics in semantic manifest and manifest (#5556)
GitOrigin-RevId: e1c1655b29da3c1f26878c664640659d69993c8d
1 parent 266ce42 commit fccc1e5

File tree

14 files changed

+900
-329
lines changed

14 files changed

+900
-329
lines changed

crates/dbt-parser/src/resolve/resolve_metrics.rs

Lines changed: 486 additions & 7 deletions
Large diffs are not rendered by default.

crates/dbt-parser/src/resolve/resolve_properties.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ pub struct MinimalProperties {
4141
pub unit_tests: BTreeMap<String, MinimalPropertiesEntry>,
4242
pub tests: BTreeMap<String, MinimalPropertiesEntry>,
4343
pub exposures: BTreeMap<String, MinimalPropertiesEntry>,
44+
pub metrics: BTreeMap<String, MinimalPropertiesEntry>,
4445
pub saved_queries: BTreeMap<String, MinimalPropertiesEntry>,
4546
pub groups: BTreeMap<String, MinimalPropertiesEntry>,
4647
}
@@ -263,6 +264,37 @@ impl MinimalProperties {
263264
);
264265
}
265266
}
267+
if let Some(metrics) = other.metrics {
268+
for metric_value in metrics {
269+
let metric = into_typed_with_jinja::<MinimalSchemaValue, _>(
270+
io_args,
271+
metric_value.clone(),
272+
false,
273+
jinja_env,
274+
base_ctx,
275+
&[],
276+
dependency_package_name_from_ctx(jinja_env, base_ctx),
277+
)?;
278+
if let Some(existing_metric) = self.metrics.get_mut(&metric.name) {
279+
existing_metric
280+
.duplicate_paths
281+
.push(properties_path.to_path_buf());
282+
} else {
283+
self.metrics.insert(
284+
metric.name.clone(),
285+
MinimalPropertiesEntry {
286+
name: validate_resource_name(&metric.name)?,
287+
name_span: Span::default(),
288+
relative_path: properties_path.to_path_buf(),
289+
schema_value: metric_value,
290+
table_value: None,
291+
version_info: None,
292+
duplicate_paths: vec![],
293+
},
294+
);
295+
}
296+
}
297+
}
266298
if let Some(saved_queries) = other.saved_queries {
267299
for saved_query_value in saved_queries {
268300
let saved_query = into_typed_with_jinja::<MinimalSchemaValue, _>(

crates/dbt-parser/src/resolve/resolve_semantic_models.rs

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,14 @@ use dbt_schemas::schemas::common::{DbtChecksum, Dimension, DimensionTypeParams,
99
use dbt_schemas::schemas::dbt_column::{
1010
ColumnPropertiesDimension, ColumnPropertiesDimensionConfig, Entity, EntityConfig,
1111
};
12+
use dbt_schemas::schemas::manifest::metric::{MeasureAggregationParameters, NonAdditiveDimension};
1213
use dbt_schemas::schemas::manifest::semantic_model::{
13-
DbtSemanticModel, DbtSemanticModelAttr, MeasureAggregationParameters, NodeRelation,
14-
SemanticEntity, SemanticMeasure, SemanticModelDefaults,
14+
DbtSemanticModel, DbtSemanticModelAttr, NodeRelation, SemanticEntity, SemanticMeasure,
15+
SemanticModelDefaults,
1516
};
1617
use dbt_schemas::schemas::project::{DefaultTo, ModelConfig, SemanticModelConfig};
1718
use dbt_schemas::schemas::properties::ModelProperties;
18-
use dbt_schemas::schemas::properties::metrics_properties::{
19-
AggregationType, MetricExpr, PercentileType,
20-
};
19+
use dbt_schemas::schemas::properties::metrics_properties::{AggregationType, PercentileType};
2120
use dbt_schemas::schemas::ref_and_source::DbtRef;
2221
use dbt_schemas::schemas::semantic_layer::semantic_manifest::SemanticLayerElementConfig;
2322
use dbt_schemas::schemas::{CommonAttributes, DbtModel, InternalDbtNodeAttributes};
@@ -159,10 +158,7 @@ pub async fn resolve_semantic_models(
159158
.map(|metric| {
160159
SemanticMeasure {
161160
name: metric.name.clone(),
162-
expr: metric.expr.clone().map(|expr| match expr {
163-
MetricExpr::String(ref str) => str.clone(),
164-
MetricExpr::Integer(ref int) => int.to_string(),
165-
}),
161+
expr: metric.expr.clone().map(String::from),
166162
description: metric.description.clone(),
167163
label: metric.label.clone(),
168164
config: metric.config.as_ref().map(|c| SemanticLayerElementConfig {
@@ -186,7 +182,10 @@ pub async fn resolve_semantic_models(
186182
} else {
187183
None
188184
},
189-
non_additive_dimension: metric.non_additive_dimension.clone(),
185+
non_additive_dimension: metric
186+
.non_additive_dimension
187+
.clone()
188+
.map(NonAdditiveDimension::from),
190189
agg_time_dimension: Some(
191190
metric
192191
.agg_time_dimension

crates/dbt-parser/src/resolver.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -558,8 +558,6 @@ pub async fn resolve_inner(
558558
nodes.exposures.extend(exposures);
559559
disabled_nodes.exposures.extend(disabled_exposures);
560560

561-
// dbg!(&nodes.clone().models);
562-
563561
let (semantic_models, disabled_semantic_models) = resolve_semantic_models(
564562
arg,
565563
package,
@@ -578,7 +576,15 @@ pub async fn resolve_inner(
578576
.extend(disabled_semantic_models);
579577

580578
let (metrics, disabled_metrics) = resolve_metrics(
581-
// TODO: pass in typed_models_properties
579+
arg,
580+
package,
581+
root_project_configs,
582+
&mut min_properties.models.clone(),
583+
&mut min_properties.metrics.clone(),
584+
&typed_models_properties,
585+
package_name,
586+
&jinja_env,
587+
&base_ctx,
582588
)
583589
.await?;
584590
nodes.metrics.extend(metrics);

crates/dbt-parser/src/utils.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,17 @@ pub fn coalesce<T: Clone>(values: Vec<Option<T>>) -> Option<T> {
3333
None
3434
}
3535

36-
/// generate the unique id for a model (can be made more extensible for each type of node)
36+
/// generate the unique id for a dbt resource (can be made more extensible for each type of node)
3737
pub fn get_unique_id(
38-
model_name: &str,
38+
resource_name: &str,
3939
package_name: &str,
4040
version: Option<String>,
4141
node_type: &str,
4242
) -> String {
4343
if let Some(version) = version {
44-
format!("{node_type}.{package_name}.{model_name}.v{version}")
44+
format!("{node_type}.{package_name}.{resource_name}.v{version}")
4545
} else {
46-
format!("{node_type}.{package_name}.{model_name}")
46+
format!("{node_type}.{package_name}.{resource_name}")
4747
}
4848
}
4949

crates/dbt-schemas/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ pub mod schemas {
5858
#[allow(clippy::module_inception)]
5959
mod manifest;
6060
mod manifest_nodes;
61-
pub(crate) mod metric;
61+
pub mod metric;
6262
mod operation;
6363
pub mod postgres;
6464
pub mod saved_query;

crates/dbt-schemas/src/schemas/manifest/common.rs

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -33,19 +33,6 @@ impl From<Vec<String>> for WhereFilterIntersection {
3333
}
3434
}
3535

36-
impl From<StringOrArrayOfStrings> for WhereFilterIntersection {
37-
fn from(source: StringOrArrayOfStrings) -> Self {
38-
match source {
39-
StringOrArrayOfStrings::String(s) => Self {
40-
where_filters: vec![WhereFilter {
41-
where_sql_template: s,
42-
}],
43-
},
44-
StringOrArrayOfStrings::ArrayOfStrings(arr) => arr.into(),
45-
}
46-
}
47-
}
48-
4936
#[skip_serializing_none]
5037
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, JsonSchema)]
5138
#[serde(rename_all = "snake_case")]

crates/dbt-schemas/src/schemas/manifest/manifest.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,12 @@ pub fn build_manifest(invocation_id: &str, resolver_state: &ResolverState) -> Db
185185
.iter()
186186
.map(|(id, semantic_model)| (id.clone(), (**semantic_model).clone().into()))
187187
.collect(),
188-
metrics: BTreeMap::new(), // TODO: map from resolver_state.nodes
188+
metrics: resolver_state
189+
.nodes
190+
.metrics
191+
.iter()
192+
.map(|(id, metric)| (id.clone(), (**metric).clone().into()))
193+
.collect(),
189194
saved_queries: resolver_state
190195
.nodes
191196
.saved_queries
@@ -423,6 +428,24 @@ fn build_parent_and_child_maps(
423428
all_nodes.push((id.clone(), unit_test.__base_attr__.depends_on.clone()));
424429
}
425430

431+
for (id, semantic_model) in &nodes.semantic_models {
432+
all_nodes.push((
433+
id.clone(),
434+
semantic_model.__semantic_model_attr__.depends_on.clone(),
435+
));
436+
}
437+
438+
for (id, metric) in &nodes.metrics {
439+
all_nodes.push((id.clone(), metric.__metric_attr__.depends_on.clone()));
440+
}
441+
442+
for (id, saved_query) in &nodes.saved_queries {
443+
all_nodes.push((
444+
id.clone(),
445+
saved_query.__saved_query_attr__.depends_on.clone(),
446+
));
447+
}
448+
426449
// Process all collected nodes
427450
for (node_id, depends_on) in all_nodes {
428451
// Initialize parent list for this node

crates/dbt-schemas/src/schemas/manifest/manifest_nodes.rs

Lines changed: 43 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,10 @@ use crate::schemas::{
1414
},
1515
dbt_column::DbtColumnRef,
1616
manifest::{
17-
DbtOperation, DbtSavedQuery, DbtSemanticModel,
17+
DbtMetric, DbtOperation, DbtSavedQuery, DbtSemanticModel,
1818
common::{DbtOwner, SourceFileMetadata, WhereFilterIntersection},
19-
semantic_model::{
20-
MeasureAggregationParameters, NodeRelation, SemanticEntity, SemanticMeasure,
21-
SemanticModelDefaults,
22-
},
19+
metric::{MeasureAggregationParameters, MetricTypeParams, NonAdditiveDimension},
20+
semantic_model::{NodeRelation, SemanticEntity, SemanticMeasure, SemanticModelDefaults},
2321
},
2422
nodes::TestMetadata,
2523
project::{
@@ -28,7 +26,7 @@ use crate::schemas::{
2826
},
2927
properties::{
3028
ModelConstraint, UnitTestOverrides,
31-
metrics_properties::{AggregationType, NonAdditiveDimension, WindowChoice},
29+
metrics_properties::{AggregationType, MetricType},
3230
},
3331
ref_and_source::{DbtRef, DbtSourceWrapper},
3432
semantic_layer::semantic_manifest::SemanticLayerElementConfig,
@@ -637,8 +635,8 @@ pub struct ManifestMetric {
637635
// Metric Specific Attributes
638636
pub label: String,
639637
#[serde(rename = "type")]
640-
pub metric_type: crate::schemas::manifest::metric::MetricType,
641-
pub type_params: crate::schemas::manifest::metric::MetricTypeParams,
638+
pub metric_type: MetricType,
639+
pub type_params: MetricTypeParams,
642640
pub filter: Option<WhereFilterIntersection>,
643641
pub metadata: Option<SourceFileMetadata>,
644642
pub time_granularity: Option<String>,
@@ -652,6 +650,41 @@ pub struct ManifestMetric {
652650
pub __other__: BTreeMap<String, YmlValue>,
653651
}
654652

653+
impl From<DbtMetric> for ManifestMetric {
654+
fn from(metric: DbtMetric) -> Self {
655+
Self {
656+
__common_attr__: ManifestCommonAttributes {
657+
unique_id: metric.__common_attr__.unique_id,
658+
name: metric.__common_attr__.name,
659+
package_name: metric.__common_attr__.package_name,
660+
fqn: metric.__common_attr__.fqn,
661+
path: metric.__common_attr__.path,
662+
original_file_path: metric.__common_attr__.original_file_path,
663+
description: metric.__common_attr__.description,
664+
tags: metric.__common_attr__.tags,
665+
meta: metric.__common_attr__.meta,
666+
},
667+
__base_attr__: ManifestMetricNodeBaseAttributes {
668+
depends_on: metric.__metric_attr__.depends_on,
669+
refs: metric.__metric_attr__.refs,
670+
sources: metric.__metric_attr__.sources,
671+
unrendered_config: metric.__metric_attr__.unrendered_config,
672+
created_at: metric.__metric_attr__.created_at,
673+
},
674+
label: metric.__metric_attr__.label.unwrap_or_default(),
675+
metric_type: metric.__metric_attr__.metric_type,
676+
type_params: metric.__metric_attr__.type_params,
677+
filter: metric.__metric_attr__.filter,
678+
metadata: metric.__metric_attr__.metadata,
679+
time_granularity: metric.__metric_attr__.time_granularity.clone(),
680+
group: metric.__metric_attr__.group.clone(),
681+
config: metric.deprecated_config.into(),
682+
__other__: metric.__other__,
683+
metrics: vec![], // TODO: metric.__metric_attr__.metrics.clone(),
684+
}
685+
}
686+
}
687+
655688
#[derive(Deserialize, Serialize, Debug, Clone, PartialEq)]
656689
pub struct ManifestMetricConfig {
657690
pub enabled: bool,
@@ -779,23 +812,6 @@ impl From<DbtSemanticModel> for ManifestSemanticModel {
779812
}
780813
}
781814

782-
#[derive(Debug, Clone, Serialize, Deserialize)]
783-
pub struct ManifestNonAdditiveDimension {
784-
pub name: String,
785-
pub window_choice: WindowChoice,
786-
pub window_groupings: Option<Vec<String>>,
787-
}
788-
789-
impl From<NonAdditiveDimension> for ManifestNonAdditiveDimension {
790-
fn from(dim: NonAdditiveDimension) -> Self {
791-
Self {
792-
name: dim.name,
793-
window_choice: dim.window_agg,
794-
window_groupings: dim.group_by,
795-
}
796-
}
797-
}
798-
799815
#[derive(Debug, Clone, Serialize, Deserialize)]
800816
pub struct ManifestSemanticModelMeasure {
801817
pub name: String,
@@ -805,7 +821,7 @@ pub struct ManifestSemanticModelMeasure {
805821
pub create_metric: Option<bool>,
806822
pub expr: Option<String>,
807823
pub agg_params: Option<MeasureAggregationParameters>,
808-
pub non_additive_dimension: Option<ManifestNonAdditiveDimension>,
824+
pub non_additive_dimension: Option<NonAdditiveDimension>,
809825
pub agg_time_dimension: Option<String>,
810826
pub config: Option<SemanticLayerElementConfig>,
811827
}
@@ -820,9 +836,7 @@ impl From<SemanticMeasure> for ManifestSemanticModelMeasure {
820836
create_metric: measure.create_metric,
821837
expr: measure.expr,
822838
agg_params: measure.agg_params,
823-
non_additive_dimension: measure
824-
.non_additive_dimension
825-
.map(ManifestNonAdditiveDimension::from),
839+
non_additive_dimension: measure.non_additive_dimension,
826840
agg_time_dimension: measure.agg_time_dimension,
827841
config: measure.config,
828842
}

0 commit comments

Comments
 (0)