Skip to content

Commit

Permalink
Fix planner when same type presented in multiple schemas but is not i…
Browse files Browse the repository at this point in the history
…mplements node
  • Loading branch information
Sergey Kananykhin committed Oct 6, 2023
1 parent 3ffae58 commit 6dde102
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 3 deletions.
12 changes: 12 additions & 0 deletions planner/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,18 @@ func (pc *PlanningContext) GetURL(typename, fieldname, fburl string) (string, er
if common.IsBuiltinName(fieldname) {
return fburl, nil
}

isImplementsNode, ok := pc.TypeURLMap.GetTypeIsImplementsNode(typename)
if !ok {
return "", fmt.Errorf("could not find location type %s", typename)
}

// return fallback url if typename is not root and not implements node
// it's required to do so for types which declared in multiple services
if !isImplementsNode && fburl != common.InternalServiceName && !common.IsRootObjectName(typename) {
return fburl, nil
}

url, ok := pc.TypeURLMap.Get(typename, fieldname)
if !ok {
return "", fmt.Errorf("could not find location for field %s of type %s", fieldname, typename)
Expand Down
26 changes: 26 additions & 0 deletions planner/fixtures_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,32 @@ var simpleTum = merger.TypeURLMap{
},
}

var sameTypeDifferentURLsSchema = `
type Human {
name: String!
}
type Query {
getHumans: [Human!]!
getAliens: [Human!]!
}
`

var sameTypeDifferentURLsTum = merger.TypeURLMap{
"Query": {
Fields: map[string]string{
"getHumans": "0",
"getAliens": "1",
},
},
"Human": {
Fields: map[string]string{
"name": "1",
},
IsImplementsNode: false,
},
}

var unionSchema = `
interface Node {
id: ID!
Expand Down
5 changes: 2 additions & 3 deletions planner/sanitize_selection_set.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ func sanitizeInterfaceInlineFragment(ctx *PlanningContext, selectionSet ast.Sele
func setMissingScrubFieldsForFieldSelectionSet(ctx *PlanningContext, insertionPoint []string, field *ast.Field, scrubFields ScrubFields, addedFields []string) ScrubFields {
for _, f := range addedFields {
path := append(insertionPoint, field.Alias)
if t, _ := ctx.Schema.Types[field.Definition.Type.Name()]; t != nil && (t.Kind == ast.Interface || t.Kind == ast.Union) {
if t := ctx.Schema.Types[field.Definition.Type.Name()]; t != nil && (t.Kind == ast.Interface || t.Kind == ast.Union) {
for _, pt := range ctx.Schema.PossibleTypes[t.Name] {
scrubFields.Set(path, pt.Name, f)
}
Expand All @@ -123,7 +123,7 @@ func addScrubFieldsToSelectionSet(ctx *PlanningContext, selectionSet ast.Selecti
var addedFields []string
var isImplementsNode bool

if t, _ := ctx.Schema.Types[fieldname]; t != nil && (t.Kind == ast.Interface || t.Kind == ast.Union) {
if t := ctx.Schema.Types[fieldname]; t != nil && (t.Kind == ast.Interface || t.Kind == ast.Union) {
pt := ctx.Schema.PossibleTypes[fieldname]
if !isContainsField(selectionSet, common.TypenameFieldName) {
selectionSet = addTypenameFieldToSelectionSet(selectionSet)
Expand All @@ -135,7 +135,6 @@ func addScrubFieldsToSelectionSet(ctx *PlanningContext, selectionSet ast.Selecti
isImplementsNode, _ = ctx.TypeURLMap.GetTypeIsImplementsNode(pt[0].Name)

isImplementsNode = isImplementsNode && fd != nil

} else {
isImplementsNode, _ = ctx.TypeURLMap.GetTypeIsImplementsNode(fieldname)
}
Expand Down
22 changes: 22 additions & 0 deletions planner/sequential_planner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,28 @@ func TestSimplePlanSpreadFragmentManyUsages(t *testing.T) {
assert.JSONEq(t, expected, actual)
}

func TestSameTypeDifferentURLsPlan(t *testing.T) {
query := `{ getHumans { name }}`

actual, _ := mustRunPlanner(t, seqPlan, sameTypeDifferentURLsSchema, query, sameTypeDifferentURLsTum)

expected := `{
"RootSteps": [
{
"URL": "0",
"ParentType": "Query",
"OperationName": null,
"SelectionSet": "{ getHumans { name } }",
"InsertionPoint": null,
"Then": null
}
],
"ScrubFields": null
}`

assert.JSONEq(t, expected, actual)
}

func TestDeepPlan(t *testing.T) {
query := `{ getAnimals { __typename id name species {__typename id name genus {__typename id name}} }}`

Expand Down

0 comments on commit 6dde102

Please sign in to comment.