Skip to content

Commit

Permalink
Merge pull request #153 from movio/issue-151
Browse files Browse the repository at this point in the history
Fix fragment spread elimination during result merge + format
  • Loading branch information
Lucian Jones authored Apr 28, 2022
2 parents 6cfb4cd + 9e0455f commit 10f30a5
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 5 deletions.
2 changes: 1 addition & 1 deletion execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -690,7 +690,7 @@ func (s *ExecutableSchema) evaluateSkipAndIncludeRec(vars map[string]interface{}
Name: selection.Name,
Directives: removeSkipAndInclude(selection.Directives),
Position: selection.Position,
ObjectDefinition: selection.Definition.Definition,
ObjectDefinition: selection.ObjectDefinition,
Definition: &ast.FragmentDefinition{
Name: selection.Definition.Name,
VariableDefinition: selection.Definition.VariableDefinition,
Expand Down
53 changes: 53 additions & 0 deletions execution_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -984,6 +984,59 @@ func TestFederatedQueryFragmentSpreads(t *testing.T) {
f.checkSuccess(t)
})

t.Run("with multiple top level fragment spreads (gadget implementation)", func(t *testing.T) {
f := &queryExecutionFixture{
services: []testService{serviceA, serviceB},
query: `
query Foo {
snapshot(id: "GADGET1") {
id
name
... GadgetFragment
... GizmoFragment
}
}
fragment GadgetFragment on GadgetImplementation {
gadgets {
id
name
agents {
name
... on Agent {
country
}
}
}
}
fragment GizmoFragment on GizmoImplementation {
gizmos {
id
name
}
}`,
expected: `
{
"snapshot": {
"id": "100",
"name": "foo",
"gadgets": [
{
"id": "GADGET1",
"name": "Gadget #1",
"agents": [
{"name": "James Bond", "country": "UK"}
]
}
]
}
}`,
}

f.checkSuccess(t)
})

}

func TestQueryExecutionMultipleServices(t *testing.T) {
Expand Down
19 changes: 15 additions & 4 deletions query_execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -843,7 +843,7 @@ func unionAndTrimSelectionSetRec(objectTypename string, schema *ast.Schema, sele
fragment := selection
if fragment.ObjectDefinition.IsAbstractType() &&
fragmentImplementsAbstractType(schema, fragment.ObjectDefinition.Name, fragment.TypeCondition) &&
objectTypenameMatchesDifferentFragment(objectTypename, fragment) {
objectTypenameMatchesDifferentFragment(objectTypename, fragment.TypeCondition) {
continue
}

Expand All @@ -853,7 +853,18 @@ func unionAndTrimSelectionSetRec(objectTypename string, schema *ast.Schema, sele
filteredSelectionSet = append(filteredSelectionSet, selection)
}
case *ast.FragmentSpread:
filteredSelectionSet = append(filteredSelectionSet, selection)
fragment := selection
if fragment.ObjectDefinition.IsAbstractType() &&
fragmentImplementsAbstractType(schema, fragment.ObjectDefinition.Name, fragment.Definition.TypeCondition) &&
objectTypenameMatchesDifferentFragment(objectTypename, fragment.Definition.TypeCondition) {
continue
}

filteredSelections := unionAndTrimSelectionSetRec(objectTypename, schema, fragment.Definition.SelectionSet, seenFields)
if len(filteredSelections) > 0 {
fragment.Definition.SelectionSet = filteredSelections
filteredSelectionSet = append(filteredSelectionSet, selection)
}
}
}

Expand All @@ -869,6 +880,6 @@ func extractAndCastTypenameField(result map[string]interface{}) string {
return typeNameInterface.(string)
}

func objectTypenameMatchesDifferentFragment(typename string, fragment *ast.InlineFragment) bool {
return fragment.TypeCondition != typename
func objectTypenameMatchesDifferentFragment(typename, fragmentTypeCondition string) bool {
return fragmentTypeCondition != typename
}

0 comments on commit 10f30a5

Please sign in to comment.