Skip to content

Commit fcfcbc3

Browse files
authored
Merge branch 'master' into fix-panic-blockstring
2 parents aafb74e + c13c47a commit fcfcbc3

File tree

6 files changed

+323
-223
lines changed

6 files changed

+323
-223
lines changed

executor.go

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ func Execute(p ExecuteParams) (result *Result) {
3636
go func(out chan<- *Result, done <-chan struct{}) {
3737
defer func() {
3838
if err := recover(); err != nil {
39-
result.Errors = append(result.Errors, gqlerrors.FormatError(err.(error)))
39+
result.AppendErrors(gqlerrors.FormatError(err.(error)))
4040
}
4141
select {
4242
case out <- result:
@@ -54,7 +54,7 @@ func Execute(p ExecuteParams) (result *Result) {
5454
})
5555

5656
if err != nil {
57-
result.Errors = append(result.Errors, gqlerrors.FormatError(err))
57+
result.AppendErrors(gqlerrors.FormatError(err))
5858
return
5959
}
6060

@@ -67,7 +67,7 @@ func Execute(p ExecuteParams) (result *Result) {
6767

6868
select {
6969
case <-ctx.Done():
70-
result.Errors = append(result.Errors, gqlerrors.FormatError(ctx.Err()))
70+
result.AppendErrors(gqlerrors.FormatError(ctx.Err()))
7171
case r := <-resultChannel:
7272
result = r
7373
}
@@ -175,15 +175,15 @@ func executeOperation(p executeOperationParams) *Result {
175175
// Extracts the root type of the operation from the schema.
176176
func getOperationRootType(schema Schema, operation ast.Definition) (*Object, error) {
177177
if operation == nil {
178-
return nil, errors.New("Can only execute queries and mutations")
178+
return nil, errors.New("Can only execute queries, mutations and subscription")
179179
}
180180

181181
switch operation.GetOperation() {
182182
case ast.OperationTypeQuery:
183183
return schema.QueryType(), nil
184184
case ast.OperationTypeMutation:
185185
mutationType := schema.MutationType()
186-
if mutationType.PrivateName == "" {
186+
if mutationType == nil || mutationType.PrivateName == "" {
187187
return nil, gqlerrors.NewError(
188188
"Schema is not configured for mutations",
189189
[]ast.Node{operation},
@@ -196,7 +196,7 @@ func getOperationRootType(schema Schema, operation ast.Definition) (*Object, err
196196
return mutationType, nil
197197
case ast.OperationTypeSubscription:
198198
subscriptionType := schema.SubscriptionType()
199-
if subscriptionType.PrivateName == "" {
199+
if subscriptionType == nil || subscriptionType.PrivateName == "" {
200200
return nil, gqlerrors.NewError(
201201
"Schema is not configured for subscriptions",
202202
[]ast.Node{operation},
@@ -964,6 +964,22 @@ func DefaultResolveFn(p ResolveParams) (interface{}, error) {
964964
return property, nil
965965
}
966966

967+
// Try accessing as map via reflection
968+
if r := reflect.ValueOf(p.Source); r.Kind() == reflect.Map && r.Type().Key().Kind() == reflect.String {
969+
val := r.MapIndex(reflect.ValueOf(p.Info.FieldName))
970+
if val.IsValid() {
971+
property := val.Interface()
972+
if val.Type().Kind() == reflect.Func {
973+
// try type casting the func to the most basic func signature
974+
// for more complex signatures, user have to define ResolveFn
975+
if propertyFn, ok := property.(func() interface{}); ok {
976+
return propertyFn(), nil
977+
}
978+
}
979+
return property, nil
980+
}
981+
}
982+
967983
// last resort, return nil
968984
return nil, nil
969985
}

executor_test.go

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,62 @@ func TestMergesParallelFragments(t *testing.T) {
297297
}
298298
}
299299

300+
type CustomMap map[string]interface{}
301+
302+
func TestCustomMapType(t *testing.T) {
303+
query := `
304+
query Example { data { a } }
305+
`
306+
data := CustomMap{
307+
"a": "1",
308+
"b": "2",
309+
}
310+
schema, err := graphql.NewSchema(graphql.SchemaConfig{
311+
Query: graphql.NewObject(graphql.ObjectConfig{
312+
Name: "RootQuery",
313+
Fields: graphql.Fields{
314+
"data": &graphql.Field{
315+
Type: graphql.NewObject(graphql.ObjectConfig{
316+
Name: "Data",
317+
Fields: graphql.Fields{
318+
"a": &graphql.Field{
319+
Type: graphql.String,
320+
},
321+
"b": &graphql.Field{
322+
Type: graphql.String,
323+
},
324+
},
325+
}),
326+
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
327+
return data, nil
328+
},
329+
},
330+
},
331+
}),
332+
})
333+
if err != nil {
334+
t.Fatalf("Error in schema %v", err.Error())
335+
}
336+
337+
result := testutil.TestExecute(t, graphql.ExecuteParams{
338+
Schema: schema,
339+
Root: data,
340+
AST: testutil.TestParse(t, query),
341+
})
342+
if len(result.Errors) > 0 {
343+
t.Fatalf("wrong result, unexpected errors: %v", result.Errors)
344+
}
345+
346+
expected := map[string]interface{}{
347+
"data": map[string]interface{}{
348+
"a": "1",
349+
},
350+
}
351+
if !reflect.DeepEqual(result.Data, expected) {
352+
t.Fatalf("Expected context.key to equal %v, got %v", expected, result.Data)
353+
}
354+
}
355+
300356
func TestThreadsSourceCorrectly(t *testing.T) {
301357

302358
query := `
@@ -843,6 +899,57 @@ func TestThrowsIfUnknownOperationNameIsProvided(t *testing.T) {
843899
t.Fatalf("unexpected result, Diff: %v", testutil.Diff(expectedErrors, result.Errors))
844900
}
845901
}
902+
903+
func TestThrowsIfOperationTypeIsUnsupported(t *testing.T) {
904+
query := `mutation Mut { a } subscription Sub { a }`
905+
operations := []string{"Mut", "Sub"}
906+
907+
expectedErrors := [][]gqlerrors.FormattedError{
908+
{{
909+
Message: `Schema is not configured for mutations`,
910+
Locations: []location.SourceLocation{{Line: 1, Column: 1}},
911+
}},
912+
{{
913+
Message: `Schema is not configured for subscriptions`,
914+
Locations: []location.SourceLocation{{Line: 1, Column: 20}},
915+
}},
916+
}
917+
918+
schema, err := graphql.NewSchema(graphql.SchemaConfig{
919+
Query: graphql.NewObject(graphql.ObjectConfig{
920+
Name: "Query",
921+
Fields: graphql.Fields{
922+
"a": &graphql.Field{
923+
Type: graphql.String,
924+
},
925+
},
926+
}),
927+
})
928+
if err != nil {
929+
t.Fatalf("Error in schema %v", err.Error())
930+
}
931+
932+
// parse query
933+
ast := testutil.TestParse(t, query)
934+
935+
for opIndex, operation := range operations {
936+
expectedErrors := expectedErrors[opIndex]
937+
938+
// execute
939+
ep := graphql.ExecuteParams{
940+
Schema: schema,
941+
AST: ast,
942+
OperationName: operation,
943+
}
944+
result := testutil.TestExecute(t, ep)
945+
if result.Data != nil {
946+
t.Fatalf("wrong result, expected nil result.Data, got %v", result.Data)
947+
}
948+
if !testutil.EqualFormattedErrors(expectedErrors, result.Errors) {
949+
t.Fatalf("unexpected result, Diff: %v", testutil.Diff(expectedErrors, result.Errors))
950+
}
951+
}
952+
}
846953
func TestUsesTheQuerySchemaForQueries(t *testing.T) {
847954

848955
doc := `query Q { a } mutation M { c } subscription S { a }`

0 commit comments

Comments
 (0)