Skip to content

Commit

Permalink
fix(federation): remove redundant typename for inline fragments
Browse files Browse the repository at this point in the history
When adding `__typename` field for abstract types, we need to check for inline fragment type condition and not the parent selection set. If we have an inline fragment without type condition and it is pointing to and abstract type, then the required `__typename` field should have already been added to its parent field.
  • Loading branch information
dariuszkuc committed Aug 22, 2024
1 parent 092170a commit db097cb
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 1 deletion.
14 changes: 13 additions & 1 deletion apollo-federation/src/operation/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -895,7 +895,19 @@ impl Selection {
}

fn sub_selection_type_position(&self) -> Option<CompositeTypeDefinitionPosition> {
Some(self.selection_set()?.type_position.clone())
match self {
Selection::Field(field_selection) => field_selection
.selection_set
.as_ref()
.map(|s| s.type_position.clone()),
Selection::FragmentSpread(fragment_selection) => {
Some(fragment_selection.spread.type_condition_position.clone())
}
Selection::InlineFragment(inline_fragment_selection) => inline_fragment_selection
.inline_fragment
.type_condition_position
.clone(),
}
}

pub(crate) fn conditions(&self) -> Result<Conditions, FederationError> {
Expand Down
40 changes: 40 additions & 0 deletions apollo-federation/tests/query_plan/build_query_plan_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -914,3 +914,43 @@ fn test_merging_fetches_do_not_create_cycle_in_fetch_dependency_graph() {
"###
);
}

#[test]
fn redundant_typename_for_inline_fragments_without_type_condition() {
let planner = planner!(
Subgraph1: r#"
type Query {
products: [Product]
}
interface Product {
name: String
}
"#,
);
assert_plan!(
&planner,
r#"
{
products {
... @skip(if: false) {
name
}
}
}
"#,
@r###"
QueryPlan {
Fetch(service: "Subgraph1") {
{
products {
__typename
... @skip(if: false) {
name
}
}
}
},
}
"###
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Composed from subgraphs with hash: d267b3f18f7736e1a3e39a951696c318d1f46a34
schema
@link(url: "https://specs.apollo.dev/link/v1.0")
@link(url: "https://specs.apollo.dev/join/v0.3", for: EXECUTION)
{
query: Query
}

directive @join__enumValue(graph: join__Graph!) repeatable on ENUM_VALUE

directive @join__field(graph: join__Graph, requires: join__FieldSet, provides: join__FieldSet, type: String, external: Boolean, override: String, usedOverridden: Boolean) repeatable on FIELD_DEFINITION | INPUT_FIELD_DEFINITION

directive @join__graph(name: String!, url: String!) on ENUM_VALUE

directive @join__implements(graph: join__Graph!, interface: String!) repeatable on OBJECT | INTERFACE

directive @join__type(graph: join__Graph!, key: join__FieldSet, extension: Boolean! = false, resolvable: Boolean! = true, isInterfaceObject: Boolean! = false) repeatable on OBJECT | INTERFACE | UNION | ENUM | INPUT_OBJECT | SCALAR

directive @join__unionMember(graph: join__Graph!, member: String!) repeatable on UNION

directive @link(url: String, as: String, for: link__Purpose, import: [link__Import]) repeatable on SCHEMA

scalar join__FieldSet

enum join__Graph {
SUBGRAPH1 @join__graph(name: "Subgraph1", url: "none")
}

scalar link__Import

enum link__Purpose {
"""
`SECURITY` features provide metadata necessary to securely resolve fields.
"""
SECURITY

"""
`EXECUTION` features provide metadata necessary for operation execution.
"""
EXECUTION
}

interface Product
@join__type(graph: SUBGRAPH1)
{
name: String
}

type Query
@join__type(graph: SUBGRAPH1)
{
products: [Product]
}

0 comments on commit db097cb

Please sign in to comment.