@@ -8,26 +8,42 @@ use std::collections::BTreeMap;
88
99use serde:: { Deserialize , Serialize } ;
1010
11- use crate :: backend:: data_hub:: { DataHubResourceInfoResponse , Group , Owners , Tag , Urn , User } ;
11+ use crate :: backend:: data_hub:: {
12+ DataHubResourceInfoResponse , DataProduct , Domain , Group , Owners , Tag , Urn , User ,
13+ } ;
1214
1315/// A single query covering every entity kind we build URNs for. We use the generic `entity(urn:)`
1416/// resolver plus per-type inline fragments, because a request can target a dataset (Trino table or
1517/// Kafka topic), a container (Trino catalog or schema), a chart or a dashboard.
16- const RESOURCE_INFO_QUERY : & str = r"
18+ const RESOURCE_INFO_QUERY : & str = r# "
1719query ResourceInfo($urn: String!) {
1820 entity(urn: $urn) {
1921 ...ResourceInfo
2022 }
2123}
2224fragment ResourceInfo on Entity {
23- ... on Dataset { tags { ...Tags } ownership { ...Owners } }
24- ... on Container { tags { ...Tags } ownership { ...Owners } }
25- ... on Chart { tags { ...Tags } ownership { ...Owners } }
26- ... on Dashboard { tags { ...Tags } ownership { ...Owners } }
25+ # DataHub has no direct "dataProduct" field on assets; membership is a graph edge that points from
26+ # the data product to its assets. From the asset's side it is therefore an INCOMING relationship.
27+ dataProducts: relationships(input: {types: ["DataProductContains"], direction: INCOMING, count: 10}) {
28+ relationships { ...DataProduct }
29+ }
30+ ... on Dataset { tags { ...Tags } ownership { ...Owners } domain { ...Domain } }
31+ ... on Container { tags { ...Tags } ownership { ...Owners } domain { ...Domain } }
32+ ... on Chart { tags { ...Tags } ownership { ...Owners } domain { ...Domain } }
33+ ... on Dashboard { tags { ...Tags } ownership { ...Owners } domain { ...Domain } }
2734}
2835fragment Tags on GlobalTags {
2936 tags { tag { urn properties { name } } }
3037}
38+ fragment Domain on DomainAssociation {
39+ domain { urn properties { name description } }
40+ }
41+ fragment DataProduct on EntityRelationship {
42+ entity {
43+ urn
44+ ... on DataProduct { properties { name description } }
45+ }
46+ }
3147fragment Owners on Ownership {
3248 owners {
3349 owner {
@@ -39,7 +55,7 @@ fragment Owners on Ownership {
3955 type
4056 }
4157}
42- " ;
58+ "# ;
4359
4460/// Builds the request body for the [`RESOURCE_INFO_QUERY`], parameterized by the entity's URN.
4561pub fn request ( urn : & Urn ) -> GraphQlRequest < ' _ > {
@@ -86,9 +102,12 @@ pub struct ResponseData {
86102/// concrete entity type. [`Default`] yields the "no metadata" entity used when DataHub does not
87103/// return an entity for a URN.
88104#[ derive( Debug , Default , Deserialize ) ]
105+ #[ serde( rename_all = "camelCase" ) ]
89106pub struct Entity {
90107 tags : Option < GlobalTags > ,
91108 ownership : Option < Ownership > ,
109+ domain : Option < DomainAssociation > ,
110+ data_products : Option < EntityRelationships > ,
92111}
93112
94113#[ derive( Debug , Deserialize ) ]
@@ -112,6 +131,47 @@ struct TagProperties {
112131 name : String ,
113132}
114133
134+ #[ derive( Debug , Deserialize ) ]
135+ struct DomainAssociation {
136+ domain : DomainNode ,
137+ }
138+
139+ #[ derive( Debug , Deserialize ) ]
140+ struct DomainNode {
141+ urn : Urn ,
142+ properties : Option < DomainProperties > ,
143+ }
144+
145+ #[ derive( Debug , Deserialize ) ]
146+ struct DomainProperties {
147+ name : String ,
148+ description : Option < String > ,
149+ }
150+
151+ /// The result of the `DataProductContains` relationship query. Each relationship's related entity is
152+ /// a data product the resource belongs to.
153+ #[ derive( Debug , Deserialize ) ]
154+ struct EntityRelationships {
155+ relationships : Vec < EntityRelationship > ,
156+ }
157+
158+ #[ derive( Debug , Deserialize ) ]
159+ struct EntityRelationship {
160+ entity : DataProductNode ,
161+ }
162+
163+ #[ derive( Debug , Deserialize ) ]
164+ struct DataProductNode {
165+ urn : Urn ,
166+ properties : Option < DataProductProperties > ,
167+ }
168+
169+ #[ derive( Debug , Deserialize ) ]
170+ struct DataProductProperties {
171+ name : String ,
172+ description : Option < String > ,
173+ }
174+
115175#[ derive( Debug , Deserialize ) ]
116176struct Ownership {
117177 owners : Vec < Owner > ,
@@ -189,6 +249,39 @@ impl Entity {
189249 } )
190250 . collect ( ) ;
191251
252+ let domain = self . domain . map ( |association| {
253+ let DomainNode { urn, properties } = association. domain ;
254+ // A domain without a properties aspect has no name; fall back to its URN.
255+ let ( name, description) = match properties {
256+ Some ( properties) => ( properties. name , properties. description ) ,
257+ None => ( urn. 0 . clone ( ) , None ) ,
258+ } ;
259+ Domain {
260+ urn,
261+ name,
262+ description,
263+ }
264+ } ) ;
265+
266+ let data_products = self
267+ . data_products
268+ . into_iter ( )
269+ . flat_map ( |relationships| relationships. relationships )
270+ . map ( |relationship| {
271+ let DataProductNode { urn, properties } = relationship. entity ;
272+ // A data product without a properties aspect has no name; fall back to its URN.
273+ let ( name, description) = match properties {
274+ Some ( properties) => ( properties. name , properties. description ) ,
275+ None => ( urn. 0 . clone ( ) , None ) ,
276+ } ;
277+ DataProduct {
278+ urn,
279+ name,
280+ description,
281+ }
282+ } )
283+ . collect ( ) ;
284+
192285 let mut owners: BTreeMap < Urn , Owners > = BTreeMap :: new ( ) ;
193286 for owner in self
194287 . ownership
@@ -210,7 +303,13 @@ impl Entity {
210303 }
211304 }
212305
213- DataHubResourceInfoResponse { urn, tags, owners }
306+ DataHubResourceInfoResponse {
307+ urn,
308+ tags,
309+ domain,
310+ data_products,
311+ owners,
312+ }
214313 }
215314}
216315
0 commit comments