From 1a8e3b4920f5e4a8123d001a2f0d379fefc08a96 Mon Sep 17 00:00:00 2001 From: Duckki Oe Date: Tue, 2 Jul 2024 01:41:55 -0700 Subject: [PATCH] fix(federation): added the `remove_introspection` step in `normalize_operation` (#5580) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Renée --- apollo-federation/src/operation/mod.rs | 16 +++++++ .../src/query_plan/query_planner.rs | 47 +++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/apollo-federation/src/operation/mod.rs b/apollo-federation/src/operation/mod.rs index cd6fbc7a377..0804321b337 100644 --- a/apollo-federation/src/operation/mod.rs +++ b/apollo-federation/src/operation/mod.rs @@ -4901,6 +4901,7 @@ pub(crate) fn normalize_operation( schema, NormalizeSelectionOption::NormalizeRecursively, )?; + remove_introspection(&mut normalized_selection_set); normalized_selection_set.optimize_sibling_typenames(interface_types_with_interface_objects)?; let normalized_operation = Operation { @@ -4915,6 +4916,21 @@ pub(crate) fn normalize_operation( Ok(normalized_operation) } +// PORT_NOTE: This is a port of `withoutIntrospection` from JS version. +fn remove_introspection(selection_set: &mut SelectionSet) { + // Note that, because we only apply this to the top-level selections, we skip all + // introspection, including __typename. In general, we don't want to ignore __typename during + // query plans, but at top-level, we can let the router execution deal with it rather than + // querying some service for that. + + Arc::make_mut(&mut selection_set.selections).retain(|_, selection| { + !matches!(selection, + Selection::Field(field_selection) if + field_selection.field.field_position.is_introspection_typename_field() + ) + }); +} + fn runtime_types_intersect( type1: &CompositeTypeDefinitionPosition, type2: &CompositeTypeDefinitionPosition, diff --git a/apollo-federation/src/query_plan/query_planner.rs b/apollo-federation/src/query_plan/query_planner.rs index 732d600c0af..f0df9fab42f 100644 --- a/apollo-federation/src/query_plan/query_planner.rs +++ b/apollo-federation/src/query_plan/query_planner.rs @@ -1313,4 +1313,51 @@ type User } "###); } + + #[test] + fn drop_operation_root_level_typename() { + let subgraph1 = Subgraph::parse_and_expand( + "Subgraph1", + "https://Subgraph1", + r#" + type Query { + t: T + } + + type T @key(fields: "id") { + id: ID! + x: Int + } + "#, + ) + .unwrap(); + let subgraphs = vec![&subgraph1]; + let supergraph = Supergraph::compose(subgraphs).unwrap(); + let planner = QueryPlanner::new(&supergraph, Default::default()).unwrap(); + let document = ExecutableDocument::parse_and_validate( + planner.api_schema().schema(), + r#" + query { + __typename + t { + x + } + } + "#, + "operation.graphql", + ) + .unwrap(); + let plan = planner.build_query_plan(&document, None).unwrap(); + insta::assert_snapshot!(plan, @r###" + QueryPlan { + Fetch(service: "Subgraph1") { + { + t { + x + } + } + }, + } + "###); + } }