-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Improve ExecutableNormalizedField.isConditional for interface fields and fix a bug regarding covariant fields #2638
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
Improve ExecutableNormalizedField.isConditional for interface fields and fix a bug regarding covariant fields #2638
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
place this ImmutableKit say
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we not work this out at ENF object creation time. eg we have the parent field in scope as we create child ones.
So iis it more efficient to know the "parent is an interface" and hence the child field is conditional?
This then becomes a boolean without having to look upwards
Thoughts??
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could but Nadel needs to manipulate and insert new objects which would need it computed for them.
An optimization for later I'd say?
2cabee4 to
6e2218b
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See the doco below for why this is wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would suggest removing it then ... this is not a public api and we don't need to deprecate thing we don't want
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Introspection fields only work directly under Query
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Deprecating these, we should never use them. As we discussed on Slack last week too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same as the others: lets remove it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed a bug here where we weren't considering ALL the field definitions. There's a test case for this.
Without this fix, the test would've returned
-Query.animal: Animal
--[Cat, Dog].parent: Cat, Dog
---[Cat].name: String
Instead of
-Query.animal: Animal
--[Cat, Dog].parent: Cat, Dog
---[Cat, Dog].name: String
6e2218b to
40c30d8
Compare
40c30d8 to
918cc71
Compare
918cc71 to
d24b0d0
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was deciding whether to mark the VariableAccumulator value as nullable or non-nullable in compileToDocument and decided to make it nullable with it defaulting to false.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would suggest removing it then ... this is not a public api and we don't need to deprecate thing we don't want
| * We MUST consider that the output type of the {@code parent} field is {@code Animal} and | ||
| * NOT {@code Cat} or {@code Dog} as their respective impls would say. | ||
| */ | ||
| public boolean isConditional(GraphQLSchema schema, @Nullable String parentOutputTypeName) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we should allow parentOutputTypeName to be null. This makes for an akward api. Or is there a strong reason for it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nah, we could make it non-nullable. I'll make that change.
| return parentOutputType != getOneObjectType(schema); | ||
| } | ||
|
|
||
| @Deprecated // using this is ALMOST always wrong |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lets remove this instead of saying it is wrong to use it.
| return getOneFieldDefinition(schema).getType(); | ||
| } | ||
|
|
||
| @Deprecated // using this is ALMOST always wrong |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here
|
|
||
| GraphQLType parentOutputType = schema.getType(parentOutputTypeName); | ||
|
|
||
| // Is not conditional if field exists in interface type, and we have specified all impls |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is hard to read: can we handle the introspection field name explicitly first?
| GraphQLInterfaceType parentOutputTypeAsInterface = (GraphQLInterfaceType) parentOutputType; | ||
| List<GraphQLObjectType> interfaceImpls = schema.getImplementations(parentOutputTypeAsInterface); | ||
| if (interfaceImpls.size() == objectTypeNames.size()) { | ||
| return parentOutputTypeAsInterface.getField(this.fieldName) == null |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do we need check for field name existing in the paren type? If it doesn't exist it would imply that the schema doesn't match the ENF and I would throw an Exception normally.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nah this is checking whether the field exists in the interface type e.g.
type Query {
pet: Pet
}
interface Pet {
name: String
}
type Dog implements Pet {
name: String
collar: String
}
So the a tree can go
- [Query].pet: Pet
-- [Dog].name
-- [Dog].collar
We need an inline fragment for collar because it's not in Pet but we don't need one for name.
I think checking number of impls and object type names is not enough? Actually now that I think about it… maybe you're right and we don't nee to check. I'll confirm tomorrow.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same as the others: lets remove it
src/main/java/graphql/normalized/ExecutableNormalizedOperationToAstCompiler.java
Show resolved
Hide resolved
| ... on Dog { | ||
| isGoodBoy | ||
| } | ||
| ... on Node { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is a great test. We should probably have another one where this is a standalone fragment and not inlined and used in another context where ...on Node actually can include File
| def printed = AstPrinter.printAst(new AstSorter().sort(result.document)) | ||
|
|
||
| then: | ||
| // Perhaps the typename should be hoisted out of the fragments, but the impl currently generates |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thinking about the __typename hanlding: I think we need to improve this
one fundamental principle of the ENF is that regardless of the query the ENF should be same if it executes the same.
Here we can generate two different ENOperation when we place __typename directly inside the Union or inside all type conditions for all types. Both of them must produce the same ENOperation.
This is not directly related to printing, but in this test it becomes obvious.
|
Fixed all comments, but please don't merge yet. Need to consider how this change affects Nadel. |
|
Ok ready to merge |
Not done, need to review the logic, clean it up and add tests etc. Just putting up for early review.
This heavily compresses some queries described in GQLGW-1181.
It got the query I had down from 4k lines to 800