Skip to content

Commit 80f35b3

Browse files
authored
Merge pull request #4059 from graphql-java/smidge-faster-unwrap-nonnull
A smidge faster unwrap non-null
2 parents 76d96ab + 7e0a66e commit 80f35b3

7 files changed

Lines changed: 59 additions & 15 deletions

File tree

src/main/java/graphql/execution/ExecutionStepInfo.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,18 @@ public GraphQLOutputType getUnwrappedNonNullType() {
126126
return (GraphQLOutputType) GraphQLTypeUtil.unwrapNonNull(this.type);
127127
}
128128

129+
/**
130+
* This returns the type which is unwrapped if it was {@link GraphQLNonNull} wrapped
131+
* and then cast to the target type.
132+
*
133+
* @param <T> for two
134+
*
135+
* @return the graphql type in question
136+
*/
137+
public <T extends GraphQLOutputType> T getUnwrappedNonNullTypeAs() {
138+
return GraphQLTypeUtil.unwrapNonNullAs(this.type);
139+
}
140+
129141
/**
130142
* This returns the field definition that is in play when this type info was created or null
131143
* if the type is a root query type

src/main/java/graphql/execution/ExecutionStepInfoFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
public class ExecutionStepInfoFactory {
2626

2727
public ExecutionStepInfo newExecutionStepInfoForListElement(ExecutionStepInfo executionInfo, ResultPath indexedPath) {
28-
GraphQLList fieldType = (GraphQLList) executionInfo.getUnwrappedNonNullType();
28+
GraphQLList fieldType = executionInfo.getUnwrappedNonNullTypeAs();
2929
GraphQLOutputType typeInList = (GraphQLOutputType) fieldType.getWrappedType();
3030
return executionInfo.transform(typeInList, executionInfo, indexedPath);
3131
}

src/main/java/graphql/execution/ExecutionStrategy.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,7 @@ protected Object resolveFieldWithInfo(ExecutionContext executionContext, Executi
394394
@DuckTyped(shape = "CompletableFuture<FetchedValue|Object> | <FetchedValue|Object>")
395395
protected Object fetchField(ExecutionContext executionContext, ExecutionStrategyParameters parameters) {
396396
MergedField field = parameters.getField();
397-
GraphQLObjectType parentType = (GraphQLObjectType) parameters.getExecutionStepInfo().getUnwrappedNonNullType();
397+
GraphQLObjectType parentType = parameters.getExecutionStepInfo().getUnwrappedNonNullTypeAs();
398398
GraphQLFieldDefinition fieldDef = getFieldDef(executionContext.getGraphQLSchema(), parentType, field.getSingleField());
399399
return fetchField(fieldDef, executionContext, parameters);
400400
}
@@ -408,7 +408,7 @@ private Object fetchField(GraphQLFieldDefinition fieldDef, ExecutionContext exec
408408
}
409409

410410
MergedField field = parameters.getField();
411-
GraphQLObjectType parentType = (GraphQLObjectType) parameters.getExecutionStepInfo().getUnwrappedNonNullType();
411+
GraphQLObjectType parentType = parameters.getExecutionStepInfo().getUnwrappedNonNullTypeAs();
412412

413413
// if the DF (like PropertyDataFetcher) does not use the arguments or execution step info then dont build any
414414

@@ -615,13 +615,13 @@ protected FieldValueInfo completeField(ExecutionContext executionContext,
615615
executionContext.throwIfCancelled();
616616

617617
Field field = parameters.getField().getSingleField();
618-
GraphQLObjectType parentType = (GraphQLObjectType) parameters.getExecutionStepInfo().getUnwrappedNonNullType();
618+
GraphQLObjectType parentType = parameters.getExecutionStepInfo().getUnwrappedNonNullTypeAs();
619619
GraphQLFieldDefinition fieldDef = getFieldDef(executionContext.getGraphQLSchema(), parentType, field);
620620
return completeField(fieldDef, executionContext, parameters, fetchedValue);
621621
}
622622

623623
private FieldValueInfo completeField(GraphQLFieldDefinition fieldDef, ExecutionContext executionContext, ExecutionStrategyParameters parameters, Object fetchedValue) {
624-
GraphQLObjectType parentType = (GraphQLObjectType) parameters.getExecutionStepInfo().getUnwrappedNonNullType();
624+
GraphQLObjectType parentType = parameters.getExecutionStepInfo().getUnwrappedNonNullTypeAs();
625625
ExecutionStepInfo executionStepInfo = createExecutionStepInfo(executionContext, parameters, fieldDef, parentType);
626626

627627
Instrumentation instrumentation = executionContext.getInstrumentation();
@@ -1008,7 +1008,7 @@ private boolean incrementAndCheckMaxNodesExceeded(ExecutionContext executionCont
10081008
* @return a {@link GraphQLFieldDefinition}
10091009
*/
10101010
protected GraphQLFieldDefinition getFieldDef(ExecutionContext executionContext, ExecutionStrategyParameters parameters, Field field) {
1011-
GraphQLObjectType parentType = (GraphQLObjectType) parameters.getExecutionStepInfo().getUnwrappedNonNullType();
1011+
GraphQLObjectType parentType = parameters.getExecutionStepInfo().getUnwrappedNonNullTypeAs();
10121012
return getFieldDef(executionContext.getGraphQLSchema(), parentType, field);
10131013
}
10141014

