diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/TableRepository.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/TableRepository.java index a25f8f13164..ba57a8f0968 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/TableRepository.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/TableRepository.java @@ -625,6 +625,12 @@ public class TableRepository extends EntityRepository { if (nullOrEmpty(table.getDescription())) { table.setDescription(dataModel.getDescription()); } + + // Carry forward the table owner from the model to table entity, if empty + if (table.getOwner() == null) { + storeOwner(table, dataModel.getOwner()); + } + // Carry forward the column description from the model to table columns, if empty for (Column modelColumn : listOrEmpty(dataModel.getColumns())) { Column stored = @@ -640,7 +646,9 @@ public class TableRepository extends EntityRepository
{ } } dao.update(table.getId(), JsonUtils.pojoToJson(table)); - setFields(table, Fields.EMPTY_FIELDS); + + setFields(table, new Fields(List.of(FIELD_OWNER), FIELD_OWNER)); + return table; } diff --git a/catalog-rest-service/src/main/resources/json/schema/entity/data/table.json b/catalog-rest-service/src/main/resources/json/schema/entity/data/table.json index d725458d26c..c9d3e6c643a 100644 --- a/catalog-rest-service/src/main/resources/json/schema/entity/data/table.json +++ b/catalog-rest-service/src/main/resources/json/schema/entity/data/table.json @@ -628,6 +628,11 @@ "type": "string" } }, + "owner": { + "description": "Owner of this Model.", + "$ref": "../../type/entityReference.json", + "default": null + }, "columns": { "description": "Columns from the schema defined during modeling. In case of DBT, the metadata here comes from `schema.yaml`.", "type": "array", diff --git a/ingestion/src/metadata/ingestion/source/database/dbt_source.py b/ingestion/src/metadata/ingestion/source/database/dbt_source.py index d1c223acf69..026f1497650 100644 --- a/ingestion/src/metadata/ingestion/source/database/dbt_source.py +++ b/ingestion/src/metadata/ingestion/source/database/dbt_source.py @@ -21,6 +21,7 @@ from metadata.generated.schema.entity.data.table import ( ModelType, Table, ) +from metadata.generated.schema.entity.teams.user import User from metadata.generated.schema.type.entityLineage import EntitiesEdge from metadata.generated.schema.type.entityReference import EntityReference from metadata.ingestion.ometa.ometa_api import OpenMetadata @@ -77,6 +78,14 @@ class DBTMixin: schema = mnode["schema"] if mnode["schema"] else "default" raw_sql = mnode.get("raw_sql", "") description = mnode.get("description") + dbt_user_name = cnode["metadata"].get("owner") + user_name = f"*{dbt_user_name}*" + user_fqn = fqn.build( + self.metadata, entity_type=User, user_name=user_name + ) + owner = self.metadata.get_entity_reference( + entity=User, fqn=user_fqn + ) model = DataModel( modelType=ModelType.DBT, description=description if description else None, @@ -85,6 +94,7 @@ class DBTMixin: sql=mnode.get("compiled_sql", raw_sql), columns=columns, upstream=upstream_nodes, + owner=owner, ) model_fqn = fqn.build( self.metadata, diff --git a/ingestion/src/metadata/utils/fqn.py b/ingestion/src/metadata/utils/fqn.py index 1f5a5e9fb7a..a7a99cd87b4 100644 --- a/ingestion/src/metadata/utils/fqn.py +++ b/ingestion/src/metadata/utils/fqn.py @@ -33,6 +33,7 @@ from metadata.generated.schema.entity.data.location import Location from metadata.generated.schema.entity.data.pipeline import Pipeline from metadata.generated.schema.entity.data.table import Column, DataModel, Table from metadata.generated.schema.entity.tags.tagCategory import Tag +from metadata.generated.schema.entity.teams.user import User from metadata.ingestion.ometa.ometa_api import OpenMetadata from metadata.utils.dispatch import class_register from metadata.utils.elasticsearch import get_entity_from_es_result @@ -280,6 +281,36 @@ def _( return _build(service_name, database_name, schema_name, table_name, column_name) +@fqn_build_registry.add(User) +def _( + metadata: OpenMetadata, + *, + user_name: str, + fetch_multiple_entities: bool = False, +) -> Union[Optional[str], Optional[List[str]]]: + """ + Building logic for User + :param metadata: OMeta client + :param user_name: User name + :return: + """ + + fqn_search_string = _build(user_name) + + es_result = metadata.es_search_from_fqn( + entity_type=User, + fqn_search_string=fqn_search_string, + ) + entity: Optional[Union[User, List[User]]] = get_entity_from_es_result( + entity_list=es_result, fetch_multiple_entities=fetch_multiple_entities + ) + if not entity: + return None + if fetch_multiple_entities: + return [str(user.fullyQualifiedName.__root__) for user in entity] + return str(entity.fullyQualifiedName.__root__) + + def split_table_name(table_name: str) -> Dict[str, Optional[str]]: """ Given a table name, try to extract database, schema and