From 72df5bc1587f7ff15a6edf6b955ec48f7aaff982 Mon Sep 17 00:00:00 2001 From: Arijit Das Date: Thu, 17 Sep 2020 11:55:42 +0530 Subject: [PATCH 01/20] Add support for Geo point type in Graphql. --- graphql/schema/dgraph_schemagen_test.yml | 17 +- graphql/schema/gqlschema.go | 23 ++ graphql/schema/rules.go | 9 +- graphql/schema/schemagen.go | 7 +- graphql/schema/schemagen_test.go | 3 + .../testdata/schemagen/input/geo-type.graphql | 5 + .../schemagen/output/geo-type.graphql | 258 ++++++++++++++++++ 7 files changed, 319 insertions(+), 3 deletions(-) create mode 100644 graphql/schema/testdata/schemagen/input/geo-type.graphql create mode 100644 graphql/schema/testdata/schemagen/output/geo-type.graphql diff --git a/graphql/schema/dgraph_schemagen_test.yml b/graphql/schema/dgraph_schemagen_test.yml index 2eb40116b60..ca9f8b685c7 100644 --- a/graphql/schema/dgraph_schemagen_test.yml +++ b/graphql/schema/dgraph_schemagen_test.yml @@ -606,4 +606,19 @@ schemas: url: "http://mock:8888/users", method: "POST" }) - } \ No newline at end of file + } + + - name: "geo type." + input: | + type Hotel { + id: ID! + name: String! + location: Point @search + } + output: | + type Hotel { + Hotel.name + Hotel.location + } + Hotel.name: string . + Hotel.location: geo @index(geo) . diff --git a/graphql/schema/gqlschema.go b/graphql/schema/gqlschema.go index 2e262cf2b47..02c95b9fe5c 100644 --- a/graphql/schema/gqlschema.go +++ b/graphql/schema/gqlschema.go @@ -89,6 +89,7 @@ enum DgraphIndex { month day hour + geo } input AuthRule { @@ -123,6 +124,25 @@ input CustomHTTP { skipIntrospection: Boolean } +type Point { + Latitude: Float! + Longitude: Float! +} + +input PointInput { + Latitude: Float! + Longitude: Float! +} + +input NearFilter { + Distance: Float! + Coordinate: PointInput! +} + +input PointGeoFilter { + near: NearFilter +} + directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION @@ -244,6 +264,7 @@ var supportedSearches = map[string]searchTypeIndex{ "month": {"DateTime", "month"}, "day": {"DateTime", "day"}, "hour": {"DateTime", "hour"}, + "geo": {"Point", "geo"}, } // GraphQL scalar type -> default search arg @@ -255,6 +276,7 @@ var defaultSearches = map[string]string{ "Float": "float", "String": "term", "DateTime": "year", + "Point": "geo", } // graphqlSpecScalars holds all the scalar types supported by the graphql spec. @@ -305,6 +327,7 @@ var builtInFilters = map[string]string{ "fulltext": "StringFullTextFilter", "exact": "StringExactFilter", "hash": "StringHashFilter", + "geo": "PointGeoFilter", } // GraphQL scalar -> Dgraph scalar diff --git a/graphql/schema/rules.go b/graphql/schema/rules.go index 598dd47af64..77fed63bd51 100644 --- a/graphql/schema/rules.go +++ b/graphql/schema/rules.go @@ -948,6 +948,13 @@ func validateSearchArg(searchArg string, return nil } +func isGeoType(typ *ast.Type) bool { + if typ.Name() == "Point" { + return true + } + return false +} + func searchValidation( sch *ast.Schema, typ *ast.Definition, @@ -961,7 +968,7 @@ func searchValidation( // If there's no arg, then it can be an enum or has to be a scalar that's // not ID. The schema generation will add the default search // for that type. - if sch.Types[field.Type.Name()].Kind == ast.Enum || + if sch.Types[field.Type.Name()].Kind == ast.Enum || isGeoType(field.Type) || (sch.Types[field.Type.Name()].Kind == ast.Scalar && !isIDField(typ, field)) { return nil } diff --git a/graphql/schema/schemagen.go b/graphql/schema/schemagen.go index 5213a88ab2e..c0774f5b21f 100644 --- a/graphql/schema/schemagen.go +++ b/graphql/schema/schemagen.go @@ -438,7 +438,12 @@ func genDgSchema(gqlSch *ast.Schema, definitions []string) string { var typStr string switch gqlSch.Types[f.Type.Name()].Kind { case ast.Object, ast.Interface: - typStr = fmt.Sprintf("%suid%s", prefix, suffix) + if isGeoType(f.Type) { + typStr = "geo" + dgPreds[fname] = getUpdatedPred(fname, typStr, "", []string{"geo"}) + } else { + typStr = fmt.Sprintf("%suid%s", prefix, suffix) + } if parentInt == nil { if strings.HasPrefix(fname, "~") { diff --git a/graphql/schema/schemagen_test.go b/graphql/schema/schemagen_test.go index 914eae7a69e..bc3693a40e0 100644 --- a/graphql/schema/schemagen_test.go +++ b/graphql/schema/schemagen_test.go @@ -77,6 +77,9 @@ func TestSchemaString(t *testing.T) { for _, testFile := range files { t.Run(testFile.Name(), func(t *testing.T) { inputFileName := inputDir + testFile.Name() + if testFile.Name() != "geo-type.graphql" { + return + } str1, err := ioutil.ReadFile(inputFileName) require.NoError(t, err) diff --git a/graphql/schema/testdata/schemagen/input/geo-type.graphql b/graphql/schema/testdata/schemagen/input/geo-type.graphql new file mode 100644 index 00000000000..43000613526 --- /dev/null +++ b/graphql/schema/testdata/schemagen/input/geo-type.graphql @@ -0,0 +1,5 @@ +type Hotel { + id: ID! + name: String! + location: Point @search +} \ No newline at end of file diff --git a/graphql/schema/testdata/schemagen/output/geo-type.graphql b/graphql/schema/testdata/schemagen/output/geo-type.graphql new file mode 100644 index 00000000000..61716fbe121 --- /dev/null +++ b/graphql/schema/testdata/schemagen/output/geo-type.graphql @@ -0,0 +1,258 @@ +####################### +# Input Schema +####################### + +type Hotel { + id: ID! + name: String! + location: Point @search +} + +####################### +# Extended Definitions +####################### + +""" +The Int64 scalar type represents a signed 64‐bit numeric non‐fractional value. +Int64 can represent values in range [-(2^63),(2^63 - 1)]. +""" +scalar Int64 + +""" +The DateTime scalar type represents date and time as a string in RFC3339 format. +For example: "1985-04-12T23:20:50.52Z" represents 20 minutes and 50.52 seconds after the 23rd hour of April 12th, 1985 in UTC. +""" +scalar DateTime + +enum DgraphIndex { + int + int64 + float + bool + hash + exact + term + fulltext + trigram + regexp + year + month + day + hour + geo +} + +input AuthRule { + and: [AuthRule] + or: [AuthRule] + not: AuthRule + rule: String +} + +enum HTTPMethod { + GET + POST + PUT + PATCH + DELETE +} + +enum Mode { + BATCH + SINGLE +} + +input CustomHTTP { + url: String! + method: HTTPMethod! + body: String + graphql: String + mode: Mode + forwardHeaders: [String!] + secretHeaders: [String!] + introspectionHeaders: [String!] + skipIntrospection: Boolean +} + +type Point { + Latitude: Float! + Longitude: Float! +} + +input PointInput { + Latitude: Float! + Longitude: Float! +} + +input NearFilter { + Distance: Float! + Coordinate: PointInput! +} + +input PointGeoFilter { + near: NearFilter +} + +directive @hasInverse(field: String!) on FIELD_DEFINITION +directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION +directive @id on FIELD_DEFINITION +directive @withSubscription on OBJECT | INTERFACE +directive @secret(field: String!, pred: String) on OBJECT | INTERFACE +directive @auth( + query: AuthRule, + add: AuthRule, + update: AuthRule, + delete:AuthRule) on OBJECT +directive @custom(http: CustomHTTP, dql: String) on FIELD_DEFINITION +directive @remote on OBJECT | INTERFACE +directive @cascade(fields: [String]) on FIELD + +input IntFilter { + eq: Int + le: Int + lt: Int + ge: Int + gt: Int +} + +input Int64Filter { + eq: Int64 + le: Int64 + lt: Int64 + ge: Int64 + gt: Int64 +} + +input FloatFilter { + eq: Float + le: Float + lt: Float + ge: Float + gt: Float +} + +input DateTimeFilter { + eq: DateTime + le: DateTime + lt: DateTime + ge: DateTime + gt: DateTime +} + +input StringTermFilter { + allofterms: String + anyofterms: String +} + +input StringRegExpFilter { + regexp: String +} + +input StringFullTextFilter { + alloftext: String + anyoftext: String +} + +input StringExactFilter { + eq: String + le: String + lt: String + ge: String + gt: String +} + +input StringHashFilter { + eq: String +} + +####################### +# Generated Types +####################### + +type AddHotelPayload { + hotel(filter: HotelFilter, order: HotelOrder, first: Int, offset: Int): [Hotel] + numUids: Int +} + +type DeleteHotelPayload { + hotel(filter: HotelFilter, order: HotelOrder, first: Int, offset: Int): [Hotel] + msg: String + numUids: Int +} + +type UpdateHotelPayload { + hotel(filter: HotelFilter, order: HotelOrder, first: Int, offset: Int): [Hotel] + numUids: Int +} + +####################### +# Generated Enums +####################### + +enum HotelHasFilter { + name + location +} + +enum HotelOrderable { + name +} + +####################### +# Generated Inputs +####################### + +input AddHotelInput { + name: String! +} + +input HotelFilter { + id: [ID!] + location: PointGeoFilter + has: HotelHasFilter + and: HotelFilter + or: HotelFilter + not: HotelFilter +} + +input HotelOrder { + asc: HotelOrderable + desc: HotelOrderable + then: HotelOrder +} + +input HotelPatch { + name: String +} + +input HotelRef { + id: ID + name: String +} + +input UpdateHotelInput { + filter: HotelFilter! + set: HotelPatch + remove: HotelPatch +} + +####################### +# Generated Query +####################### + +type Query { + getHotel(id: ID!): Hotel + queryHotel(filter: HotelFilter, order: HotelOrder, first: Int, offset: Int): [Hotel] +} + +####################### +# Generated Mutations +####################### + +type Mutation { + addHotel(input: [AddHotelInput!]!): AddHotelPayload + updateHotel(input: UpdateHotelInput!): UpdateHotelPayload + deleteHotel(filter: HotelFilter!): DeleteHotelPayload +} + From b2ab70cf95faa7d275f26d2032c58e7e1b683d2d Mon Sep 17 00:00:00 2001 From: Arijit Das Date: Wed, 23 Sep 2020 15:19:48 +0530 Subject: [PATCH 02/20] Query filter. --- graphql/dgraph/graphquery.go | 3 +++ graphql/resolve/query_rewriter.go | 39 ++++++++++++++++++++++++------- graphql/resolve/query_test.go | 3 +++ graphql/resolve/query_test.yaml | 16 +++++++++++++ graphql/resolve/schema.graphql | 6 +++++ graphql/schema/gqlschema.go | 14 +++++------ 6 files changed, 66 insertions(+), 15 deletions(-) diff --git a/graphql/dgraph/graphquery.go b/graphql/dgraph/graphquery.go index 6d54964cbb8..4222677af7c 100644 --- a/graphql/dgraph/graphquery.go +++ b/graphql/dgraph/graphquery.go @@ -155,6 +155,9 @@ func writeFilterFunction(b *strings.Builder, f *gql.Function) { x.Check2(b.WriteString(fmt.Sprintf("%s(%s)", f.Name, f.Args[0].Value))) case len(f.Args) == 2: x.Check2(b.WriteString(fmt.Sprintf("%s(%s, %s)", f.Name, f.Args[0].Value, f.Args[1].Value))) + case len(f.Args) == 3: + x.Check2(b.WriteString(fmt.Sprintf("%s(%s, %s, %s)", f.Name, f.Args[0].Value, f.Args[1].Value, + f.Args[2].Value))) } } diff --git a/graphql/resolve/query_rewriter.go b/graphql/resolve/query_rewriter.go index 3d835af488b..26f82b3723c 100644 --- a/graphql/resolve/query_rewriter.go +++ b/graphql/resolve/query_rewriter.go @@ -1057,15 +1057,38 @@ func buildFilter(typ schema.Type, filter map[string]interface{}) *gql.FilterTree // OR // numLikes: { le: 10 } -> le(Post.numLikes, 10) fn, val := first(dgFunc) - ands = append(ands, &gql.FilterTree{ - Func: &gql.Function{ - Name: fn, - Args: []gql.Arg{ - {Value: typ.DgraphPredicate(field)}, - {Value: maybeQuoteArg(fn, val)}, + switch fn { + case "near": + geoParams := val.(map[string]interface{}) + distance, _ := geoParams["distance"] + + coordinate, _ := geoParams["coordinate"].(map[string]interface{}) + lat, _ := coordinate["latitude"] + long, _ := coordinate["longitude"] + + args := []gql.Arg{ + {Value: typ.DgraphPredicate(field)}, + {Value: fmt.Sprintf("[%v,%v]", long, lat)}, + {Value: fmt.Sprintf("%v", distance)}, + } + + ands = append(ands, &gql.FilterTree{ + Func: &gql.Function{ + Name: fn, + Args: args, }, - }, - }) + }) + default: + ands = append(ands, &gql.FilterTree{ + Func: &gql.Function{ + Name: fn, + Args: []gql.Arg{ + {Value: typ.DgraphPredicate(field)}, + {Value: maybeQuoteArg(fn, val)}, + }, + }, + }) + } case []interface{}: // ids: [ 0x123, 0x124 ] -> uid(0x123, 0x124) ids := convertIDs(dgFunc) diff --git a/graphql/resolve/query_test.go b/graphql/resolve/query_test.go index a20a74dc79d..0c4828a4abb 100644 --- a/graphql/resolve/query_test.go +++ b/graphql/resolve/query_test.go @@ -56,6 +56,9 @@ func TestQueryRewriting(t *testing.T) { for _, tcase := range tests { t.Run(tcase.Name, func(t *testing.T) { + if tcase.Name != "Geo query" { + return + } op, err := gqlSchema.Operation( &schema.Request{ diff --git a/graphql/resolve/query_test.yaml b/graphql/resolve/query_test.yaml index 1eb0bfabe22..9809505e3a6 100644 --- a/graphql/resolve/query_test.yaml +++ b/graphql/resolve/query_test.yaml @@ -1,3 +1,19 @@ +- + name: "Geo query" + gqlquery: | + query { + queryHotel(filter: { location: { near: { distance: 33.33, coordinate: { latitude: 11.11, longitude: 22.22} } } }) { + name + } + } + dgquery: |- + query { + queryHotel(func: type(Hotel))) @filter(near(Hotel.location, [22.22,11.11], 33.33)) { + name : Hotel.name + dgraph.uid : uid + } + } + - name: "ID query" gqlquery: | diff --git a/graphql/resolve/schema.graphql b/graphql/resolve/schema.graphql index f6e131708da..2d467a04457 100644 --- a/graphql/resolve/schema.graphql +++ b/graphql/resolve/schema.graphql @@ -1,6 +1,12 @@ # Test schema that contains an example of everything that's useful to # test for query rewriting. +type Hotel { + id: ID! + name: String! + location: Point @search +} + type Country { id: ID! name: String! @search(by: [trigram, exact]) diff --git a/graphql/schema/gqlschema.go b/graphql/schema/gqlschema.go index 02c95b9fe5c..d13f4da743c 100644 --- a/graphql/schema/gqlschema.go +++ b/graphql/schema/gqlschema.go @@ -125,22 +125,22 @@ input CustomHTTP { } type Point { - Latitude: Float! - Longitude: Float! + latitude: Float! + longitude: Float! } input PointInput { - Latitude: Float! - Longitude: Float! + latitude: Float! + longitude: Float! } input NearFilter { - Distance: Float! - Coordinate: PointInput! + distance: Float! + coordinate: PointInput! } input PointGeoFilter { - near: NearFilter + near: NearFilter! } directive @hasInverse(field: String!) on FIELD_DEFINITION From 8b19ad428ffb04c564a0bc949163d6ba5e90cdd3 Mon Sep 17 00:00:00 2001 From: Arijit Das Date: Fri, 25 Sep 2020 11:04:44 +0530 Subject: [PATCH 03/20] Temp --- graphql/resolve/add_mutation_test.yaml | 33 +++++++++++++++++++ graphql/resolve/mutation_test.go | 3 ++ graphql/schema/gqlschema.go | 8 ++--- .../schemagen/output/geo-type.graphql | 19 ++++++----- 4 files changed, 51 insertions(+), 12 deletions(-) diff --git a/graphql/resolve/add_mutation_test.yaml b/graphql/resolve/add_mutation_test.yaml index 91a80162e4f..a312f293f32 100644 --- a/graphql/resolve/add_mutation_test.yaml +++ b/graphql/resolve/add_mutation_test.yaml @@ -1,3 +1,36 @@ +- + name: "Add mutation with geo" + gqlmutation: | + mutation addHotel($hotel: AddHotelInput!) { + addHotel(input: [$hotel]) { + hotel { + name + location { + latitude + longitude + } + } + } + } + gqlvariables: | + { "hotel": + { "name": "Taj Hotel", + "location": { "latitude": 11.11 , "longitude" : 22.22} + } + } + explanation: "A uid and type should get injected and all data transformed to + underlying Dgraph edge names" + dgmutations: + - setjson: | + { "uid":"_:Hotel1", + "dgraph.type":["Hotel"], + "Hotel.name":"Taj Hotel", + "Hotel.location": { + "type": "Point", + "coordinates": [22.22, 11.11] + } + } + - name: "Add mutation with variables" gqlmutation: | diff --git a/graphql/resolve/mutation_test.go b/graphql/resolve/mutation_test.go index 37997384d88..e49aa0d5851 100644 --- a/graphql/resolve/mutation_test.go +++ b/graphql/resolve/mutation_test.go @@ -182,6 +182,9 @@ func mutationRewriting(t *testing.T, file string, rewriterFactory func() Mutatio for _, tcase := range tests { t.Run(tcase.Name, func(t *testing.T) { + if tcase.Name != "Add mutation with geo" { + return + } // -- Arrange -- var vars map[string]interface{} if tcase.GQLVariables != "" { diff --git a/graphql/schema/gqlschema.go b/graphql/schema/gqlschema.go index d13f4da743c..91c36f2d4eb 100644 --- a/graphql/schema/gqlschema.go +++ b/graphql/schema/gqlschema.go @@ -125,18 +125,18 @@ input CustomHTTP { } type Point { - latitude: Float! longitude: Float! + latitude: Float! } -input PointInput { - latitude: Float! +input PointRef { longitude: Float! + latitude: Float! } input NearFilter { distance: Float! - coordinate: PointInput! + coordinate: PointRef! } input PointGeoFilter { diff --git a/graphql/schema/testdata/schemagen/output/geo-type.graphql b/graphql/schema/testdata/schemagen/output/geo-type.graphql index 61716fbe121..f05910cb954 100644 --- a/graphql/schema/testdata/schemagen/output/geo-type.graphql +++ b/graphql/schema/testdata/schemagen/output/geo-type.graphql @@ -75,22 +75,22 @@ input CustomHTTP { } type Point { - Latitude: Float! - Longitude: Float! + longitude: Float! + latitude: Float! } -input PointInput { - Latitude: Float! - Longitude: Float! +input PointRef { + longitude: Float! + latitude: Float! } input NearFilter { - Distance: Float! - Coordinate: PointInput! + distance: Float! + coordinate: PointRef! } input PointGeoFilter { - near: NearFilter + near: NearFilter! } directive @hasInverse(field: String!) on FIELD_DEFINITION @@ -205,6 +205,7 @@ enum HotelOrderable { input AddHotelInput { name: String! + location: PointRef } input HotelFilter { @@ -224,11 +225,13 @@ input HotelOrder { input HotelPatch { name: String + location: PointRef } input HotelRef { id: ID name: String + location: PointRef } input UpdateHotelInput { From c7abe0054f88c7398ff8db356d284026dbfb829f Mon Sep 17 00:00:00 2001 From: Arijit Das Date: Fri, 25 Sep 2020 18:25:34 +0530 Subject: [PATCH 04/20] Add and fix unit test. --- graphql/resolve/mutation_rewriter.go | 21 ++++- graphql/resolve/mutation_test.go | 3 - graphql/resolve/query_test.yaml | 2 +- graphql/resolve/update_mutation_test.yaml | 83 +++++++++++++++++++ graphql/schema/schemagen_test.go | 4 +- .../schemagen/output/authorization.graphql | 20 +++++ .../output/comments-and-descriptions.graphql | 20 +++++ .../schemagen/output/custom-mutation.graphql | 20 +++++ .../output/custom-nested-types.graphql | 20 +++++ .../output/custom-query-mixed-types.graphql | 20 +++++ .../custom-query-not-dgraph-type.graphql | 20 +++++ .../custom-query-with-dgraph-type.graphql | 20 +++++ .../schemagen/output/deprecated.graphql | 20 +++++ ...e-on-concrete-type-with-interfaces.graphql | 20 +++++ ...-reverse-directive-with-interfaces.graphql | 20 +++++ .../output/field-with-id-directive.graphql | 20 +++++ ...erse-predicate-in-dgraph-directive.graphql | 20 +++++ .../filter-cleanSchema-all-empty.graphql | 20 +++++ .../filter-cleanSchema-circular.graphql | 20 +++++ ...filter-cleanSchema-custom-mutation.graphql | 20 +++++ .../filter-cleanSchema-directLink.graphql | 20 +++++ ...se-with-interface-having-directive.graphql | 20 +++++ .../output/hasInverse-with-interface.graphql | 20 +++++ ...Inverse-with-type-having-directive.graphql | 20 +++++ .../schemagen/output/hasInverse.graphql | 20 +++++ .../hasInverse_withSubscription.graphql | 20 +++++ .../schemagen/output/hasfilter.graphql | 20 +++++ .../ignore-unsupported-directive.graphql | 20 +++++ .../output/interface-with-dgraph-pred.graphql | 20 +++++ .../interface-with-id-directive.graphql | 20 +++++ .../output/interface-with-no-ids.graphql | 20 +++++ ...interfaces-with-types-and-password.graphql | 20 +++++ .../output/interfaces-with-types.graphql | 20 +++++ .../no-id-field-with-searchables.graphql | 20 +++++ .../schemagen/output/no-id-field.graphql | 20 +++++ .../schemagen/output/password-type.graphql | 20 +++++ .../output/searchables-references.graphql | 20 +++++ .../schemagen/output/searchables.graphql | 20 +++++ .../output/single-type-with-enum.graphql | 20 +++++ .../schemagen/output/single-type.graphql | 20 +++++ ...ype-implements-multiple-interfaces.graphql | 20 +++++ .../schemagen/output/type-reference.graphql | 20 +++++ .../type-with-arguments-on-field.graphql | 20 +++++ ...e-with-custom-field-on-dgraph-type.graphql | 20 +++++ ...-with-custom-fields-on-remote-type.graphql | 20 +++++ .../output/type-without-orderables.graphql | 20 +++++ graphql/schema/wrappers.go | 5 ++ graphql/schema/wrappers_test.go | 8 ++ 48 files changed, 936 insertions(+), 10 deletions(-) diff --git a/graphql/resolve/mutation_rewriter.go b/graphql/resolve/mutation_rewriter.go index fdb1ea909b5..6a38750af3f 100644 --- a/graphql/resolve/mutation_rewriter.go +++ b/graphql/resolve/mutation_rewriter.go @@ -1165,9 +1165,24 @@ func rewriteObject( // or giving the data to create the object as part of a deep mutation // { "title": "...", "author": { "username": "new user", "dob": "...", ... } // like here ^^ - frags = - rewriteObject(ctx, typ, fieldDef.Type(), fieldDef, myUID, varGen, - withAdditionalDeletes, val, deepXID, xidMetadata) + if fieldDef.Type().IsGeo() { + lat, _ := val["latitude"] + long, _ := val["longitude"] + frags = &mutationRes{ + secondPass: []*mutationFragment{ + newFragment( + map[string]interface{}{ + "type": "Point", + "coordinates": []interface{}{long, lat}, + }, + ), + }, + } + } else { + frags = + rewriteObject(ctx, typ, fieldDef.Type(), fieldDef, myUID, varGen, + withAdditionalDeletes, val, deepXID, xidMetadata) + } case []interface{}: // This field is either: diff --git a/graphql/resolve/mutation_test.go b/graphql/resolve/mutation_test.go index e49aa0d5851..37997384d88 100644 --- a/graphql/resolve/mutation_test.go +++ b/graphql/resolve/mutation_test.go @@ -182,9 +182,6 @@ func mutationRewriting(t *testing.T, file string, rewriterFactory func() Mutatio for _, tcase := range tests { t.Run(tcase.Name, func(t *testing.T) { - if tcase.Name != "Add mutation with geo" { - return - } // -- Arrange -- var vars map[string]interface{} if tcase.GQLVariables != "" { diff --git a/graphql/resolve/query_test.yaml b/graphql/resolve/query_test.yaml index 9809505e3a6..d7bb6ce5d32 100644 --- a/graphql/resolve/query_test.yaml +++ b/graphql/resolve/query_test.yaml @@ -8,7 +8,7 @@ } dgquery: |- query { - queryHotel(func: type(Hotel))) @filter(near(Hotel.location, [22.22,11.11], 33.33)) { + queryHotel(func: type(Hotel)) @filter(near(Hotel.location, [22.22,11.11], 33.33)) { name : Hotel.name dgraph.uid : uid } diff --git a/graphql/resolve/update_mutation_test.yaml b/graphql/resolve/update_mutation_test.yaml index 93b9fc276bb..e658ad6d79b 100644 --- a/graphql/resolve/update_mutation_test.yaml +++ b/graphql/resolve/update_mutation_test.yaml @@ -1,3 +1,86 @@ +- + name: "Update set mutation on geo type" + gqlmutation: | + mutation updateHotel($patch: UpdateHotelInput!) { + updateHotel(input: $patch) { + hotel { + name + location { + latitude + longitude + } + } + } + } + gqlvariables: | + { "patch": + { "filter": { + "location": { "near" : { "distance": 33.33, "coordinate" : { "latitude": 11.11, "longitude": 22.22 } } } + }, + "set": { + "location": { "latitude": 11.11 , "longitude" : 22.22} + } + } + } + explanation: "The update patch should get rewritten into the Dgraph set mutation" + dgmutations: + - setjson: | + { "uid" : "uid(x)", + "Hotel.location": { + "type": "Point", + "coordinates": [22.22, 11.11] + } + } + cond: "@if(gt(len(x), 0))" + dgquery: |- + query { + x as updateHotel(func: type(Hotel)) @filter(near(Hotel.location, [22.22,11.11], 33.33)) { + uid + } + } + +- + name: "Update remove mutation on geo type" + gqlmutation: | + mutation updateHotel($patch: UpdateHotelInput!) { + updateHotel(input: $patch) { + hotel { + name + location { + latitude + longitude + } + } + } + } + gqlvariables: | + { "patch": + { "filter": { + "id": ["0x123", "0x124"] + }, + "remove": { + "location": { "latitude": 11.11 , "longitude" : 22.22} + } + } + } + explanation: "The update patch should get rewritten into the Dgraph set mutation" + dgmutations: + - deletejson: | + { "uid" : "uid(x)", + "Hotel.location": { + "type": "Point", + "coordinates": [22.22, 11.11] + } + } + cond: "@if(gt(len(x), 0))" + dgquery: |- + query { + x as updateHotel(func: uid(0x123, 0x124)) @filter(type(Hotel)) { + uid + } + } + + - name: "Update set mutation with variables" gqlmutation: | diff --git a/graphql/schema/schemagen_test.go b/graphql/schema/schemagen_test.go index bc3693a40e0..2d13b83e723 100644 --- a/graphql/schema/schemagen_test.go +++ b/graphql/schema/schemagen_test.go @@ -77,9 +77,7 @@ func TestSchemaString(t *testing.T) { for _, testFile := range files { t.Run(testFile.Name(), func(t *testing.T) { inputFileName := inputDir + testFile.Name() - if testFile.Name() != "geo-type.graphql" { - return - } + str1, err := ioutil.ReadFile(inputFileName) require.NoError(t, err) diff --git a/graphql/schema/testdata/schemagen/output/authorization.graphql b/graphql/schema/testdata/schemagen/output/authorization.graphql index 7af7f7bae62..bd01c883411 100644 --- a/graphql/schema/testdata/schemagen/output/authorization.graphql +++ b/graphql/schema/testdata/schemagen/output/authorization.graphql @@ -49,6 +49,7 @@ enum DgraphIndex { month day hour + geo } input AuthRule { @@ -83,6 +84,25 @@ input CustomHTTP { skipIntrospection: Boolean } +type Point { + longitude: Float! + latitude: Float! +} + +input PointRef { + longitude: Float! + latitude: Float! +} + +input NearFilter { + distance: Float! + coordinate: PointRef! +} + +input PointGeoFilter { + near: NearFilter! +} + directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/comments-and-descriptions.graphql b/graphql/schema/testdata/schemagen/output/comments-and-descriptions.graphql index 7454feda418..1d1ebf14034 100755 --- a/graphql/schema/testdata/schemagen/output/comments-and-descriptions.graphql +++ b/graphql/schema/testdata/schemagen/output/comments-and-descriptions.graphql @@ -54,6 +54,7 @@ enum DgraphIndex { month day hour + geo } input AuthRule { @@ -88,6 +89,25 @@ input CustomHTTP { skipIntrospection: Boolean } +type Point { + longitude: Float! + latitude: Float! +} + +input PointRef { + longitude: Float! + latitude: Float! +} + +input NearFilter { + distance: Float! + coordinate: PointRef! +} + +input PointGeoFilter { + near: NearFilter! +} + directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/custom-mutation.graphql b/graphql/schema/testdata/schemagen/output/custom-mutation.graphql index 1c088532586..63fedff64f2 100644 --- a/graphql/schema/testdata/schemagen/output/custom-mutation.graphql +++ b/graphql/schema/testdata/schemagen/output/custom-mutation.graphql @@ -42,6 +42,7 @@ enum DgraphIndex { month day hour + geo } input AuthRule { @@ -76,6 +77,25 @@ input CustomHTTP { skipIntrospection: Boolean } +type Point { + longitude: Float! + latitude: Float! +} + +input PointRef { + longitude: Float! + latitude: Float! +} + +input NearFilter { + distance: Float! + coordinate: PointRef! +} + +input PointGeoFilter { + near: NearFilter! +} + directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/custom-nested-types.graphql b/graphql/schema/testdata/schemagen/output/custom-nested-types.graphql index 7af021c6449..b24d98a509a 100755 --- a/graphql/schema/testdata/schemagen/output/custom-nested-types.graphql +++ b/graphql/schema/testdata/schemagen/output/custom-nested-types.graphql @@ -59,6 +59,7 @@ enum DgraphIndex { month day hour + geo } input AuthRule { @@ -93,6 +94,25 @@ input CustomHTTP { skipIntrospection: Boolean } +type Point { + longitude: Float! + latitude: Float! +} + +input PointRef { + longitude: Float! + latitude: Float! +} + +input NearFilter { + distance: Float! + coordinate: PointRef! +} + +input PointGeoFilter { + near: NearFilter! +} + directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/custom-query-mixed-types.graphql b/graphql/schema/testdata/schemagen/output/custom-query-mixed-types.graphql index fc30f925421..69f617be1fd 100644 --- a/graphql/schema/testdata/schemagen/output/custom-query-mixed-types.graphql +++ b/graphql/schema/testdata/schemagen/output/custom-query-mixed-types.graphql @@ -43,6 +43,7 @@ enum DgraphIndex { month day hour + geo } input AuthRule { @@ -77,6 +78,25 @@ input CustomHTTP { skipIntrospection: Boolean } +type Point { + longitude: Float! + latitude: Float! +} + +input PointRef { + longitude: Float! + latitude: Float! +} + +input NearFilter { + distance: Float! + coordinate: PointRef! +} + +input PointGeoFilter { + near: NearFilter! +} + directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/custom-query-not-dgraph-type.graphql b/graphql/schema/testdata/schemagen/output/custom-query-not-dgraph-type.graphql index ca377eab778..4fa3ea6cd20 100755 --- a/graphql/schema/testdata/schemagen/output/custom-query-not-dgraph-type.graphql +++ b/graphql/schema/testdata/schemagen/output/custom-query-not-dgraph-type.graphql @@ -42,6 +42,7 @@ enum DgraphIndex { month day hour + geo } input AuthRule { @@ -76,6 +77,25 @@ input CustomHTTP { skipIntrospection: Boolean } +type Point { + longitude: Float! + latitude: Float! +} + +input PointRef { + longitude: Float! + latitude: Float! +} + +input NearFilter { + distance: Float! + coordinate: PointRef! +} + +input PointGeoFilter { + near: NearFilter! +} + directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/custom-query-with-dgraph-type.graphql b/graphql/schema/testdata/schemagen/output/custom-query-with-dgraph-type.graphql index ecef28a3b37..8a1fee58147 100755 --- a/graphql/schema/testdata/schemagen/output/custom-query-with-dgraph-type.graphql +++ b/graphql/schema/testdata/schemagen/output/custom-query-with-dgraph-type.graphql @@ -38,6 +38,7 @@ enum DgraphIndex { month day hour + geo } input AuthRule { @@ -72,6 +73,25 @@ input CustomHTTP { skipIntrospection: Boolean } +type Point { + longitude: Float! + latitude: Float! +} + +input PointRef { + longitude: Float! + latitude: Float! +} + +input NearFilter { + distance: Float! + coordinate: PointRef! +} + +input PointGeoFilter { + near: NearFilter! +} + directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/deprecated.graphql b/graphql/schema/testdata/schemagen/output/deprecated.graphql index 6ef77403775..ed22fdb1c90 100755 --- a/graphql/schema/testdata/schemagen/output/deprecated.graphql +++ b/graphql/schema/testdata/schemagen/output/deprecated.graphql @@ -38,6 +38,7 @@ enum DgraphIndex { month day hour + geo } input AuthRule { @@ -72,6 +73,25 @@ input CustomHTTP { skipIntrospection: Boolean } +type Point { + longitude: Float! + latitude: Float! +} + +input PointRef { + longitude: Float! + latitude: Float! +} + +input NearFilter { + distance: Float! + coordinate: PointRef! +} + +input PointGeoFilter { + near: NearFilter! +} + directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/dgraph-reverse-directive-on-concrete-type-with-interfaces.graphql b/graphql/schema/testdata/schemagen/output/dgraph-reverse-directive-on-concrete-type-with-interfaces.graphql index 438c9b216d9..8e053cabbc7 100755 --- a/graphql/schema/testdata/schemagen/output/dgraph-reverse-directive-on-concrete-type-with-interfaces.graphql +++ b/graphql/schema/testdata/schemagen/output/dgraph-reverse-directive-on-concrete-type-with-interfaces.graphql @@ -52,6 +52,7 @@ enum DgraphIndex { month day hour + geo } input AuthRule { @@ -86,6 +87,25 @@ input CustomHTTP { skipIntrospection: Boolean } +type Point { + longitude: Float! + latitude: Float! +} + +input PointRef { + longitude: Float! + latitude: Float! +} + +input NearFilter { + distance: Float! + coordinate: PointRef! +} + +input PointGeoFilter { + near: NearFilter! +} + directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/dgraph-reverse-directive-with-interfaces.graphql b/graphql/schema/testdata/schemagen/output/dgraph-reverse-directive-with-interfaces.graphql index d9f5872613c..b178998d901 100755 --- a/graphql/schema/testdata/schemagen/output/dgraph-reverse-directive-with-interfaces.graphql +++ b/graphql/schema/testdata/schemagen/output/dgraph-reverse-directive-with-interfaces.graphql @@ -52,6 +52,7 @@ enum DgraphIndex { month day hour + geo } input AuthRule { @@ -86,6 +87,25 @@ input CustomHTTP { skipIntrospection: Boolean } +type Point { + longitude: Float! + latitude: Float! +} + +input PointRef { + longitude: Float! + latitude: Float! +} + +input NearFilter { + distance: Float! + coordinate: PointRef! +} + +input PointGeoFilter { + near: NearFilter! +} + directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/field-with-id-directive.graphql b/graphql/schema/testdata/schemagen/output/field-with-id-directive.graphql index 34c6394ff21..3b64367c78c 100755 --- a/graphql/schema/testdata/schemagen/output/field-with-id-directive.graphql +++ b/graphql/schema/testdata/schemagen/output/field-with-id-directive.graphql @@ -51,6 +51,7 @@ enum DgraphIndex { month day hour + geo } input AuthRule { @@ -85,6 +86,25 @@ input CustomHTTP { skipIntrospection: Boolean } +type Point { + longitude: Float! + latitude: Float! +} + +input PointRef { + longitude: Float! + latitude: Float! +} + +input NearFilter { + distance: Float! + coordinate: PointRef! +} + +input PointGeoFilter { + near: NearFilter! +} + directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/field-with-reverse-predicate-in-dgraph-directive.graphql b/graphql/schema/testdata/schemagen/output/field-with-reverse-predicate-in-dgraph-directive.graphql index a60fb008083..36a293607c4 100755 --- a/graphql/schema/testdata/schemagen/output/field-with-reverse-predicate-in-dgraph-directive.graphql +++ b/graphql/schema/testdata/schemagen/output/field-with-reverse-predicate-in-dgraph-directive.graphql @@ -45,6 +45,7 @@ enum DgraphIndex { month day hour + geo } input AuthRule { @@ -79,6 +80,25 @@ input CustomHTTP { skipIntrospection: Boolean } +type Point { + longitude: Float! + latitude: Float! +} + +input PointRef { + longitude: Float! + latitude: Float! +} + +input NearFilter { + distance: Float! + coordinate: PointRef! +} + +input PointGeoFilter { + near: NearFilter! +} + directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/filter-cleanSchema-all-empty.graphql b/graphql/schema/testdata/schemagen/output/filter-cleanSchema-all-empty.graphql index 4fe1e985fef..978f5039aff 100644 --- a/graphql/schema/testdata/schemagen/output/filter-cleanSchema-all-empty.graphql +++ b/graphql/schema/testdata/schemagen/output/filter-cleanSchema-all-empty.graphql @@ -46,6 +46,7 @@ enum DgraphIndex { month day hour + geo } input AuthRule { @@ -80,6 +81,25 @@ input CustomHTTP { skipIntrospection: Boolean } +type Point { + longitude: Float! + latitude: Float! +} + +input PointRef { + longitude: Float! + latitude: Float! +} + +input NearFilter { + distance: Float! + coordinate: PointRef! +} + +input PointGeoFilter { + near: NearFilter! +} + directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/filter-cleanSchema-circular.graphql b/graphql/schema/testdata/schemagen/output/filter-cleanSchema-circular.graphql index a2dc284a013..396d5e090ae 100644 --- a/graphql/schema/testdata/schemagen/output/filter-cleanSchema-circular.graphql +++ b/graphql/schema/testdata/schemagen/output/filter-cleanSchema-circular.graphql @@ -48,6 +48,7 @@ enum DgraphIndex { month day hour + geo } input AuthRule { @@ -82,6 +83,25 @@ input CustomHTTP { skipIntrospection: Boolean } +type Point { + longitude: Float! + latitude: Float! +} + +input PointRef { + longitude: Float! + latitude: Float! +} + +input NearFilter { + distance: Float! + coordinate: PointRef! +} + +input PointGeoFilter { + near: NearFilter! +} + directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/filter-cleanSchema-custom-mutation.graphql b/graphql/schema/testdata/schemagen/output/filter-cleanSchema-custom-mutation.graphql index 0d3a24f74be..dbc370e3486 100644 --- a/graphql/schema/testdata/schemagen/output/filter-cleanSchema-custom-mutation.graphql +++ b/graphql/schema/testdata/schemagen/output/filter-cleanSchema-custom-mutation.graphql @@ -42,6 +42,7 @@ enum DgraphIndex { month day hour + geo } input AuthRule { @@ -76,6 +77,25 @@ input CustomHTTP { skipIntrospection: Boolean } +type Point { + longitude: Float! + latitude: Float! +} + +input PointRef { + longitude: Float! + latitude: Float! +} + +input NearFilter { + distance: Float! + coordinate: PointRef! +} + +input PointGeoFilter { + near: NearFilter! +} + directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/filter-cleanSchema-directLink.graphql b/graphql/schema/testdata/schemagen/output/filter-cleanSchema-directLink.graphql index ca25f13d823..7f03d06f38b 100644 --- a/graphql/schema/testdata/schemagen/output/filter-cleanSchema-directLink.graphql +++ b/graphql/schema/testdata/schemagen/output/filter-cleanSchema-directLink.graphql @@ -48,6 +48,7 @@ enum DgraphIndex { month day hour + geo } input AuthRule { @@ -82,6 +83,25 @@ input CustomHTTP { skipIntrospection: Boolean } +type Point { + longitude: Float! + latitude: Float! +} + +input PointRef { + longitude: Float! + latitude: Float! +} + +input NearFilter { + distance: Float! + coordinate: PointRef! +} + +input PointGeoFilter { + near: NearFilter! +} + directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/hasInverse-with-interface-having-directive.graphql b/graphql/schema/testdata/schemagen/output/hasInverse-with-interface-having-directive.graphql index 096dd5a1c63..bab62fc6450 100755 --- a/graphql/schema/testdata/schemagen/output/hasInverse-with-interface-having-directive.graphql +++ b/graphql/schema/testdata/schemagen/output/hasInverse-with-interface-having-directive.graphql @@ -62,6 +62,7 @@ enum DgraphIndex { month day hour + geo } input AuthRule { @@ -96,6 +97,25 @@ input CustomHTTP { skipIntrospection: Boolean } +type Point { + longitude: Float! + latitude: Float! +} + +input PointRef { + longitude: Float! + latitude: Float! +} + +input NearFilter { + distance: Float! + coordinate: PointRef! +} + +input PointGeoFilter { + near: NearFilter! +} + directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/hasInverse-with-interface.graphql b/graphql/schema/testdata/schemagen/output/hasInverse-with-interface.graphql index d5124ef7984..08fb681daf6 100755 --- a/graphql/schema/testdata/schemagen/output/hasInverse-with-interface.graphql +++ b/graphql/schema/testdata/schemagen/output/hasInverse-with-interface.graphql @@ -63,6 +63,7 @@ enum DgraphIndex { month day hour + geo } input AuthRule { @@ -97,6 +98,25 @@ input CustomHTTP { skipIntrospection: Boolean } +type Point { + longitude: Float! + latitude: Float! +} + +input PointRef { + longitude: Float! + latitude: Float! +} + +input NearFilter { + distance: Float! + coordinate: PointRef! +} + +input PointGeoFilter { + near: NearFilter! +} + directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/hasInverse-with-type-having-directive.graphql b/graphql/schema/testdata/schemagen/output/hasInverse-with-type-having-directive.graphql index 096dd5a1c63..bab62fc6450 100755 --- a/graphql/schema/testdata/schemagen/output/hasInverse-with-type-having-directive.graphql +++ b/graphql/schema/testdata/schemagen/output/hasInverse-with-type-having-directive.graphql @@ -62,6 +62,7 @@ enum DgraphIndex { month day hour + geo } input AuthRule { @@ -96,6 +97,25 @@ input CustomHTTP { skipIntrospection: Boolean } +type Point { + longitude: Float! + latitude: Float! +} + +input PointRef { + longitude: Float! + latitude: Float! +} + +input NearFilter { + distance: Float! + coordinate: PointRef! +} + +input PointGeoFilter { + near: NearFilter! +} + directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/hasInverse.graphql b/graphql/schema/testdata/schemagen/output/hasInverse.graphql index 638821f9419..a6635e49104 100755 --- a/graphql/schema/testdata/schemagen/output/hasInverse.graphql +++ b/graphql/schema/testdata/schemagen/output/hasInverse.graphql @@ -43,6 +43,7 @@ enum DgraphIndex { month day hour + geo } input AuthRule { @@ -77,6 +78,25 @@ input CustomHTTP { skipIntrospection: Boolean } +type Point { + longitude: Float! + latitude: Float! +} + +input PointRef { + longitude: Float! + latitude: Float! +} + +input NearFilter { + distance: Float! + coordinate: PointRef! +} + +input PointGeoFilter { + near: NearFilter! +} + directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/hasInverse_withSubscription.graphql b/graphql/schema/testdata/schemagen/output/hasInverse_withSubscription.graphql index 079c8a22ec5..c88a7be307e 100755 --- a/graphql/schema/testdata/schemagen/output/hasInverse_withSubscription.graphql +++ b/graphql/schema/testdata/schemagen/output/hasInverse_withSubscription.graphql @@ -43,6 +43,7 @@ enum DgraphIndex { month day hour + geo } input AuthRule { @@ -77,6 +78,25 @@ input CustomHTTP { skipIntrospection: Boolean } +type Point { + longitude: Float! + latitude: Float! +} + +input PointRef { + longitude: Float! + latitude: Float! +} + +input NearFilter { + distance: Float! + coordinate: PointRef! +} + +input PointGeoFilter { + near: NearFilter! +} + directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/hasfilter.graphql b/graphql/schema/testdata/schemagen/output/hasfilter.graphql index a3593f8316d..1a73a5b4229 100644 --- a/graphql/schema/testdata/schemagen/output/hasfilter.graphql +++ b/graphql/schema/testdata/schemagen/output/hasfilter.graphql @@ -46,6 +46,7 @@ enum DgraphIndex { month day hour + geo } input AuthRule { @@ -80,6 +81,25 @@ input CustomHTTP { skipIntrospection: Boolean } +type Point { + longitude: Float! + latitude: Float! +} + +input PointRef { + longitude: Float! + latitude: Float! +} + +input NearFilter { + distance: Float! + coordinate: PointRef! +} + +input PointGeoFilter { + near: NearFilter! +} + directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/ignore-unsupported-directive.graphql b/graphql/schema/testdata/schemagen/output/ignore-unsupported-directive.graphql index b2d55af4d7f..155ce01809b 100755 --- a/graphql/schema/testdata/schemagen/output/ignore-unsupported-directive.graphql +++ b/graphql/schema/testdata/schemagen/output/ignore-unsupported-directive.graphql @@ -45,6 +45,7 @@ enum DgraphIndex { month day hour + geo } input AuthRule { @@ -79,6 +80,25 @@ input CustomHTTP { skipIntrospection: Boolean } +type Point { + longitude: Float! + latitude: Float! +} + +input PointRef { + longitude: Float! + latitude: Float! +} + +input NearFilter { + distance: Float! + coordinate: PointRef! +} + +input PointGeoFilter { + near: NearFilter! +} + directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/interface-with-dgraph-pred.graphql b/graphql/schema/testdata/schemagen/output/interface-with-dgraph-pred.graphql index db5ce0d48f9..cc48b1e47af 100644 --- a/graphql/schema/testdata/schemagen/output/interface-with-dgraph-pred.graphql +++ b/graphql/schema/testdata/schemagen/output/interface-with-dgraph-pred.graphql @@ -52,6 +52,7 @@ enum DgraphIndex { month day hour + geo } input AuthRule { @@ -86,6 +87,25 @@ input CustomHTTP { skipIntrospection: Boolean } +type Point { + longitude: Float! + latitude: Float! +} + +input PointRef { + longitude: Float! + latitude: Float! +} + +input NearFilter { + distance: Float! + coordinate: PointRef! +} + +input PointGeoFilter { + near: NearFilter! +} + directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/interface-with-id-directive.graphql b/graphql/schema/testdata/schemagen/output/interface-with-id-directive.graphql index ff2a76024ee..efa6626cc47 100755 --- a/graphql/schema/testdata/schemagen/output/interface-with-id-directive.graphql +++ b/graphql/schema/testdata/schemagen/output/interface-with-id-directive.graphql @@ -47,6 +47,7 @@ enum DgraphIndex { month day hour + geo } input AuthRule { @@ -81,6 +82,25 @@ input CustomHTTP { skipIntrospection: Boolean } +type Point { + longitude: Float! + latitude: Float! +} + +input PointRef { + longitude: Float! + latitude: Float! +} + +input NearFilter { + distance: Float! + coordinate: PointRef! +} + +input PointGeoFilter { + near: NearFilter! +} + directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/interface-with-no-ids.graphql b/graphql/schema/testdata/schemagen/output/interface-with-no-ids.graphql index 341b920b2d4..603d60fa33c 100755 --- a/graphql/schema/testdata/schemagen/output/interface-with-no-ids.graphql +++ b/graphql/schema/testdata/schemagen/output/interface-with-no-ids.graphql @@ -47,6 +47,7 @@ enum DgraphIndex { month day hour + geo } input AuthRule { @@ -81,6 +82,25 @@ input CustomHTTP { skipIntrospection: Boolean } +type Point { + longitude: Float! + latitude: Float! +} + +input PointRef { + longitude: Float! + latitude: Float! +} + +input NearFilter { + distance: Float! + coordinate: PointRef! +} + +input PointGeoFilter { + near: NearFilter! +} + directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/interfaces-with-types-and-password.graphql b/graphql/schema/testdata/schemagen/output/interfaces-with-types-and-password.graphql index 9af7c5f32ff..e5c8fb367ae 100755 --- a/graphql/schema/testdata/schemagen/output/interfaces-with-types-and-password.graphql +++ b/graphql/schema/testdata/schemagen/output/interfaces-with-types-and-password.graphql @@ -69,6 +69,7 @@ enum DgraphIndex { month day hour + geo } input AuthRule { @@ -103,6 +104,25 @@ input CustomHTTP { skipIntrospection: Boolean } +type Point { + longitude: Float! + latitude: Float! +} + +input PointRef { + longitude: Float! + latitude: Float! +} + +input NearFilter { + distance: Float! + coordinate: PointRef! +} + +input PointGeoFilter { + near: NearFilter! +} + directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/interfaces-with-types.graphql b/graphql/schema/testdata/schemagen/output/interfaces-with-types.graphql index 7bedb0d9ca3..dd1ae9018d4 100755 --- a/graphql/schema/testdata/schemagen/output/interfaces-with-types.graphql +++ b/graphql/schema/testdata/schemagen/output/interfaces-with-types.graphql @@ -69,6 +69,7 @@ enum DgraphIndex { month day hour + geo } input AuthRule { @@ -103,6 +104,25 @@ input CustomHTTP { skipIntrospection: Boolean } +type Point { + longitude: Float! + latitude: Float! +} + +input PointRef { + longitude: Float! + latitude: Float! +} + +input NearFilter { + distance: Float! + coordinate: PointRef! +} + +input PointGeoFilter { + near: NearFilter! +} + directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/no-id-field-with-searchables.graphql b/graphql/schema/testdata/schemagen/output/no-id-field-with-searchables.graphql index 34fafc3eab2..0d8a256c4e0 100755 --- a/graphql/schema/testdata/schemagen/output/no-id-field-with-searchables.graphql +++ b/graphql/schema/testdata/schemagen/output/no-id-field-with-searchables.graphql @@ -37,6 +37,7 @@ enum DgraphIndex { month day hour + geo } input AuthRule { @@ -71,6 +72,25 @@ input CustomHTTP { skipIntrospection: Boolean } +type Point { + longitude: Float! + latitude: Float! +} + +input PointRef { + longitude: Float! + latitude: Float! +} + +input NearFilter { + distance: Float! + coordinate: PointRef! +} + +input PointGeoFilter { + near: NearFilter! +} + directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/no-id-field.graphql b/graphql/schema/testdata/schemagen/output/no-id-field.graphql index a158f737c5b..1c1a454d092 100755 --- a/graphql/schema/testdata/schemagen/output/no-id-field.graphql +++ b/graphql/schema/testdata/schemagen/output/no-id-field.graphql @@ -49,6 +49,7 @@ enum DgraphIndex { month day hour + geo } input AuthRule { @@ -83,6 +84,25 @@ input CustomHTTP { skipIntrospection: Boolean } +type Point { + longitude: Float! + latitude: Float! +} + +input PointRef { + longitude: Float! + latitude: Float! +} + +input NearFilter { + distance: Float! + coordinate: PointRef! +} + +input PointGeoFilter { + near: NearFilter! +} + directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/password-type.graphql b/graphql/schema/testdata/schemagen/output/password-type.graphql index 17be5d4fd5e..f2c78464b86 100755 --- a/graphql/schema/testdata/schemagen/output/password-type.graphql +++ b/graphql/schema/testdata/schemagen/output/password-type.graphql @@ -38,6 +38,7 @@ enum DgraphIndex { month day hour + geo } input AuthRule { @@ -72,6 +73,25 @@ input CustomHTTP { skipIntrospection: Boolean } +type Point { + longitude: Float! + latitude: Float! +} + +input PointRef { + longitude: Float! + latitude: Float! +} + +input NearFilter { + distance: Float! + coordinate: PointRef! +} + +input PointGeoFilter { + near: NearFilter! +} + directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/searchables-references.graphql b/graphql/schema/testdata/schemagen/output/searchables-references.graphql index a40a3df87fc..9a0882cd0e1 100755 --- a/graphql/schema/testdata/schemagen/output/searchables-references.graphql +++ b/graphql/schema/testdata/schemagen/output/searchables-references.graphql @@ -47,6 +47,7 @@ enum DgraphIndex { month day hour + geo } input AuthRule { @@ -81,6 +82,25 @@ input CustomHTTP { skipIntrospection: Boolean } +type Point { + longitude: Float! + latitude: Float! +} + +input PointRef { + longitude: Float! + latitude: Float! +} + +input NearFilter { + distance: Float! + coordinate: PointRef! +} + +input PointGeoFilter { + near: NearFilter! +} + directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/searchables.graphql b/graphql/schema/testdata/schemagen/output/searchables.graphql index a3bd9dd5fd7..db324c8f4e4 100755 --- a/graphql/schema/testdata/schemagen/output/searchables.graphql +++ b/graphql/schema/testdata/schemagen/output/searchables.graphql @@ -66,6 +66,7 @@ enum DgraphIndex { month day hour + geo } input AuthRule { @@ -100,6 +101,25 @@ input CustomHTTP { skipIntrospection: Boolean } +type Point { + longitude: Float! + latitude: Float! +} + +input PointRef { + longitude: Float! + latitude: Float! +} + +input NearFilter { + distance: Float! + coordinate: PointRef! +} + +input PointGeoFilter { + near: NearFilter! +} + directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/single-type-with-enum.graphql b/graphql/schema/testdata/schemagen/output/single-type-with-enum.graphql index c58221a8faa..34733fa8c25 100755 --- a/graphql/schema/testdata/schemagen/output/single-type-with-enum.graphql +++ b/graphql/schema/testdata/schemagen/output/single-type-with-enum.graphql @@ -46,6 +46,7 @@ enum DgraphIndex { month day hour + geo } input AuthRule { @@ -80,6 +81,25 @@ input CustomHTTP { skipIntrospection: Boolean } +type Point { + longitude: Float! + latitude: Float! +} + +input PointRef { + longitude: Float! + latitude: Float! +} + +input NearFilter { + distance: Float! + coordinate: PointRef! +} + +input PointGeoFilter { + near: NearFilter! +} + directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/single-type.graphql b/graphql/schema/testdata/schemagen/output/single-type.graphql index 89dc6d09ba7..ec2e19b41d8 100755 --- a/graphql/schema/testdata/schemagen/output/single-type.graphql +++ b/graphql/schema/testdata/schemagen/output/single-type.graphql @@ -41,6 +41,7 @@ enum DgraphIndex { month day hour + geo } input AuthRule { @@ -75,6 +76,25 @@ input CustomHTTP { skipIntrospection: Boolean } +type Point { + longitude: Float! + latitude: Float! +} + +input PointRef { + longitude: Float! + latitude: Float! +} + +input NearFilter { + distance: Float! + coordinate: PointRef! +} + +input PointGeoFilter { + near: NearFilter! +} + directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/type-implements-multiple-interfaces.graphql b/graphql/schema/testdata/schemagen/output/type-implements-multiple-interfaces.graphql index 7b15ed97fc0..bdf8618b652 100755 --- a/graphql/schema/testdata/schemagen/output/type-implements-multiple-interfaces.graphql +++ b/graphql/schema/testdata/schemagen/output/type-implements-multiple-interfaces.graphql @@ -53,6 +53,7 @@ enum DgraphIndex { month day hour + geo } input AuthRule { @@ -87,6 +88,25 @@ input CustomHTTP { skipIntrospection: Boolean } +type Point { + longitude: Float! + latitude: Float! +} + +input PointRef { + longitude: Float! + latitude: Float! +} + +input NearFilter { + distance: Float! + coordinate: PointRef! +} + +input PointGeoFilter { + near: NearFilter! +} + directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/type-reference.graphql b/graphql/schema/testdata/schemagen/output/type-reference.graphql index 06e6e39c404..a11b1827e1c 100755 --- a/graphql/schema/testdata/schemagen/output/type-reference.graphql +++ b/graphql/schema/testdata/schemagen/output/type-reference.graphql @@ -45,6 +45,7 @@ enum DgraphIndex { month day hour + geo } input AuthRule { @@ -79,6 +80,25 @@ input CustomHTTP { skipIntrospection: Boolean } +type Point { + longitude: Float! + latitude: Float! +} + +input PointRef { + longitude: Float! + latitude: Float! +} + +input NearFilter { + distance: Float! + coordinate: PointRef! +} + +input PointGeoFilter { + near: NearFilter! +} + directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/type-with-arguments-on-field.graphql b/graphql/schema/testdata/schemagen/output/type-with-arguments-on-field.graphql index 3c8bdfc3269..9395061a19c 100644 --- a/graphql/schema/testdata/schemagen/output/type-with-arguments-on-field.graphql +++ b/graphql/schema/testdata/schemagen/output/type-with-arguments-on-field.graphql @@ -46,6 +46,7 @@ enum DgraphIndex { month day hour + geo } input AuthRule { @@ -80,6 +81,25 @@ input CustomHTTP { skipIntrospection: Boolean } +type Point { + longitude: Float! + latitude: Float! +} + +input PointRef { + longitude: Float! + latitude: Float! +} + +input NearFilter { + distance: Float! + coordinate: PointRef! +} + +input PointGeoFilter { + near: NearFilter! +} + directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/type-with-custom-field-on-dgraph-type.graphql b/graphql/schema/testdata/schemagen/output/type-with-custom-field-on-dgraph-type.graphql index b6957ee9e31..4172d007869 100644 --- a/graphql/schema/testdata/schemagen/output/type-with-custom-field-on-dgraph-type.graphql +++ b/graphql/schema/testdata/schemagen/output/type-with-custom-field-on-dgraph-type.graphql @@ -45,6 +45,7 @@ enum DgraphIndex { month day hour + geo } input AuthRule { @@ -79,6 +80,25 @@ input CustomHTTP { skipIntrospection: Boolean } +type Point { + longitude: Float! + latitude: Float! +} + +input PointRef { + longitude: Float! + latitude: Float! +} + +input NearFilter { + distance: Float! + coordinate: PointRef! +} + +input PointGeoFilter { + near: NearFilter! +} + directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/type-with-custom-fields-on-remote-type.graphql b/graphql/schema/testdata/schemagen/output/type-with-custom-fields-on-remote-type.graphql index aa940fdd4c4..9c6d17f2c31 100644 --- a/graphql/schema/testdata/schemagen/output/type-with-custom-fields-on-remote-type.graphql +++ b/graphql/schema/testdata/schemagen/output/type-with-custom-fields-on-remote-type.graphql @@ -45,6 +45,7 @@ enum DgraphIndex { month day hour + geo } input AuthRule { @@ -79,6 +80,25 @@ input CustomHTTP { skipIntrospection: Boolean } +type Point { + longitude: Float! + latitude: Float! +} + +input PointRef { + longitude: Float! + latitude: Float! +} + +input NearFilter { + distance: Float! + coordinate: PointRef! +} + +input PointGeoFilter { + near: NearFilter! +} + directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/type-without-orderables.graphql b/graphql/schema/testdata/schemagen/output/type-without-orderables.graphql index f361a23b0cd..0e65cab2211 100644 --- a/graphql/schema/testdata/schemagen/output/type-without-orderables.graphql +++ b/graphql/schema/testdata/schemagen/output/type-without-orderables.graphql @@ -40,6 +40,7 @@ enum DgraphIndex { month day hour + geo } input AuthRule { @@ -74,6 +75,25 @@ input CustomHTTP { skipIntrospection: Boolean } +type Point { + longitude: Float! + latitude: Float! +} + +input PointRef { + longitude: Float! + latitude: Float! +} + +input NearFilter { + distance: Float! + coordinate: PointRef! +} + +input PointGeoFilter { + near: NearFilter! +} + directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/wrappers.go b/graphql/schema/wrappers.go index 2dff38c1404..630279eb128 100644 --- a/graphql/schema/wrappers.go +++ b/graphql/schema/wrappers.go @@ -177,6 +177,7 @@ type Type interface { EnsureNonNulls(map[string]interface{}, string) error FieldOriginatedFrom(fieldName string) string AuthRules() *TypeAuth + IsGeo() bool fmt.Stringer } @@ -1445,6 +1446,10 @@ func (t *astType) AuthRules() *TypeAuth { return t.inSchema.authRules[t.DgraphName()] } +func (t *astType) IsGeo() bool { + return t.Name() == "Point" +} + func (t *astType) Field(name string) FieldDefinition { return &fieldDefinition{ // this ForName lookup is a loop in the underlying schema :-( diff --git a/graphql/schema/wrappers_test.go b/graphql/schema/wrappers_test.go index c174b4573a2..ed380d31a85 100644 --- a/graphql/schema/wrappers_test.go +++ b/graphql/schema/wrappers_test.go @@ -132,6 +132,10 @@ type Starship { "Employee": map[string]string{ "ename": "Employee.ename", }, + "Point": map[string]string{ + "latitude": "Point.latitude", + "longitude": "Point.longitude", + }, "Character": character, "UpdateCharacterPayload": character, "DeleteCharacterPayload": character, @@ -254,6 +258,10 @@ func TestDgraphMapping_WithDirectives(t *testing.T) { "Employee": map[string]string{ "ename": "dgraph.employee.en.ename", }, + "Point": map[string]string{ + "latitude": "Point.latitude", + "longitude": "Point.longitude", + }, "Character": character, "UpdateCharacterPayload": character, "DeleteCharacterPayload": character, From ccc3ddd7f48e27e13d4267afaadf8bc9c671e2ea Mon Sep 17 00:00:00 2001 From: Arijit Das Date: Fri, 25 Sep 2020 18:29:01 +0530 Subject: [PATCH 05/20] Fix test. --- graphql/resolve/query_test.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/graphql/resolve/query_test.go b/graphql/resolve/query_test.go index 0c4828a4abb..5d21928825d 100644 --- a/graphql/resolve/query_test.go +++ b/graphql/resolve/query_test.go @@ -56,10 +56,6 @@ func TestQueryRewriting(t *testing.T) { for _, tcase := range tests { t.Run(tcase.Name, func(t *testing.T) { - if tcase.Name != "Geo query" { - return - } - op, err := gqlSchema.Operation( &schema.Request{ Query: tcase.GQLQuery, From 3f6346feb122ea9cfb277606ee82b4f89fbd96c0 Mon Sep 17 00:00:00 2001 From: Arijit Das Date: Fri, 25 Sep 2020 18:30:22 +0530 Subject: [PATCH 06/20] Minor nit. --- graphql/schema/dgraph_schemagen_test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graphql/schema/dgraph_schemagen_test.yml b/graphql/schema/dgraph_schemagen_test.yml index ca9f8b685c7..af054f8e6e7 100644 --- a/graphql/schema/dgraph_schemagen_test.yml +++ b/graphql/schema/dgraph_schemagen_test.yml @@ -608,7 +608,7 @@ schemas: }) } - - name: "geo type." + - name: "Geo field in schema." input: | type Hotel { id: ID! From b61c96b621e0bfcf871bbd83606d1a800f5ace91 Mon Sep 17 00:00:00 2001 From: Arijit Das Date: Mon, 28 Sep 2020 16:37:11 +0530 Subject: [PATCH 07/20] Fix bugs and add E2E test. --- graphql/e2e/common/common.go | 1 + graphql/e2e/common/mutation.go | 43 +++++++++++++++++++++++ graphql/e2e/normal/schema.graphql | 6 ++++ graphql/resolve/add_mutation_test.yaml | 2 +- graphql/resolve/mutation_rewriter.go | 2 ++ graphql/resolve/query_rewriter.go | 7 +++- graphql/resolve/query_test.yaml | 5 +++ graphql/resolve/resolver.go | 42 ++++++++++++++++++++++ graphql/resolve/update_mutation_test.yaml | 1 - graphql/schema/schemagen.go | 3 +- graphql/schema/schemagen_test.go | 1 - 11 files changed, 107 insertions(+), 6 deletions(-) diff --git a/graphql/e2e/common/common.go b/graphql/e2e/common/common.go index b6e1173f3be..a39b3269882 100644 --- a/graphql/e2e/common/common.go +++ b/graphql/e2e/common/common.go @@ -377,6 +377,7 @@ func RunAll(t *testing.T) { t.Run("update mutation without set & remove", updateMutationWithoutSetRemove) t.Run("Input coercing for int64 type", int64BoundaryTesting) t.Run("Check cascade with mutation without ID field", checkCascadeWithMutationWithoutIDField) + t.Run("Geo type", mutationGeoType) // error tests t.Run("graphql completion on", graphQLCompletionOn) diff --git a/graphql/e2e/common/mutation.go b/graphql/e2e/common/mutation.go index f7a336d379f..22ab1e4da00 100644 --- a/graphql/e2e/common/mutation.go +++ b/graphql/e2e/common/mutation.go @@ -3746,3 +3746,46 @@ func nestedAddMutationWithHasInverse(t *testing.T) { // cleanup deleteGqlType(t, "Person1", map[string]interface{}{}, 3, nil) } + +func mutationGeoType(t *testing.T) { + addHotelParams := &GraphQLParams{ + Query: ` + mutation addHotel($hotel: AddHotelInput!) { + addHotel(input: [$hotel]) { + hotel { + name + location { + latitude + longitude + } + } + } + }`, + Variables: map[string]interface{}{"hotel": map[string]interface{}{ + "name": "Taj Hotel", + "location": map[string]interface{}{ + "latitude": 11.11, + "longitude": 22.22, + }, + }}, + } + gqlResponse := addHotelParams.ExecuteAsPost(t, GraphqlURL) + RequireNoGQLErrors(t, gqlResponse) + + addHotelExpected := ` + { + "addHotel": { + "hotel": [{ + "name": "Taj Hotel", + "location": { + "latitude": 11.11, + "longitude": 22.22 + } + }] + } + }` + testutil.CompareJSON(t, addHotelExpected, string(gqlResponse.Data)) + + // Cleanup + deleteGqlType(t, "Hotel", map[string]interface{}{}, 2, nil) +} diff --git a/graphql/e2e/normal/schema.graphql b/graphql/e2e/normal/schema.graphql index 5da2c7c654d..bb53af43d7c 100644 --- a/graphql/e2e/normal/schema.graphql +++ b/graphql/e2e/normal/schema.graphql @@ -1,6 +1,12 @@ # **Don't delete** Comments at top of schemas should work # See: https://github.com/dgraph-io/dgraph/issues/4227 +type Hotel { + id: ID! + name: String! @search(by: [exact]) + location: Point @search +} + type Country { # **Don't delete** Comments in types should work id: ID! # **Don't delete** Comments in in lines should work diff --git a/graphql/resolve/add_mutation_test.yaml b/graphql/resolve/add_mutation_test.yaml index a312f293f32..4e850d57733 100644 --- a/graphql/resolve/add_mutation_test.yaml +++ b/graphql/resolve/add_mutation_test.yaml @@ -27,7 +27,7 @@ "Hotel.name":"Taj Hotel", "Hotel.location": { "type": "Point", - "coordinates": [22.22, 11.11] + "coordinates": [22.22, 11.11] } } diff --git a/graphql/resolve/mutation_rewriter.go b/graphql/resolve/mutation_rewriter.go index 6a38750af3f..0e030908213 100644 --- a/graphql/resolve/mutation_rewriter.go +++ b/graphql/resolve/mutation_rewriter.go @@ -1166,6 +1166,8 @@ func rewriteObject( // { "title": "...", "author": { "username": "new user", "dob": "...", ... } // like here ^^ if fieldDef.Type().IsGeo() { + // For Geo type, the mutation json is as follows: + // { "type": "Point", "coordinates": [11.11, 22.22]} lat, _ := val["latitude"] long, _ := val["longitude"] frags = &mutationRes{ diff --git a/graphql/resolve/query_rewriter.go b/graphql/resolve/query_rewriter.go index 26f82b3723c..4fddb73cf29 100644 --- a/graphql/resolve/query_rewriter.go +++ b/graphql/resolve/query_rewriter.go @@ -751,7 +751,10 @@ func addSelectionSetFrom( auth.varName = parentQryName } - selectionAuth := addSelectionSetFrom(child, f, auth) + var selectionAuth []*gql.GraphQuery + if !f.Type().IsGeo() { + selectionAuth = addSelectionSetFrom(child, f, auth) + } addedFields[f.Name()] = true if len(f.SelectionSet()) > 0 && !auth.isWritingAuth && auth.hasAuthRules { @@ -1059,6 +1062,8 @@ func buildFilter(typ schema.Type, filter map[string]interface{}) *gql.FilterTree fn, val := first(dgFunc) switch fn { case "near": + // For Geo type we have `near` filter which is written as follows: + // { near: { distance: 33.33, coordinate: { latitude: 11.11, longitude: 22.22 } } } geoParams := val.(map[string]interface{}) distance, _ := geoParams["distance"] diff --git a/graphql/resolve/query_test.yaml b/graphql/resolve/query_test.yaml index d7bb6ce5d32..93681a57930 100644 --- a/graphql/resolve/query_test.yaml +++ b/graphql/resolve/query_test.yaml @@ -4,12 +4,17 @@ query { queryHotel(filter: { location: { near: { distance: 33.33, coordinate: { latitude: 11.11, longitude: 22.22} } } }) { name + location { + latitude + longitude + } } } dgquery: |- query { queryHotel(func: type(Hotel)) @filter(near(Hotel.location, [22.22,11.11], 33.33)) { name : Hotel.name + location : Hotel.location dgraph.uid : uid } } diff --git a/graphql/resolve/resolver.go b/graphql/resolve/resolver.go index b04c4bb6e1e..9f174faefcf 100644 --- a/graphql/resolve/resolver.go +++ b/graphql/resolve/resolver.go @@ -20,6 +20,7 @@ import ( "bytes" "context" "encoding/json" + "fmt" "io" "io/ioutil" "math" @@ -1226,6 +1227,44 @@ func resolveCustomFields(fields []schema.Field, data interface{}) error { return errs } +// completeGeoObject builds a json GraphQL result object for the geo type. +// It returns a bracketed json object like { "longitude" : 12.32 , "latitude" : 123.32 }. +func completeGeoObject( + path []interface{}, + fields []schema.Field, + val map[string]interface{}) ([]byte, x.GqlErrorList) { + var buf bytes.Buffer + x.Check2(buf.WriteRune('{')) + + coordinate, _ := val["coordinates"].([]interface{}) + comma := "" + + longitude := fmt.Sprintf("%s", coordinate[0]) + latitude := fmt.Sprintf("%s", coordinate[1]) + for _, field := range fields { + x.Check2(buf.WriteString(comma)) + x.Check2(buf.WriteRune('"')) + x.Check2(buf.WriteString(field.ResponseName())) + x.Check2(buf.WriteString(`": `)) + + if field.ResponseName() == "longitude" { + x.Check2(buf.WriteString(longitude)) + } else if field.ResponseName() == "latitude" { + x.Check2(buf.WriteString(latitude)) + } else { + return nil, x.GqlErrorList{&x.GqlError{ + Message: "Invalid field for Geo type", + Locations: []x.Location{field.Location()}, + Path: copyPath(path), + }} + } + comma = "," + } + + x.Check2(buf.WriteRune('}')) + return buf.Bytes(), nil +} + // completeObject builds a json GraphQL result object for the current query level. // It returns a bracketed json object like { f1:..., f2:..., ... }. // @@ -1367,6 +1406,9 @@ func completeValue( Path: copyPath(path), }} } + if field.Type().IsGeo() { + return completeGeoObject(path, field.SelectionSet(), val) + } return completeObject(path, field.SelectionSet(), val) case []interface{}: diff --git a/graphql/resolve/update_mutation_test.yaml b/graphql/resolve/update_mutation_test.yaml index e658ad6d79b..392247d79ae 100644 --- a/graphql/resolve/update_mutation_test.yaml +++ b/graphql/resolve/update_mutation_test.yaml @@ -80,7 +80,6 @@ } } - - name: "Update set mutation with variables" gqlmutation: | diff --git a/graphql/schema/schemagen.go b/graphql/schema/schemagen.go index c0774f5b21f..5e2acd15380 100644 --- a/graphql/schema/schemagen.go +++ b/graphql/schema/schemagen.go @@ -439,8 +439,7 @@ func genDgSchema(gqlSch *ast.Schema, definitions []string) string { switch gqlSch.Types[f.Type.Name()].Kind { case ast.Object, ast.Interface: if isGeoType(f.Type) { - typStr = "geo" - dgPreds[fname] = getUpdatedPred(fname, typStr, "", []string{"geo"}) + dgPreds[fname] = getUpdatedPred(fname, "geo", "", []string{"geo"}) } else { typStr = fmt.Sprintf("%suid%s", prefix, suffix) } diff --git a/graphql/schema/schemagen_test.go b/graphql/schema/schemagen_test.go index 2d13b83e723..914eae7a69e 100644 --- a/graphql/schema/schemagen_test.go +++ b/graphql/schema/schemagen_test.go @@ -77,7 +77,6 @@ func TestSchemaString(t *testing.T) { for _, testFile := range files { t.Run(testFile.Name(), func(t *testing.T) { inputFileName := inputDir + testFile.Name() - str1, err := ioutil.ReadFile(inputFileName) require.NoError(t, err) From 290ea9394aa99ceff2684226fcc128abfe772688 Mon Sep 17 00:00:00 2001 From: Arijit Das Date: Mon, 28 Sep 2020 17:12:26 +0530 Subject: [PATCH 08/20] Fix unit test. --- graphql/schema/schemagen.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/graphql/schema/schemagen.go b/graphql/schema/schemagen.go index 5e2acd15380..c0774f5b21f 100644 --- a/graphql/schema/schemagen.go +++ b/graphql/schema/schemagen.go @@ -439,7 +439,8 @@ func genDgSchema(gqlSch *ast.Schema, definitions []string) string { switch gqlSch.Types[f.Type.Name()].Kind { case ast.Object, ast.Interface: if isGeoType(f.Type) { - dgPreds[fname] = getUpdatedPred(fname, "geo", "", []string{"geo"}) + typStr = "geo" + dgPreds[fname] = getUpdatedPred(fname, typStr, "", []string{"geo"}) } else { typStr = fmt.Sprintf("%suid%s", prefix, suffix) } From f5d4548592b560fbd12d2e29cff60d84815a7ca7 Mon Sep 17 00:00:00 2001 From: Arijit Das Date: Mon, 28 Sep 2020 17:43:37 +0530 Subject: [PATCH 09/20] Fix schema E2E test. --- graphql/e2e/schema/generatedSchema.graphql | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/graphql/e2e/schema/generatedSchema.graphql b/graphql/e2e/schema/generatedSchema.graphql index c28e59a375f..214fb3d5aa0 100644 --- a/graphql/e2e/schema/generatedSchema.graphql +++ b/graphql/e2e/schema/generatedSchema.graphql @@ -38,6 +38,7 @@ enum DgraphIndex { month day hour + geo } input AuthRule { @@ -72,6 +73,25 @@ input CustomHTTP { skipIntrospection: Boolean } +type Point { + longitude: Float! + latitude: Float! +} + +input PointRef { + longitude: Float! + latitude: Float! +} + +input NearFilter { + distance: Float! + coordinate: PointRef! +} + +input PointGeoFilter { + near: NearFilter! +} + directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION From 5cf476140ecfeaf5fd34c822e9ad624a1ea2f70e Mon Sep 17 00:00:00 2001 From: Arijit Das Date: Mon, 28 Sep 2020 18:15:11 +0530 Subject: [PATCH 10/20] Fix GQL directives E2E tests. --- graphql/e2e/common/mutation.go | 2 +- graphql/e2e/directives/schema.graphql | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/graphql/e2e/common/mutation.go b/graphql/e2e/common/mutation.go index 22ab1e4da00..83da11e03fb 100644 --- a/graphql/e2e/common/mutation.go +++ b/graphql/e2e/common/mutation.go @@ -3787,5 +3787,5 @@ func mutationGeoType(t *testing.T) { testutil.CompareJSON(t, addHotelExpected, string(gqlResponse.Data)) // Cleanup - deleteGqlType(t, "Hotel", map[string]interface{}{}, 2, nil) + deleteGqlType(t, "Hotel", map[string]interface{}{}, 1, nil) } diff --git a/graphql/e2e/directives/schema.graphql b/graphql/e2e/directives/schema.graphql index 5089880267d..6e4fcfadef7 100644 --- a/graphql/e2e/directives/schema.graphql +++ b/graphql/e2e/directives/schema.graphql @@ -1,6 +1,12 @@ # **Don't delete** Comments at top of schemas should work # See: https://github.com/dgraph-io/dgraph/issues/4227 +type Hotel { + id: ID! + name: String! @search(by: [exact]) + location: Point @search +} + type Country { # **Don't delete** Comments in types should work id: ID! # **Don't delete** Comments in lines should work From 8192fa8e25645bf1c4f1ce66168041255fd09984 Mon Sep 17 00:00:00 2001 From: Arijit Das Date: Mon, 28 Sep 2020 18:25:57 +0530 Subject: [PATCH 11/20] Fix deepsource errors. --- graphql/resolve/mutation_rewriter.go | 4 ++-- graphql/resolve/query_rewriter.go | 6 +++--- graphql/schema/rules.go | 5 +---- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/graphql/resolve/mutation_rewriter.go b/graphql/resolve/mutation_rewriter.go index 0e030908213..731b6d31f95 100644 --- a/graphql/resolve/mutation_rewriter.go +++ b/graphql/resolve/mutation_rewriter.go @@ -1168,8 +1168,8 @@ func rewriteObject( if fieldDef.Type().IsGeo() { // For Geo type, the mutation json is as follows: // { "type": "Point", "coordinates": [11.11, 22.22]} - lat, _ := val["latitude"] - long, _ := val["longitude"] + lat := val["latitude"] + long := val["longitude"] frags = &mutationRes{ secondPass: []*mutationFragment{ newFragment( diff --git a/graphql/resolve/query_rewriter.go b/graphql/resolve/query_rewriter.go index 4fddb73cf29..4e1bdd95cb5 100644 --- a/graphql/resolve/query_rewriter.go +++ b/graphql/resolve/query_rewriter.go @@ -1065,11 +1065,11 @@ func buildFilter(typ schema.Type, filter map[string]interface{}) *gql.FilterTree // For Geo type we have `near` filter which is written as follows: // { near: { distance: 33.33, coordinate: { latitude: 11.11, longitude: 22.22 } } } geoParams := val.(map[string]interface{}) - distance, _ := geoParams["distance"] + distance := geoParams["distance"] coordinate, _ := geoParams["coordinate"].(map[string]interface{}) - lat, _ := coordinate["latitude"] - long, _ := coordinate["longitude"] + lat := coordinate["latitude"] + long := coordinate["longitude"] args := []gql.Arg{ {Value: typ.DgraphPredicate(field)}, diff --git a/graphql/schema/rules.go b/graphql/schema/rules.go index 77fed63bd51..bf17ad4b5da 100644 --- a/graphql/schema/rules.go +++ b/graphql/schema/rules.go @@ -949,10 +949,7 @@ func validateSearchArg(searchArg string, } func isGeoType(typ *ast.Type) bool { - if typ.Name() == "Point" { - return true - } - return false + return typ.Name() == "Point" } func searchValidation( From ca32d2e173db34b8cfd8bc6e358b2aa598558b6d Mon Sep 17 00:00:00 2001 From: Arijit Das Date: Tue, 29 Sep 2020 16:56:27 +0530 Subject: [PATCH 12/20] Fix test and address comments. --- graphql/e2e/directives/schema_response.json | 661 ++++++++------- graphql/e2e/normal/schema_response.json | 874 +++++++++++++------- graphql/resolve/add_mutation_test.yaml | 3 +- graphql/resolve/resolver.go | 21 +- graphql/schema/dgraph_schemagen_test.yml | 3 + graphql/schema/gqlschema_test.yml | 9 + graphql/schema/rules.go | 6 +- graphql/schema/schemagen.go | 6 +- graphql/schema/wrappers.go | 4 +- graphql/schema/wrappers_test.go | 8 - 10 files changed, 974 insertions(+), 621 deletions(-) diff --git a/graphql/e2e/directives/schema_response.json b/graphql/e2e/directives/schema_response.json index 31f4b72bbf7..278a2f56f55 100644 --- a/graphql/e2e/directives/schema_response.json +++ b/graphql/e2e/directives/schema_response.json @@ -1,54 +1,69 @@ { "schema": [ + { + "predicate": "dgraph.graphql.schema_history", + "type": "string" + }, + { + "predicate": "credits", + "type": "float" + }, + { + "predicate": "Movie.name", + "type": "string" + }, + { + "predicate": "myPost.category", + "type": "uid" + }, { "index": true, "list": true, "predicate": "dgraph.cors", "tokenizer": [ - "exact" + "exact" ], "type": "string", "upsert": true }, { - "predicate": "Category.name", + "predicate": "State.name", "type": "string" }, { - "predicate": "Category.posts", - "type": "uid", - "list": true + "list": true, + "predicate": "Comment1.replies", + "type": "uid" }, { - "predicate": "Comment1.id", - "type": "string", "index": true, + "predicate": "People.xid", "tokenizer": [ "hash" ], + "type": "string", "upsert": true }, { - "predicate": "Comment1.replies", - "type": "uid", - "list": true + "predicate": "post", + "type": "string" }, { - "predicate": "Country.name", - "type": "string", "index": true, + "list": true, + "predicate": "dgraph.type", "tokenizer": [ - "hash", - "trigram" - ] - }, - { - "predicate": "Human.starships", - "type": "uid", - "list": true + "exact" + ], + "type": "string" }, { - "predicate": "Movie.name", + "index": true, + "list": true, + "predicate": "myPost.tags", + "tokenizer": [ + "exact" + ], "type": "string" }, { @@ -56,248 +71,255 @@ "type": "string" }, { - "predicate": "People.name", + "index": true, + "predicate": "star.ship.name", + "tokenizer": [ + "term" + ], "type": "string" }, { - "predicate": "People.xid", - "type": "string", "index": true, + "predicate": "text", "tokenizer": [ - "hash" + "fulltext" ], - "upsert": true + "type": "string" }, { - "predicate": "Person1.name", + "predicate": "Category.name", "type": "string" }, { - "predicate": "Person1.friends", - "type": "uid", - "list": true + "list": true, + "predicate": "Post1.comments", + "type": "uid" }, { - "predicate": "Post1.comments", - "type": "uid", - "list": true + "list": true, + "predicate": "hasStates", + "type": "uid" + }, + { + "predicate": "Person1.name", + "type": "string" }, { - "predicate": "Post1.id", - "type": "string", "index": true, + "predicate": "myPost.title", + "tokenizer": [ + "fulltext", + "term" + ], + "type": "string" + }, + { + "index": true, + "predicate": "Comment1.id", "tokenizer": [ "hash" ], + "type": "string", "upsert": true }, { - "predicate": "post1.title", - "type": "string", "index": true, - "tokenizer": ["trigram", "hash"], + "predicate": "User.name", + "tokenizer": [ + "hash" + ], + "type": "string", "upsert": true }, { - "predicate": "post1.numLikes", - "type": "int" + "list": true, + "predicate": "directed.movies", + "reverse": true, + "type": "uid" }, { - "predicate": "State.capital", + "index": true, + "predicate": "Hotel.name", + "tokenizer": [ + "exact" + ], "type": "string" }, { - "predicate": "State.name", - "type": "string" + "index": true, + "predicate": "test.dgraph.author.dob", + "tokenizer": [ + "year" + ], + "type": "datetime" }, { - "predicate": "State.xcode", - "type": "string", "index": true, + "predicate": "post1.title", "tokenizer": [ "hash", "trigram" ], + "type": "string", "upsert": true }, { - "predicate": "Student.taughtBy", - "type": "uid", - "list": true - }, - { - "predicate": "Teacher.subject", - "type": "string" - }, - { - "predicate": "Teacher.teaches", - "type": "uid", - "list": true - }, - { - "predicate": "Thing.name", - "type": "string" + "list": true, + "predicate": "test.dgraph.author.posts", + "type": "uid" }, { - "predicate": "ThingOne.color", - "type": "string" + "predicate": "post.author", + "type": "uid" }, { - "predicate": "ThingOne.usedBy", + "index": true, + "predicate": "test.dgraph.topic", + "tokenizer": [ + "exact" + ], "type": "string" }, { - "predicate": "ThingTwo.color", - "type": "string" + "index": true, + "predicate": "State.xcode", + "tokenizer": [ + "hash", + "trigram" + ], + "type": "string", + "upsert": true }, { - "predicate": "ThingTwo.owner", + "index": true, + "predicate": "performance.character.name", + "tokenizer": [ + "exact" + ], "type": "string" }, { - "predicate": "User.name", - "type": "string", "index": true, + "predicate": "test.dgraph.author.name", "tokenizer": [ - "hash" + "hash", + "trigram" ], - "upsert": true + "type": "string" }, { - "predicate": "appears_in", - "type": "string", "index": true, + "predicate": "Country.name", "tokenizer": [ - "hash" + "hash", + "trigram" ], - "list": true - }, - { - "predicate": "credits", - "type": "float" + "type": "string" }, { - "predicate": "dgraph.graphql.schema", - "type": "string" + "list": true, + "predicate": "Human.starships", + "type": "uid" }, { "predicate": "dgraph.graphql.schema_created_at", "type": "datetime" }, { - "predicate": "dgraph.graphql.schema_history", + "predicate": "dgraph.graphql.schema", "type": "string" }, { - "predicate": "dgraph.graphql.xid", - "type": "string", - "index": true, - "tokenizer": [ - "exact" - ], - "upsert": true - }, - { - "predicate": "dgraph.type", - "type": "string", "index": true, + "predicate": "myPost.postType", "tokenizer": [ - "exact" + "hash", + "trigram" ], - "list": true + "type": "string" }, { - "predicate": "directed.movies", - "type": "uid", - "reverse": true, - "list": true + "predicate": "post1.numLikes", + "type": "int" }, { - "predicate": "hasStates", - "type": "uid", - "list": true + "predicate": "test.dgraph.employee.en.ename", + "type": "string" }, { - "predicate": "inCountry", + "list": true, + "predicate": "Category.posts", "type": "uid" }, { - "predicate": "is_published", - "type": "bool", - "index": true, - "tokenizer": [ - "bool" - ] - }, - { - "predicate": "myPost.category", - "type": "uid" + "predicate": "职业", + "type": "string" }, { - "predicate": "myPost.numLikes", - "type": "int", "index": true, + "predicate": "myPost.numLikes", "tokenizer": [ "int" - ] + ], + "type": "int" }, { - "predicate": "myPost.numViews", - "type": "int", "index": true, + "predicate": "myPost.numViews", "tokenizer": [ "int" - ] - }, - { - "predicate": "myPost.postType", - "type": "string", - "index": true, - "tokenizer": [ - "hash", - "trigram" - ] + ], + "type": "int" }, { - "predicate": "myPost.tags", - "type": "string", "index": true, + "predicate": "dgraph.graphql.xid", "tokenizer": [ "exact" ], - "list": true + "type": "string", + "upsert": true }, { - "predicate": "myPost.title", - "type": "string", - "index": true, - "tokenizer": [ - "fulltext", - "term" - ] + "predicate": "test.dgraph.author.country", + "type": "uid" }, { - "predicate": "performance.character.name", - "type": "string", - "index": true, - "tokenizer": [ - "exact" - ] + "list": true, + "predicate": "Person1.friends", + "type": "uid" }, { - "predicate": "post", + "predicate": "ThingOne.usedBy", "type": "string" }, { - "predicate": "post.author", - "type": "uid" + "index": true, + "predicate": "is_published", + "tokenizer": [ + "bool" + ], + "type": "bool" }, { "predicate": "pwd", "type": "password" }, { - "predicate": "roboDroid.primaryFunction", + "predicate": "inCountry", + "type": "uid" + }, + { + "index": true, + "list": true, + "predicate": "appears_in", + "tokenizer": [ + "hash" + ], + "type": "string" + }, + { + "predicate": "Thing.name", "type": "string" }, { @@ -305,280 +327,315 @@ "type": "float" }, { - "predicate": "star.ship.name", - "type": "string", + "predicate": "Teacher.subject", + "type": "string" + }, + { "index": true, + "predicate": "test.dgraph.author.reputation", "tokenizer": [ - "term" - ] + "float" + ], + "type": "float" }, { - "predicate": "test.dgraph.author.country", - "type": "uid" + "predicate": "State.capital", + "type": "string" }, { - "predicate": "test.dgraph.author.dob", - "type": "datetime", "index": true, + "predicate": "Hotel.location", "tokenizer": [ - "year" - ] + "geo" + ], + "type": "geo" }, { - "predicate": "test.dgraph.author.name", - "type": "string", - "index": true, - "tokenizer": [ - "hash", - "trigram" - ] + "predicate": "ThingTwo.owner", + "type": "string" }, { - "predicate": "test.dgraph.author.posts", - "type": "uid", - "list": true + "predicate": "ThingTwo.color", + "type": "string" }, { - "predicate": "test.dgraph.author.reputation", - "type": "float", - "index": true, - "tokenizer": [ - "float" - ] + "predicate": "roboDroid.primaryFunction", + "type": "string" }, { - "predicate": "test.dgraph.employee.en.ename", + "list": true, + "predicate": "Teacher.teaches", + "type": "uid" + }, + { + "predicate": "People.name", "type": "string" }, { - "predicate": "test.dgraph.topic", - "type": "string", - "index": true, - "tokenizer": [ - "exact" - ] + "predicate": "ThingOne.color", + "type": "string" }, { - "predicate": "text", - "type": "string", - "index": true, - "tokenizer": [ - "fulltext" - ] + "list": true, + "predicate": "Student.taughtBy", + "type": "uid" }, { - "predicate": "职业", - "type": "string" + "index": true, + "predicate": "Post1.id", + "tokenizer": [ + "hash" + ], + "type": "string", + "upsert": true } ], "types": [ { "fields": [ { - "name": "Category.name" + "name": "Movie.name" + } + ], + "name": "Movie" + }, + { + "fields": [ + { + "name": "People.xid" }, { - "name": "Category.posts" + "name": "People.name" + }, + { + "name": "Student.taughtBy" } ], - "name": "Category" + "name": "Student" }, { "fields": [ { - "name": "Comment1.id" + "name": "MovieDirector.name" }, { - "name": "Comment1.replies" + "name": "directed.movies" } ], - "name": "Comment1" + "name": "MovieDirector" }, { "fields": [ { - "name": "Country.name" + "name": "dgraph.graphql.schema" }, { - "name": "hasStates" + "name": "dgraph.graphql.xid" } ], - "name": "Country" + "name": "dgraph.graphql" }, { "fields": [ { - "name": "test.dgraph.employee.en.ename" + "name": "test.dgraph.author.dob" }, { - "name": "performance.character.name" + "name": "test.dgraph.author.posts" }, { - "name": "appears_in" + "name": "test.dgraph.author.name" }, { - "name": "Human.starships" + "name": "test.dgraph.author.country" }, { - "name": "credits" + "name": "test.dgraph.author.reputation" } ], - "name": "Human" + "name": "test.dgraph.author" }, { "fields": [ { - "name": "post" + "name": "pwd" }, { - "name": "职业" + "name": "User.name" } ], - "name": "Message" + "name": "User" }, { "fields": [ { - "name": "Movie.name" + "name": "test.dgraph.employee.en.ename" } ], - "name": "Movie" + "name": "test.dgraph.employee.en" }, { "fields": [ { - "name": "MovieDirector.name" + "name": "text" }, { - "name": "directed.movies" + "name": "myPost.category" + }, + { + "name": "myPost.tags" + }, + { + "name": "post.author" + }, + { + "name": "myPost.title" + }, + { + "name": "test.dgraph.topic" + }, + { + "name": "myPost.postType" + }, + { + "name": "is_published" + }, + { + "name": "myPost.numLikes" + }, + { + "name": "myPost.numViews" } ], - "name": "MovieDirector" + "name": "myPost" }, { "fields": [ { - "name": "People.xid" + "name": "performance.character.name" }, { - "name": "People.name" + "name": "appears_in" + }, + { + "name": "roboDroid.primaryFunction" } ], - "name": "People" + "name": "roboDroid" }, { "fields": [ { - "name": "Person1.name" + "name": "State.name" }, { - "name": "Person1.friends" + "name": "State.xcode" + }, + { + "name": "State.capital" + }, + { + "name": "inCountry" } ], - "name": "Person1" + "name": "State" }, { "fields": [ { - "name": "Post1.id" + "name": "Comment1.replies" }, { - "name": "Post1.comments" + "name": "Comment1.id" } ], - "name": "Post1" + "name": "Comment1" }, { "fields": [ { - "name": "post1.title" + "name": "hasStates" }, { - "name": "post1.numLikes" + "name": "Country.name" } ], - "name": "post1" + "name": "Country" }, { "fields": [ { - "name": "State.xcode" + "name": "credits" }, { - "name": "State.name" + "name": "Human.starships" }, { - "name": "State.capital" + "name": "performance.character.name" }, { - "name": "inCountry" + "name": "test.dgraph.employee.en.ename" + }, + { + "name": "appears_in" } ], - "name": "State" + "name": "Human" }, { "fields": [ { - "name": "People.xid" - }, - { - "name": "People.name" + "name": "Post1.comments" }, { - "name": "Student.taughtBy" + "name": "Post1.id" } ], - "name": "Student" + "name": "Post1" }, { "fields": [ { - "name": "People.xid" - }, - { - "name": "People.name" - }, - { - "name": "Teacher.subject" + "name": "post1.title" }, { - "name": "Teacher.teaches" + "name": "post1.numLikes" } ], - "name": "Teacher" + "name": "post1" }, { "fields": [ { - "name": "Thing.name" + "name": "star.ship.name" + }, + { + "name": "star.ship.length" } ], - "name": "Thing" + "name": "star.ship" }, { "fields": [ { - "name": "Thing.name" - }, - { - "name": "ThingOne.color" + "name": "dgraph.graphql.schema_history" }, { - "name": "ThingOne.usedBy" + "name": "dgraph.graphql.schema_created_at" } ], - "name": "ThingOne" + "name": "dgraph.graphql.history" }, { "fields": [ - { - "name": "Thing.name" - }, { "name": "ThingTwo.color" }, { "name": "ThingTwo.owner" + }, + { + "name": "Thing.name" } ], "name": "ThingTwo" @@ -586,69 +643,43 @@ { "fields": [ { - "name": "User.name" + "name": "post" }, { - "name": "pwd" + "name": "职业" } ], - "name": "User" + "name": "Message" }, { "fields": [ { - "name": "dgraph.graphql.schema" + "name": "Hotel.name" }, { - "name": "dgraph.graphql.xid" + "name": "Hotel.location" } ], - "name": "dgraph.graphql" + "name": "Hotel" }, { "fields": [ { - "name": "dgraph.graphql.schema_history" - },{ - "name": "dgraph.graphql.schema_created_at" + "name": "Category.name" + }, + { + "name": "Category.posts" } ], - "name": "dgraph.graphql.history" + "name": "Category" }, { "fields": [ { - "name": "myPost.title" - }, - { - "name": "text" - }, - { - "name": "myPost.tags" - }, - { - "name": "test.dgraph.topic" - }, - { - "name": "myPost.numLikes" - }, - { - "name": "myPost.numViews" - }, - { - "name": "is_published" - }, - { - "name": "myPost.postType" - }, - { - "name": "post.author" - }, - { - "name": "myPost.category" + "name": "Thing.name" } ], - "name": "myPost" + "name": "Thing" }, { "fields": [ @@ -664,55 +695,55 @@ { "fields": [ { - "name": "performance.character.name" + "name": "People.xid" }, { - "name": "appears_in" + "name": "People.name" }, { - "name": "roboDroid.primaryFunction" + "name": "Teacher.subject" + }, + { + "name": "Teacher.teaches" } ], - "name": "roboDroid" + "name": "Teacher" }, { "fields": [ { - "name": "star.ship.name" + "name": "ThingOne.usedBy" }, { - "name": "star.ship.length" + "name": "ThingOne.color" + }, + { + "name": "Thing.name" } ], - "name": "star.ship" + "name": "ThingOne" }, { "fields": [ { - "name": "test.dgraph.author.name" - }, - { - "name": "test.dgraph.author.dob" - }, - { - "name": "test.dgraph.author.reputation" - }, - { - "name": "test.dgraph.author.country" + "name": "People.xid" }, { - "name": "test.dgraph.author.posts" + "name": "People.name" } ], - "name": "test.dgraph.author" + "name": "People" }, { "fields": [ { - "name": "test.dgraph.employee.en.ename" + "name": "Person1.name" + }, + { + "name": "Person1.friends" } ], - "name": "test.dgraph.employee.en" + "name": "Person1" } ] } \ No newline at end of file diff --git a/graphql/e2e/normal/schema_response.json b/graphql/e2e/normal/schema_response.json index 39767d12e22..b6d514d10d0 100644 --- a/graphql/e2e/normal/schema_response.json +++ b/graphql/e2e/normal/schema_response.json @@ -1,633 +1,961 @@ { "schema": [ + { + "predicate": "dgraph.graphql.schema_history", + "type": "string" + }, + { + "predicate": "credits", + "type": "float" + }, + { + "predicate": "Movie.name", + "type": "string" + }, + { + "predicate": "Post.category", + "type": "uid" + }, + { + "predicate": "myPost.category", + "type": "uid" + }, { "index": true, "list": true, "predicate": "dgraph.cors", "tokenizer": [ - "exact" + "exact" ], "type": "string", "upsert": true }, { - "predicate": "Author.country", + "list": true, + "predicate": "Author.posts", + "type": "uid" + }, + { + "predicate": "State.name", + "type": "string" + }, + { + "list": true, + "predicate": "Comment1.replies", "type": "uid" }, { - "predicate": "Author.dob", - "type": "datetime", "index": true, + "predicate": "People.xid", "tokenizer": [ - "year" - ] + "hash" + ], + "type": "string", + "upsert": true }, { - "predicate": "Author.name", - "type": "string", "index": true, + "predicate": "Author.name", "tokenizer": [ "hash", "trigram" - ] - }, - { - "predicate": "Author.posts", - "type": "uid", - "list": true + ], + "type": "string" }, { - "predicate": "Author.reputation", - "type": "float", "index": true, + "predicate": "Author.reputation", "tokenizer": [ "float" - ] + ], + "type": "float" }, { - "predicate": "Category.name", + "predicate": "Human.totalCredits", + "type": "float" + }, + { + "predicate": "post", "type": "string" }, { - "predicate": "Category.posts", - "type": "uid", - "list": true + "index": true, + "list": true, + "predicate": "dgraph.type", + "tokenizer": [ + "exact" + ], + "type": "string" }, { - "predicate": "Character.appearsIn", - "type": "string", "index": true, + "predicate": "Author.dob", "tokenizer": [ - "hash" + "year" ], - "list": true + "type": "datetime" }, { - "predicate": "Character.name", - "type": "string", "index": true, + "list": true, + "predicate": "myPost.tags", "tokenizer": [ "exact" - ] + ], + "type": "string" }, { - "predicate": "Comment1.id", - "type": "string", "index": true, + "list": true, + "predicate": "Post.tags", "tokenizer": [ - "hash" + "exact" ], - "upsert": true + "type": "string" }, { - "predicate": "Comment1.replies", - "type": "uid", - "list": true + "predicate": "MovieDirector.name", + "type": "string" }, { - "predicate": "Country.name", - "type": "string", "index": true, + "predicate": "star.ship.name", "tokenizer": [ - "hash", - "trigram" - ] + "term" + ], + "type": "string" }, { - "predicate": "Country.states", - "type": "uid", - "list": true + "index": true, + "predicate": "Starship.name", + "tokenizer": [ + "term" + ], + "type": "string" }, { - "predicate": "Droid.primaryFunction", + "list": true, + "predicate": "Movie.director", + "type": "uid" + }, + { + "index": true, + "predicate": "text", + "tokenizer": [ + "fulltext" + ], "type": "string" }, { - "predicate": "Employee.ename", + "predicate": "Category.name", "type": "string" }, { - "predicate": "Human.starships", - "type": "uid", - "list": true + "list": true, + "predicate": "Post1.comments", + "type": "uid" }, { - "predicate": "Human.totalCredits", - "type": "float" + "index": true, + "predicate": "Post.text", + "tokenizer": [ + "fulltext" + ], + "type": "string" }, { - "predicate": "Movie.director", - "type": "uid", - "list": true + "list": true, + "predicate": "hasStates", + "type": "uid" }, { - "predicate": "Movie.name", + "predicate": "Person1.name", "type": "string" }, { - "predicate": "MovieDirector.directed", - "type": "uid", - "list": true + "predicate": "Droid.primaryFunction", + "type": "string" }, { - "predicate": "MovieDirector.name", + "index": true, + "predicate": "Post.title", + "tokenizer": [ + "fulltext", + "term" + ], "type": "string" }, { - "predicate": "People.name", + "index": true, + "predicate": "myPost.title", + "tokenizer": [ + "fulltext", + "term" + ], "type": "string" }, { - "predicate": "People.xid", + "index": true, + "predicate": "Comment1.id", + "tokenizer": [ + "hash" + ], "type": "string", + "upsert": true + }, + { "index": true, + "predicate": "User.name", "tokenizer": [ "hash" ], + "type": "string", "upsert": true }, { - "predicate": "Person.name", + "list": true, + "predicate": "directed.movies", + "reverse": true, + "type": "uid" + }, + { + "index": true, + "predicate": "Character.name", + "tokenizer": [ + "exact" + ], "type": "string" }, { - "predicate": "Person1.name", + "index": true, + "predicate": "Hotel.name", + "tokenizer": [ + "exact" + ], "type": "string" }, { - "predicate": "Person1.friends", - "type": "uid", - "list": true + "index": true, + "predicate": "test.dgraph.author.dob", + "tokenizer": [ + "year" + ], + "type": "datetime" }, { - "predicate": "Post.author", + "index": true, + "predicate": "post1.title", + "tokenizer": [ + "hash", + "trigram" + ], + "type": "string", + "upsert": true + }, + { + "list": true, + "predicate": "test.dgraph.author.posts", "type": "uid" }, { - "predicate": "Post.category", + "predicate": "Person.name", + "type": "string" + }, + { + "predicate": "post.author", "type": "uid" }, { - "predicate": "Post.isPublished", - "type": "bool", - "index": true, - "tokenizer": [ - "bool" - ] + "predicate": "Post.author", + "type": "uid" }, { - "predicate": "Post.numLikes", - "type": "int", "index": true, + "predicate": "Post.topic", "tokenizer": [ - "int" - ] + "exact" + ], + "type": "string" }, { - "predicate": "Post.numViews", - "type": "int", "index": true, + "predicate": "test.dgraph.topic", "tokenizer": [ - "int" - ] + "exact" + ], + "type": "string" }, { - "predicate": "Post.postType", - "type": "string", "index": true, + "predicate": "State.xcode", "tokenizer": [ "hash", "trigram" - ] + ], + "type": "string", + "upsert": true }, { - "predicate": "Post.tags", - "type": "string", "index": true, + "predicate": "performance.character.name", "tokenizer": [ "exact" ], - "list": true + "type": "string" }, { - "predicate": "Post.text", - "type": "string", "index": true, + "predicate": "test.dgraph.author.name", "tokenizer": [ - "fulltext" - ] + "hash", + "trigram" + ], + "type": "string" }, { - "predicate": "Post.title", - "type": "string", "index": true, + "predicate": "Country.name", "tokenizer": [ - "fulltext", - "term" - ] + "hash", + "trigram" + ], + "type": "string" + }, + { + "list": true, + "predicate": "Human.starships", + "type": "uid" + }, + { + "predicate": "User.password", + "type": "password" + }, + { + "predicate": "dgraph.graphql.schema_created_at", + "type": "datetime" + }, + { + "predicate": "dgraph.graphql.schema", + "type": "string" }, { - "predicate": "Post.topic", - "type": "string", "index": true, + "predicate": "Post.postType", "tokenizer": [ - "exact" - ] + "hash", + "trigram" + ], + "type": "string" }, { - "predicate": "Post1.comments", - "type": "uid", - "list": true + "index": true, + "predicate": "myPost.postType", + "tokenizer": [ + "hash", + "trigram" + ], + "type": "string" + }, + { + "predicate": "post1.numLikes", + "type": "int" + }, + { + "predicate": "test.dgraph.employee.en.ename", + "type": "string" + }, + { + "list": true, + "predicate": "MovieDirector.directed", + "type": "uid" + }, + { + "list": true, + "predicate": "Category.posts", + "type": "uid" + }, + { + "predicate": "职业", + "type": "string" }, { - "predicate": "Post1.id", - "type": "string", "index": true, + "predicate": "myPost.numLikes", "tokenizer": [ - "hash" + "int" ], - "upsert": true + "type": "int" }, { - "predicate": "post1.title", - "type": "string", "index": true, - "tokenizer": ["trigram", "hash"], - "upsert": true + "predicate": "Post.numLikes", + "tokenizer": [ + "int" + ], + "type": "int" }, { - "predicate": "post1.numLikes", + "index": true, + "predicate": "Post.numViews", + "tokenizer": [ + "int" + ], "type": "int" }, { - "predicate": "Starship.length", - "type": "float" + "index": true, + "predicate": "myPost.numViews", + "tokenizer": [ + "int" + ], + "type": "int" }, { - "predicate": "Starship.name", + "index": true, + "predicate": "dgraph.graphql.xid", + "tokenizer": [ + "exact" + ], "type": "string", + "upsert": true + }, + { + "predicate": "test.dgraph.author.country", + "type": "uid" + }, + { "index": true, + "list": true, + "predicate": "Character.appearsIn", "tokenizer": [ - "term" - ] + "hash" + ], + "type": "string" }, { - "predicate": "State.capital", + "predicate": "Employee.ename", "type": "string" }, { - "predicate": "State.country", + "list": true, + "predicate": "Person1.friends", "type": "uid" }, { - "predicate": "State.name", + "predicate": "ThingOne.usedBy", "type": "string" }, { - "predicate": "State.xcode", - "type": "string", "index": true, + "predicate": "is_published", "tokenizer": [ - "hash", - "trigram" + "bool" ], - "upsert": true + "type": "bool" }, { - "predicate": "Student.taughtBy", - "type": "uid", - "list": true + "predicate": "pwd", + "type": "password" }, { - "predicate": "Teacher.subject", + "predicate": "inCountry", + "type": "uid" + }, + { + "index": true, + "list": true, + "predicate": "appears_in", + "tokenizer": [ + "hash" + ], "type": "string" }, { - "predicate": "Teacher.teaches", - "type": "uid", - "list": true + "predicate": "State.country", + "type": "uid" }, { "predicate": "Thing.name", "type": "string" }, { - "predicate": "ThingOne.color", - "type": "string" + "predicate": "star.ship.length", + "type": "float" }, { - "predicate": "ThingOne.usedBy", + "predicate": "Teacher.subject", "type": "string" }, { - "predicate": "ThingTwo.color", - "type": "string" + "index": true, + "predicate": "test.dgraph.author.reputation", + "tokenizer": [ + "float" + ], + "type": "float" }, { - "predicate": "ThingTwo.owner", + "predicate": "State.capital", "type": "string" }, { - "predicate": "User.name", - "type": "string", "index": true, + "predicate": "Hotel.location", "tokenizer": [ - "hash" + "geo" ], - "upsert": true + "type": "geo" }, { - "predicate": "User.password", - "type": "password" + "predicate": "ThingTwo.owner", + "type": "string" }, { - "predicate": "dgraph.graphql.schema", + "predicate": "ThingTwo.color", "type": "string" }, { - "predicate": "dgraph.graphql.schema_created_at", - "type": "datetime" - }, + "predicate": "Author.country", + "type": "uid" + }, { - "predicate": "dgraph.graphql.schema_history", + "predicate": "roboDroid.primaryFunction", "type": "string" - }, + }, { - "predicate": "dgraph.graphql.xid", + "list": true, + "predicate": "Teacher.teaches", + "type": "uid" + }, + { + "predicate": "People.name", + "type": "string" + }, + { + "predicate": "ThingOne.color", + "type": "string" + }, + { + "list": true, + "predicate": "Student.taughtBy", + "type": "uid" + }, + { + "predicate": "Starship.length", + "type": "float" + }, + { + "index": true, + "predicate": "Post1.id", + "tokenizer": [ + "hash" + ], "type": "string", + "upsert": true + }, + { "index": true, + "predicate": "Post.isPublished", "tokenizer": [ - "exact" + "bool" + ], + "type": "bool" + }, + { + "list": true, + "predicate": "Country.states", + "type": "uid" + } + ], + "types": [ + { + "fields": [ + { + "name": "People.xid" + }, + { + "name": "People.name" + }, + { + "name": "Student.taughtBy" + } + ], + "name": "Student" + }, + { + "fields": [ + { + "name": "dgraph.graphql.schema" + }, + { + "name": "dgraph.graphql.xid" + } + ], + "name": "dgraph.graphql" + }, + { + "fields": [ + { + "name": "Movie.director" + }, + { + "name": "Movie.name" + } + ], + "name": "Movie" + }, + { + "fields": [ + { + "name": "Employee.ename" + } + ], + "name": "Employee" + }, + { + "fields": [ + { + "name": "Post.category" + }, + { + "name": "Post.tags" + }, + { + "name": "Post.text" + }, + { + "name": "Post.author" + }, + { + "name": "Post.title" + }, + { + "name": "Post.topic" + }, + { + "name": "Post.postType" + }, + { + "name": "Post.numLikes" + }, + { + "name": "Post.numViews" + }, + { + "name": "Post.isPublished" + } ], - "upsert": true + "name": "Post" }, { - "predicate": "dgraph.type", - "type": "string", - "index": true, - "tokenizer": [ - "exact" + "fields": [ + { + "name": "Human.totalCredits" + }, + { + "name": "Human.starships" + }, + { + "name": "Character.name" + }, + { + "name": "Employee.ename" + }, + { + "name": "Character.appearsIn" + } ], - "list": true - } - ], - "types": [ + "name": "Human" + }, { "fields": [ { - "name": "Author.name" + "name": "test.dgraph.author.dob" }, { - "name": "Author.dob" + "name": "test.dgraph.author.posts" }, { - "name": "Author.reputation" + "name": "test.dgraph.author.name" }, { - "name": "Author.country" + "name": "test.dgraph.author.country" }, { - "name": "Author.posts" + "name": "test.dgraph.author.reputation" } ], - "name": "Author" + "name": "test.dgraph.author" }, { "fields": [ { - "name": "Category.name" - }, + "name": "Person.name" + } + ], + "name": "Person" + }, + { + "fields": [ { - "name": "Category.posts" + "name": "test.dgraph.employee.en.ename" } ], - "name": "Category" + "name": "test.dgraph.employee.en" }, { "fields": [ { - "name": "Character.name" + "name": "text" }, { - "name": "Character.appearsIn" + "name": "myPost.category" + }, + { + "name": "myPost.tags" + }, + { + "name": "post.author" + }, + { + "name": "myPost.title" + }, + { + "name": "test.dgraph.topic" + }, + { + "name": "myPost.postType" + }, + { + "name": "is_published" + }, + { + "name": "myPost.numLikes" + }, + { + "name": "myPost.numViews" } ], - "name": "Character" + "name": "myPost" }, { "fields": [ { - "name": "Comment1.id" + "name": "performance.character.name" }, { - "name": "Comment1.replies" + "name": "appears_in" + }, + { + "name": "roboDroid.primaryFunction" } ], - "name": "Comment1" + "name": "roboDroid" }, { "fields": [ { - "name": "Country.name" + "name": "Comment1.replies" }, { - "name": "Country.states" + "name": "Comment1.id" } ], - "name": "Country" + "name": "Comment1" }, { "fields": [ { - "name": "Character.name" + "name": "State.name" }, { - "name": "Character.appearsIn" + "name": "State.xcode" }, { - "name": "Droid.primaryFunction" + "name": "State.capital" + }, + { + "name": "State.country" } ], - "name": "Droid" + "name": "State" }, { "fields": [ { - "name": "Employee.ename" + "name": "Post1.comments" + }, + { + "name": "Post1.id" } ], - "name": "Employee" + "name": "Post1" }, { "fields": [ { - "name": "Employee.ename" + "name": "Author.posts" }, { - "name": "Character.name" + "name": "Author.name" }, { - "name": "Character.appearsIn" + "name": "Author.reputation" }, { - "name": "Human.starships" + "name": "Author.dob" }, { - "name": "Human.totalCredits" + "name": "Author.country" } ], - "name": "Human" + "name": "Author" }, { "fields": [ { - "name": "Movie.name" + "name": "Starship.name" }, { - "name": "Movie.director" + "name": "Starship.length" } ], - "name": "Movie" + "name": "Starship" }, { "fields": [ { - "name": "MovieDirector.name" + "name": "Character.name" }, { - "name": "MovieDirector.directed" + "name": "Droid.primaryFunction" + }, + { + "name": "Character.appearsIn" } ], - "name": "MovieDirector" + "name": "Droid" }, { "fields": [ { - "name": "People.xid" + "name": "post1.title" }, { - "name": "People.name" + "name": "post1.numLikes" } ], - "name": "People" + "name": "post1" }, { "fields": [ { - "name": "Person.name" + "name": "star.ship.name" + }, + { + "name": "star.ship.length" } ], - "name": "Person" + "name": "star.ship" }, { "fields": [ { - "name": "Person1.name" + "name": "dgraph.graphql.schema_history" }, { - "name": "Person1.friends" + "name": "dgraph.graphql.schema_created_at" } ], - "name": "Person1" + "name": "dgraph.graphql.history" }, { "fields": [ { - "name": "Post.title" - }, - { - "name": "Post.text" - }, - { - "name": "Post.tags" - }, - { - "name": "Post.topic" - }, - { - "name": "Post.numLikes" - }, - { - "name": "Post.numViews" + "name": "ThingTwo.color" }, { - "name": "Post.isPublished" + "name": "ThingTwo.owner" }, { - "name": "Post.postType" - }, + "name": "Thing.name" + } + ], + "name": "ThingTwo" + }, + { + "fields": [ { - "name": "Post.author" + "name": "post" }, { - "name": "Post.category" + "name": "职业" } ], - "name": "Post" + "name": "Message" }, { "fields": [ { - "name": "Post1.id" + "name": "Hotel.name" }, { - "name": "Post1.comments" + "name": "Hotel.location" } ], - "name": "Post1" + "name": "Hotel" }, { "fields": [ { - "name": "post1.title" + "name": "Country.name" }, { - "name": "post1.numLikes" + "name": "Country.states" } ], - "name": "post1" + "name": "Country" }, { "fields": [ { - "name": "Starship.name" + "name": "Category.name" }, { - "name": "Starship.length" + "name": "Category.posts" } ], - "name": "Starship" + "name": "Category" }, { "fields": [ { - "name": "State.xcode" - }, - { - "name": "State.name" - }, + "name": "Thing.name" + } + ], + "name": "Thing" + }, + { + "fields": [ { - "name": "State.capital" + "name": "performance.character.name" }, { - "name": "State.country" + "name": "appears_in" } ], - "name": "State" + "name": "performance.character" }, { "fields": [ { - "name": "People.xid" - }, - { - "name": "People.name" + "name": "Character.name" }, { - "name": "Student.taughtBy" + "name": "Character.appearsIn" } ], - "name": "Student" + "name": "Character" }, { "fields": [ @@ -649,21 +977,24 @@ { "fields": [ { - "name": "Thing.name" + "name": "User.name" + }, + { + "name": "User.password" } ], - "name": "Thing" + "name": "User" }, { "fields": [ { - "name": "Thing.name" + "name": "ThingOne.usedBy" }, { "name": "ThingOne.color" }, { - "name": "ThingOne.usedBy" + "name": "Thing.name" } ], "name": "ThingOne" @@ -671,48 +1002,35 @@ { "fields": [ { - "name": "Thing.name" - }, - { - "name": "ThingTwo.color" + "name": "MovieDirector.name" }, { - "name": "ThingTwo.owner" + "name": "MovieDirector.directed" } ], - "name": "ThingTwo" + "name": "MovieDirector" }, { "fields": [ { - "name": "User.name" + "name": "People.xid" }, { - "name": "User.password" + "name": "People.name" } ], - "name": "User" + "name": "People" }, { "fields": [ { - "name": "dgraph.graphql.schema" + "name": "Person1.name" }, { - "name": "dgraph.graphql.xid" - } - ], - "name": "dgraph.graphql" - }, - { - "fields": [ - { - "name": "dgraph.graphql.schema_history" - },{ - "name": "dgraph.graphql.schema_created_at" + "name": "Person1.friends" } ], - "name": "dgraph.graphql.history" + "name": "Person1" } ] } \ No newline at end of file diff --git a/graphql/resolve/add_mutation_test.yaml b/graphql/resolve/add_mutation_test.yaml index 4e850d57733..6663194f7b9 100644 --- a/graphql/resolve/add_mutation_test.yaml +++ b/graphql/resolve/add_mutation_test.yaml @@ -18,8 +18,7 @@ "location": { "latitude": 11.11 , "longitude" : 22.22} } } - explanation: "A uid and type should get injected and all data transformed to - underlying Dgraph edge names" + explanation: "Add mutation should convert the Point type mutation to corresponding Dgraph JSON mutation" dgmutations: - setjson: | { "uid":"_:Hotel1", diff --git a/graphql/resolve/resolver.go b/graphql/resolve/resolver.go index 9f174faefcf..4828b12f029 100644 --- a/graphql/resolve/resolver.go +++ b/graphql/resolve/resolver.go @@ -1229,10 +1229,7 @@ func resolveCustomFields(fields []schema.Field, data interface{}) error { // completeGeoObject builds a json GraphQL result object for the geo type. // It returns a bracketed json object like { "longitude" : 12.32 , "latitude" : 123.32 }. -func completeGeoObject( - path []interface{}, - fields []schema.Field, - val map[string]interface{}) ([]byte, x.GqlErrorList) { +func completeGeoObject(fields []schema.Field, val map[string]interface{}) []byte { var buf bytes.Buffer x.Check2(buf.WriteRune('{')) @@ -1247,22 +1244,18 @@ func completeGeoObject( x.Check2(buf.WriteString(field.ResponseName())) x.Check2(buf.WriteString(`": `)) - if field.ResponseName() == "longitude" { + switch field.ResponseName() { + case "latitude": x.Check2(buf.WriteString(longitude)) - } else if field.ResponseName() == "latitude" { + case "longitude": x.Check2(buf.WriteString(latitude)) - } else { - return nil, x.GqlErrorList{&x.GqlError{ - Message: "Invalid field for Geo type", - Locations: []x.Location{field.Location()}, - Path: copyPath(path), - }} } + comma = "," } x.Check2(buf.WriteRune('}')) - return buf.Bytes(), nil + return buf.Bytes() } // completeObject builds a json GraphQL result object for the current query level. @@ -1407,7 +1400,7 @@ func completeValue( }} } if field.Type().IsGeo() { - return completeGeoObject(path, field.SelectionSet(), val) + return completeGeoObject(field.SelectionSet(), val), nil } return completeObject(path, field.SelectionSet(), val) diff --git a/graphql/schema/dgraph_schemagen_test.yml b/graphql/schema/dgraph_schemagen_test.yml index af054f8e6e7..022e25112ee 100644 --- a/graphql/schema/dgraph_schemagen_test.yml +++ b/graphql/schema/dgraph_schemagen_test.yml @@ -614,11 +614,14 @@ schemas: id: ID! name: String! location: Point @search + landmark: Point } output: | type Hotel { Hotel.name Hotel.location + Hotel.landmark } Hotel.name: string . Hotel.location: geo @index(geo) . + Hotel.landmark: geo . diff --git a/graphql/schema/gqlschema_test.yml b/graphql/schema/gqlschema_test.yml index bcb4f33a765..1a44f20e0cd 100644 --- a/graphql/schema/gqlschema_test.yml +++ b/graphql/schema/gqlschema_test.yml @@ -126,6 +126,15 @@ invalid_schemas: {"message":"String is a reserved word, so you can't declare a type with this name. Pick a different name for the type.", "locations":[{"line":1, "column":6}]}, ] + - name: "Point is reserved word" + input: | + type Point { + id: ID! + } + errlist: [ + { "message": "Point is a reserved word, so you can't declare a type with this name. Pick a different name for the type.", "locations": [ { "line": 1, "column": 6 } ] }, + ] + - name: "More than 1 errors" input: | diff --git a/graphql/schema/rules.go b/graphql/schema/rules.go index bf17ad4b5da..d1309be3e65 100644 --- a/graphql/schema/rules.go +++ b/graphql/schema/rules.go @@ -275,6 +275,9 @@ func inputTypeNameValidation(schema *ast.SchemaDocument) gqlerror.List { "StringFullTextFilter": true, "StringExactFilter": true, "StringHashFilter": true, + "PointGeoFilter": true, + "PointRef": true, + "NearFilter": true, } definedInputTypes := make([]*ast.Definition, 0) @@ -962,7 +965,7 @@ func searchValidation( arg := dir.Arguments.ForName(searchArgs) if arg == nil { - // If there's no arg, then it can be an enum or has to be a scalar that's + // If there's no arg, then it can be an enum or Geo type or has to be a scalar that's // not ID. The schema generation will add the default search // for that type. if sch.Types[field.Type.Name()].Kind == ast.Enum || isGeoType(field.Type) || @@ -1867,6 +1870,7 @@ func isReservedKeyWord(name string) bool { // Reserved Type names "uid": true, "Subscription": true, + "Point": true, } if isScalar(name) || isQueryOrMutation(name) || reservedTypeNames[name] { diff --git a/graphql/schema/schemagen.go b/graphql/schema/schemagen.go index c0774f5b21f..efb6d96a02c 100644 --- a/graphql/schema/schemagen.go +++ b/graphql/schema/schemagen.go @@ -440,7 +440,11 @@ func genDgSchema(gqlSch *ast.Schema, definitions []string) string { case ast.Object, ast.Interface: if isGeoType(f.Type) { typStr = "geo" - dgPreds[fname] = getUpdatedPred(fname, typStr, "", []string{"geo"}) + var indexes []string + if f.Directives.ForName(searchDirective) != nil { + indexes = append(indexes, "geo") + } + dgPreds[fname] = getUpdatedPred(fname, typStr, "", indexes) } else { typStr = fmt.Sprintf("%suid%s", prefix, suffix) } diff --git a/graphql/schema/wrappers.go b/graphql/schema/wrappers.go index 630279eb128..6d9ef55d4ff 100644 --- a/graphql/schema/wrappers.go +++ b/graphql/schema/wrappers.go @@ -428,9 +428,9 @@ func dgraphMapping(sch *ast.Schema) map[string]map[string]string { dgraphPredicate := make(map[string]map[string]string) for _, inputTyp := range sch.Types { // We only want to consider input types (object and interface) defined by the user as part - // of the schema hence we ignore BuiltIn, query and mutation types. + // of the schema hence we ignore BuiltIn, query and mutation types and Geo types. if inputTyp.BuiltIn || isQueryOrMutationType(inputTyp) || inputTyp.Name == "Subscription" || - (inputTyp.Kind != ast.Object && inputTyp.Kind != ast.Interface) { + (inputTyp.Kind != ast.Object && inputTyp.Kind != ast.Interface) || inputTyp.Name == "Point" { continue } diff --git a/graphql/schema/wrappers_test.go b/graphql/schema/wrappers_test.go index ed380d31a85..c174b4573a2 100644 --- a/graphql/schema/wrappers_test.go +++ b/graphql/schema/wrappers_test.go @@ -132,10 +132,6 @@ type Starship { "Employee": map[string]string{ "ename": "Employee.ename", }, - "Point": map[string]string{ - "latitude": "Point.latitude", - "longitude": "Point.longitude", - }, "Character": character, "UpdateCharacterPayload": character, "DeleteCharacterPayload": character, @@ -258,10 +254,6 @@ func TestDgraphMapping_WithDirectives(t *testing.T) { "Employee": map[string]string{ "ename": "dgraph.employee.en.ename", }, - "Point": map[string]string{ - "latitude": "Point.latitude", - "longitude": "Point.longitude", - }, "Character": character, "UpdateCharacterPayload": character, "DeleteCharacterPayload": character, From 4d711a975e5e4f14f97f7a7d052b78a8214c8fbe Mon Sep 17 00:00:00 2001 From: Arijit Das Date: Tue, 29 Sep 2020 17:35:53 +0530 Subject: [PATCH 13/20] Fix E2E test. --- graphql/resolve/resolver.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/graphql/resolve/resolver.go b/graphql/resolve/resolver.go index 4828b12f029..4ea7cd5424e 100644 --- a/graphql/resolve/resolver.go +++ b/graphql/resolve/resolver.go @@ -1246,9 +1246,9 @@ func completeGeoObject(fields []schema.Field, val map[string]interface{}) []byte switch field.ResponseName() { case "latitude": - x.Check2(buf.WriteString(longitude)) - case "longitude": x.Check2(buf.WriteString(latitude)) + case "longitude": + x.Check2(buf.WriteString(longitude)) } comma = "," From b5f9ee195e4888c4b758631a35544febe38ac599 Mon Sep 17 00:00:00 2001 From: Arijit Das Date: Tue, 29 Sep 2020 18:20:57 +0530 Subject: [PATCH 14/20] Fix test failures after merge. --- graphql/e2e/normal/schema_response.json | 287 ------------------------ 1 file changed, 287 deletions(-) diff --git a/graphql/e2e/normal/schema_response.json b/graphql/e2e/normal/schema_response.json index b6d514d10d0..eda9b1d24f2 100644 --- a/graphql/e2e/normal/schema_response.json +++ b/graphql/e2e/normal/schema_response.json @@ -4,10 +4,6 @@ "predicate": "dgraph.graphql.schema_history", "type": "string" }, - { - "predicate": "credits", - "type": "float" - }, { "predicate": "Movie.name", "type": "string" @@ -16,10 +12,6 @@ "predicate": "Post.category", "type": "uid" }, - { - "predicate": "myPost.category", - "type": "uid" - }, { "index": true, "list": true, @@ -74,10 +66,6 @@ "predicate": "Human.totalCredits", "type": "float" }, - { - "predicate": "post", - "type": "string" - }, { "index": true, "list": true, @@ -95,15 +83,6 @@ ], "type": "datetime" }, - { - "index": true, - "list": true, - "predicate": "myPost.tags", - "tokenizer": [ - "exact" - ], - "type": "string" - }, { "index": true, "list": true, @@ -117,14 +96,6 @@ "predicate": "MovieDirector.name", "type": "string" }, - { - "index": true, - "predicate": "star.ship.name", - "tokenizer": [ - "term" - ], - "type": "string" - }, { "index": true, "predicate": "Starship.name", @@ -138,14 +109,6 @@ "predicate": "Movie.director", "type": "uid" }, - { - "index": true, - "predicate": "text", - "tokenizer": [ - "fulltext" - ], - "type": "string" - }, { "predicate": "Category.name", "type": "string" @@ -163,11 +126,6 @@ ], "type": "string" }, - { - "list": true, - "predicate": "hasStates", - "type": "uid" - }, { "predicate": "Person1.name", "type": "string" @@ -185,15 +143,6 @@ ], "type": "string" }, - { - "index": true, - "predicate": "myPost.title", - "tokenizer": [ - "fulltext", - "term" - ], - "type": "string" - }, { "index": true, "predicate": "Comment1.id", @@ -212,12 +161,6 @@ "type": "string", "upsert": true }, - { - "list": true, - "predicate": "directed.movies", - "reverse": true, - "type": "uid" - }, { "index": true, "predicate": "Character.name", @@ -234,14 +177,6 @@ ], "type": "string" }, - { - "index": true, - "predicate": "test.dgraph.author.dob", - "tokenizer": [ - "year" - ], - "type": "datetime" - }, { "index": true, "predicate": "post1.title", @@ -252,19 +187,10 @@ "type": "string", "upsert": true }, - { - "list": true, - "predicate": "test.dgraph.author.posts", - "type": "uid" - }, { "predicate": "Person.name", "type": "string" }, - { - "predicate": "post.author", - "type": "uid" - }, { "predicate": "Post.author", "type": "uid" @@ -277,14 +203,6 @@ ], "type": "string" }, - { - "index": true, - "predicate": "test.dgraph.topic", - "tokenizer": [ - "exact" - ], - "type": "string" - }, { "index": true, "predicate": "State.xcode", @@ -295,23 +213,6 @@ "type": "string", "upsert": true }, - { - "index": true, - "predicate": "performance.character.name", - "tokenizer": [ - "exact" - ], - "type": "string" - }, - { - "index": true, - "predicate": "test.dgraph.author.name", - "tokenizer": [ - "hash", - "trigram" - ], - "type": "string" - }, { "index": true, "predicate": "Country.name", @@ -347,23 +248,10 @@ ], "type": "string" }, - { - "index": true, - "predicate": "myPost.postType", - "tokenizer": [ - "hash", - "trigram" - ], - "type": "string" - }, { "predicate": "post1.numLikes", "type": "int" }, - { - "predicate": "test.dgraph.employee.en.ename", - "type": "string" - }, { "list": true, "predicate": "MovieDirector.directed", @@ -374,18 +262,6 @@ "predicate": "Category.posts", "type": "uid" }, - { - "predicate": "职业", - "type": "string" - }, - { - "index": true, - "predicate": "myPost.numLikes", - "tokenizer": [ - "int" - ], - "type": "int" - }, { "index": true, "predicate": "Post.numLikes", @@ -402,14 +278,6 @@ ], "type": "int" }, - { - "index": true, - "predicate": "myPost.numViews", - "tokenizer": [ - "int" - ], - "type": "int" - }, { "index": true, "predicate": "dgraph.graphql.xid", @@ -419,10 +287,6 @@ "type": "string", "upsert": true }, - { - "predicate": "test.dgraph.author.country", - "type": "uid" - }, { "index": true, "list": true, @@ -445,31 +309,6 @@ "predicate": "ThingOne.usedBy", "type": "string" }, - { - "index": true, - "predicate": "is_published", - "tokenizer": [ - "bool" - ], - "type": "bool" - }, - { - "predicate": "pwd", - "type": "password" - }, - { - "predicate": "inCountry", - "type": "uid" - }, - { - "index": true, - "list": true, - "predicate": "appears_in", - "tokenizer": [ - "hash" - ], - "type": "string" - }, { "predicate": "State.country", "type": "uid" @@ -478,22 +317,10 @@ "predicate": "Thing.name", "type": "string" }, - { - "predicate": "star.ship.length", - "type": "float" - }, { "predicate": "Teacher.subject", "type": "string" }, - { - "index": true, - "predicate": "test.dgraph.author.reputation", - "tokenizer": [ - "float" - ], - "type": "float" - }, { "predicate": "State.capital", "type": "string" @@ -518,10 +345,6 @@ "predicate": "Author.country", "type": "uid" }, - { - "predicate": "roboDroid.primaryFunction", - "type": "string" - }, { "list": true, "predicate": "Teacher.teaches", @@ -667,26 +490,6 @@ ], "name": "Human" }, - { - "fields": [ - { - "name": "test.dgraph.author.dob" - }, - { - "name": "test.dgraph.author.posts" - }, - { - "name": "test.dgraph.author.name" - }, - { - "name": "test.dgraph.author.country" - }, - { - "name": "test.dgraph.author.reputation" - } - ], - "name": "test.dgraph.author" - }, { "fields": [ { @@ -695,63 +498,6 @@ ], "name": "Person" }, - { - "fields": [ - { - "name": "test.dgraph.employee.en.ename" - } - ], - "name": "test.dgraph.employee.en" - }, - { - "fields": [ - { - "name": "text" - }, - { - "name": "myPost.category" - }, - { - "name": "myPost.tags" - }, - { - "name": "post.author" - }, - { - "name": "myPost.title" - }, - { - "name": "test.dgraph.topic" - }, - { - "name": "myPost.postType" - }, - { - "name": "is_published" - }, - { - "name": "myPost.numLikes" - }, - { - "name": "myPost.numViews" - } - ], - "name": "myPost" - }, - { - "fields": [ - { - "name": "performance.character.name" - }, - { - "name": "appears_in" - }, - { - "name": "roboDroid.primaryFunction" - } - ], - "name": "roboDroid" - }, { "fields": [ { @@ -847,17 +593,6 @@ ], "name": "post1" }, - { - "fields": [ - { - "name": "star.ship.name" - }, - { - "name": "star.ship.length" - } - ], - "name": "star.ship" - }, { "fields": [ { @@ -883,17 +618,6 @@ ], "name": "ThingTwo" }, - { - "fields": [ - { - "name": "post" - }, - { - "name": "职业" - } - ], - "name": "Message" - }, { "fields": [ { @@ -935,17 +659,6 @@ ], "name": "Thing" }, - { - "fields": [ - { - "name": "performance.character.name" - }, - { - "name": "appears_in" - } - ], - "name": "performance.character" - }, { "fields": [ { From 7a2307e7b7cab6f962d209f6a68bb7ab57064ac2 Mon Sep 17 00:00:00 2001 From: Arijit Das Date: Wed, 30 Sep 2020 14:24:19 +0530 Subject: [PATCH 15/20] Resolve merge conflict. --- .../filter-cleanSchema-all-empty.graphql | 224 -------------- .../filter-cleanSchema-circular.graphql | 284 ----------------- ...filter-cleanSchema-custom-mutation.graphql | 260 ---------------- .../filter-cleanSchema-directLink.graphql | 288 ------------------ 4 files changed, 1056 deletions(-) delete mode 100644 graphql/schema/testdata/schemagen/output/filter-cleanSchema-all-empty.graphql delete mode 100644 graphql/schema/testdata/schemagen/output/filter-cleanSchema-circular.graphql delete mode 100644 graphql/schema/testdata/schemagen/output/filter-cleanSchema-custom-mutation.graphql delete mode 100644 graphql/schema/testdata/schemagen/output/filter-cleanSchema-directLink.graphql diff --git a/graphql/schema/testdata/schemagen/output/filter-cleanSchema-all-empty.graphql b/graphql/schema/testdata/schemagen/output/filter-cleanSchema-all-empty.graphql deleted file mode 100644 index 978f5039aff..00000000000 --- a/graphql/schema/testdata/schemagen/output/filter-cleanSchema-all-empty.graphql +++ /dev/null @@ -1,224 +0,0 @@ -####################### -# Input Schema -####################### - -type X { - name(first: Int, offset: Int): [Y] - f1(first: Int, offset: Int): [Y] @dgraph(pred: "f1") -} - -type Y { - f1(first: Int, offset: Int): [X] @dgraph(pred: "~f1") -} - -type Z { - add(first: Int, offset: Int): [X] -} - -####################### -# Extended Definitions -####################### - -""" -The Int64 scalar type represents a signed 64‐bit numeric non‐fractional value. -Int64 can represent values in range [-(2^63),(2^63 - 1)]. -""" -scalar Int64 - -""" -The DateTime scalar type represents date and time as a string in RFC3339 format. -For example: "1985-04-12T23:20:50.52Z" represents 20 minutes and 50.52 seconds after the 23rd hour of April 12th, 1985 in UTC. -""" -scalar DateTime - -enum DgraphIndex { - int - int64 - float - bool - hash - exact - term - fulltext - trigram - regexp - year - month - day - hour - geo -} - -input AuthRule { - and: [AuthRule] - or: [AuthRule] - not: AuthRule - rule: String -} - -enum HTTPMethod { - GET - POST - PUT - PATCH - DELETE -} - -enum Mode { - BATCH - SINGLE -} - -input CustomHTTP { - url: String! - method: HTTPMethod! - body: String - graphql: String - mode: Mode - forwardHeaders: [String!] - secretHeaders: [String!] - introspectionHeaders: [String!] - skipIntrospection: Boolean -} - -type Point { - longitude: Float! - latitude: Float! -} - -input PointRef { - longitude: Float! - latitude: Float! -} - -input NearFilter { - distance: Float! - coordinate: PointRef! -} - -input PointGeoFilter { - near: NearFilter! -} - -directive @hasInverse(field: String!) on FIELD_DEFINITION -directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION -directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION -directive @id on FIELD_DEFINITION -directive @withSubscription on OBJECT | INTERFACE -directive @secret(field: String!, pred: String) on OBJECT | INTERFACE -directive @auth( - query: AuthRule, - add: AuthRule, - update: AuthRule, - delete:AuthRule) on OBJECT -directive @custom(http: CustomHTTP, dql: String) on FIELD_DEFINITION -directive @remote on OBJECT | INTERFACE -directive @cascade(fields: [String]) on FIELD - -input IntFilter { - eq: Int - le: Int - lt: Int - ge: Int - gt: Int -} - -input Int64Filter { - eq: Int64 - le: Int64 - lt: Int64 - ge: Int64 - gt: Int64 -} - -input FloatFilter { - eq: Float - le: Float - lt: Float - ge: Float - gt: Float -} - -input DateTimeFilter { - eq: DateTime - le: DateTime - lt: DateTime - ge: DateTime - gt: DateTime -} - -input StringTermFilter { - allofterms: String - anyofterms: String -} - -input StringRegExpFilter { - regexp: String -} - -input StringFullTextFilter { - alloftext: String - anyoftext: String -} - -input StringExactFilter { - eq: String - le: String - lt: String - ge: String - gt: String -} - -input StringHashFilter { - eq: String -} - -####################### -# Generated Enums -####################### - -enum XHasFilter { - name - f1 -} - -enum YHasFilter { - f1 -} - -enum ZHasFilter { - add -} - -####################### -# Generated Inputs -####################### - -input XFilter { - has: XHasFilter - and: XFilter - or: XFilter - not: XFilter -} - -input YFilter { - not: YFilter -} - -input ZFilter { - has: ZHasFilter - and: ZFilter - or: ZFilter - not: ZFilter -} - -####################### -# Generated Query -####################### - -type Query { - queryX(first: Int, offset: Int): [X] - queryY(first: Int, offset: Int): [Y] - queryZ(first: Int, offset: Int): [Z] -} - diff --git a/graphql/schema/testdata/schemagen/output/filter-cleanSchema-circular.graphql b/graphql/schema/testdata/schemagen/output/filter-cleanSchema-circular.graphql deleted file mode 100644 index 396d5e090ae..00000000000 --- a/graphql/schema/testdata/schemagen/output/filter-cleanSchema-circular.graphql +++ /dev/null @@ -1,284 +0,0 @@ -####################### -# Input Schema -####################### - -type X { - f1(first: Int, offset: Int): [Y] @dgraph(pred: "f1") - f3(first: Int, offset: Int): [Z] @dgraph(pred: "~f3") -} - -type Y { - f1(first: Int, offset: Int): [X] @dgraph(pred: "~f1") - f2(first: Int, offset: Int): [Z] @dgraph(pred: "f2") -} - -type Z { - f2(first: Int, offset: Int): [Y] @dgraph(pred: "~f2") - f3(first: Int, offset: Int): [X] @dgraph(pred: "f3") -} - -####################### -# Extended Definitions -####################### - -""" -The Int64 scalar type represents a signed 64‐bit numeric non‐fractional value. -Int64 can represent values in range [-(2^63),(2^63 - 1)]. -""" -scalar Int64 - -""" -The DateTime scalar type represents date and time as a string in RFC3339 format. -For example: "1985-04-12T23:20:50.52Z" represents 20 minutes and 50.52 seconds after the 23rd hour of April 12th, 1985 in UTC. -""" -scalar DateTime - -enum DgraphIndex { - int - int64 - float - bool - hash - exact - term - fulltext - trigram - regexp - year - month - day - hour - geo -} - -input AuthRule { - and: [AuthRule] - or: [AuthRule] - not: AuthRule - rule: String -} - -enum HTTPMethod { - GET - POST - PUT - PATCH - DELETE -} - -enum Mode { - BATCH - SINGLE -} - -input CustomHTTP { - url: String! - method: HTTPMethod! - body: String - graphql: String - mode: Mode - forwardHeaders: [String!] - secretHeaders: [String!] - introspectionHeaders: [String!] - skipIntrospection: Boolean -} - -type Point { - longitude: Float! - latitude: Float! -} - -input PointRef { - longitude: Float! - latitude: Float! -} - -input NearFilter { - distance: Float! - coordinate: PointRef! -} - -input PointGeoFilter { - near: NearFilter! -} - -directive @hasInverse(field: String!) on FIELD_DEFINITION -directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION -directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION -directive @id on FIELD_DEFINITION -directive @withSubscription on OBJECT | INTERFACE -directive @secret(field: String!, pred: String) on OBJECT | INTERFACE -directive @auth( - query: AuthRule, - add: AuthRule, - update: AuthRule, - delete:AuthRule) on OBJECT -directive @custom(http: CustomHTTP, dql: String) on FIELD_DEFINITION -directive @remote on OBJECT | INTERFACE -directive @cascade(fields: [String]) on FIELD - -input IntFilter { - eq: Int - le: Int - lt: Int - ge: Int - gt: Int -} - -input Int64Filter { - eq: Int64 - le: Int64 - lt: Int64 - ge: Int64 - gt: Int64 -} - -input FloatFilter { - eq: Float - le: Float - lt: Float - ge: Float - gt: Float -} - -input DateTimeFilter { - eq: DateTime - le: DateTime - lt: DateTime - ge: DateTime - gt: DateTime -} - -input StringTermFilter { - allofterms: String - anyofterms: String -} - -input StringRegExpFilter { - regexp: String -} - -input StringFullTextFilter { - alloftext: String - anyoftext: String -} - -input StringExactFilter { - eq: String - le: String - lt: String - ge: String - gt: String -} - -input StringHashFilter { - eq: String -} - -####################### -# Generated Types -####################### - -type AddXPayload { - x(first: Int, offset: Int): [X] - numUids: Int -} - -type AddYPayload { - y(first: Int, offset: Int): [Y] - numUids: Int -} - -type AddZPayload { - z(first: Int, offset: Int): [Z] - numUids: Int -} - -####################### -# Generated Enums -####################### - -enum XHasFilter { - f1 - f3 -} - -enum YHasFilter { - f1 - f2 -} - -enum ZHasFilter { - f2 - f3 -} - -####################### -# Generated Inputs -####################### - -input AddXInput { - f1: [YRef] -} - -input AddYInput { - f2: [ZRef] -} - -input AddZInput { - f3: [XRef] -} - -input XFilter { - has: XHasFilter - and: XFilter - or: XFilter - not: XFilter -} - -input XRef { - f1: [YRef] -} - -input YFilter { - has: YHasFilter - and: YFilter - or: YFilter - not: YFilter -} - -input YRef { - f2: [ZRef] -} - -input ZFilter { - has: ZHasFilter - and: ZFilter - or: ZFilter - not: ZFilter -} - -input ZRef { - f3: [XRef] -} - -####################### -# Generated Query -####################### - -type Query { - queryX(first: Int, offset: Int): [X] - queryY(first: Int, offset: Int): [Y] - queryZ(first: Int, offset: Int): [Z] -} - -####################### -# Generated Mutations -####################### - -type Mutation { - addX(input: [AddXInput!]!): AddXPayload - addY(input: [AddYInput!]!): AddYPayload - addZ(input: [AddZInput!]!): AddZPayload -} - diff --git a/graphql/schema/testdata/schemagen/output/filter-cleanSchema-custom-mutation.graphql b/graphql/schema/testdata/schemagen/output/filter-cleanSchema-custom-mutation.graphql deleted file mode 100644 index dbc370e3486..00000000000 --- a/graphql/schema/testdata/schemagen/output/filter-cleanSchema-custom-mutation.graphql +++ /dev/null @@ -1,260 +0,0 @@ -####################### -# Input Schema -####################### - -type User { - id: ID! - name: String! -} - -input UserInput { - name: String! -} - -####################### -# Extended Definitions -####################### - -""" -The Int64 scalar type represents a signed 64‐bit numeric non‐fractional value. -Int64 can represent values in range [-(2^63),(2^63 - 1)]. -""" -scalar Int64 - -""" -The DateTime scalar type represents date and time as a string in RFC3339 format. -For example: "1985-04-12T23:20:50.52Z" represents 20 minutes and 50.52 seconds after the 23rd hour of April 12th, 1985 in UTC. -""" -scalar DateTime - -enum DgraphIndex { - int - int64 - float - bool - hash - exact - term - fulltext - trigram - regexp - year - month - day - hour - geo -} - -input AuthRule { - and: [AuthRule] - or: [AuthRule] - not: AuthRule - rule: String -} - -enum HTTPMethod { - GET - POST - PUT - PATCH - DELETE -} - -enum Mode { - BATCH - SINGLE -} - -input CustomHTTP { - url: String! - method: HTTPMethod! - body: String - graphql: String - mode: Mode - forwardHeaders: [String!] - secretHeaders: [String!] - introspectionHeaders: [String!] - skipIntrospection: Boolean -} - -type Point { - longitude: Float! - latitude: Float! -} - -input PointRef { - longitude: Float! - latitude: Float! -} - -input NearFilter { - distance: Float! - coordinate: PointRef! -} - -input PointGeoFilter { - near: NearFilter! -} - -directive @hasInverse(field: String!) on FIELD_DEFINITION -directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION -directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION -directive @id on FIELD_DEFINITION -directive @withSubscription on OBJECT | INTERFACE -directive @secret(field: String!, pred: String) on OBJECT | INTERFACE -directive @auth( - query: AuthRule, - add: AuthRule, - update: AuthRule, - delete:AuthRule) on OBJECT -directive @custom(http: CustomHTTP, dql: String) on FIELD_DEFINITION -directive @remote on OBJECT | INTERFACE -directive @cascade(fields: [String]) on FIELD - -input IntFilter { - eq: Int - le: Int - lt: Int - ge: Int - gt: Int -} - -input Int64Filter { - eq: Int64 - le: Int64 - lt: Int64 - ge: Int64 - gt: Int64 -} - -input FloatFilter { - eq: Float - le: Float - lt: Float - ge: Float - gt: Float -} - -input DateTimeFilter { - eq: DateTime - le: DateTime - lt: DateTime - ge: DateTime - gt: DateTime -} - -input StringTermFilter { - allofterms: String - anyofterms: String -} - -input StringRegExpFilter { - regexp: String -} - -input StringFullTextFilter { - alloftext: String - anyoftext: String -} - -input StringExactFilter { - eq: String - le: String - lt: String - ge: String - gt: String -} - -input StringHashFilter { - eq: String -} - -####################### -# Generated Types -####################### - -type AddUserPayload { - user(filter: UserFilter, order: UserOrder, first: Int, offset: Int): [User] - numUids: Int -} - -type DeleteUserPayload { - user(filter: UserFilter, order: UserOrder, first: Int, offset: Int): [User] - msg: String - numUids: Int -} - -type UpdateUserPayload { - user(filter: UserFilter, order: UserOrder, first: Int, offset: Int): [User] - numUids: Int -} - -####################### -# Generated Enums -####################### - -enum UserHasFilter { - name -} - -enum UserOrderable { - name -} - -####################### -# Generated Inputs -####################### - -input AddUserInput { - name: String! -} - -input UpdateUserInput { - filter: UserFilter! - set: UserPatch - remove: UserPatch -} - -input UserFilter { - id: [ID!] - has: UserHasFilter - and: UserFilter - or: UserFilter - not: UserFilter -} - -input UserOrder { - asc: UserOrderable - desc: UserOrderable - then: UserOrder -} - -input UserPatch { - name: String -} - -input UserRef { - id: ID - name: String -} - -####################### -# Generated Query -####################### - -type Query { - getUser(id: ID!): User - queryUser(filter: UserFilter, order: UserOrder, first: Int, offset: Int): [User] -} - -####################### -# Generated Mutations -####################### - -type Mutation { - addMyFavouriteUsers(input: [UserInput!]!): [User] @custom(http: {url:"http://my-api.com",method:"POST",body:"{ data: $input }"}) - addUser(input: [AddUserInput!]!): AddUserPayload - updateUser(input: UpdateUserInput!): UpdateUserPayload - deleteUser(filter: UserFilter!): DeleteUserPayload -} - diff --git a/graphql/schema/testdata/schemagen/output/filter-cleanSchema-directLink.graphql b/graphql/schema/testdata/schemagen/output/filter-cleanSchema-directLink.graphql deleted file mode 100644 index 7f03d06f38b..00000000000 --- a/graphql/schema/testdata/schemagen/output/filter-cleanSchema-directLink.graphql +++ /dev/null @@ -1,288 +0,0 @@ -####################### -# Input Schema -####################### - -type X { - f1(first: Int, offset: Int): [Y] @dgraph(pred: "f1") - name: String - id: ID -} - -type Y { - f2(first: Int, offset: Int): [Z] @dgraph(pred: "~f2") - f1(filter: XFilter, order: XOrder, first: Int, offset: Int): [X] @dgraph(pred: "~f1") -} - -type Z { - f2(first: Int, offset: Int): [Y] @dgraph(pred: "f2") -} - -####################### -# Extended Definitions -####################### - -""" -The Int64 scalar type represents a signed 64‐bit numeric non‐fractional value. -Int64 can represent values in range [-(2^63),(2^63 - 1)]. -""" -scalar Int64 - -""" -The DateTime scalar type represents date and time as a string in RFC3339 format. -For example: "1985-04-12T23:20:50.52Z" represents 20 minutes and 50.52 seconds after the 23rd hour of April 12th, 1985 in UTC. -""" -scalar DateTime - -enum DgraphIndex { - int - int64 - float - bool - hash - exact - term - fulltext - trigram - regexp - year - month - day - hour - geo -} - -input AuthRule { - and: [AuthRule] - or: [AuthRule] - not: AuthRule - rule: String -} - -enum HTTPMethod { - GET - POST - PUT - PATCH - DELETE -} - -enum Mode { - BATCH - SINGLE -} - -input CustomHTTP { - url: String! - method: HTTPMethod! - body: String - graphql: String - mode: Mode - forwardHeaders: [String!] - secretHeaders: [String!] - introspectionHeaders: [String!] - skipIntrospection: Boolean -} - -type Point { - longitude: Float! - latitude: Float! -} - -input PointRef { - longitude: Float! - latitude: Float! -} - -input NearFilter { - distance: Float! - coordinate: PointRef! -} - -input PointGeoFilter { - near: NearFilter! -} - -directive @hasInverse(field: String!) on FIELD_DEFINITION -directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION -directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION -directive @id on FIELD_DEFINITION -directive @withSubscription on OBJECT | INTERFACE -directive @secret(field: String!, pred: String) on OBJECT | INTERFACE -directive @auth( - query: AuthRule, - add: AuthRule, - update: AuthRule, - delete:AuthRule) on OBJECT -directive @custom(http: CustomHTTP, dql: String) on FIELD_DEFINITION -directive @remote on OBJECT | INTERFACE -directive @cascade(fields: [String]) on FIELD - -input IntFilter { - eq: Int - le: Int - lt: Int - ge: Int - gt: Int -} - -input Int64Filter { - eq: Int64 - le: Int64 - lt: Int64 - ge: Int64 - gt: Int64 -} - -input FloatFilter { - eq: Float - le: Float - lt: Float - ge: Float - gt: Float -} - -input DateTimeFilter { - eq: DateTime - le: DateTime - lt: DateTime - ge: DateTime - gt: DateTime -} - -input StringTermFilter { - allofterms: String - anyofterms: String -} - -input StringRegExpFilter { - regexp: String -} - -input StringFullTextFilter { - alloftext: String - anyoftext: String -} - -input StringExactFilter { - eq: String - le: String - lt: String - ge: String - gt: String -} - -input StringHashFilter { - eq: String -} - -####################### -# Generated Types -####################### - -type AddXPayload { - x(filter: XFilter, order: XOrder, first: Int, offset: Int): [X] - numUids: Int -} - -type DeleteXPayload { - x(filter: XFilter, order: XOrder, first: Int, offset: Int): [X] - msg: String - numUids: Int -} - -type UpdateXPayload { - x(filter: XFilter, order: XOrder, first: Int, offset: Int): [X] - numUids: Int -} - -####################### -# Generated Enums -####################### - -enum XHasFilter { - f1 - name -} - -enum XOrderable { - name -} - -enum YHasFilter { - f2 - f1 -} - -enum ZHasFilter { - f2 -} - -####################### -# Generated Inputs -####################### - -input AddXInput { - name: String -} - -input UpdateXInput { - filter: XFilter! - set: XPatch - remove: XPatch -} - -input XFilter { - id: [ID!] - has: XHasFilter - and: XFilter - or: XFilter - not: XFilter -} - -input XOrder { - asc: XOrderable - desc: XOrderable - then: XOrder -} - -input XPatch { - name: String -} - -input XRef { - id: ID - name: String -} - -input YFilter { - not: YFilter -} - -input ZFilter { - has: ZHasFilter - and: ZFilter - or: ZFilter - not: ZFilter -} - -####################### -# Generated Query -####################### - -type Query { - getX(id: ID!): X - queryX(filter: XFilter, order: XOrder, first: Int, offset: Int): [X] - queryY(first: Int, offset: Int): [Y] - queryZ(first: Int, offset: Int): [Z] -} - -####################### -# Generated Mutations -####################### - -type Mutation { - addX(input: [AddXInput!]!): AddXPayload - updateX(input: UpdateXInput!): UpdateXPayload - deleteX(filter: XFilter!): DeleteXPayload -} - From fa30a59c825436fa6b57cacf42d08f618ef2f4a4 Mon Sep 17 00:00:00 2001 From: Arijit Das Date: Wed, 30 Sep 2020 14:44:54 +0530 Subject: [PATCH 16/20] Address comments. --- graphql/resolve/resolver.go | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/graphql/resolve/resolver.go b/graphql/resolve/resolver.go index e960bdd605a..70281272e7f 100644 --- a/graphql/resolve/resolver.go +++ b/graphql/resolve/resolver.go @@ -75,6 +75,9 @@ const ( "and as much other data as possible returned." errInternal = "Internal error" + + errExpectedNonNull = "Non-nullable field '%s' (type %s) was not present in result from Dgraph. " + + "GraphQL error propagation triggered." ) // A ResolverFactory finds the right resolver for a query/mutation. @@ -1229,11 +1232,18 @@ func resolveCustomFields(fields []schema.Field, data interface{}) error { // completeGeoObject builds a json GraphQL result object for the geo type. // It returns a bracketed json object like { "longitude" : 12.32 , "latitude" : 123.32 }. -func completeGeoObject(fields []schema.Field, val map[string]interface{}) []byte { +func completeGeoObject(field schema.Field, val map[string]interface{}, path []interface{}) ([]byte, x.GqlErrorList) { var buf bytes.Buffer x.Check2(buf.WriteRune('{')) coordinate, _ := val["coordinates"].([]interface{}) + if coordinate == nil { + gqlErr := x.GqlErrorf(errExpectedNonNull, field.Name(), field.Type()).WithLocations(field.Location()) + gqlErr.Path = copyPath(path) + return nil, x.GqlErrorList{gqlErr} + } + + fields := field.SelectionSet() comma := "" longitude := fmt.Sprintf("%s", coordinate[0]) @@ -1255,7 +1265,7 @@ func completeGeoObject(fields []schema.Field, val map[string]interface{}) []byte } x.Check2(buf.WriteRune('}')) - return buf.Bytes() + return buf.Bytes(), nil } // completeObject builds a json GraphQL result object for the current query level. @@ -1409,7 +1419,7 @@ func completeValue( }} } if field.Type().IsGeo() { - return completeGeoObject(field.SelectionSet(), val), nil + return completeGeoObject(field, val, path) } return completeObject(path, field.SelectionSet(), val) @@ -1444,12 +1454,8 @@ func completeValue( return []byte("null"), nil } - gqlErr := x.GqlErrorf( - "Non-nullable field '%s' (type %s) was not present in result from Dgraph. "+ - "GraphQL error propagation triggered.", field.Name(), field.Type()). - WithLocations(field.Location()) + gqlErr := x.GqlErrorf(errExpectedNonNull, field.Name(), field.Type()).WithLocations(field.Location()) gqlErr.Path = copyPath(path) - return nil, x.GqlErrorList{gqlErr} } From 5a649ecb828e1d3fc57ba27d9b3f44e62fde5d40 Mon Sep 17 00:00:00 2001 From: Arijit Das Date: Thu, 1 Oct 2020 18:30:08 +0530 Subject: [PATCH 17/20] Address comments. --- graphql/e2e/common/mutation.go | 2 +- graphql/resolve/add_mutation_test.yaml | 24 ++++++++++++++++++++++++ graphql/resolve/mutation_rewriter.go | 4 ++-- graphql/resolve/mutation_test.go | 8 +++++++- graphql/resolve/query_rewriter.go | 2 +- graphql/resolve/resolver.go | 2 +- graphql/schema/gqlschema_test.yml | 11 +++++++++++ graphql/schema/rules.go | 4 ++-- graphql/schema/schemagen.go | 2 +- graphql/schema/wrappers.go | 4 ++-- 10 files changed, 52 insertions(+), 11 deletions(-) diff --git a/graphql/e2e/common/mutation.go b/graphql/e2e/common/mutation.go index 28c5f3130c0..3339bf0a33a 100644 --- a/graphql/e2e/common/mutation.go +++ b/graphql/e2e/common/mutation.go @@ -3749,7 +3749,7 @@ func nestedAddMutationWithHasInverse(t *testing.T) { func mutationGeoType(t *testing.T) { addHotelParams := &GraphQLParams{ - Query: ` + Query: ` mutation addHotel($hotel: AddHotelInput!) { addHotel(input: [$hotel]) { hotel { diff --git a/graphql/resolve/add_mutation_test.yaml b/graphql/resolve/add_mutation_test.yaml index 52fd5a74720..b44287d53df 100644 --- a/graphql/resolve/add_mutation_test.yaml +++ b/graphql/resolve/add_mutation_test.yaml @@ -30,6 +30,30 @@ } } +- + name: "Add mutation with geo without longitude" + gqlmutation: | + mutation addHotel($hotel: AddHotelInput!) { + addHotel(input: [$hotel]) { + hotel { + name + location { + latitude + longitude + } + } + } + } + gqlvariables: | + { "hotel": + { "name": "Taj Hotel", + "location": { "latitude": 11.11 } + } + } + explanation: "Add mutation for Point type mutation should have both latitude and longitude" + validationerror: + { "message": "input: variable.hotel.location.longitude must be defined" } + - name: "Add mutation with variables" gqlmutation: | diff --git a/graphql/resolve/mutation_rewriter.go b/graphql/resolve/mutation_rewriter.go index 85c52d2b5b9..dfd2a3e32b8 100644 --- a/graphql/resolve/mutation_rewriter.go +++ b/graphql/resolve/mutation_rewriter.go @@ -1211,8 +1211,8 @@ func rewriteObject( // or giving the data to create the object as part of a deep mutation // { "title": "...", "author": { "username": "new user", "dob": "...", ... } // like here ^^ - if fieldDef.Type().IsGeo() { - // For Geo type, the mutation json is as follows: + if fieldDef.Type().IsPoint() { + // For Point type, the mutation json in Dgraph is as follows: // { "type": "Point", "coordinates": [11.11, 22.22]} lat := val["latitude"] long := val["longitude"] diff --git a/graphql/resolve/mutation_test.go b/graphql/resolve/mutation_test.go index 37997384d88..475ac022f27 100644 --- a/graphql/resolve/mutation_test.go +++ b/graphql/resolve/mutation_test.go @@ -194,7 +194,13 @@ func mutationRewriting(t *testing.T, file string, rewriterFactory func() Mutatio Query: tcase.GQLMutation, Variables: vars, }) - require.NoError(t, err) + if tcase.ValidationError != nil { + require.NotNil(t, err) + require.Equal(t, tcase.ValidationError.Error(), err.Error()) + return + } else { + require.NoError(t, err) + } mut := test.GetMutation(t, op) rewriterToTest := rewriterFactory() diff --git a/graphql/resolve/query_rewriter.go b/graphql/resolve/query_rewriter.go index 4e1bdd95cb5..f3eda14894b 100644 --- a/graphql/resolve/query_rewriter.go +++ b/graphql/resolve/query_rewriter.go @@ -752,7 +752,7 @@ func addSelectionSetFrom( } var selectionAuth []*gql.GraphQuery - if !f.Type().IsGeo() { + if !f.Type().IsPoint() { selectionAuth = addSelectionSetFrom(child, f, auth) } addedFields[f.Name()] = true diff --git a/graphql/resolve/resolver.go b/graphql/resolve/resolver.go index 70281272e7f..504231e866b 100644 --- a/graphql/resolve/resolver.go +++ b/graphql/resolve/resolver.go @@ -1418,7 +1418,7 @@ func completeValue( Path: copyPath(path), }} } - if field.Type().IsGeo() { + if field.Type().IsPoint() { return completeGeoObject(field, val, path) } diff --git a/graphql/schema/gqlschema_test.yml b/graphql/schema/gqlschema_test.yml index 3766eb3c8ff..a5bfd0351c1 100644 --- a/graphql/schema/gqlschema_test.yml +++ b/graphql/schema/gqlschema_test.yml @@ -12,6 +12,17 @@ invalid_schemas: {"message":"Type P; is invalid, a type must have atleast one field that is not of ID! type and doesn't have @custom directive.", "locations":[{"line":1, "column":6}]} ] + - name: "Geo field with invalid argument in @search." + input: | + type Hotel { + id: ID! + name: String! + location: Point @search(by: [int]) + } + errlist: [ + {"message":"Type Hotel; Field location: has the @search directive but the argument int doesn't apply to field type Point. Search by int applies to fields of type Int. Fields of type Point are searchable by just @search.", "locations":[ { "line": 4, "column":20}]}, + ] + - name: "UID as a field name" input: | diff --git a/graphql/schema/rules.go b/graphql/schema/rules.go index 9749ce80eea..a7711cf7245 100644 --- a/graphql/schema/rules.go +++ b/graphql/schema/rules.go @@ -959,7 +959,7 @@ func validateSearchArg(searchArg string, return nil } -func isGeoType(typ *ast.Type) bool { +func isPointType(typ *ast.Type) bool { return typ.Name() == "Point" } @@ -976,7 +976,7 @@ func searchValidation( // If there's no arg, then it can be an enum or Geo type or has to be a scalar that's // not ID. The schema generation will add the default search // for that type. - if sch.Types[field.Type.Name()].Kind == ast.Enum || isGeoType(field.Type) || + if sch.Types[field.Type.Name()].Kind == ast.Enum || isPointType(field.Type) || (sch.Types[field.Type.Name()].Kind == ast.Scalar && !isIDField(typ, field)) { return nil } diff --git a/graphql/schema/schemagen.go b/graphql/schema/schemagen.go index bd90a4d1182..8000a8f5d92 100644 --- a/graphql/schema/schemagen.go +++ b/graphql/schema/schemagen.go @@ -437,7 +437,7 @@ func genDgSchema(gqlSch *ast.Schema, definitions []string) string { var typStr string switch gqlSch.Types[f.Type.Name()].Kind { case ast.Object, ast.Interface: - if isGeoType(f.Type) { + if isPointType(f.Type) { typStr = "geo" var indexes []string if f.Directives.ForName(searchDirective) != nil { diff --git a/graphql/schema/wrappers.go b/graphql/schema/wrappers.go index 6d9ef55d4ff..b8dcee4e4f7 100644 --- a/graphql/schema/wrappers.go +++ b/graphql/schema/wrappers.go @@ -177,7 +177,7 @@ type Type interface { EnsureNonNulls(map[string]interface{}, string) error FieldOriginatedFrom(fieldName string) string AuthRules() *TypeAuth - IsGeo() bool + IsPoint() bool fmt.Stringer } @@ -1446,7 +1446,7 @@ func (t *astType) AuthRules() *TypeAuth { return t.inSchema.authRules[t.DgraphName()] } -func (t *astType) IsGeo() bool { +func (t *astType) IsPoint() bool { return t.Name() == "Point" } From cfeff0f92f8fc0c191d0000b77a8be013e816eba Mon Sep 17 00:00:00 2001 From: Pawan Rawal Date: Thu, 1 Oct 2020 21:21:14 +0530 Subject: [PATCH 18/20] Update the schema response for e2e tests --- graphql/e2e/directives/schema_response.json | 672 +++++++++---------- graphql/e2e/normal/schema_response.json | 676 ++++++++++---------- 2 files changed, 674 insertions(+), 674 deletions(-) diff --git a/graphql/e2e/directives/schema_response.json b/graphql/e2e/directives/schema_response.json index 278a2f56f55..89040bba11a 100644 --- a/graphql/e2e/directives/schema_response.json +++ b/graphql/e2e/directives/schema_response.json @@ -1,325 +1,322 @@ { "schema": [ { - "predicate": "dgraph.graphql.schema_history", - "type": "string" - }, - { - "predicate": "credits", - "type": "float" - }, - { - "predicate": "Movie.name", + "predicate": "Category.name", "type": "string" }, { - "predicate": "myPost.category", - "type": "uid" + "predicate": "Category.posts", + "type": "uid", + "list": true }, { + "predicate": "Comment1.id", + "type": "string", "index": true, - "list": true, - "predicate": "dgraph.cors", "tokenizer": [ - "exact" + "hash" ], - "type": "string", "upsert": true }, { - "predicate": "State.name", - "type": "string" - }, - { - "list": true, "predicate": "Comment1.replies", - "type": "uid" + "type": "uid", + "list": true }, { + "predicate": "Country.name", + "type": "string", "index": true, - "predicate": "People.xid", "tokenizer": [ - "hash" - ], - "type": "string", - "upsert": true - }, - { - "predicate": "post", - "type": "string" + "hash", + "trigram" + ] }, { + "predicate": "Hotel.location", + "type": "geo", "index": true, - "list": true, - "predicate": "dgraph.type", "tokenizer": [ - "exact" - ], - "type": "string" + "geo" + ] }, { + "predicate": "Hotel.name", + "type": "string", "index": true, - "list": true, - "predicate": "myPost.tags", "tokenizer": [ "exact" - ], - "type": "string" + ] }, { - "predicate": "MovieDirector.name", - "type": "string" + "predicate": "Human.starships", + "type": "uid", + "list": true }, { - "index": true, - "predicate": "star.ship.name", - "tokenizer": [ - "term" - ], + "predicate": "Movie.name", "type": "string" }, { - "index": true, - "predicate": "text", - "tokenizer": [ - "fulltext" - ], + "predicate": "MovieDirector.name", "type": "string" }, { - "predicate": "Category.name", + "predicate": "People.name", "type": "string" }, { - "list": true, - "predicate": "Post1.comments", - "type": "uid" + "predicate": "People.xid", + "type": "string", + "index": true, + "tokenizer": [ + "hash" + ], + "upsert": true }, { - "list": true, - "predicate": "hasStates", - "type": "uid" + "predicate": "Person1.friends", + "type": "uid", + "list": true }, { "predicate": "Person1.name", "type": "string" }, { - "index": true, - "predicate": "myPost.title", - "tokenizer": [ - "fulltext", - "term" - ], - "type": "string" + "predicate": "Post1.comments", + "type": "uid", + "list": true }, { + "predicate": "Post1.id", + "type": "string", "index": true, - "predicate": "Comment1.id", "tokenizer": [ "hash" ], - "type": "string", "upsert": true }, { + "predicate": "State.capital", + "type": "string" + }, + { + "predicate": "State.name", + "type": "string" + }, + { + "predicate": "State.xcode", + "type": "string", "index": true, - "predicate": "User.name", "tokenizer": [ - "hash" + "hash", + "trigram" ], - "type": "string", "upsert": true }, { - "list": true, - "predicate": "directed.movies", - "reverse": true, - "type": "uid" + "predicate": "Student.taughtBy", + "type": "uid", + "list": true }, { - "index": true, - "predicate": "Hotel.name", - "tokenizer": [ - "exact" - ], + "predicate": "Teacher.subject", "type": "string" }, { - "index": true, - "predicate": "test.dgraph.author.dob", - "tokenizer": [ - "year" - ], - "type": "datetime" + "predicate": "Teacher.teaches", + "type": "uid", + "list": true }, { - "index": true, - "predicate": "post1.title", - "tokenizer": [ - "hash", - "trigram" - ], - "type": "string", - "upsert": true + "predicate": "Thing.name", + "type": "string" }, { - "list": true, - "predicate": "test.dgraph.author.posts", - "type": "uid" + "predicate": "ThingOne.color", + "type": "string" }, { - "predicate": "post.author", - "type": "uid" + "predicate": "ThingOne.usedBy", + "type": "string" }, { - "index": true, - "predicate": "test.dgraph.topic", - "tokenizer": [ - "exact" - ], + "predicate": "ThingTwo.color", + "type": "string" + }, + { + "predicate": "ThingTwo.owner", "type": "string" }, { + "predicate": "User.name", + "type": "string", "index": true, - "predicate": "State.xcode", "tokenizer": [ - "hash", - "trigram" + "hash" ], - "type": "string", "upsert": true }, { + "predicate": "appears_in", + "type": "string", "index": true, - "predicate": "performance.character.name", "tokenizer": [ - "exact" + "hash" ], - "type": "string" + "list": true }, { - "index": true, - "predicate": "test.dgraph.author.name", - "tokenizer": [ - "hash", - "trigram" - ], - "type": "string" + "predicate": "credits", + "type": "float" }, { + "predicate": "dgraph.cors", + "type": "string", "index": true, - "predicate": "Country.name", "tokenizer": [ - "hash", - "trigram" + "exact" ], - "type": "string" + "list": true, + "upsert": true }, { - "list": true, - "predicate": "Human.starships", - "type": "uid" + "predicate": "dgraph.graphql.schema", + "type": "string" }, { "predicate": "dgraph.graphql.schema_created_at", "type": "datetime" }, { - "predicate": "dgraph.graphql.schema", + "predicate": "dgraph.graphql.schema_history", "type": "string" }, { + "predicate": "dgraph.graphql.xid", + "type": "string", "index": true, - "predicate": "myPost.postType", "tokenizer": [ - "hash", - "trigram" + "exact" ], - "type": "string" + "upsert": true }, { - "predicate": "post1.numLikes", - "type": "int" + "predicate": "dgraph.type", + "type": "string", + "index": true, + "tokenizer": [ + "exact" + ], + "list": true }, { - "predicate": "test.dgraph.employee.en.ename", - "type": "string" + "predicate": "directed.movies", + "type": "uid", + "reverse": true, + "list": true }, { - "list": true, - "predicate": "Category.posts", - "type": "uid" + "predicate": "hasStates", + "type": "uid", + "list": true }, { - "predicate": "职业", - "type": "string" + "predicate": "inCountry", + "type": "uid" }, { + "predicate": "is_published", + "type": "bool", "index": true, + "tokenizer": [ + "bool" + ] + }, + { + "predicate": "myPost.category", + "type": "uid" + }, + { "predicate": "myPost.numLikes", + "type": "int", + "index": true, "tokenizer": [ "int" - ], - "type": "int" + ] }, { - "index": true, "predicate": "myPost.numViews", + "type": "int", + "index": true, "tokenizer": [ "int" - ], - "type": "int" + ] }, { + "predicate": "myPost.postType", + "type": "string", + "index": true, + "tokenizer": [ + "hash", + "trigram" + ] + }, + { + "predicate": "myPost.tags", + "type": "string", "index": true, - "predicate": "dgraph.graphql.xid", "tokenizer": [ "exact" ], + "list": true + }, + { + "predicate": "myPost.title", "type": "string", - "upsert": true + "index": true, + "tokenizer": [ + "fulltext", + "term" + ] }, { - "predicate": "test.dgraph.author.country", - "type": "uid" + "predicate": "performance.character.name", + "type": "string", + "index": true, + "tokenizer": [ + "exact" + ] }, { - "list": true, - "predicate": "Person1.friends", + "predicate": "post", + "type": "string" + }, + { + "predicate": "post.author", "type": "uid" }, { - "predicate": "ThingOne.usedBy", - "type": "string" + "predicate": "post1.numLikes", + "type": "int" }, { + "predicate": "post1.title", + "type": "string", "index": true, - "predicate": "is_published", "tokenizer": [ - "bool" + "hash", + "trigram" ], - "type": "bool" + "upsert": true }, { "predicate": "pwd", "type": "password" }, { - "predicate": "inCountry", - "type": "uid" - }, - { - "index": true, - "list": true, - "predicate": "appears_in", - "tokenizer": [ - "hash" - ], - "type": "string" - }, - { - "predicate": "Thing.name", + "predicate": "roboDroid.primaryFunction", "type": "string" }, { @@ -327,209 +324,207 @@ "type": "float" }, { - "predicate": "Teacher.subject", - "type": "string" - }, - { + "predicate": "star.ship.name", + "type": "string", "index": true, - "predicate": "test.dgraph.author.reputation", "tokenizer": [ - "float" - ], - "type": "float" + "term" + ] }, { - "predicate": "State.capital", - "type": "string" + "predicate": "test.dgraph.author.country", + "type": "uid" }, { + "predicate": "test.dgraph.author.dob", + "type": "datetime", "index": true, - "predicate": "Hotel.location", "tokenizer": [ - "geo" - ], - "type": "geo" - }, - { - "predicate": "ThingTwo.owner", - "type": "string" - }, - { - "predicate": "ThingTwo.color", - "type": "string" + "year" + ] }, { - "predicate": "roboDroid.primaryFunction", - "type": "string" + "predicate": "test.dgraph.author.name", + "type": "string", + "index": true, + "tokenizer": [ + "hash", + "trigram" + ] }, { - "list": true, - "predicate": "Teacher.teaches", - "type": "uid" + "predicate": "test.dgraph.author.posts", + "type": "uid", + "list": true }, { - "predicate": "People.name", - "type": "string" + "predicate": "test.dgraph.author.reputation", + "type": "float", + "index": true, + "tokenizer": [ + "float" + ] }, { - "predicate": "ThingOne.color", + "predicate": "test.dgraph.employee.en.ename", "type": "string" }, { - "list": true, - "predicate": "Student.taughtBy", - "type": "uid" + "predicate": "test.dgraph.topic", + "type": "string", + "index": true, + "tokenizer": [ + "exact" + ] }, { + "predicate": "text", + "type": "string", "index": true, - "predicate": "Post1.id", "tokenizer": [ - "hash" - ], - "type": "string", - "upsert": true + "fulltext" + ] + }, + { + "predicate": "职业", + "type": "string" } ], "types": [ { "fields": [ { - "name": "Movie.name" + "name": "Category.name" + }, + { + "name": "Category.posts" } ], - "name": "Movie" + "name": "Category" }, { "fields": [ { - "name": "People.xid" - }, - { - "name": "People.name" + "name": "Comment1.id" }, { - "name": "Student.taughtBy" + "name": "Comment1.replies" } ], - "name": "Student" + "name": "Comment1" }, { "fields": [ { - "name": "MovieDirector.name" + "name": "Country.name" }, { - "name": "directed.movies" + "name": "hasStates" } ], - "name": "MovieDirector" + "name": "Country" }, { "fields": [ { - "name": "dgraph.graphql.schema" + "name": "Hotel.name" }, { - "name": "dgraph.graphql.xid" + "name": "Hotel.location" } ], - "name": "dgraph.graphql" + "name": "Hotel" }, { "fields": [ { - "name": "test.dgraph.author.dob" + "name": "test.dgraph.employee.en.ename" }, { - "name": "test.dgraph.author.posts" + "name": "performance.character.name" }, { - "name": "test.dgraph.author.name" + "name": "appears_in" }, { - "name": "test.dgraph.author.country" + "name": "Human.starships" }, { - "name": "test.dgraph.author.reputation" + "name": "credits" } ], - "name": "test.dgraph.author" + "name": "Human" }, { "fields": [ { - "name": "pwd" + "name": "post" }, { - "name": "User.name" + "name": "职业" } ], - "name": "User" + "name": "Message" }, { "fields": [ { - "name": "test.dgraph.employee.en.ename" + "name": "Movie.name" } ], - "name": "test.dgraph.employee.en" + "name": "Movie" }, { "fields": [ { - "name": "text" - }, - { - "name": "myPost.category" - }, - { - "name": "myPost.tags" - }, - { - "name": "post.author" - }, - { - "name": "myPost.title" + "name": "MovieDirector.name" }, { - "name": "test.dgraph.topic" - }, + "name": "directed.movies" + } + ], + "name": "MovieDirector" + }, + { + "fields": [ { - "name": "myPost.postType" + "name": "People.xid" }, { - "name": "is_published" - }, + "name": "People.name" + } + ], + "name": "People" + }, + { + "fields": [ { - "name": "myPost.numLikes" + "name": "Person1.name" }, { - "name": "myPost.numViews" + "name": "Person1.friends" } ], - "name": "myPost" + "name": "Person1" }, { "fields": [ { - "name": "performance.character.name" - }, - { - "name": "appears_in" + "name": "Post1.id" }, { - "name": "roboDroid.primaryFunction" + "name": "Post1.comments" } ], - "name": "roboDroid" + "name": "Post1" }, { "fields": [ { - "name": "State.name" + "name": "State.xcode" }, { - "name": "State.xcode" + "name": "State.name" }, { "name": "State.capital" @@ -543,77 +538,91 @@ { "fields": [ { - "name": "Comment1.replies" + "name": "People.xid" }, { - "name": "Comment1.id" + "name": "People.name" + }, + { + "name": "Student.taughtBy" } ], - "name": "Comment1" + "name": "Student" }, { "fields": [ { - "name": "hasStates" + "name": "People.xid" }, { - "name": "Country.name" + "name": "People.name" + }, + { + "name": "Teacher.subject" + }, + { + "name": "Teacher.teaches" } ], - "name": "Country" + "name": "Teacher" }, { "fields": [ { - "name": "credits" - }, - { - "name": "Human.starships" - }, + "name": "Thing.name" + } + ], + "name": "Thing" + }, + { + "fields": [ { - "name": "performance.character.name" + "name": "Thing.name" }, { - "name": "test.dgraph.employee.en.ename" + "name": "ThingOne.color" }, { - "name": "appears_in" + "name": "ThingOne.usedBy" } ], - "name": "Human" + "name": "ThingOne" }, { "fields": [ { - "name": "Post1.comments" + "name": "Thing.name" }, { - "name": "Post1.id" + "name": "ThingTwo.color" + }, + { + "name": "ThingTwo.owner" } ], - "name": "Post1" + "name": "ThingTwo" }, { "fields": [ { - "name": "post1.title" + "name": "User.name" }, { - "name": "post1.numLikes" + "name": "pwd" } ], - "name": "post1" + "name": "User" }, { "fields": [ { - "name": "star.ship.name" + "name": "dgraph.graphql.schema" }, { - "name": "star.ship.length" + "name": "dgraph.graphql.xid" } ], - "name": "star.ship" + "name": "dgraph.graphql" }, { "fields": [ @@ -629,57 +638,59 @@ { "fields": [ { - "name": "ThingTwo.color" + "name": "myPost.title" }, { - "name": "ThingTwo.owner" + "name": "text" }, { - "name": "Thing.name" - } - ], - "name": "ThingTwo" - }, - { - "fields": [ + "name": "myPost.tags" + }, { - "name": "post" + "name": "test.dgraph.topic" }, { - "name": "职业" - } - ], - "name": "Message" - }, - { - "fields": [ + "name": "myPost.numLikes" + }, { - "name": "Hotel.name" + "name": "myPost.numViews" }, { - "name": "Hotel.location" + "name": "is_published" + }, + { + "name": "myPost.postType" + }, + { + "name": "post.author" + }, + { + "name": "myPost.category" } ], - "name": "Hotel" + "name": "myPost" }, { "fields": [ { - "name": "Category.name" + "name": "performance.character.name" }, { - "name": "Category.posts" + "name": "appears_in" } ], - "name": "Category" + "name": "performance.character" }, { "fields": [ { - "name": "Thing.name" + "name": "post1.title" + }, + { + "name": "post1.numLikes" } ], - "name": "Thing" + "name": "post1" }, { "fields": [ @@ -688,62 +699,51 @@ }, { "name": "appears_in" + }, + { + "name": "roboDroid.primaryFunction" } ], - "name": "performance.character" + "name": "roboDroid" }, { "fields": [ { - "name": "People.xid" - }, - { - "name": "People.name" - }, - { - "name": "Teacher.subject" + "name": "star.ship.name" }, { - "name": "Teacher.teaches" + "name": "star.ship.length" } ], - "name": "Teacher" + "name": "star.ship" }, { "fields": [ { - "name": "ThingOne.usedBy" + "name": "test.dgraph.author.name" }, { - "name": "ThingOne.color" + "name": "test.dgraph.author.dob" }, { - "name": "Thing.name" - } - ], - "name": "ThingOne" - }, - { - "fields": [ + "name": "test.dgraph.author.reputation" + }, { - "name": "People.xid" + "name": "test.dgraph.author.country" }, { - "name": "People.name" + "name": "test.dgraph.author.posts" } ], - "name": "People" + "name": "test.dgraph.author" }, { "fields": [ { - "name": "Person1.name" - }, - { - "name": "Person1.friends" + "name": "test.dgraph.employee.en.ename" } ], - "name": "Person1" + "name": "test.dgraph.employee.en" } ] } \ No newline at end of file diff --git a/graphql/e2e/normal/schema_response.json b/graphql/e2e/normal/schema_response.json index eda9b1d24f2..2a1d2dacb9f 100644 --- a/graphql/e2e/normal/schema_response.json +++ b/graphql/e2e/normal/schema_response.json @@ -1,491 +1,509 @@ { "schema": [ { - "predicate": "dgraph.graphql.schema_history", - "type": "string" - }, - { - "predicate": "Movie.name", - "type": "string" - }, - { - "predicate": "Post.category", + "predicate": "Author.country", "type": "uid" }, { + "predicate": "Author.dob", + "type": "datetime", "index": true, - "list": true, - "predicate": "dgraph.cors", "tokenizer": [ - "exact" - ], + "year" + ] + }, + { + "predicate": "Author.name", "type": "string", - "upsert": true + "index": true, + "tokenizer": [ + "hash", + "trigram" + ] }, { - "list": true, "predicate": "Author.posts", - "type": "uid" + "type": "uid", + "list": true }, { - "predicate": "State.name", + "predicate": "Author.reputation", + "type": "float", + "index": true, + "tokenizer": [ + "float" + ] + }, + { + "predicate": "Category.name", "type": "string" }, { - "list": true, - "predicate": "Comment1.replies", - "type": "uid" + "predicate": "Category.posts", + "type": "uid", + "list": true }, { + "predicate": "Character.appearsIn", + "type": "string", "index": true, - "predicate": "People.xid", "tokenizer": [ "hash" ], - "type": "string", - "upsert": true + "list": true }, { + "predicate": "Character.name", + "type": "string", "index": true, - "predicate": "Author.name", "tokenizer": [ - "hash", - "trigram" - ], - "type": "string" + "exact" + ] }, { + "predicate": "Comment1.id", + "type": "string", "index": true, - "predicate": "Author.reputation", "tokenizer": [ - "float" + "hash" ], - "type": "float" + "upsert": true }, { - "predicate": "Human.totalCredits", - "type": "float" + "predicate": "Comment1.replies", + "type": "uid", + "list": true }, { + "predicate": "Country.name", + "type": "string", "index": true, - "list": true, - "predicate": "dgraph.type", "tokenizer": [ - "exact" - ], + "hash", + "trigram" + ] + }, + { + "predicate": "Country.states", + "type": "uid", + "list": true + }, + { + "predicate": "Droid.primaryFunction", + "type": "string" + }, + { + "predicate": "Employee.ename", "type": "string" }, { + "predicate": "Hotel.location", + "type": "geo", "index": true, - "predicate": "Author.dob", "tokenizer": [ - "year" - ], - "type": "datetime" + "geo" + ] }, { + "predicate": "Hotel.name", + "type": "string", "index": true, - "list": true, - "predicate": "Post.tags", "tokenizer": [ "exact" - ], - "type": "string" + ] }, { - "predicate": "MovieDirector.name", - "type": "string" + "predicate": "Human.starships", + "type": "uid", + "list": true }, { - "index": true, - "predicate": "Starship.name", - "tokenizer": [ - "term" - ], - "type": "string" + "predicate": "Human.totalCredits", + "type": "float" }, { - "list": true, "predicate": "Movie.director", - "type": "uid" + "type": "uid", + "list": true }, { - "predicate": "Category.name", + "predicate": "Movie.name", "type": "string" }, { - "list": true, - "predicate": "Post1.comments", - "type": "uid" + "predicate": "MovieDirector.directed", + "type": "uid", + "list": true + }, + { + "predicate": "MovieDirector.name", + "type": "string" }, { + "predicate": "People.name", + "type": "string" + }, + { + "predicate": "People.xid", + "type": "string", "index": true, - "predicate": "Post.text", "tokenizer": [ - "fulltext" + "hash" ], - "type": "string" + "upsert": true }, { - "predicate": "Person1.name", + "predicate": "Person.name", "type": "string" }, { - "predicate": "Droid.primaryFunction", - "type": "string" + "predicate": "Person1.friends", + "type": "uid", + "list": true }, { - "index": true, - "predicate": "Post.title", - "tokenizer": [ - "fulltext", - "term" - ], + "predicate": "Person1.name", "type": "string" }, { - "index": true, - "predicate": "Comment1.id", - "tokenizer": [ - "hash" - ], - "type": "string", - "upsert": true + "predicate": "Post.author", + "type": "uid" }, { + "predicate": "Post.category", + "type": "uid" + }, + { + "predicate": "Post.isPublished", + "type": "bool", "index": true, - "predicate": "User.name", "tokenizer": [ - "hash" - ], - "type": "string", - "upsert": true + "bool" + ] }, { + "predicate": "Post.numLikes", + "type": "int", "index": true, - "predicate": "Character.name", "tokenizer": [ - "exact" - ], - "type": "string" + "int" + ] }, { + "predicate": "Post.numViews", + "type": "int", "index": true, - "predicate": "Hotel.name", "tokenizer": [ - "exact" - ], - "type": "string" + "int" + ] }, { + "predicate": "Post.postType", + "type": "string", "index": true, - "predicate": "post1.title", "tokenizer": [ "hash", "trigram" - ], - "type": "string", - "upsert": true - }, - { - "predicate": "Person.name", - "type": "string" - }, - { - "predicate": "Post.author", - "type": "uid" + ] }, { + "predicate": "Post.tags", + "type": "string", "index": true, - "predicate": "Post.topic", "tokenizer": [ "exact" ], - "type": "string" + "list": true }, { + "predicate": "Post.text", + "type": "string", "index": true, - "predicate": "State.xcode", "tokenizer": [ - "hash", - "trigram" - ], - "type": "string", - "upsert": true + "fulltext" + ] }, { + "predicate": "Post.title", + "type": "string", "index": true, - "predicate": "Country.name", "tokenizer": [ - "hash", - "trigram" - ], - "type": "string" - }, - { - "list": true, - "predicate": "Human.starships", - "type": "uid" - }, - { - "predicate": "User.password", - "type": "password" + "fulltext", + "term" + ] }, { - "predicate": "dgraph.graphql.schema_created_at", - "type": "datetime" + "predicate": "Post.topic", + "type": "string", + "index": true, + "tokenizer": [ + "exact" + ] }, { - "predicate": "dgraph.graphql.schema", - "type": "string" + "predicate": "Post1.comments", + "type": "uid", + "list": true }, { + "predicate": "Post1.id", + "type": "string", "index": true, - "predicate": "Post.postType", "tokenizer": [ - "hash", - "trigram" + "hash" ], - "type": "string" + "upsert": true }, { - "predicate": "post1.numLikes", - "type": "int" + "predicate": "Starship.length", + "type": "float" }, { - "list": true, - "predicate": "MovieDirector.directed", - "type": "uid" + "predicate": "Starship.name", + "type": "string", + "index": true, + "tokenizer": [ + "term" + ] }, { - "list": true, - "predicate": "Category.posts", - "type": "uid" + "predicate": "State.capital", + "type": "string" }, { - "index": true, - "predicate": "Post.numLikes", - "tokenizer": [ - "int" - ], - "type": "int" + "predicate": "State.country", + "type": "uid" }, { - "index": true, - "predicate": "Post.numViews", - "tokenizer": [ - "int" - ], - "type": "int" + "predicate": "State.name", + "type": "string" }, { + "predicate": "State.xcode", + "type": "string", "index": true, - "predicate": "dgraph.graphql.xid", "tokenizer": [ - "exact" + "hash", + "trigram" ], - "type": "string", "upsert": true }, { - "index": true, - "list": true, - "predicate": "Character.appearsIn", - "tokenizer": [ - "hash" - ], - "type": "string" + "predicate": "Student.taughtBy", + "type": "uid", + "list": true }, { - "predicate": "Employee.ename", + "predicate": "Teacher.subject", "type": "string" }, { - "list": true, - "predicate": "Person1.friends", - "type": "uid" + "predicate": "Teacher.teaches", + "type": "uid", + "list": true }, { - "predicate": "ThingOne.usedBy", + "predicate": "Thing.name", "type": "string" }, { - "predicate": "State.country", - "type": "uid" + "predicate": "ThingOne.color", + "type": "string" }, { - "predicate": "Thing.name", + "predicate": "ThingOne.usedBy", "type": "string" }, { - "predicate": "Teacher.subject", + "predicate": "ThingTwo.color", "type": "string" }, { - "predicate": "State.capital", + "predicate": "ThingTwo.owner", "type": "string" }, { + "predicate": "User.name", + "type": "string", "index": true, - "predicate": "Hotel.location", "tokenizer": [ - "geo" + "hash" ], - "type": "geo" - }, - { - "predicate": "ThingTwo.owner", - "type": "string" - }, - { - "predicate": "ThingTwo.color", - "type": "string" + "upsert": true }, { - "predicate": "Author.country", - "type": "uid" + "predicate": "User.password", + "type": "password" }, { + "predicate": "dgraph.cors", + "type": "string", + "index": true, + "tokenizer": [ + "exact" + ], "list": true, - "predicate": "Teacher.teaches", - "type": "uid" - }, - { - "predicate": "People.name", - "type": "string" + "upsert": true }, { - "predicate": "ThingOne.color", + "predicate": "dgraph.graphql.schema", "type": "string" }, { - "list": true, - "predicate": "Student.taughtBy", - "type": "uid" + "predicate": "dgraph.graphql.schema_created_at", + "type": "datetime" }, { - "predicate": "Starship.length", - "type": "float" + "predicate": "dgraph.graphql.schema_history", + "type": "string" }, { + "predicate": "dgraph.graphql.xid", + "type": "string", "index": true, - "predicate": "Post1.id", "tokenizer": [ - "hash" + "exact" ], - "type": "string", "upsert": true }, { + "predicate": "dgraph.type", + "type": "string", "index": true, - "predicate": "Post.isPublished", "tokenizer": [ - "bool" + "exact" ], - "type": "bool" + "list": true }, { - "list": true, - "predicate": "Country.states", - "type": "uid" + "predicate": "post1.numLikes", + "type": "int" + }, + { + "predicate": "post1.title", + "type": "string", + "index": true, + "tokenizer": [ + "hash", + "trigram" + ], + "upsert": true } ], "types": [ { "fields": [ { - "name": "People.xid" + "name": "Author.name" + }, + { + "name": "Author.dob" + }, + { + "name": "Author.reputation" }, { - "name": "People.name" + "name": "Author.country" }, { - "name": "Student.taughtBy" + "name": "Author.posts" } ], - "name": "Student" + "name": "Author" }, { "fields": [ { - "name": "dgraph.graphql.schema" + "name": "Category.name" }, { - "name": "dgraph.graphql.xid" + "name": "Category.posts" } ], - "name": "dgraph.graphql" + "name": "Category" }, { "fields": [ { - "name": "Movie.director" + "name": "Character.name" }, { - "name": "Movie.name" + "name": "Character.appearsIn" } ], - "name": "Movie" + "name": "Character" }, { "fields": [ { - "name": "Employee.ename" + "name": "Comment1.id" + }, + { + "name": "Comment1.replies" } ], - "name": "Employee" + "name": "Comment1" }, { "fields": [ { - "name": "Post.category" - }, - { - "name": "Post.tags" - }, - { - "name": "Post.text" + "name": "Country.name" }, { - "name": "Post.author" - }, + "name": "Country.states" + } + ], + "name": "Country" + }, + { + "fields": [ { - "name": "Post.title" + "name": "Character.name" }, { - "name": "Post.topic" + "name": "Character.appearsIn" }, { - "name": "Post.postType" - }, + "name": "Droid.primaryFunction" + } + ], + "name": "Droid" + }, + { + "fields": [ { - "name": "Post.numLikes" - }, + "name": "Employee.ename" + } + ], + "name": "Employee" + }, + { + "fields": [ { - "name": "Post.numViews" + "name": "Hotel.name" }, { - "name": "Post.isPublished" + "name": "Hotel.location" } ], - "name": "Post" + "name": "Hotel" }, { "fields": [ { - "name": "Human.totalCredits" + "name": "Employee.ename" }, { - "name": "Human.starships" + "name": "Character.name" }, { - "name": "Character.name" + "name": "Character.appearsIn" }, { - "name": "Employee.ename" + "name": "Human.starships" }, { - "name": "Character.appearsIn" + "name": "Human.totalCredits" } ], "name": "Human" @@ -493,163 +511,159 @@ { "fields": [ { - "name": "Person.name" + "name": "Movie.name" + }, + { + "name": "Movie.director" } ], - "name": "Person" + "name": "Movie" }, { "fields": [ { - "name": "Comment1.replies" + "name": "MovieDirector.name" }, { - "name": "Comment1.id" + "name": "MovieDirector.directed" } ], - "name": "Comment1" + "name": "MovieDirector" }, { "fields": [ { - "name": "State.name" - }, - { - "name": "State.xcode" + "name": "People.xid" }, { - "name": "State.capital" - }, + "name": "People.name" + } + ], + "name": "People" + }, + { + "fields": [ { - "name": "State.country" + "name": "Person.name" } ], - "name": "State" + "name": "Person" }, { "fields": [ { - "name": "Post1.comments" + "name": "Person1.name" }, { - "name": "Post1.id" + "name": "Person1.friends" } ], - "name": "Post1" + "name": "Person1" }, { "fields": [ { - "name": "Author.posts" + "name": "Post.title" }, { - "name": "Author.name" + "name": "Post.text" }, { - "name": "Author.reputation" + "name": "Post.tags" }, { - "name": "Author.dob" + "name": "Post.topic" }, { - "name": "Author.country" - } - ], - "name": "Author" - }, - { - "fields": [ + "name": "Post.numLikes" + }, { - "name": "Starship.name" + "name": "Post.numViews" }, { - "name": "Starship.length" - } - ], - "name": "Starship" - }, - { - "fields": [ + "name": "Post.isPublished" + }, { - "name": "Character.name" + "name": "Post.postType" }, { - "name": "Droid.primaryFunction" + "name": "Post.author" }, { - "name": "Character.appearsIn" + "name": "Post.category" } ], - "name": "Droid" + "name": "Post" }, { "fields": [ { - "name": "post1.title" + "name": "Post1.id" }, { - "name": "post1.numLikes" + "name": "Post1.comments" } ], - "name": "post1" + "name": "Post1" }, { "fields": [ { - "name": "dgraph.graphql.schema_history" + "name": "Starship.name" }, { - "name": "dgraph.graphql.schema_created_at" + "name": "Starship.length" } ], - "name": "dgraph.graphql.history" + "name": "Starship" }, { "fields": [ { - "name": "ThingTwo.color" + "name": "State.xcode" }, { - "name": "ThingTwo.owner" + "name": "State.name" }, { - "name": "Thing.name" + "name": "State.capital" + }, + { + "name": "State.country" } ], - "name": "ThingTwo" + "name": "State" }, { "fields": [ { - "name": "Hotel.name" + "name": "People.xid" }, { - "name": "Hotel.location" + "name": "People.name" + }, + { + "name": "Student.taughtBy" } ], - "name": "Hotel" + "name": "Student" }, { "fields": [ { - "name": "Country.name" + "name": "People.xid" }, { - "name": "Country.states" - } - ], - "name": "Country" - }, - { - "fields": [ + "name": "People.name" + }, { - "name": "Category.name" + "name": "Teacher.subject" }, { - "name": "Category.posts" + "name": "Teacher.teaches" } ], - "name": "Category" + "name": "Teacher" }, { "fields": [ @@ -662,30 +676,30 @@ { "fields": [ { - "name": "Character.name" + "name": "Thing.name" }, { - "name": "Character.appearsIn" + "name": "ThingOne.color" + }, + { + "name": "ThingOne.usedBy" } ], - "name": "Character" + "name": "ThingOne" }, { "fields": [ { - "name": "People.xid" - }, - { - "name": "People.name" + "name": "Thing.name" }, { - "name": "Teacher.subject" + "name": "ThingTwo.color" }, { - "name": "Teacher.teaches" + "name": "ThingTwo.owner" } ], - "name": "Teacher" + "name": "ThingTwo" }, { "fields": [ @@ -701,49 +715,35 @@ { "fields": [ { - "name": "ThingOne.usedBy" - }, - { - "name": "ThingOne.color" - }, - { - "name": "Thing.name" - } - ], - "name": "ThingOne" - }, - { - "fields": [ - { - "name": "MovieDirector.name" + "name": "dgraph.graphql.schema" }, { - "name": "MovieDirector.directed" + "name": "dgraph.graphql.xid" } ], - "name": "MovieDirector" + "name": "dgraph.graphql" }, { "fields": [ { - "name": "People.xid" + "name": "dgraph.graphql.schema_history" }, { - "name": "People.name" + "name": "dgraph.graphql.schema_created_at" } ], - "name": "People" + "name": "dgraph.graphql.history" }, { "fields": [ { - "name": "Person1.name" + "name": "post1.title" }, { - "name": "Person1.friends" + "name": "post1.numLikes" } ], - "name": "Person1" + "name": "post1" } ] } \ No newline at end of file From b65fcd45bd9759779dea572a21336e0b34452afd Mon Sep 17 00:00:00 2001 From: Arijit Das Date: Mon, 5 Oct 2020 18:23:33 +0530 Subject: [PATCH 19/20] Add E2E test for near filter. --- graphql/e2e/common/common.go | 1 + graphql/e2e/common/query.go | 72 ++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+) diff --git a/graphql/e2e/common/common.go b/graphql/e2e/common/common.go index da6ae4fe705..76cd3e2e059 100644 --- a/graphql/e2e/common/common.go +++ b/graphql/e2e/common/common.go @@ -336,6 +336,7 @@ func RunAll(t *testing.T) { t.Run("queries have extensions", queriesHaveExtensions) t.Run("alias works for queries", queryWithAlias) t.Run("cascade directive", queryWithCascade) + t.Run("query geo near filter", queryGeoNearFilter) // mutation tests t.Run("add mutation", addMutation) diff --git a/graphql/e2e/common/query.go b/graphql/e2e/common/query.go index 53b00f5af07..b2f1f489c63 100644 --- a/graphql/e2e/common/query.go +++ b/graphql/e2e/common/query.go @@ -2084,3 +2084,75 @@ func queryWithCascade(t *testing.T) { nil) cleanupStarwars(t, newStarship.ID, humanID, "") } + +func queryGeoNearFilter(t *testing.T) { + addHotelParams := &GraphQLParams{ + Query: ` + mutation addHotel($hotels: [AddHotelInput!]!) { + addHotel(input: $hotels) { + hotel { + name + location { + latitude + longitude + } + } + } + }`, + Variables: map[string]interface{}{"hotels": []interface{}{ + map[string]interface{}{ + "name": "Taj Hotel 1", + "location": map[string]interface{}{ + "latitude": 11.11, + "longitude": 22.22, + }, + }, + map[string]interface{}{ + "name": "Taj Hotel 2", + "location": map[string]interface{}{ + "latitude": 33.33, + "longitude": 22.22, + }, + }, + map[string]interface{}{ + "name": "Taj Hotel 3", + "location": map[string]interface{}{ + "latitude": 11.11, + "longitude": 33.33, + }, + }, + }, + }, + } + gqlResponse := addHotelParams.ExecuteAsPost(t, GraphqlURL) + RequireNoGQLErrors(t, gqlResponse) + + queryHotel := &GraphQLParams{ + Query: ` + query { + queryHotel(filter: { location: { near: { distance: 100, coordinate: { latitude: 11.11, longitude: 22.22} } } }) { + name + location { + latitude + longitude + } + } + }`, + } + gqlResponse = queryHotel.ExecuteAsPost(t, GraphqlURL) + RequireNoGQLErrors(t, gqlResponse) + + queryHotelExpected := ` + { + "queryHotel":[{ + "name" : "Taj Hotel 1", + "location" : { + "latitude" : 11.11, + "longitude" : 22.22 + } + }] + }` + testutil.CompareJSON(t, queryHotelExpected, string(gqlResponse.Data)) + // Cleanup + deleteGqlType(t, "Hotel", map[string]interface{}{}, 3, nil) +} From ba94862cb2d4c8733f5f19ca81afec66d34e0246 Mon Sep 17 00:00:00 2001 From: Arijit Das Date: Wed, 7 Oct 2020 18:45:56 +0530 Subject: [PATCH 20/20] Fix E2E test after merging. --- .../schemagen/output/geo-type.graphql | 1 + .../schemagen/output/lambda-directive.graphql | 20 +++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/graphql/schema/testdata/schemagen/output/geo-type.graphql b/graphql/schema/testdata/schemagen/output/geo-type.graphql index f05910cb954..4ce56607a82 100644 --- a/graphql/schema/testdata/schemagen/output/geo-type.graphql +++ b/graphql/schema/testdata/schemagen/output/geo-type.graphql @@ -107,6 +107,7 @@ directive @auth( directive @custom(http: CustomHTTP, dql: String) on FIELD_DEFINITION directive @remote on OBJECT | INTERFACE directive @cascade(fields: [String]) on FIELD +directive @lambda on FIELD_DEFINITION input IntFilter { eq: Int diff --git a/graphql/schema/testdata/schemagen/output/lambda-directive.graphql b/graphql/schema/testdata/schemagen/output/lambda-directive.graphql index 2232f907823..e1bc4932be1 100644 --- a/graphql/schema/testdata/schemagen/output/lambda-directive.graphql +++ b/graphql/schema/testdata/schemagen/output/lambda-directive.graphql @@ -40,6 +40,7 @@ enum DgraphIndex { month day hour + geo } input AuthRule { @@ -74,6 +75,25 @@ input CustomHTTP { skipIntrospection: Boolean } +type Point { + longitude: Float! + latitude: Float! +} + +input PointRef { + longitude: Float! + latitude: Float! +} + +input NearFilter { + distance: Float! + coordinate: PointRef! +} + +input PointGeoFilter { + near: NearFilter! +} + directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION