Skip to content

Conversation

@gnawf
Copy link
Contributor

@gnawf gnawf commented Dec 9, 2021

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

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

place this ImmutableKit say

Copy link
Member

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??

Copy link
Contributor Author

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?

@gnawf gnawf force-pushed the fwang/improve-isConditional branch from 2cabee4 to 6e2218b Compare February 21, 2022 22:09
Copy link
Contributor Author

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.

Copy link
Member

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

Copy link
Contributor Author

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

Copy link
Contributor Author

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.

Copy link
Member

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

Copy link
Contributor Author

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.

https://github.com/graphql-java/graphql-java/blob/6e2218b7fe66d9b1003e0a863b180b2ebc622786/src/test/groovy/graphql/normalized/ExecutableNormalizedOperationFactoryTest.groovy#L747-L791

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 

@gnawf gnawf marked this pull request as ready for review February 21, 2022 22:16
@gnawf gnawf force-pushed the fwang/improve-isConditional branch from 6e2218b to 40c30d8 Compare February 22, 2022 22:37
@gnawf gnawf force-pushed the fwang/improve-isConditional branch from 40c30d8 to 918cc71 Compare February 22, 2022 22:40
@gnawf gnawf force-pushed the fwang/improve-isConditional branch from 918cc71 to d24b0d0 Compare February 22, 2022 22:43
Copy link
Contributor Author

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.

Copy link
Member

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) {
Copy link
Member

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?

Copy link
Contributor Author

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
Copy link
Member

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
Copy link
Member

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
Copy link
Member

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
Copy link
Member

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.

Copy link
Contributor Author

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.

Copy link
Member

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

... on Dog {
isGoodBoy
}
... on Node {
Copy link
Member

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
Copy link
Member

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.

@gnawf
Copy link
Contributor Author

gnawf commented Feb 24, 2022

Fixed all comments, but please don't merge yet. Need to consider how this change affects Nadel.

@andimarek andimarek changed the title Improve ExecutableNormalizedField.isConditional for interface fields Improve ExecutableNormalizedField.isConditional for interface fields and fix a bug regarding covariant fields Feb 24, 2022
@gnawf
Copy link
Contributor Author

gnawf commented Feb 27, 2022

Ok ready to merge

@andimarek andimarek merged commit 7fe0d84 into graphql-java:master Feb 28, 2022
@andimarek andimarek added this to the 18.0 milestone Feb 28, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants