Skip to content

Commit

Permalink
Convert other model selections to use enum (#1494)
Browse files Browse the repository at this point in the history
<!-- The PR description should answer 2 important questions: -->

### What

Currently it's possible to make OpenDD tests pass just because they
ignore the `GraphqlRequestPipeline` flag and work the old way. To reduce
this confusion, let's add the enum in a bunch more places and stub out
with `todo` so they definitely fail.

Doesn't do:
- aggregates (these are being worked on separately)
- commands (these will follow and need thought)

Functional no-op.

V3_GIT_ORIGIN_REV_ID: c42498f711e637eaa11e082e8a05210808943ab2
  • Loading branch information
danieljharvey authored and hasura-bot committed Jan 6, 2025
1 parent 11f9890 commit 456316a
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 9 deletions.
2 changes: 1 addition & 1 deletion v3/crates/graphql/ir/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
21 changes: 17 additions & 4 deletions v3/crates/graphql/ir/src/plan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
6 changes: 6 additions & 0 deletions v3/crates/graphql/ir/src/query_root.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -287,13 +289,15 @@ 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<ast::TypeName, NodeFieldTypeNameMapping>,
session: &Session,
request_headers: &reqwest::header::HeaderMap,
) -> Result<root_field::QueryRootField<'n, 's>, error::Error> {
let ir = root_field::QueryRootField::NodeSelect(node_field::relay_node_ir(
request_pipeline,
field,
field_call,
typename_mappings,
Expand All @@ -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<ast::TypeName, EntityFieldTypeNameMapping>,
Expand All @@ -312,6 +317,7 @@ fn generate_entities_ir<'n, 's>(
) -> Result<root_field::QueryRootField<'n, 's>, error::Error> {
let ir = root_field::QueryRootField::ApolloFederation(
root_field::ApolloFederationRootFields::EntitiesSelect(apollo_federation::entities_ir(
request_pipeline,
field,
field_call,
typename_mappings,
Expand Down
15 changes: 13 additions & 2 deletions v3/crates/graphql/ir/src/query_root/apollo_federation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -20,14 +21,20 @@ 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> {
// The name of the field as published in the schema
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.
Expand Down Expand Up @@ -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<ast::TypeName, EntityFieldTypeNameMapping>,
session_variables: &SessionVariables,
request_headers: &reqwest::header::HeaderMap,
) -> Result<Vec<EntitySelect<'n, 's>>, error::Error> {
if request_pipeline == GraphqlRequestPipeline::OpenDd {
todo!("entities_ir for OpenDd");
}
let representations = field_call
.expected_argument(&lang_graphql::mk_name!("representations"))?
.value
Expand Down Expand Up @@ -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,
});
Expand Down
16 changes: 14 additions & 2 deletions v3/crates/graphql/ir/src/query_root/node_field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -20,14 +21,20 @@ 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> {
// The name of the field as published in the schema
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
Expand Down Expand Up @@ -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<ast::TypeName, NodeFieldTypeNameMapping>,
Expand Down Expand Up @@ -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,
Expand All @@ -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,
}))
Expand Down

0 comments on commit 456316a

Please sign in to comment.