Skip to content

Commit 61f1068

Browse files
authored
fix: align Query mutations with DataHub v1.3+ GraphQL schema (#64)
The CreateQuery and UpdateQuery mutations used a fabricated QuerySubjects wrapper type that doesn't exist in DataHub's schema. This caused GraphQL validation errors at runtime: Field 'datasets' in type 'QuerySubject' is undefined Three issues fixed: 1. Response selection: subjects { datasets { dataset { urn } } } changed to subjects { dataset { urn } } — QueryEntity.subjects returns [QuerySubject!] directly, not a wrapper. 2. Input format: {"subjects": {"datasets": [{datasetUrn: ...}]}} changed to {"subjects": [{datasetUrn: ...}]} — CreateQueryInput expects [CreateQuerySubjectInput!]!, a flat array. 3. subjects is now always sent (required field in schema) as an empty array when no DatasetURNs are provided, instead of being omitted.
1 parent bef3896 commit 61f1068

File tree

3 files changed

+32
-43
lines changed

3 files changed

+32
-43
lines changed

pkg/client/queries.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -600,10 +600,8 @@ mutation createQuery($input: CreateQueryInput!) {
600600
}
601601
}
602602
subjects {
603-
datasets {
604-
dataset {
605-
urn
606-
}
603+
dataset {
604+
urn
607605
}
608606
}
609607
}

pkg/client/write_queries.go

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,9 @@ type deleteQueryResponse struct {
6363

6464
// queryEntityResponse is the nested query entity returned by mutations.
6565
type queryEntityResponse struct {
66-
URN string `json:"urn"`
67-
Properties *queryPropertiesRaw `json:"properties"`
68-
Subjects *querySubjectsRawOuter `json:"subjects"`
66+
URN string `json:"urn"`
67+
Properties *queryPropertiesRaw `json:"properties"`
68+
Subjects []querySubjectRaw `json:"subjects"`
6969
}
7070

7171
// queryPropertiesRaw maps the GraphQL QueryProperties type.
@@ -89,13 +89,8 @@ type auditStampGQL struct {
8989
Actor string `json:"actor"`
9090
}
9191

92-
// querySubjectsRawOuter maps the QuerySubjects type.
93-
type querySubjectsRawOuter struct {
94-
Datasets []queryDatasetRef `json:"datasets"`
95-
}
96-
97-
// queryDatasetRef maps QuerySubjects.datasets[].dataset.
98-
type queryDatasetRef struct {
92+
// querySubjectRaw maps the QuerySubject type (one per subject).
93+
type querySubjectRaw struct {
9994
Dataset struct {
10095
URN string `json:"urn"`
10196
} `json:"dataset"`
@@ -123,15 +118,11 @@ func (c *Client) CreateQuery(ctx context.Context, input CreateQueryInput) (*type
123118
},
124119
}
125120

126-
if len(input.DatasetURNs) > 0 {
127-
datasets := make([]map[string]string, len(input.DatasetURNs))
128-
for i, urn := range input.DatasetURNs {
129-
datasets[i] = map[string]string{"datasetUrn": urn}
130-
}
131-
gqlInput["subjects"] = map[string]any{
132-
"datasets": datasets,
133-
}
121+
subjects := make([]map[string]string, len(input.DatasetURNs))
122+
for i, urn := range input.DatasetURNs {
123+
subjects[i] = map[string]string{"datasetUrn": urn}
134124
}
125+
gqlInput["subjects"] = subjects
135126

136127
variables := map[string]any{"input": gqlInput}
137128

@@ -178,13 +169,11 @@ func (c *Client) UpdateQuery(ctx context.Context, input UpdateQueryInput) (*type
178169
}
179170

180171
if input.DatasetURNs != nil {
181-
datasets := make([]map[string]string, len(input.DatasetURNs))
172+
subjects := make([]map[string]string, len(input.DatasetURNs))
182173
for i, urn := range input.DatasetURNs {
183-
datasets[i] = map[string]string{"datasetUrn": urn}
184-
}
185-
gqlInput["subjects"] = map[string]any{
186-
"datasets": datasets,
174+
subjects[i] = map[string]string{"datasetUrn": urn}
187175
}
176+
gqlInput["subjects"] = subjects
188177
}
189178

190179
variables := map[string]any{

pkg/client/write_queries_test.go

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -81,21 +81,27 @@ func TestCreateQuery_WithDatasetURNs(t *testing.T) {
8181
t.Fatalf("failed to decode request: %v", err)
8282
}
8383

84-
// Verify subjects are passed through
84+
// Verify subjects are passed as a flat array
8585
inputRaw, ok := req.Variables["input"].(map[string]any)
8686
if !ok {
8787
t.Fatal("expected input variable")
8888
}
89-
subjects, ok := inputRaw["subjects"].(map[string]any)
89+
subjects, ok := inputRaw["subjects"].([]any)
9090
if !ok {
91-
t.Fatal("expected subjects in input")
91+
t.Fatalf("expected subjects as array in input, got %T", inputRaw["subjects"])
9292
}
93-
datasets, ok := subjects["datasets"].([]any)
94-
if !ok {
95-
t.Fatal("expected datasets in subjects")
93+
if len(subjects) != 2 {
94+
t.Errorf("expected 2 subjects, got %d", len(subjects))
9695
}
97-
if len(datasets) != 2 {
98-
t.Errorf("expected 2 datasets, got %d", len(datasets))
96+
// Verify each subject has datasetUrn
97+
for i, s := range subjects {
98+
subj, ok := s.(map[string]any)
99+
if !ok {
100+
t.Fatalf("subject[%d]: expected map, got %T", i, s)
101+
}
102+
if _, ok := subj["datasetUrn"]; !ok {
103+
t.Errorf("subject[%d]: missing datasetUrn field", i)
104+
}
99105
}
100106

101107
resp := `{
@@ -270,16 +276,12 @@ func TestUpdateQuery_WithDatasetURNs(t *testing.T) {
270276
if !ok {
271277
t.Fatal("expected input variable")
272278
}
273-
subjects, ok := inputRaw["subjects"].(map[string]any)
274-
if !ok {
275-
t.Fatal("expected subjects in input")
276-
}
277-
datasets, ok := subjects["datasets"].([]any)
279+
subjects, ok := inputRaw["subjects"].([]any)
278280
if !ok {
279-
t.Fatal("expected datasets in subjects")
281+
t.Fatalf("expected subjects as array in input, got %T", inputRaw["subjects"])
280282
}
281-
if len(datasets) != 1 {
282-
t.Errorf("expected 1 dataset, got %d", len(datasets))
283+
if len(subjects) != 1 {
284+
t.Errorf("expected 1 subject, got %d", len(subjects))
283285
}
284286

285287
resp := `{"data":{"updateQuery":{"urn":"urn:li:query:abc123",` +

0 commit comments

Comments
 (0)