Skip to content

Commit daf36bd

Browse files
Fix relative path logic when eliding subgraph jump for @fromContext (#3005)
This PR makes some changes to #2988, specifically: - It fixes a bug where the relative path is computed incorrectly when a subgraph jump is skipped/elided in the case of `@fromContext`. - It changes the selection-set-to-renamer conversion logic to create multiple inline fragments instead of introducing a new syntax, in the case of a type condition on an abstract type. (This saves us from having to update router to understand it.) - It tweaks the iteration over the `GraphPath` in `canSatisfyConditions()` to be cleaner/easier to understand. - When I looked at that code again, I noticed it was strange that we initialized `levelsInDataPath` at `1` even though we aren't guaranteed that the last element in `GraphPath` is a field. The gist is that at the first match, we know it's a field, so that ends up being okay. But I think it's easier to understand code-wise if both `levelsInQueryPath` and `levelsInDataPath` start off at 0, and every time we get a new element (at the start of the `for` block) we increment the counts accordingly.
1 parent c4744da commit daf36bd

File tree

4 files changed

+23
-13
lines changed

4 files changed

+23
-13
lines changed

.changeset/rare-grapes-dream.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@apollo/query-planner": patch
3+
---
4+
5+
Fix relative path logic when eliding subgraph jumps for `@fromContext`

query-graphs-js/src/graphPath.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -1909,10 +1909,14 @@ function canSatisfyConditions<TTrigger, V extends Vertex, TNullEdge extends null
19091909
// if one of the conditions fails to satisfy, it's ok to bail
19101910
let someSelectionUnsatisfied = false;
19111911
for (const cxt of requiredContexts) {
1912-
let levelsInQueryPath = 1;
1913-
let levelsInDataPath = 1;
1912+
let levelsInQueryPath = 0;
1913+
let levelsInDataPath = 0;
19141914
for (const [e, trigger] of [...path].reverse()) {
19151915
const parentType = getFieldParentType(trigger);
1916+
levelsInQueryPath += 1;
1917+
if (parentType) {
1918+
levelsInDataPath += 1;
1919+
}
19161920
if (e !== null && !contextMap.has(cxt.namedParameter) && !someSelectionUnsatisfied) {
19171921
const matches = Array.from(cxt.typesWithContextSet).some(t => {
19181922
if (parentType) {
@@ -1965,10 +1969,6 @@ function canSatisfyConditions<TTrigger, V extends Vertex, TNullEdge extends null
19651969
}
19661970
}
19671971
}
1968-
levelsInQueryPath += 1;
1969-
if (parentType) {
1970-
levelsInDataPath += 1;
1971-
}
19721972
}
19731973
}
19741974

query-planner-js/src/__tests__/buildPlan.test.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -9478,7 +9478,12 @@ describe('@fromContext impacts on query planning', () => {
94789478
expect((plan as any).node.nodes[1].node.contextRewrites).toEqual([
94799479
{
94809480
kind: 'KeyRenamer',
9481-
path: ['..', '... on A,B', 'prop'],
9481+
path: ['..', '... on A', 'prop'],
9482+
renameKeyTo: 'contextualArgument_1_0',
9483+
},
9484+
{
9485+
kind: 'KeyRenamer',
9486+
path: ['..', '... on B', 'prop'],
94829487
renameKeyTo: 'contextualArgument_1_0',
94839488
},
94849489
]);

query-planner-js/src/buildPlan.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -1678,13 +1678,11 @@ function selectionSetAsKeyRenamers(selectionSet: SelectionSet, relPath: string[]
16781678
if (selection.kind === 'FieldSelection') {
16791679
// We always have at least one '..' in the relative path.
16801680
if (relPath[relPath.length - 1] === '..') {
1681-
const runtimeTypes =
1682-
possibleRuntimeTypes(selectionSet.parentType).map((t) => t.name).join(",");
1683-
return [{
1681+
return possibleRuntimeTypes(selectionSet.parentType).map((t) => ({
16841682
kind: 'KeyRenamer',
1685-
path: [...relPath, `... on ${runtimeTypes}`, selection.element.name],
1683+
path: [...relPath, `... on ${t.name}`, selection.element.name],
16861684
renameKeyTo: alias,
1687-
}];
1685+
}));
16881686
} else {
16891687
return [{
16901688
kind: 'KeyRenamer',
@@ -4445,9 +4443,11 @@ function computeGroupsForTree(
44454443
} else {
44464444
// in this case we can just continue with the current group, but we need to add the context rewrites
44474445
if (parameterToContext) {
4446+
const numFields = updated.path.inGroup().filter((e) => e.kind === 'Field').length;
44484447
for (const [_, { selectionSet, relativePath, contextId, subgraphArgType }] of parameterToContext) {
4448+
const newRelativePath = relativePath.slice(0, relativePath.length - numFields);
44494449
updated.group.addInputContext(contextId, subgraphArgType);
4450-
const keyRenamers = selectionSetAsKeyRenamers(selectionSet, relativePath, contextId);
4450+
const keyRenamers = selectionSetAsKeyRenamers(selectionSet, newRelativePath, contextId);
44514451
for (const keyRenamer of keyRenamers) {
44524452
updated.group.addContextRenamer(keyRenamer);
44534453
}

0 commit comments

Comments
 (0)