diff --git a/converters/dbt/src/ossie_dbt/osi_to_msi.py b/converters/dbt/src/ossie_dbt/osi_to_msi.py index c8f155fc..b2502dc4 100644 --- a/converters/dbt/src/ossie_dbt/osi_to_msi.py +++ b/converters/dbt/src/ossie_dbt/osi_to_msi.py @@ -188,7 +188,7 @@ def _classify_field( Aggregation info lives on metrics (`metric_aggregation_params`), not on semantic model measures, so there is no measure classification step. """ - if field.name in primary_key_cols: + if field.name in primary_key_cols or expr in primary_key_cols: entities.append( PydanticEntity( name=field.name, @@ -201,7 +201,7 @@ def _classify_field( ) ) return - if field.name in unique_key_cols: + if field.name in unique_key_cols or expr in unique_key_cols: entities.append( PydanticEntity( name=field.name, @@ -214,7 +214,7 @@ def _classify_field( ) ) return - if field.name in foreign_key_cols: + if field.name in foreign_key_cols or expr in foreign_key_cols: entities.append( PydanticEntity( name=field.name, diff --git a/converters/dbt/tests/test_osi_to_msi.py b/converters/dbt/tests/test_osi_to_msi.py index dfed1e42..4f4b74f0 100644 --- a/converters/dbt/tests/test_osi_to_msi.py +++ b/converters/dbt/tests/test_osi_to_msi.py @@ -23,12 +23,16 @@ from ossie import OSIDataType, OSIDimension from ossie_dbt.msi_to_osi import MSIToOSIConverter from ossie_dbt.osi_to_msi import OSIToMSIConverter +from metricflow_semantic_interfaces.test_utils import semantic_model_with_guaranteed_meta from metricflow_semantic_interfaces.type_enums import ( AggregationType, DimensionType, + EntityType, MetricType, ) from tests.helpers import ( + _entity, + _manifest, _osi_dataset, _osi_doc, _osi_field, @@ -445,3 +449,22 @@ def test_osi_to_msi_to_osi_preserves_structure(self, snapshot: SnapshotAssertion assert metrics[0].name == "revenue" assert metrics[0].expression.dialects[0].expression == "SUM(orders.amount)" assert osi_doc.to_osi_yaml() == snapshot + + def test_entity_with_expr_different_from_name_survives_round_trip(self) -> None: + """A PRIMARY entity whose expr differs from its name is not lost on MSI -> OSI -> MSI.""" + orders = semantic_model_with_guaranteed_meta( + name="orders", + entities=[_entity("customer_id", entity_type=EntityType.PRIMARY, expr="id")], + ) + + osi_doc = MSIToOSIConverter().convert(_manifest(semantic_models=[orders])).output + + assert osi_doc.semantic_model[0].datasets[0].primary_key == ["id"] + + back = OSIToMSIConverter().convert(osi_doc).output + sm = back.semantic_models[0] + + assert len(sm.entities) == 1 + assert sm.entities[0].name == "customer_id" + assert sm.entities[0].expr == "id" + assert sm.entities[0].type is EntityType.PRIMARY