Skip to content

Commit 3024ecb

Browse files
committed
Remove all document variables hint
1 parent 58c419e commit 3024ecb

532 files changed

Lines changed: 6271 additions & 3129 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

lib/src/main/java/graphql/nadel/NadelExecutionHints.kt

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package graphql.nadel
22

3-
import graphql.nadel.hints.AllDocumentVariablesHint
43
import graphql.nadel.hints.LegacyOperationNamesHint
54
import graphql.nadel.hints.NadelBatchRootFieldsHint
65
import graphql.nadel.hints.NadelDeferSupportHint
@@ -18,7 +17,6 @@ import graphql.nadel.hints.NewResultMergerAndNamespacedTypename
1817

1918
data class NadelExecutionHints(
2019
val legacyOperationNames: LegacyOperationNamesHint,
21-
val allDocumentVariablesHint: AllDocumentVariablesHint,
2220
val newResultMergerAndNamespacedTypename: NewResultMergerAndNamespacedTypename,
2321
val deferSupport: NadelDeferSupportHint,
2422
val sharedTypeRenames: NadelSharedTypeRenamesHint,
@@ -45,7 +43,6 @@ data class NadelExecutionHints(
4543

4644
class Builder {
4745
private var legacyOperationNames = LegacyOperationNamesHint { false }
48-
private var allDocumentVariablesHint = AllDocumentVariablesHint { false }
4946
private var newResultMergerAndNamespacedTypename = NewResultMergerAndNamespacedTypename { false }
5047
private var deferSupport = NadelDeferSupportHint { false }
5148
private var shortCircuitEmptyQuery = NadelShortCircuitEmptyQueryHint { false }
@@ -64,7 +61,6 @@ data class NadelExecutionHints(
6461

6562
constructor(nadelExecutionHints: NadelExecutionHints) {
6663
legacyOperationNames = nadelExecutionHints.legacyOperationNames
67-
allDocumentVariablesHint = nadelExecutionHints.allDocumentVariablesHint
6864
newResultMergerAndNamespacedTypename = nadelExecutionHints.newResultMergerAndNamespacedTypename
6965
deferSupport = nadelExecutionHints.deferSupport
7066
shortCircuitEmptyQuery = nadelExecutionHints.shortCircuitEmptyQuery
@@ -85,11 +81,6 @@ data class NadelExecutionHints(
8581
return this
8682
}
8783

88-
fun allDocumentVariablesHint(flag: AllDocumentVariablesHint): Builder {
89-
allDocumentVariablesHint = flag
90-
return this
91-
}
92-
9384
fun newResultMergerAndNamespacedTypename(flag: NewResultMergerAndNamespacedTypename): Builder {
9485
newResultMergerAndNamespacedTypename = flag
9586
return this
@@ -158,7 +149,6 @@ data class NadelExecutionHints(
158149
fun build(): NadelExecutionHints {
159150
return NadelExecutionHints(
160151
legacyOperationNames,
161-
allDocumentVariablesHint,
162152
newResultMergerAndNamespacedTypename,
163153
deferSupport,
164154
sharedTypeRenames,

lib/src/main/java/graphql/nadel/NextgenEngine.kt

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ import graphql.nadel.util.OperationNameUtil
5656
import graphql.nadel.validation.NadelSchemaValidation
5757
import graphql.normalized.ExecutableNormalizedField
5858
import graphql.normalized.ExecutableNormalizedOperationFactory.createExecutableNormalizedOperationWithRawVariables
59-
import graphql.normalized.VariablePredicate
6059
import graphql.schema.GraphQLSchema
6160
import kotlinx.coroutines.CoroutineScope
6261
import kotlinx.coroutines.Dispatchers
@@ -384,15 +383,13 @@ internal class NextgenEngine(
384383

385384
val executionInput = executionContext.executionInput
386385

387-
val jsonPredicate: VariablePredicate = getDocumentVariablePredicate(executionContext.hints, service)
388-
389386
val compileResult = timer.time(step = DocumentCompilation) {
390387
compileToDocument(
391388
schema = service.underlyingSchema,
392389
operationKind = topLevelFields.first().getOperationKind(engineSchema),
393390
operationName = getOperationName(service, executionContext),
394391
topLevelFields = topLevelFields,
395-
variablePredicate = jsonPredicate,
392+
variablePredicate = DocumentPredicates.allVariablesPredicate,
396393
deferSupport = executionContext.hints.deferSupport(),
397394
forcePrintBareFields = forcePrintBareFields,
398395
)
@@ -498,14 +495,6 @@ internal class NextgenEngine(
498495
&& topLevelField.children.all { it.name == TypeNameMetaFieldDef.name }
499496
}
500497

501-
private fun getDocumentVariablePredicate(hints: NadelExecutionHints, service: Service): VariablePredicate {
502-
return if (hints.allDocumentVariablesHint.invoke(service)) {
503-
DocumentPredicates.allVariablesPredicate
504-
} else {
505-
DocumentPredicates.jsonPredicate
506-
}
507-
}
508-
509498
private fun getOperationName(service: Service, executionContext: NadelExecutionContext): String? {
510499
val originalOperationName = executionContext.query.operationName
511500
return if (executionContext.hints.legacyOperationNames(service)) {

lib/src/main/java/graphql/nadel/engine/document/DocumentPredicates.kt

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,6 @@ import graphql.normalized.VariablePredicate
55
class DocumentPredicates {
66

77
companion object {
8-
/**
9-
* A predicate that causes JSON arguments to be compiled as variables
10-
*/
11-
val jsonPredicate =
12-
VariablePredicate { _, _, normalizedInputValue ->
13-
"JSON" == normalizedInputValue.unwrappedTypeName && normalizedInputValue.value != null
14-
}
15-
168
/**
179
* A predicate that causes ALL arguments to be compiled as variables
1810
*/

lib/src/main/java/graphql/nadel/engine/transform/hydration/NadelHydrationInputBuilder.kt

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ internal class NadelHydrationInputBuilder private constructor(
124124
inputDef: NadelHydrationArgument,
125125
): NormalizedInputValue? {
126126
return when (val valueSource = inputDef.valueSource) {
127-
is ValueSource.ArgumentValue -> getArgumentValue(valueSource)
127+
is ValueSource.ArgumentValue -> getArgumentValue(inputDef, valueSource)
128128
is ValueSource.FieldResultValue -> makeInputValue(
129129
inputDef,
130130
value = getResultValue(valueSource),
@@ -162,9 +162,16 @@ internal class NadelHydrationInputBuilder private constructor(
162162
}
163163

164164
private fun getArgumentValue(
165+
inputDef: NadelHydrationArgument,
165166
valueSource: ValueSource.ArgumentValue,
166167
): NormalizedInputValue? {
167-
return virtualField.getNormalizedArgument(valueSource.argumentName) ?: valueSource.defaultValue
168+
val argumentValue = virtualField.getNormalizedArgument(valueSource.argumentName) ?: valueSource.defaultValue
169+
return argumentValue?.let {
170+
NormalizedInputValue(
171+
GraphQLTypeUtil.simplePrint(inputDef.backingArgumentDef.type),
172+
it.value,
173+
)
174+
}
168175
}
169176

170177
private fun getResultValue(

lib/src/main/java/graphql/nadel/engine/transform/hydration/batch/NadelBatchHydrationInputBuilder.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@ internal object NadelBatchHydrationInputBuilder {
3030
virtualField.normalizedArguments[valueSource.argumentName]
3131
?: valueSource.defaultValue
3232
if (argValue != null) {
33-
argument to argValue
33+
argument to NormalizedInputValue(
34+
GraphQLTypeUtil.simplePrint(argument.backingArgumentDef.type),
35+
argValue.value,
36+
)
3437
} else {
3538
null
3639
}

lib/src/main/java/graphql/nadel/hints/AllDocumentVariablesHint.kt

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

lib/src/test/kotlin/graphql/nadel/archunit/NadelPrefixTest.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@ class NadelPrefixTest {
6767
"graphql.nadel.engine.transform.result.json.JsonNodeExtractor",
6868
"graphql.nadel.engine.transform.result.json.JsonNodes",
6969
"graphql.nadel.engine.util.AliasesKt",
70-
"graphql.nadel.hints.AllDocumentVariablesHint",
7170
"graphql.nadel.hints.LegacyOperationNamesHint",
7271
"graphql.nadel.hints.NewBatchHydrationGroupingHint",
7372
"graphql.nadel.hints.NewResultMergerAndNamespacedTypename",

test/src/test/kotlin/graphql/nadel/tests/EngineTests.kt

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ import graphql.GraphQLError
55
import graphql.incremental.DeferPayload
66
import graphql.incremental.DelayedIncrementalPartialResult
77
import graphql.incremental.DelayedIncrementalPartialResultImpl.newIncrementalExecutionResult
8-
import graphql.language.AstPrinter
9-
import graphql.language.AstSorter
108
import graphql.nadel.Nadel
119
import graphql.nadel.NadelExecutionHints
1210
import graphql.nadel.NadelExecutionInput.Companion.newNadelExecutionInput
@@ -34,6 +32,7 @@ import kotlinx.coroutines.reactive.asPublisher
3432
import org.junit.jupiter.api.fail
3533
import org.reactivestreams.Publisher
3634
import java.io.File
35+
import java.math.BigDecimal
3736
import java.math.BigInteger
3837
import java.util.concurrent.CompletableFuture
3938

@@ -163,7 +162,6 @@ private suspend fun execute(
163162
.overallWiringFactory(testHook.wiringFactory)
164163
.underlyingWiringFactory(testHook.wiringFactory)
165164
.serviceExecutionFactory(object : ServiceExecutionFactory {
166-
private val astSorter = AstSorter()
167165
private val serviceCalls = fixture.serviceCalls.toMutableList()
168166

169167
override fun getServiceExecution(serviceName: String): ServiceExecution {
@@ -172,9 +170,11 @@ private suspend fun execute(
172170
val incomingQuery = params.query
173171
val actualVariables = fixVariables(params.variables)
174172
val actualOperationName = params.operationDefinition.name
175-
val actualQuery = AstPrinter.printAst(
176-
astSorter.sort(incomingQuery),
173+
val actualRequest = canonicalizeServiceRequest(
174+
document = incomingQuery,
175+
variables = actualVariables,
177176
)
177+
val actualQuery = actualRequest.query
178178
printSyncLine(actualQuery)
179179

180180
fun failWithFixtureContext(message: String): Nothing {
@@ -192,10 +192,14 @@ private suspend fun execute(
192192
synchronized(serviceCalls) {
193193
val indexOfCall = serviceCalls
194194
.indexOfFirst {
195+
val expectedRequest = canonicalizeServiceRequest(
196+
document = it.request.document,
197+
variables = it.request.variables,
198+
)
199+
195200
it.serviceName == serviceName
196-
&& AstPrinter.printAst(it.request.document) == actualQuery
201+
&& expectedRequest == actualRequest
197202
&& it.request.operationName == actualOperationName
198-
&& it.request.variables == actualVariables
199203
}
200204
.takeIf { it != -1 }
201205

@@ -303,6 +307,9 @@ private suspend fun execute(
303307
} else {
304308
value.toLong()
305309
}
310+
} else if (value is BigDecimal) {
311+
// Jackson parses floating point fixture variables as Double
312+
value.toDouble()
306313
} else if (value is AnyMap) {
307314
@Suppress("UNCHECKED_CAST")
308315
fixVariables(value as JsonMap)
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
package graphql.nadel.tests
2+
3+
import graphql.language.AstPrinter
4+
import graphql.language.AstSorter
5+
import graphql.language.AstTransformer
6+
import graphql.language.Document
7+
import graphql.language.Node
8+
import graphql.language.NodeTraverser
9+
import graphql.language.NodeVisitorStub
10+
import graphql.language.OperationDefinition
11+
import graphql.language.VariableDefinition
12+
import graphql.language.VariableReference
13+
import graphql.nadel.engine.util.JsonMap
14+
import graphql.parser.Parser
15+
import graphql.util.TraversalControl
16+
import graphql.util.TraverserContext
17+
import graphql.util.TreeTransformerUtil.changeNode
18+
19+
internal data class CanonicalServiceRequest(
20+
val query: String,
21+
val variables: JsonMap,
22+
)
23+
24+
internal fun canonicalizeServiceRequest(
25+
query: String,
26+
variables: JsonMap,
27+
): CanonicalServiceRequest {
28+
return canonicalizeServiceRequest(
29+
document = Parser().parseDocument(query),
30+
variables = variables,
31+
)
32+
}
33+
34+
internal fun canonicalizeServiceRequest(
35+
document: Document,
36+
variables: JsonMap,
37+
): CanonicalServiceRequest {
38+
val sortedDocument = AstSorter().sort(document)
39+
val variableNames = linkedSetOf<String>()
40+
41+
NodeTraverser().preOrder(
42+
object : NodeVisitorStub() {
43+
override fun visitVariableReference(
44+
node: VariableReference,
45+
context: TraverserContext<Node<*>>,
46+
): TraversalControl {
47+
variableNames += node.name
48+
return TraversalControl.CONTINUE
49+
}
50+
},
51+
sortedDocument,
52+
)
53+
54+
val operation = sortedDocument.definitions
55+
.filterIsInstance<OperationDefinition>()
56+
.single()
57+
val definedVariableNames = operation.variableDefinitions
58+
.mapTo(linkedSetOf()) { it.name }
59+
60+
require(variableNames == definedVariableNames) {
61+
"Service query variable definitions and references must match"
62+
}
63+
require(variables.keys.all(definedVariableNames::contains)) {
64+
"Service variables must be declared by the service query"
65+
}
66+
67+
val canonicalNames = variableNames
68+
.withIndex()
69+
.associate { (index, name) ->
70+
name to "v$index"
71+
}
72+
73+
val renamedDocument = AstTransformer().transform(
74+
sortedDocument,
75+
object : NodeVisitorStub() {
76+
override fun visitVariableDefinition(
77+
node: VariableDefinition,
78+
context: TraverserContext<Node<*>>,
79+
): TraversalControl {
80+
return changeNode(
81+
context,
82+
node.transform { builder ->
83+
builder.name(canonicalNames.getValue(node.name))
84+
},
85+
)
86+
}
87+
88+
override fun visitVariableReference(
89+
node: VariableReference,
90+
context: TraverserContext<Node<*>>,
91+
): TraversalControl {
92+
return changeNode(
93+
context,
94+
node.transform { builder ->
95+
builder.name(canonicalNames.getValue(node.name))
96+
},
97+
)
98+
}
99+
},
100+
) as Document
101+
102+
val canonicalVariables = linkedMapOf<String, Any?>()
103+
canonicalNames.forEach { (name, canonicalName) ->
104+
if (variables.containsKey(name)) {
105+
canonicalVariables[canonicalName] = variables[name]
106+
}
107+
}
108+
109+
return CanonicalServiceRequest(
110+
query = AstPrinter.printAst(
111+
AstSorter().sort(renamedDocument),
112+
),
113+
variables = canonicalVariables,
114+
)
115+
}

0 commit comments

Comments
 (0)