diff --git a/v3/crates/graphql/ir/src/lib.rs b/v3/crates/graphql/ir/src/lib.rs index 77d4453728a09..993a709c1a7a5 100644 --- a/v3/crates/graphql/ir/src/lib.rs +++ b/v3/crates/graphql/ir/src/lib.rs @@ -45,7 +45,7 @@ pub use subscription_root::generate_ir as generate_subscription_ir; /// Feature flag to decide whether to use the new OpenDD-based GraphQL request pipeline /// Only used in development and tests atm, `Old` is exposed to users -#[derive(Clone, Copy)] +#[derive(Clone, Copy, PartialEq)] pub enum GraphqlRequestPipeline { Old, OpenDd, diff --git a/v3/crates/graphql/ir/src/plan.rs b/v3/crates/graphql/ir/src/plan.rs index c729dc4e15c32..f49a1063d657f 100644 --- a/v3/crates/graphql/ir/src/plan.rs +++ b/v3/crates/graphql/ir/src/plan.rs @@ -7,6 +7,8 @@ mod order_by; mod relationships; mod selection_set; mod types; +use crate::query_root::apollo_federation::ModelEntitySelection; +use crate::query_root::node_field::ModelNodeSelection; use crate::query_root::select_many::ModelSelectManySelection; use crate::query_root::select_one::ModelSelectOneSelection; use crate::{ @@ -370,8 +372,13 @@ fn plan_query<'n, 's, 'ir>( } QueryRootField::NodeSelect(optional_ir) => match optional_ir { Some(ir) => { - let execution_tree = - model_selection::plan_query_execution(&ir.model_selection, unique_number)?; + let execution_tree = match ir.model_selection { + ModelNodeSelection::Ir(ref model_selection) => { + model_selection::plan_query_execution(model_selection, unique_number) + } + ModelNodeSelection::OpenDd(_) => todo!("Plan NodeSelect for OpenDd"), + }?; + NodeQueryPlan::RelayNodeSelect(Some(( NDCQueryExecution { execution_tree, @@ -404,8 +411,14 @@ fn plan_query<'n, 's, 'ir>( QueryRootField::ApolloFederation(ApolloFederationRootFields::EntitiesSelect(irs)) => { let mut ndc_query_executions = Vec::new(); for ir in irs { - let execution_tree = - model_selection::plan_query_execution(&ir.model_selection, unique_number)?; + let execution_tree = match ir.model_selection { + ModelEntitySelection::Ir(ref model_selection) => { + model_selection::plan_query_execution(model_selection, unique_number)? + } + ModelEntitySelection::OpenDd(_) => { + todo!("ApolloFederationRootFields for OpenDd") + } + }; ndc_query_executions.push(( NDCQueryExecution { execution_tree, diff --git a/v3/crates/graphql/ir/src/query_root.rs b/v3/crates/graphql/ir/src/query_root.rs index dc416741012f7..cec2f14fd7fbd 100644 --- a/v3/crates/graphql/ir/src/query_root.rs +++ b/v3/crates/graphql/ir/src/query_root.rs @@ -103,6 +103,7 @@ pub fn generate_ir<'n, 's>( } RootFieldAnnotation::RelayNode { typename_mappings } => { let ir = generate_nodefield_ir( + request_pipeline, field, field_call, typename_mappings, @@ -115,6 +116,7 @@ pub fn generate_ir<'n, 's>( ApolloFederationRootFields::Entities { typename_mappings }, ) => { let ir = generate_entities_ir( + request_pipeline, field, field_call, typename_mappings, @@ -287,6 +289,7 @@ fn generate_command_rootfield_ir<'n, 's>( } fn generate_nodefield_ir<'n, 's>( + request_pipeline: GraphqlRequestPipeline, field: &'n gql::normalized_ast::Field<'s, GDS>, field_call: &'n gql::normalized_ast::FieldCall<'s, GDS>, typename_mappings: &'s HashMap, @@ -294,6 +297,7 @@ fn generate_nodefield_ir<'n, 's>( request_headers: &reqwest::header::HeaderMap, ) -> Result, error::Error> { let ir = root_field::QueryRootField::NodeSelect(node_field::relay_node_ir( + request_pipeline, field, field_call, typename_mappings, @@ -304,6 +308,7 @@ fn generate_nodefield_ir<'n, 's>( } fn generate_entities_ir<'n, 's>( + request_pipeline: GraphqlRequestPipeline, field: &'n gql::normalized_ast::Field<'s, GDS>, field_call: &'n gql::normalized_ast::FieldCall<'s, GDS>, typename_mappings: &'s HashMap, @@ -312,6 +317,7 @@ fn generate_entities_ir<'n, 's>( ) -> Result, error::Error> { let ir = root_field::QueryRootField::ApolloFederation( root_field::ApolloFederationRootFields::EntitiesSelect(apollo_federation::entities_ir( + request_pipeline, field, field_call, typename_mappings, diff --git a/v3/crates/graphql/ir/src/query_root/apollo_federation.rs b/v3/crates/graphql/ir/src/query_root/apollo_federation.rs index 051d33c9fd3ba..4922d7c1d7967 100644 --- a/v3/crates/graphql/ir/src/query_root/apollo_federation.rs +++ b/v3/crates/graphql/ir/src/query_root/apollo_federation.rs @@ -10,6 +10,7 @@ use serde::Serialize; use crate::error; use crate::filter; use crate::model_selection; +use crate::GraphqlRequestPipeline; use graphql_schema::GDS; use graphql_schema::{EntityFieldTypeNameMapping, NamespaceAnnotation}; use json_ext::HashMapWithJsonKey; @@ -20,6 +21,12 @@ use plan_types::{ ComparisonTarget, ComparisonValue, Expression, LocalFieldComparison, UsagesCounts, }; +#[derive(Debug, Serialize)] +pub enum ModelEntitySelection<'s> { + Ir(model_selection::ModelSelection<'s>), + OpenDd(open_dds::query::ModelSelection), +} + /// IR for the '_entities' operation for a model #[derive(Serialize, Debug)] pub struct EntitySelect<'n, 's> { @@ -27,7 +34,7 @@ pub struct EntitySelect<'n, 's> { pub field_name: &'n ast::Name, /// Model Selection IR fragment - pub model_selection: model_selection::ModelSelection<'s>, + pub model_selection: ModelEntitySelection<'s>, // We need this for validating the response from the data connector. This is not a reference as it is constructed // from the original selection set by filtering fields that are relevant. @@ -79,12 +86,16 @@ fn get_entity_namespace_typename_mappings<'s>( /// the entities. The `__typename` field is used to determine the type of the entity and the fields are used to filter /// the entities. pub(crate) fn entities_ir<'n, 's>( + request_pipeline: GraphqlRequestPipeline, field: &'n normalized_ast::Field<'s, GDS>, field_call: &'n normalized_ast::FieldCall<'s, GDS>, typename_mappings: &'s HashMap, session_variables: &SessionVariables, request_headers: &reqwest::header::HeaderMap, ) -> Result>, error::Error> { + if request_pipeline == GraphqlRequestPipeline::OpenDd { + todo!("entities_ir for OpenDd"); + } let representations = field_call .expected_argument(&lang_graphql::mk_name!("representations"))? .value @@ -186,7 +197,7 @@ pub(crate) fn entities_ir<'n, 's>( )?; entity_selects.push(EntitySelect { field_name: &field_call.name, - model_selection, + model_selection: ModelEntitySelection::Ir(model_selection), selection_set: new_selection_set, usage_counts, }); diff --git a/v3/crates/graphql/ir/src/query_root/node_field.rs b/v3/crates/graphql/ir/src/query_root/node_field.rs index 4be43e6904dd3..affa6a78bab0a 100644 --- a/v3/crates/graphql/ir/src/query_root/node_field.rs +++ b/v3/crates/graphql/ir/src/query_root/node_field.rs @@ -11,6 +11,7 @@ use serde::Serialize; use crate::error; use crate::filter; use crate::model_selection; +use crate::GraphqlRequestPipeline; use graphql_schema::GDS; use graphql_schema::{GlobalID, NamespaceAnnotation, NodeFieldTypeNameMapping}; use json_ext::HashMapWithJsonKey; @@ -20,6 +21,12 @@ use plan_types::{ ComparisonTarget, ComparisonValue, Expression, LocalFieldComparison, UsagesCounts, }; +#[derive(Debug, Serialize)] +pub enum ModelNodeSelection<'s> { + Ir(model_selection::ModelSelection<'s>), + OpenDd(open_dds::query::ModelSelection), +} + /// IR for the 'select_one' operation on a model #[derive(Serialize, Debug)] pub struct NodeSelect<'n, 's> { @@ -27,7 +34,7 @@ pub struct NodeSelect<'n, 's> { pub field_name: &'n ast::Name, /// Model Selection IR fragment - pub model_selection: model_selection::ModelSelection<'s>, + pub model_selection: ModelNodeSelection<'s>, // We need this to post process the response for `__typename` fields and for // validating the response from the data connector. This is not a reference @@ -74,6 +81,7 @@ fn get_relay_node_namespace_typename_mappings<'s>( /// object type that was decoded, then this function /// returns `None`. pub(crate) fn relay_node_ir<'n, 's>( + request_pipeline: GraphqlRequestPipeline, field: &'n normalized_ast::Field<'s, GDS>, field_call: &'n normalized_ast::FieldCall<'s, GDS>, typename_mappings: &'s HashMap, @@ -151,6 +159,10 @@ pub(crate) fn relay_node_ir<'n, 's>( additional_filter: Some(Expression::mk_and(filter_clause_expressions)), }; + if request_pipeline == GraphqlRequestPipeline::OpenDd { + todo!("NodeSelect for OpenDd") + }; + let model_selection = model_selection::model_selection_ir( &new_selection_set, &typename_mapping.type_name, @@ -168,7 +180,7 @@ pub(crate) fn relay_node_ir<'n, 's>( )?; Ok(Some(NodeSelect { field_name: &field_call.name, - model_selection, + model_selection: ModelNodeSelection::Ir(model_selection), selection_set: new_selection_set, usage_counts, }))