src/main/java/graphql/execution/SubscriptionExecutionStrategy.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ private ExecutionStrategyParameters firstFieldOfSubscriptionSelection(ExecutionC
226226
private ExecutionStepInfo createSubscribedFieldStepInfo(ExecutionContext
227227
executionContext, ExecutionStrategyParameters parameters) {
228228
Field field = parameters.getField().getSingleField();
229-
GraphQLObjectType parentType = (GraphQLObjectType) parameters.getExecutionStepInfo().getUnwrappedNonNullType();
229+
GraphQLObjectType parentType = parameters.getExecutionStepInfo().getUnwrappedNonNullTypeAs();
230230
GraphQLFieldDefinition fieldDef = getFieldDef(executionContext.getGraphQLSchema(), parentType, field);
231231
return createExecutionStepInfo(executionContext, parameters, fieldDef, parentType);
232232
}

src/main/java/graphql/schema/GraphQLNonNull.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ public GraphQLNonNull(GraphQLType wrappedType) {
4646
}
4747

4848
private void assertNonNullWrapping(GraphQLType wrappedType) {
49-
assertTrue(!GraphQLTypeUtil.isNonNull(wrappedType),
50-
"A non null type cannot wrap an existing non null type '%s'", GraphQLTypeUtil.simplePrint(wrappedType));
49+
assertTrue(!GraphQLTypeUtil.isNonNull(wrappedType), () ->
50+
"A non null type cannot wrap an existing non null type");
5151
}
5252

5353
@Override

src/main/java/graphql/schema/GraphQLTypeUtil.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -219,22 +219,26 @@ private static GraphQLType unwrapAllImpl(GraphQLType type) {
219219

220220

221221
/**
222-
* Unwraps all non nullable layers of the type until it reaches a type that is not {@link GraphQLNonNull}
222+
* Unwraps a single non-nullable layer of the type if its present. Note there can
223+
* only ever be one non-nullable wrapping of a type and this is enforced by {@link GraphQLNonNull}
223224
*
224225
* @param type the type to unwrap
225226
*
226227
* @return the underlying type that is not {@link GraphQLNonNull}
227228
*/
228229
public static GraphQLType unwrapNonNull(GraphQLType type) {
229-
while (isNonNull(type)) {
230-
type = unwrapOne(type);
230+
// its illegal to have a type that is a non-null wrapping a non-null type
231+
// and GraphQLNonNull has code that prevents it so we can just check once during the unwrapping
232+
if (isNonNull(type)) {
233+
// is cheaper doing this direct rather than calling #unwrapOne
234+
type = ((GraphQLNonNull) type).getWrappedType();
231235
}
232236
return type;
233237
}
234238

235239
/**
236-
* Unwraps all non nullable layers of the type until it reaches a type that is not {@link GraphQLNonNull}
237-
* and then cast to the target type.
240+
* Unwraps a single non-nullable layer of the type if its present and then cast to the target type. Note there can
241+
* only ever be one non-nullable wrapping of a type and this is enforced by {@link GraphQLNonNull}
238242
*
239243
* @param type the type to unwrap
240244
* @param <T> for two

src/test/groovy/graphql/schema/GraphQLTypeUtilTest.groovy

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import static graphql.Scalars.GraphQLString
66
import static graphql.schema.GraphQLList.list
77
import static graphql.schema.GraphQLNonNull.nonNull
88
import static graphql.schema.GraphQLObjectType.newObject
9-
import static graphql.schema.GraphQLTypeReference.*
9+
import static graphql.schema.GraphQLTypeReference.typeRef
1010

1111
class GraphQLTypeUtilTest extends Specification {
1212

@@ -205,4 +205,32 @@ class GraphQLTypeUtilTest extends Specification {
205205
then:
206206
!GraphQLTypeUtil.isInput(type)
207207
}
208+
209+
def "can unwrap non null-ness"() {
210+
211+
when:
212+
def type = GraphQLTypeUtil.unwrapNonNull(nonNull(GraphQLString))
213+
214+
then:
215+
(type as GraphQLNamedType).getName() == "String"
216+
217+
when:
218+
type = GraphQLTypeUtil.unwrapNonNull(nonNull(list(GraphQLString)))
219+
220+
then:
221+
type instanceof GraphQLList
222+
223+
when:
224+
type = GraphQLTypeUtil.unwrapNonNull(list(GraphQLString))
225+
226+
then:
227+
type instanceof GraphQLList
228+
229+
when:
230+
type = GraphQLTypeUtil.unwrapNonNull(GraphQLString)
231+
232+
then:
233+
(type as GraphQLNamedType).getName() == "String"
234+
235+
}
208236
}

0 commit comments

Comments
 (0)