Skip to content

Commit

Permalink
fix(GRAPHQL):[Breaking] Don't generate get query on interface if it d…
Browse files Browse the repository at this point in the history
…oesn't have field of type ID and also disallow get query on field of type @id in inerface. (#7158)

Fixes GRAPHQL-886
We were allowing get query on the field of type @id on the interface type. This causes an error in cases when interface is implemented by multiple types and they try to have same value for field of type @id.
To resolve this we are disallowing get query on the interface if it doesn't have a field of type ID , and if we have both fields of type ID and @id then we don't allow get query on the field of type @id.
  • Loading branch information
JatinDev543 authored Dec 21, 2020
1 parent ac07cc2 commit 96b1fa5
Show file tree
Hide file tree
Showing 4 changed files with 363 additions and 3 deletions.
4 changes: 2 additions & 2 deletions graphql/schema/gqlschema.go
Original file line number Diff line number Diff line change
Expand Up @@ -1732,7 +1732,7 @@ func addAggregationResultType(schema *ast.Schema, defn *ast.Definition) {
func addGetQuery(schema *ast.Schema, defn *ast.Definition, generateSubscription bool) {
hasIDField := hasID(defn)
hasXIDField := hasXID(defn)
if !hasIDField && !hasXIDField {
if !hasIDField && (defn.Kind == "INTERFACE" || !hasXIDField) {
return
}

Expand All @@ -1755,7 +1755,7 @@ func addGetQuery(schema *ast.Schema, defn *ast.Definition, generateSubscription
},
})
}
if hasXIDField {
if hasXIDField && defn.Kind != "INTERFACE" {
name, dtype := xidTypeFor(defn)
qry.Arguments = append(qry.Arguments, &ast.ArgumentDefinition{
Name: name,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
interface Student {
rollNo: String! @id
regNo: ID!
name: String!
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,356 @@
#######################
# Input Schema
#######################

interface Student {
rollNo: String! @id
regNo: ID!
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

input IntRange{
min: Int!
max: Int!
}

input FloatRange{
min: Float!
max: Float!
}

input Int64Range{
min: Int64!
max: Int64!
}

input DateTimeRange{
min: DateTime!
max: DateTime!
}

input StringRange{
min: String!
max: String!
}

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
within: WithinFilter
}

type PointList {
points: [Point!]!
}

input PointListRef {
points: [PointRef!]!
}

type Polygon {
coordinates: [PointList!]!
}

input PolygonRef {
coordinates: [PointListRef!]!
}

type MultiPolygon {
polygons: [Polygon!]!
}

input MultiPolygonRef {
polygons: [PolygonRef!]!
}

input WithinFilter {
polygon: PolygonRef!
}

input ContainsFilter {
point: PointRef
polygon: PolygonRef
}

input IntersectsFilter {
polygon: PolygonRef
multiPolygon: MultiPolygonRef
}

input PolygonGeoFilter {
near: NearFilter
within: WithinFilter
contains: ContainsFilter
intersects: IntersectsFilter
}

input GenerateQueryParams {
get: Boolean
query: Boolean
password: Boolean
aggregate: Boolean
}

input GenerateMutationParams {
add: Boolean
update: Boolean
delete: Boolean
}

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(
password: AuthRule
query: AuthRule,
add: AuthRule,
update: AuthRule,
delete: AuthRule) on OBJECT | INTERFACE
directive @custom(http: CustomHTTP, dql: String) on FIELD_DEFINITION
directive @remote on OBJECT | INTERFACE | UNION | INPUT_OBJECT | ENUM
directive @cascade(fields: [String]) on FIELD
directive @lambda on FIELD_DEFINITION
directive @cacheControl(maxAge: Int!) on QUERY
directive @generate(
query: GenerateQueryParams,
mutation: GenerateMutationParams,
subscription: Boolean) on OBJECT | INTERFACE

input IntFilter {
eq: Int
le: Int
lt: Int
ge: Int
gt: Int
between: IntRange
}

input Int64Filter {
eq: Int64
le: Int64
lt: Int64
ge: Int64
gt: Int64
between: Int64Range
}

input FloatFilter {
eq: Float
le: Float
lt: Float
ge: Float
gt: Float
between: FloatRange
}

input DateTimeFilter {
eq: DateTime
le: DateTime
lt: DateTime
ge: DateTime
gt: DateTime
between: DateTimeRange
}

input StringTermFilter {
allofterms: String
anyofterms: String
}

input StringRegExpFilter {
regexp: String
}

input StringFullTextFilter {
alloftext: String
anyoftext: String
}

input StringExactFilter {
eq: String
in: [String]
le: String
lt: String
ge: String
gt: String
between: StringRange
}

input StringHashFilter {
eq: String
in: [String]
}

#######################
# Generated Types
#######################

type DeleteStudentPayload {
student(filter: StudentFilter, order: StudentOrder, first: Int, offset: Int): [Student]
msg: String
numUids: Int
}

type StudentAggregateResult {
count: Int
rollNoMin: String
rollNoMax: String
nameMin: String
nameMax: String
}

type UpdateStudentPayload {
student(filter: StudentFilter, order: StudentOrder, first: Int, offset: Int): [Student]
numUids: Int
}

#######################
# Generated Enums
#######################

enum StudentHasFilter {
rollNo
name
}

enum StudentOrderable {
rollNo
name
}

#######################
# Generated Inputs
#######################

input StudentFilter {
rollNo: StringHashFilter
regNo: [ID!]
has: StudentHasFilter
and: [StudentFilter]
or: [StudentFilter]
not: StudentFilter
}

input StudentOrder {
asc: StudentOrderable
desc: StudentOrderable
then: StudentOrder
}

input StudentPatch {
name: String
}

input StudentRef {
regNo: ID
rollNo: String @id
}

input UpdateStudentInput {
filter: StudentFilter!
set: StudentPatch
remove: StudentPatch
}

#######################
# Generated Query
#######################

type Query {
getStudent(regNo: ID): Student
queryStudent(filter: StudentFilter, order: StudentOrder, first: Int, offset: Int): [Student]
aggregateStudent(filter: StudentFilter): StudentAggregateResult
}

#######################
# Generated Mutations
#######################

type Mutation {
updateStudent(input: UpdateStudentInput!): UpdateStudentPayload
deleteStudent(filter: StudentFilter!): DeleteStudentPayload
}

Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,6 @@ input UpdateLibraryInput {
#######################

type Query {
getLibraryItem(refID: String!): LibraryItem
queryLibraryItem(filter: LibraryItemFilter, order: LibraryItemOrder, first: Int, offset: Int): [LibraryItem]
aggregateLibraryItem(filter: LibraryItemFilter): LibraryItemAggregateResult
getBook(refID: String!): Book
Expand Down

0 comments on commit 96b1fa5

Please sign in to comment.