From b94f2afe22033bcb4b1a68d64adab00986abeea4 Mon Sep 17 00:00:00 2001 From: Richard Musiol Date: Mon, 21 Nov 2016 12:43:28 +0100 Subject: [PATCH] improved support for null --- graphql_test.go | 9 +++++++++ internal/common/values.go | 2 ++ internal/exec/exec.go | 5 ++++- internal/exec/packer.go | 19 ++++++++++++------- 4 files changed, 27 insertions(+), 8 deletions(-) diff --git a/graphql_test.go b/graphql_test.go index 6db8880da1..2e17ef3f61 100644 --- a/graphql_test.go +++ b/graphql_test.go @@ -1258,6 +1258,10 @@ func (r *inputResolver) Boolean(args *struct{ Value bool }) bool { return args.Value } +func (r *inputResolver) Nullable(args *struct{ Value *int32 }) *int32 { + return args.Value +} + func (r *inputResolver) List(args *struct{ Value []*struct{ V int32 } }) []int32 { l := make([]int32, len(args.Value)) for i, entry := range args.Value { @@ -1277,6 +1281,7 @@ func TestInput(t *testing.T) { float(value: Float!): Float! string(value: String!): String! boolean(value: Boolean!): Boolean! + nullable(value: Int): Int list(value: [Input!]!): [Int!]! } @@ -1295,6 +1300,8 @@ func TestInput(t *testing.T) { float2: float(value: 42.5) string(value: "foo") boolean(value: true) + nullable1: nullable(value: 42) + nullable2: nullable(value: null) list(value: [{v: 41}, {v: 42}, {v: 43}]) } `, @@ -1306,6 +1313,8 @@ func TestInput(t *testing.T) { "float2": 42.5, "string": "foo", "boolean": true, + "nullable1": 42, + "nullable2": null, "list": [41, 42, 43] } `, diff --git a/internal/common/values.go b/internal/common/values.go index f1ad2bd679..4b871464f2 100644 --- a/internal/common/values.go +++ b/internal/common/values.go @@ -54,6 +54,8 @@ func ParseValue(l *lexer.Lexer, constOnly bool) interface{} { return true case "false": return false + case "null": + return nil default: return ident } diff --git a/internal/exec/exec.go b/internal/exec/exec.go index f7b17c62dc..f805081c94 100644 --- a/internal/exec/exec.go +++ b/internal/exec/exec.go @@ -632,7 +632,10 @@ func coerceValue(r *request, typ common.Type, value interface{}) (interface{}, e return r.vars[string(v)], nil } - t, _ := unwrapNonNull(typ) + t, nonNull := unwrapNonNull(typ) + if !nonNull && value == nil { + return nil, nil + } switch t := t.(type) { case *scalar: v, err := t.coerceInput(value) diff --git a/internal/exec/packer.go b/internal/exec/packer.go index f03720990f..bc097edf1a 100644 --- a/internal/exec/packer.go +++ b/internal/exec/packer.go @@ -28,7 +28,8 @@ func makePacker(s *schema.Schema, schemaType common.Type, hasDefault bool, refle return nil, fmt.Errorf("wrong type, expected %s", want) } return &valuePacker{ - nonNull: nonNull, + valueType: reflectType, + nonNull: nonNull, }, nil case *schema.Enum: want := reflect.TypeOf("") @@ -39,7 +40,8 @@ func makePacker(s *schema.Schema, schemaType common.Type, hasDefault bool, refle return nil, fmt.Errorf("wrong type, expected %s", want) } return &valuePacker{ - nonNull: nonNull, + valueType: reflectType, + nonNull: nonNull, }, nil case *schema.InputObject: e, err := makeStructPacker(s, &t.InputMap, reflectType) @@ -150,15 +152,18 @@ func (e *listPacker) pack(value interface{}) reflect.Value { } type valuePacker struct { - nonNull bool + valueType reflect.Type + nonNull bool } func (p *valuePacker) pack(value interface{}) reflect.Value { - v := reflect.ValueOf(value) if !p.nonNull { - ptr := reflect.New(v.Type()) - ptr.Elem().Set(v) + if value == nil { + return reflect.Zero(p.valueType) + } + ptr := reflect.New(p.valueType.Elem()) + ptr.Elem().Set(reflect.ValueOf(value)) return ptr } - return v + return reflect.ValueOf(value) }