Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Semantic Models to DAG #7896

Closed
wants to merge 9 commits into from
6 changes: 6 additions & 0 deletions .changes/unreleased/Features-20230616-163045.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
kind: Features
body: Added semantic models to the DAG and partial parsing module
time: 2023-06-16T16:30:45.513314-04:00
custom:
Author: peterallenwebb
Issue: "7800"
3 changes: 3 additions & 0 deletions core/dbt/compilation.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,9 @@ def link_node(self, node: GraphMemberNode, manifest: Manifest):
def link_graph(self, manifest: Manifest):
for source in manifest.sources.values():
self.add_node(source.unique_id)
for semantic_node in manifest.semantic_nodes.values():
self.add_node(semantic_node.unique_id)

for node in manifest.nodes.values():
self.link_node(node, manifest)
for exposure in manifest.exposures.values():
Expand Down
15 changes: 14 additions & 1 deletion core/dbt/contracts/graph/manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -762,6 +762,9 @@ def build_flat_graph(self):
"nodes": {k: v.to_dict(omit_none=False) for k, v in self.nodes.items()},
"sources": {k: v.to_dict(omit_none=False) for k, v in self.sources.items()},
"public_nodes": {k: v.to_dict(omit_none=False) for k, v in self.public_nodes.items()},
"semantic_nodes": {
k: v.to_dict(omit_none=False) for k, v in self.semantic_nodes.items()
},
}

def build_disabled_by_file_id(self):
Expand Down Expand Up @@ -822,6 +825,7 @@ def get_resource_fqns(self) -> Mapping[str, PathSet]:
self.nodes.values(),
self.sources.values(),
self.metrics.values(),
self.semantic_nodes.values(),
)
for resource in all_resources:
resource_type_plural = resource.resource_type.pluralize()
Expand Down Expand Up @@ -857,6 +861,8 @@ def deepcopy(self):
public_nodes={k: _deepcopy(v) for k, v in self.public_nodes.items()},
files={k: _deepcopy(v) for k, v in self.files.items()},
state_check=_deepcopy(self.state_check),
publications={k: _deepcopy(v) for k, v in self.publications.items()},
semantic_nodes={k: _deepcopy(v) for k, v in self.semantic_nodes.items()},
)
copy.build_flat_graph()
return copy
Expand All @@ -869,6 +875,7 @@ def build_parent_and_child_maps(self):
self.exposures.values(),
self.metrics.values(),
self.public_nodes.values(),
self.semantic_nodes.values(),
)
)
forward_edges, backward_edges = build_node_edges(edge_members)
Expand Down Expand Up @@ -933,6 +940,8 @@ def expect(self, unique_id: str) -> GraphMemberNode:
return self.exposures[unique_id]
elif unique_id in self.metrics:
return self.metrics[unique_id]
elif unique_id in self.semantic_nodes:
return self.semantic_nodes[unique_id]
else:
# something terrible has happened
raise dbt.exceptions.DbtInternalError(
Expand Down Expand Up @@ -1002,7 +1011,9 @@ def pydantic_semantic_manifest(self) -> PydanticSemanticManifest:
return pydantic_semantic_manifest

def resolve_refs(
self, source_node: GraphMemberNode, current_project: str
self,
source_node: ModelNode,
current_project: str, # TODO: ModelNode is overly restrictive typing
) -> List[MaybeNonSource]:
resolved_refs: List[MaybeNonSource] = []
for ref in source_node.refs:
Expand Down Expand Up @@ -1297,6 +1308,8 @@ def __reduce_ex__(self, protocol):
self.disabled,
self.env_vars,
self.public_nodes,
self.publications,
self.semantic_nodes,
self._doc_lookup,
self._source_lookup,
self._ref_lookup,
Expand Down
15 changes: 15 additions & 0 deletions core/dbt/contracts/graph/nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -1478,12 +1478,14 @@ class NodeRelation(dbtClassMixin):
class SemanticModel(GraphNode):
model: str
node_relation: Optional[NodeRelation]
depends_on: DependsOn = field(default_factory=DependsOn)
description: Optional[str] = None
defaults: Optional[Defaults] = None
entities: Sequence[Entity] = field(default_factory=list)
measures: Sequence[Measure] = field(default_factory=list)
dimensions: Sequence[Dimension] = field(default_factory=list)
metadata: Optional[SourceFileMetadata] = None
created_at: float = field(default_factory=lambda: time.time()) # REVIEW: Needed?

@property
def entity_references(self) -> List[LinkableElementReference]:
Expand Down Expand Up @@ -1534,6 +1536,18 @@ def partition(self) -> Optional[Dimension]:
def reference(self) -> SemanticModelReference:
return SemanticModelReference(semantic_model_name=self.name)

@property
def depends_on_nodes(self):
return self.depends_on.nodes

@property
def depends_on_public_nodes(self):
return self.depends_on.public_nodes

@property
def depends_on_macros(self):
return self.depends_on.macros


# ====================================
# Patches
Expand Down Expand Up @@ -1641,6 +1655,7 @@ def alias(self):
ResultNode,
Exposure,
Metric,
SemanticModel,
]

# All "nodes" (or node-like objects) in this file
Expand Down
2 changes: 2 additions & 0 deletions core/dbt/parser/manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,7 @@ def check_for_model_deprecations(self):

resolved_refs = self.manifest.resolve_refs(node, self.root_project.project_name)
resolved_model_refs = [r for r in resolved_refs if isinstance(r, ModelNode)]
node.depends_on
for resolved_ref in resolved_model_refs:
if resolved_ref.deprecation_date:

Expand Down Expand Up @@ -1198,6 +1199,7 @@ def process_semantic_models(self) -> None:
schema_name=refd_node.schema,
database=refd_node.database,
)
semantic_model.depends_on.add_node(refd_node.unique_id)

# nodes: node and column descriptions
# sources: source and table descriptions, column descriptions
Expand Down
Loading