Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(GraphQL) fix empty type Query with single extended type definition in the schema. #7517

Merged
merged 3 commits into from
Mar 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion graphql/schema/gqlschema.go
Original file line number Diff line number Diff line change
Expand Up @@ -2428,6 +2428,17 @@ func generateUnionString(typ *ast.Definition) string {
strings.Join(typ.Types, " | "))
}

func hasStringifiableFields(typ *ast.Definition) bool {
queriesToWrite := false
for _, fld := range typ.Fields {
if !strings.HasPrefix(fld.Name, "__") {
queriesToWrite = true
break
}
}
return queriesToWrite
}

// Stringify the schema as a GraphQL SDL string. It's assumed that the schema was
// built by completeSchema, and so contains an original set of definitions, the
// definitions from schemaExtras and generated types, queries and mutations.
Expand Down Expand Up @@ -2554,7 +2565,7 @@ func Stringify(schema *ast.Schema, originalTypes []string, apolloServiceQuery bo
x.Check2(sch.WriteString(input.String()))
}

if len(schema.Query.Fields) > 0 {
if hasStringifiableFields(schema.Query) {
x.Check2(sch.WriteString(
"#######################\n# Generated Query\n#######################\n\n"))
x.Check2(sch.WriteString(generateObjectString(schema.Query) + "\n"))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
extend type Product @key(fields: "id") {
id: String! @id @external
name: String!
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,349 @@
#######################
# Input Schema
#######################

type Product @key(fields: "id") @extends {
id: String! @id @external
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 | FIELD_DEFINITION
directive @secret(field: String!, pred: String) on OBJECT | INTERFACE
directive @remote on OBJECT | INTERFACE | UNION | INPUT_OBJECT | ENUM
directive @remoteResponse(name: String) on FIELD_DEFINITION
directive @cascade(fields: [String]) on FIELD
directive @lambda on FIELD_DEFINITION
directive @cacheControl(maxAge: Int!) on QUERY

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

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

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

input DateTimeFilter {
eq: DateTime
in: [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 AddProductPayload {
product(filter: ProductFilter, order: ProductOrder, first: Int, offset: Int): [Product]
numUids: Int
}

type DeleteProductPayload {
product(filter: ProductFilter, order: ProductOrder, first: Int, offset: Int): [Product]
msg: String
numUids: Int
}

type ProductAggregateResult {
count: Int
idMin: String
idMax: String
nameMin: String
nameMax: String
}

type UpdateProductPayload {
product(filter: ProductFilter, order: ProductOrder, first: Int, offset: Int): [Product]
numUids: Int
}

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

enum ProductHasFilter {
id
name
}

enum ProductOrderable {
id
name
}

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

input AddProductInput {
id: String!
name: String!
}

input ProductFilter {
id: StringHashFilter
has: [ProductHasFilter]
and: [ProductFilter]
or: [ProductFilter]
not: ProductFilter
}

input ProductOrder {
asc: ProductOrderable
desc: ProductOrderable
then: ProductOrder
}

input ProductPatch {
name: String
}

input ProductRef {
id: String
name: String
}

input UpdateProductInput {
filter: ProductFilter!
set: ProductPatch
remove: ProductPatch
}

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

type Mutation {
addProduct(input: [AddProductInput!]!, upsert: Boolean): AddProductPayload
updateProduct(input: UpdateProductInput!): UpdateProductPayload
deleteProduct(filter: ProductFilter!): DeleteProductPayload
}