E5EF Made the field definition lookup more optimised by bbakerman · Pull Request #3494 · graphql-java/graphql-java · GitHub
[go: up one dir, main page]

Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ public TraversalControl visitArgument(Argument argument, TraverserContext<Node>
QueryVisitorFieldEnvironment fieldEnv = fieldCtx.getEnvironment();
GraphQLFieldsContainer fieldsContainer = fieldEnv.getFieldsContainer();

GraphQLFieldDefinition fieldDefinition = Introspection.getFieldDef(schema, fieldsContainer, field.getName());
GraphQLFieldDefinition fieldDefinition = Introspection.getFieldDefinition(schema, fieldsContainer, field.getName());
GraphQLArgument graphQLArgument = fieldDefinition.getArgument(argument.getName());
String argumentName = graphQLArgument.getName();

Expand Down
2 changes: 1 addition & 1 deletion src/main/java/graphql/execution/ExecutionStrategy.java
Original file line number Diff line number Diff line change
Expand Up @@ -946,7 +946,7 @@ protected GraphQLFieldDefinition getFieldDef(ExecutionContext executionContext,
* @return a {@link GraphQLFieldDefinition}
*/
protected GraphQLFieldDefinition getFieldDef(GraphQLSchema schema, GraphQLObjectType parentType, Field field) {
return Introspection.getFieldDef(schema, parentType, field.getName());
return Introspection.getFieldDefinition(schema, parentType, field.getName());
10BC0 }

/**
Expand Down
49 changes: 41 additions & 8 deletions src/main/java/graphql/introspection/Introspection.java
Original file line number Diff line number Diff line change
Expand Up @@ -784,7 +784,8 @@ public static boolean isIntrospectionTypes(String typeName) {

/**
* This will look up a field definition by name, and understand that fields like __typename and __schema are special
* and take precedence in field resolution
* and take precedence in field resolution. If the parent type is a union type, then the only field allowed
* is `__typename`.
*
* @param schema the schema to use
* @param parentType the type of the parent object
Expand All @@ -794,6 +795,43 @@ public static boolean isIntrospectionTypes(String typeName) {
*/
public static GraphQLFieldDefinition getFieldDef(GraphQLSchema schema, GraphQLCompositeType parentType, String fieldName) {

GraphQLFieldDefinition fieldDefinition = getSystemFieldDef(schema, parentType, fieldName);
if (fieldDefinition != null) {
return fieldDefinition;
}

assertTrue(parentType instanceof GraphQLFieldsContainer, "should not happen : parent type must be an object or interface %s", parentType);
GraphQLFieldsContainer fieldsContainer = (GraphQLFieldsContainer) parentType;
fieldDefinition = schema.getCodeRegistry().getFieldVisibility().getFieldDefinition(fieldsContainer, fieldName);
assertTrue(fieldDefinition != null, "Unknown field '%s' for type %s", fieldName, fieldsContainer.getName());
return fieldDefinition;
}
Copy link
Member Author

Choose a reason for hiding this comment

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

I have left the old method in place for semantic reasons and also its signature is not what the execution engine needs.

The parentType instanceof GraphQLFieldsContainer is not needed say.


/**
* This will look up a field definition by name, and understand that fields like __typename and __schema are special
* and take precedence in field resolution
*
* @param schema the schema to use
* @param parentType the type of the parent {@link GraphQLFieldsContainer}
* @param fieldName the field to look up
*
* @return a field definition otherwise throws an assertion exception if it's null
*/
public static GraphQLFieldDefinition getFieldDefinition(GraphQLSchema schema, GraphQLFieldsContainer parentType, String fieldName) {
// this method is optimized to look up the most common case first (type for field) and hence suits the hot path of the execution engine
// and as a small benefit does not allocate any assertions unless it completely failed
GraphQLFieldDefinition fieldDefinition = schema.getCodeRegistry().getFieldVisibility().getFieldDefinition(parentType, fieldName);
if (fieldDefinition == null) {
// we look up system fields second because they are less likely to be the field in question
fieldDefinition = getSystemFieldDef(schema, parentType, fieldName);
if (fieldDefinition == null) {
Assert.assertShouldNeverHappen(String.format("Unknown field '%s' for type %s", fieldName, parentType.getName()));
}
}
return fieldDefinition;
}
Copy link
Member Author

Choose a reason for hiding this comment

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

The comments above outlines the reasoning


private static GraphQLFieldDefinition getSystemFieldDef(GraphQLSchema schema, GraphQLCompositeType parentType, String fieldName) {
Copy link
Member Author

Choose a reason for hiding this comment

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

I made a common private method for the system field lookup code to share some between the two methods

if (schema.getQueryType() == parentType) {
if (fieldName.equals(schema.getIntrospectionSchemaFieldDefinition().getName())) {
return schema.getIntrospectionSchemaFieldDefinition();
Expand All @@ -805,11 +843,6 @@ public static GraphQLFieldDefinition getFieldDef(GraphQLSchema schema, GraphQLCo
i AF00 f (fieldName.equals(schema.getIntrospectionTypenameFieldDefinition().getName())) {
return schema.getIntrospectionTypenameFieldDefinition();
}

assertTrue(parentType instanceof GraphQLFieldsContainer, "Should not happen : parent type must be an object or interface %s", parentType);
GraphQLFieldsContainer fieldsContainer = (GraphQLFieldsContainer) parentType;
GraphQLFieldDefinition fieldDefinition = schema.getCodeRegistry().getFieldVisibility().getFieldDefinition(fieldsContainer, fieldName);
assertTrue(fieldDefinition != null, "Unknown field '%s' for type %s", fieldName, fieldsContainer.getName());
return fieldDefinition;
return null;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import graphql.schema.FieldCoordinates;
import graphql.schema.GraphQLCompositeType;
import graphql.schema.GraphQLFieldDefinition;
import graphql.schema.GraphQLFieldsContainer;
import graphql.schema.GraphQLInterfaceType;
import graphql.schema.GraphQLNamedOutputType;
import graphql.schema.GraphQLObjectType;
Expand Down Expand Up @@ -644,7 +645,7 @@ private ExecutableNormalizedField createNF(CollectedFieldGroup collectedFieldGro
Set<GraphQLObjectType> objectTypes = collectedFieldGroup.objectTypes;
field = collectedFieldGroup.fields.iterator().next().field;
String fieldName = field.getName();
GraphQLFieldDefinition fieldDefinition = Introspection.getFieldDef(graphQLSchema, objectTypes.iterator().next(), fieldName);
GraphQLFieldDefinition fieldDefinition = Introspection.getFieldDefinition(graphQLSchema, objectTypes.iterator().next(), fieldName);

Map<String, Object> argumentValues = ValuesResolver.getArgumentValues(fieldDefinition.getArguments(), field.getArguments(), CoercedVariables.of(this.coercedVariableValues.toMap()), this.options.graphQLContext, this.options.locale);
Map<String, NormalizedInputValue> normalizedArgumentValues = null;
Expand Down
0