Skip to content

Commit 24f2e2e

Browse files
[Fusion] Fail Query Plan generation early (#7989)
1 parent 82886c5 commit 24f2e2e

File tree

4 files changed

+84
-10
lines changed

4 files changed

+84
-10
lines changed

src/HotChocolate/Fusion/src/Core/Planning/Pipeline/ExecutionStepDiscoveryMiddleware.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -797,9 +797,9 @@ private bool EnsureStepCanBeResolvedFromRoot(
797797

798798
while (current is not null)
799799
{
800-
var typeMetadata = _config.GetType<ObjectTypeMetadata>(path.Selection.DeclaringType.Name);
800+
var typeMetadata = _config.GetType<ObjectTypeMetadata>(current.Selection.DeclaringType.Name);
801801

802-
if (!typeMetadata.Fields[path.Selection.Field.Name].Bindings.ContainsSubgraph(subgraphName))
802+
if (!typeMetadata.Fields[current.Selection.Field.Name].Bindings.ContainsSubgraph(subgraphName))
803803
{
804804
return false;
805805
}

src/HotChocolate/Fusion/src/Core/Planning/Steps/SelectionExecutionStep.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ internal sealed class SelectionExecutionStep : ExecutionStep
2222
/// <param name="subgraphName">
2323
/// The name of the subgraph from which this execution step will fetch data.
2424
/// </param>
25-
/// <param name="selectionSet">
25+
/// <param name="selectionSetType">
2626
/// The selection set that is part of this execution step.
2727
/// </param>
2828
/// <param name="selectionSetTypeMetadata">
@@ -31,9 +31,9 @@ internal sealed class SelectionExecutionStep : ExecutionStep
3131
public SelectionExecutionStep(
3232
int id,
3333
string subgraphName,
34-
IObjectType selectionSet,
34+
IObjectType selectionSetType,
3535
ObjectTypeMetadata selectionSetTypeMetadata)
36-
: this(id, subgraphName, null, null, selectionSet, selectionSetTypeMetadata)
36+
: this(id, subgraphName, null, null, selectionSetType, selectionSetTypeMetadata)
3737
{
3838
}
3939

@@ -52,7 +52,7 @@ public SelectionExecutionStep(
5252
/// <param name="parentSelectionPath">
5353
/// The selection path from which this execution step was spawned.
5454
/// </param>
55-
/// <param name="selectionSet">
55+
/// <param name="selectionSetType">
5656
/// The selection set that is part of this execution step.
5757
/// </param>
5858
/// <param name="selectionSetTypeMetadata">
@@ -63,9 +63,9 @@ public SelectionExecutionStep(
6363
string subgraphName,
6464
ISelection? parentSelection,
6565
SelectionPath? parentSelectionPath,
66-
IObjectType selectionSet,
66+
IObjectType selectionSetType,
6767
ObjectTypeMetadata selectionSetTypeMetadata)
68-
: base(id, parentSelection, selectionSet, selectionSetTypeMetadata)
68+
: base(id, parentSelection, selectionSetType, selectionSetTypeMetadata)
6969
{
7070
SubgraphName = subgraphName;
7171
ParentSelectionPath = parentSelectionPath;

src/HotChocolate/Fusion/src/Core/Planning/Steps/SelectionPath.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ public override string ToString()
3535

3636
while (current is not null)
3737
{
38-
sb.Append('/');
39-
sb.Append(Selection.ResponseName);
38+
sb.Insert(0, '/');
39+
sb.Insert(1, current.Selection.ResponseName);
4040
current = current.Parent;
4141
}
4242

src/HotChocolate/Fusion/test/Core.Tests/RequestPlannerTests.cs

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2650,6 +2650,80 @@ query Requires {
26502650
await snapshot.MatchMarkdownAsync();
26512651
}
26522652

2653+
[Fact]
2654+
public async Task Throw_Instead_Of_Creating_Faulty_QueryPlan()
2655+
{
2656+
// arrange
2657+
var subgraphA = await TestSubgraph.CreateAsync(
2658+
"""
2659+
type Query {
2660+
node(id: ID!): Node
2661+
productById(id: ID!): Product
2662+
}
2663+
2664+
interface Node {
2665+
id: ID!
2666+
}
2667+
2668+
type Product implements Node {
2669+
id: ID!
2670+
review: Review
2671+
}
2672+
2673+
type Review implements Node {
2674+
id: ID!
2675+
ratings: Ratings
2676+
}
2677+
2678+
type Ratings {
2679+
upvotes: Int!
2680+
}
2681+
""");
2682+
2683+
var subgraphB = await TestSubgraph.CreateAsync(
2684+
"""
2685+
type Query {
2686+
node(id: ID!): Node
2687+
}
2688+
2689+
interface Node {
2690+
id: ID!
2691+
}
2692+
2693+
type Review implements Node {
2694+
id: ID!
2695+
ratings: Ratings
2696+
}
2697+
2698+
type Ratings {
2699+
downvotes: Int!
2700+
}
2701+
""");
2702+
2703+
using var subgraphs = new TestSubgraphCollection(output, [subgraphA, subgraphB]);
2704+
var fusionGraph = await subgraphs.GetFusionGraphAsync();
2705+
2706+
// act
2707+
var act = () => CreateQueryPlanAsync(
2708+
fusionGraph,
2709+
"""
2710+
query {
2711+
productById(id: "1") {
2712+
review {
2713+
ratings {
2714+
upvotes
2715+
downvotes
2716+
}
2717+
}
2718+
}
2719+
}
2720+
""");
2721+
2722+
// assert
2723+
var exception = await Assert.ThrowsAsync<InvalidOperationException>(act);
2724+
Assert.Equal(FusionResources.ThrowHelper_NoResolverInContext, exception.Message);
2725+
}
2726+
26532727
private static async Task<(DocumentNode UserRequest, Execution.Nodes.QueryPlan QueryPlan)> CreateQueryPlanAsync(
26542728
Skimmed.SchemaDefinition fusionGraph,
26552729
[StringSyntax("graphql")] string query)

0 commit comments

Comments
 (0)