Skip to content

Commit

Permalink
Merge pull request #117 from lucianjon/null-boundary-results
Browse files Browse the repository at this point in the history
Filter out null boundary results before calling nested child step
  • Loading branch information
Lucian Jones authored Dec 20, 2021
2 parents c69e57f + 9d7b09a commit cedb672
Show file tree
Hide file tree
Showing 2 changed files with 250 additions and 3 deletions.
233 changes: 233 additions & 0 deletions execution_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1479,6 +1479,239 @@ func TestTrimInsertionPointForNestedBoundaryQuery(t *testing.T) {
require.Equal(t, expected, result)
}

func TestNestingNullableBoundaryTypes(t *testing.T) {
t.Run("nested boundary types are all null", func(t *testing.T) {
f := &queryExecutionFixture{
services: []testService{
{
schema: `directive @boundary on OBJECT | FIELD_DEFINITION
type Gizmo @boundary {
id: ID!
}
type Query {
tastyGizmos: [Gizmo!]!
gizmo(ids: [ID!]!): [Gizmo]! @boundary
}`,
handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(`
{
"data": {
"tastyGizmos": [
{
"_bramble_id": "beehasknees",
"id": "beehasknees"
},
{
"_bramble_id": "umlaut",
"id": "umlaut"
},
{
"_bramble_id": "probanana",
"id": "probanana"
}
]
}
}
`))
}),
},
{
schema: `directive @boundary on OBJECT | FIELD_DEFINITION
type Gizmo @boundary {
id: ID!
wizzle: Wizzle
}
type Wizzle @boundary {
id: ID!
}
type Query {
wizzles(ids: [ID!]): [Wizzle]! @boundary
gizmo(ids: [ID!]): [Gizmo]! @boundary
}`,
handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(`{
"data": {
"_result": [null, null, null]
}
}`))
}),
},
{
schema: `directive @boundary on OBJECT | FIELD_DEFINITION
type Wizzle @boundary {
id: ID!
bazingaFactor: Int
}
type Query {
wizzles(ids: [ID!]): [Wizzle]! @boundary
}`,
handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(`should not be called...`))
}),
},
},

query: `{
tastyGizmos {
id
wizzle {
id
bazingaFactor
}
}
}`,
expected: `{
"tastyGizmos": [
{
"id": "beehasknees",
"wizzle": null
},
{
"id": "umlaut",
"wizzle": null
},
{
"id": "probanana",
"wizzle": null
}
]
}`,
}

f.checkSuccess(t)
})

t.Run("nested boundary types sometimes null", func(t *testing.T) {
f := &queryExecutionFixture{
services: []testService{
{
schema: `directive @boundary on OBJECT | FIELD_DEFINITION
type Gizmo @boundary {
id: ID!
}
type Query {
tastyGizmos: [Gizmo!]!
gizmo(ids: [ID!]!): [Gizmo]! @boundary
}`,
handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(`
{
"data": {
"tastyGizmos": [
{
"_bramble_id": "beehasknees",
"id": "beehasknees"
},
{
"_bramble_id": "umlaut",
"id": "umlaut"
},
{
"_bramble_id": "probanana",
"id": "probanana"
}
]
}
}
`))
}),
},
{
schema: `directive @boundary on OBJECT | FIELD_DEFINITION
type Gizmo @boundary {
id: ID!
wizzle: Wizzle
}
type Wizzle @boundary {
id: ID!
}
type Query {
wizzles(ids: [ID!]): [Wizzle]! @boundary
gizmos(ids: [ID!]): [Gizmo]! @boundary
}`,
handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(`{
"data": {
"_result": [
null,
{
"_bramble_id": "umlaut",
"id": "umlaut",
"wizzle": null
},
{
"_bramble_id": "probanana",
"id": "probanana",
"wizzle": {
"_bramble_id": "bananawizzle",
"id": "bananawizzle"
}
}
]
}
}`))
}),
},
{
schema: `directive @boundary on OBJECT | FIELD_DEFINITION
type Wizzle @boundary {
id: ID!
bazingaFactor: Int
}
type Query {
wizzles(ids: [ID!]): [Wizzle]! @boundary
}`,
handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(`{
"data": {
"_result": [
{
"_bramble_id": "bananawizzle",
"id": "bananawizzle",
"bazingaFactor": 4
}
]
}
}`))
}),
},
},

query: `{
tastyGizmos {
id
wizzle {
id
bazingaFactor
}
}
}`,
expected: `{
"tastyGizmos": [
{
"id": "beehasknees",
"wizzle": null
},
{
"id": "umlaut",
"wizzle": null
},
{
"id": "probanana",
"wizzle": {
"id": "bananawizzle",
"bazingaFactor": 4
}
}
]
}`,
}

f.checkSuccess(t)
})

}

func TestBuildBoundaryQueryDocuments(t *testing.T) {
ddl := `
type Gizmo {
Expand Down
20 changes: 17 additions & 3 deletions query_execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,13 +172,15 @@ func (q *queryExecution) executeChildStep(step *QueryPlanStep, boundaryIDs []str

q.writeExecutionResult(step, data, nil)

if len(data) > 0 {
nonNillBoundaryResults := extractNonNilBoundaryResults(data)

if len(nonNillBoundaryResults) > 0 {
for _, childStep := range step.Then {
boundaryResultInsertionPoint, err := trimInsertionPointForNestedBoundaryStep(data, childStep.InsertionPoint)
boundaryResultInsertionPoint, err := trimInsertionPointForNestedBoundaryStep(nonNillBoundaryResults, childStep.InsertionPoint)
if err != nil {
return err
}
boundaryIDs, err := extractAndDedupeBoundaryIDs(data, boundaryResultInsertionPoint)
boundaryIDs, err := extractAndDedupeBoundaryIDs(nonNillBoundaryResults, boundaryResultInsertionPoint)
if err != nil {
return err
}
Expand All @@ -195,6 +197,18 @@ func (q *queryExecution) executeChildStep(step *QueryPlanStep, boundaryIDs []str
return nil
}

func extractNonNilBoundaryResults(data []interface{}) []interface{} {
var nonNilResults []interface{}
for _, d := range data {
if d != nil {
nonNilResults = append(nonNilResults, d)
}

}

return nonNilResults
}

func (q *queryExecution) executeBoundaryQuery(documents []string, serviceURL string, boundaryFieldGetter BoundaryField) ([]interface{}, error) {
output := make([]interface{}, 0)
if !boundaryFieldGetter.Array {
Expand Down

0 comments on commit cedb672

Please sign in to comment.