Skip to content

Commit f61eb35

Browse files
Update selection path with type refinement
1 parent 37eb310 commit f61eb35

File tree

4 files changed

+58
-22
lines changed

4 files changed

+58
-22
lines changed

src/HotChocolate/Fusion-vnext/src/Fusion.Execution/Planning/OperationDefinitionBuilder.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ internal sealed class OperationDefinitionBuilder
1212
private string? _name;
1313
private string? _description;
1414
private Lookup? _lookup;
15+
private string? _lookupTypeRefinement;
1516
private string? _requirementKey;
1617
private SelectionSetNode? _selectionSet;
1718

@@ -40,9 +41,10 @@ public OperationDefinitionBuilder SetDescription(string? description)
4041
return this;
4142
}
4243

43-
public OperationDefinitionBuilder SetLookup(Lookup? lookup, string? requirementKey)
44+
public OperationDefinitionBuilder SetLookup(Lookup? lookup, string? lookupTypeRefinement, string? requirementKey)
4445
{
4546
_lookup = lookup;
47+
_lookupTypeRefinement = lookupTypeRefinement;
4648
_requirementKey = requirementKey;
4749
return this;
4850
}
@@ -87,6 +89,12 @@ public OperationDefinitionBuilder SetSelectionSet(SelectionSetNode selectionSet)
8789
var indexBuilder = index.ToBuilder();
8890
indexBuilder.Register(selectionSet);
8991
index = indexBuilder;
92+
93+
if (!string.IsNullOrEmpty(_lookupTypeRefinement))
94+
{
95+
selectionPath = selectionPath.AppendFragment(_lookupTypeRefinement);
96+
}
97+
9098
selectionPath = selectionPath.AppendField(_lookup.FieldName);
9199
}
92100

src/HotChocolate/Fusion-vnext/src/Fusion.Execution/Planning/OperationPlanner.cs

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -293,10 +293,11 @@ lookup is null
293293
requirements = requirements.Add(argumentRequirementKey, operationRequirement);
294294
}
295295

296-
// If the lookup returns an abstract type, we might need to insert a type refinement
297-
// around our selection set.
296+
string? lookupTypeRefinement = null;
298297
if (_schema.Types.TryGetType(lookup.FieldType, out var lookupFieldType)
299-
&& lookupFieldType != workItem.SelectionSet.Type)
298+
&& lookupFieldType != workItem.SelectionSet.Type
299+
&& !resolvable.Selections.All(s => s is InlineFragmentNode inlineFragment
300+
&& inlineFragment.TypeCondition?.Name.Value == workItem.SelectionSet.Type.Name))
300301
{
301302
var typeRefinement =
302303
new InlineFragmentNode(
@@ -313,9 +314,11 @@ lookup is null
313314
index = indexBuilder;
314315

315316
operationBuilder.SetSelectionSet(selectionSetWithTypeRefinement);
317+
318+
lookupTypeRefinement = workItem.SelectionSet.Type.Name;
316319
}
317320

318-
operationBuilder.SetLookup(lookup, requirementKey);
321+
operationBuilder.SetLookup(lookup, lookupTypeRefinement, requirementKey);
319322
}
320323

321324
(var definition, index, var source) = operationBuilder.Build(index);
@@ -686,7 +689,32 @@ private void PlanFieldWithRequirement(
686689
requirements = requirements.Add(argumentRequirementKey, operationRequirement);
687690
}
688691

689-
operationBuilder.SetLookup(workItem.Lookup, requirementKey);
692+
string? lookupTypeRefinement = null;
693+
if (_schema.Types.TryGetType(lookup.FieldType, out var lookupFieldType)
694+
&& lookupFieldType != selectionSetStub.Type
695+
&& !selectionSetNode.Selections.All(s => s is InlineFragmentNode inlineFragment
696+
&& inlineFragment.TypeCondition?.Name.Value == selectionSetStub.Type.Name))
697+
{
698+
var typeRefinement =
699+
new InlineFragmentNode(
700+
null,
701+
new NamedTypeNode(selectionSetStub.Type.Name),
702+
[],
703+
selectionSetNode);
704+
var selectionSetWithTypeRefinement = new SelectionSetNode(null, [typeRefinement]);
705+
706+
var indexBuilder = index.ToBuilder();
707+
708+
indexBuilder.Register(selectionSetNode, selectionSetWithTypeRefinement);
709+
710+
index = indexBuilder;
711+
712+
operationBuilder.SetSelectionSet(selectionSetWithTypeRefinement);
713+
714+
lookupTypeRefinement = selectionSetStub.Type.Name;
715+
}
716+
717+
operationBuilder.SetLookup(workItem.Lookup, lookupTypeRefinement, requirementKey);
690718

691719
var (definition, _, source) = operationBuilder.Build(index);
692720

src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/Planning/__snapshots__/OperationPlannerTests.Plan_Simple_Interface_Lookup.yaml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
operation:
22
- document: >-
3-
query GetTopProducts {
4-
topProduct {
5-
id
6-
name
7-
price
8-
id @fusion__requirement
3+
query GetTopProducts {
4+
topProduct {
5+
id
6+
name
7+
price
8+
id @fusion__requirement
9+
}
910
}
10-
}
1111
name: GetTopProducts
1212
hash: 123
1313
nodes:
@@ -32,7 +32,7 @@ nodes:
3232
}
3333
}
3434
}
35-
source: $.node
35+
source: $.node.<Product>
3636
target: $.topProduct
3737
requirements:
3838
- name: __fusion_1_id

src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/Planning/__snapshots__/OperationPlannerTests.Plan_Simple_Union_Lookup.yaml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
operation:
22
- document: >-
3-
query GetTopProducts {
4-
topProduct {
5-
id
6-
name
7-
price
8-
id @fusion__requirement
3+
query GetTopProducts {
4+
topProduct {
5+
id
6+
name
7+
price
8+
id @fusion__requirement
9+
}
910
}
10-
}
1111
name: GetTopProducts
1212
hash: 123
1313
nodes:
@@ -32,7 +32,7 @@ nodes:
3232
}
3333
}
3434
}
35-
source: $.lookupUnionById
35+
source: $.lookupUnionById.<Product>
3636
target: $.topProduct
3737
requirements:
3838
- name: __fusion_1_id

0 commit comments

Comments
 (0)