Skip to content

Commit 3c44f06

Browse files
authored
Merge pull request graphql-java#1031 from graphql-java/query-traversal-improvements
improve query traversal and make it public
2 parents 5eb2ab7 + c6f5ead commit 3c44f06

23 files changed

Lines changed: 932 additions & 230 deletions

src/main/java/graphql/analysis/FieldVisitor.java

Lines changed: 0 additions & 10 deletions
This file was deleted.

src/main/java/graphql/analysis/MaxQueryComplexityInstrumentation.java

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -54,16 +54,19 @@ public InstrumentationContext<List<ValidationError>> beginValidation(Instrumenta
5454
}
5555
QueryTraversal queryTraversal = newQueryTraversal(parameters);
5656

57-
Map<QueryVisitorEnvironment, List<Integer>> valuesByParent = new LinkedHashMap<>();
58-
queryTraversal.visitPostOrder(env -> {
59-
int childsComplexity = 0;
60-
QueryVisitorEnvironment thisNodeAsParent = new QueryVisitorEnvironment(env.getField(), env.getFieldDefinition(), env.getParentType(), env.getParentEnvironment(), env.getArguments());
61-
if (valuesByParent.containsKey(thisNodeAsParent)) {
62-
childsComplexity = valuesByParent.get(thisNodeAsParent).stream().mapToInt(Integer::intValue).sum();
57+
Map<QueryVisitorFieldEnvironment, List<Integer>> valuesByParent = new LinkedHashMap<>();
58+
queryTraversal.visitPostOrder(new QueryVisitorStub() {
59+
@Override
60+
public void visitField(QueryVisitorFieldEnvironment env) {
61+
int childsComplexity = 0;
62+
QueryVisitorFieldEnvironment thisNodeAsParent = new QueryVisitorFieldEnvironmentImpl(env.getField(), env.getFieldDefinition(), env.getParentType(), env.getParentEnvironment(), env.getArguments(), env.getSelectionSetContainer());
63+
if (valuesByParent.containsKey(thisNodeAsParent)) {
64+
childsComplexity = valuesByParent.get(thisNodeAsParent).stream().mapToInt(Integer::intValue).sum();
65+
}
66+
int value = calculateComplexity(env, childsComplexity);
67+
valuesByParent.putIfAbsent(env.getParentEnvironment(), new ArrayList<>());
68+
valuesByParent.get(env.getParentEnvironment()).add(value);
6369
}
64-
int value = calculateComplexity(env, childsComplexity);
65-
valuesByParent.putIfAbsent(env.getParentEnvironment(), new ArrayList<>());
66-
valuesByParent.get(env.getParentEnvironment()).add(value);
6770
});
6871
int totalComplexity = valuesByParent.get(null).stream().mapToInt(Integer::intValue).sum();
6972
if (totalComplexity > maxComplexity) {
@@ -85,29 +88,29 @@ protected AbortExecutionException mkAbortException(int totalComplexity, int maxC
8588
}
8689

8790
QueryTraversal newQueryTraversal(InstrumentationValidationParameters parameters) {
88-
return new QueryTraversal(
89-
parameters.getSchema(),
90-
parameters.getDocument(),
91-
parameters.getOperation(),
92-
parameters.getVariables()
93-
);
91+
return QueryTraversal.newQueryTraversal()
92+
.schema(parameters.getSchema())
93+
.document(parameters.getDocument())
94+
.operationName(parameters.getOperation())
95+
.variables(parameters.getVariables())
96+
.build();
9497
}
9598

96-
private int calculateComplexity(QueryVisitorEnvironment queryVisitorEnvironment, int childsComplexity) {
97-
FieldComplexityEnvironment fieldComplexityEnvironment = convertEnv(queryVisitorEnvironment);
99+
private int calculateComplexity(QueryVisitorFieldEnvironment QueryVisitorFieldEnvironment, int childsComplexity) {
100+
FieldComplexityEnvironment fieldComplexityEnvironment = convertEnv(QueryVisitorFieldEnvironment);
98101
return fieldComplexityCalculator.calculate(fieldComplexityEnvironment, childsComplexity);
99102
}
100103

101-
private FieldComplexityEnvironment convertEnv(QueryVisitorEnvironment queryVisitorEnvironment) {
104+
private FieldComplexityEnvironment convertEnv(QueryVisitorFieldEnvironment QueryVisitorFieldEnvironment) {
102105
FieldComplexityEnvironment parentEnv = null;
103-
if (queryVisitorEnvironment.getParentEnvironment() != null) {
104-
parentEnv = convertEnv(queryVisitorEnvironment.getParentEnvironment());
106+
if (QueryVisitorFieldEnvironment.getParentEnvironment() != null) {
107+
parentEnv = convertEnv(QueryVisitorFieldEnvironment.getParentEnvironment());
105108
}
106109
return new FieldComplexityEnvironment(
107-
queryVisitorEnvironment.getField(),
108-
queryVisitorEnvironment.getFieldDefinition(),
109-
queryVisitorEnvironment.getParentType(),
110-
queryVisitorEnvironment.getArguments(),
110+
QueryVisitorFieldEnvironment.getField(),
111+
QueryVisitorFieldEnvironment.getFieldDefinition(),
112+
QueryVisitorFieldEnvironment.getParentType(),
113+
QueryVisitorFieldEnvironment.getArguments(),
111114
parentEnv
112115
);
113116
}

src/main/java/graphql/analysis/MaxQueryDepthInstrumentation.java

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,12 @@
44
import graphql.execution.AbortExecutionException;
55
import graphql.execution.instrumentation.InstrumentationContext;
66
import graphql.execution.instrumentation.SimpleInstrumentation;
7-
import graphql.execution.instrumentation.SimpleInstrumentationContext;
87
import graphql.execution.instrumentation.parameters.InstrumentationValidationParameters;
98
import graphql.validation.ValidationError;
109

1110
import java.util.List;
1211

13-
import static graphql.execution.instrumentation.SimpleInstrumentationContext.*;
12+
import static graphql.execution.instrumentation.SimpleInstrumentationContext.whenCompleted;
1413

1514
/**
1615
* Prevents execution if the query depth is greater than the specified maxDepth
@@ -51,15 +50,15 @@ protected AbortExecutionException mkAbortException(int depth, int maxDepth) {
5150
}
5251

5352
QueryTraversal newQueryTraversal(InstrumentationValidationParameters parameters) {
54-
return new QueryTraversal(
55-
parameters.getSchema(),
56-
parameters.getDocument(),
57-
parameters.getOperation(),
58-
parameters.getVariables()
59-
);
53+
return QueryTraversal.newQueryTraversal()
54+
.schema(parameters.getSchema())
55+
.document(parameters.getDocument())
56+
.operationName(parameters.getOperation())
57+
.variables(parameters.getVariables())
58+
.build();
6059
}
6160

62-
private int getPathLength(QueryVisitorEnvironment path) {
61+
private int getPathLength(QueryVisitorFieldEnvironment path) {
6362
int length = 1;
6463
while (path != null) {
6564
path = path.getParentEnvironment();
Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,27 @@
11
package graphql.analysis;
22

3-
import graphql.Internal;
3+
import graphql.PublicApi;
44

5-
@Internal
5+
/**
6+
* Used by {@link QueryTraversal} to reduce the fields of a Document (or part of it) to a single value.
7+
* <p/>
8+
* How this happens in detail (pre vs post-order for example) is defined by {@link QueryTraversal}.
9+
* <p/>
10+
* See {@link QueryTraversal#reducePostOrder(QueryReducer, Object)} and {@link QueryTraversal#reducePreOrder(QueryReducer, Object)}
11+
*
12+
* @param <T>
13+
*/
14+
@PublicApi
615
@FunctionalInterface
716
public interface QueryReducer<T> {
817

9-
T reduceField(QueryVisitorEnvironment reducerEnvironment, T acc);
18+
/**
19+
* Called each time a field is visited.
20+
*
21+
* @param fieldEnvironment
22+
* @param acc the previous result
23+
*
24+
* @return the new result
25+
*/
26+
T reduceField(QueryVisitorFieldEnvironment fieldEnvironment, T acc);
1027
}

0 commit comments

Comments
 (0)