Defer local relationship check until IR creation (#716)

<!-- Thank you for submitting this PR! :) -->

## Description

Making the schema work for boolean expressions has been challenging as
they are no longer tied to a single data connector, so we cannot do any
checks of whether a relationships is local or remote. We defer this to
the IR step when the source data connector for a relationship is known,
so that we can generate schema for boolean expressions decoupled from
any concept of data connector.

Functional no-op.

V3_GIT_ORIGIN_REV_ID: d2923acedf92b031ba092bb83c515812c4d346f0
This commit is contained in:
Daniel Harvey 2024-06-13 16:25:39 +01:00 committed by hasura-bot
parent e8edc5e596
commit 0f245de566
2 changed files with 117 additions and 114 deletions

View File

@ -201,7 +201,28 @@ fn build_filter_expression_from_boolean_expression<'s>(
// Add the target model being used in the usage counts
count_model(target_model_name, usage_counts);
let ndc_relationship_name = NDCRelationshipName::new(source_type, relationship_name)?;
// filter expression with relationships is currently only supported for local relationships
// this is the first point at which we know the source data connector, so we must
// ensure only a local relationship is used
match metadata_resolve::relationship_execution_category(
data_connector_link,
&target_source.model.data_connector,
&target_source.capabilities,
) {
metadata_resolve::RelationshipExecutionCategory::RemoteForEach => {
Err(error::Error::Internal(error::InternalError::Engine(
error::InternalEngineError::InternalGeneric {
description:
"Remote relationships are not supported in boolean expressions"
.to_string(),
},
)))
}
metadata_resolve::RelationshipExecutionCategory::Local => {
let ndc_relationship_name =
NDCRelationshipName::new(source_type, relationship_name)?;
relationships.insert(
ndc_relationship_name.clone(),
LocalModelRelationshipInfo {
@ -245,6 +266,8 @@ fn build_filter_expression_from_boolean_expression<'s>(
predicate: Some(Box::new(exists_filter_clause)),
})
}
}
}
other_boolean_annotation => Err(error::InternalEngineError::UnexpectedAnnotation {
annotation: schema::Annotation::Input(InputAnnotation::BooleanExpression(
other_boolean_annotation.clone(),

View File

@ -9,8 +9,8 @@ use super::types::output_type::relationship::FilterRelationshipAnnotation;
use super::types::{BooleanExpressionAnnotation, InputAnnotation, TypeId};
use metadata_resolve::{
mk_name, BooleanExpressionGraphqlConfig, ModelExpressionType, ModelWithPermissions,
ObjectBooleanExpressionDataConnector, ObjectBooleanExpressionType, ObjectTypeWithRelationships,
Qualified, Relationship, RelationshipModelMapping, ResolvedObjectBooleanExpressionType,
ObjectBooleanExpressionType, ObjectTypeWithRelationships, Qualified, Relationship,
RelationshipModelMapping, ResolvedObjectBooleanExpressionType,
};
use crate::permissions;
@ -187,7 +187,6 @@ fn build_comparable_fields_schema(
fn build_comparable_relationships_schema(
gds: &GDS,
object_type_representation: &ObjectTypeWithRelationships,
object_boolean_expression_data_connector: &Option<ObjectBooleanExpressionDataConnector>,
builder: &mut gql_schema::Builder<GDS>,
) -> Result<BTreeMap<ast::Name, gql_schema::Namespaced<GDS, gql_schema::InputField<GDS>>>, Error> {
let mut input_fields = BTreeMap::new();
@ -214,7 +213,6 @@ fn build_comparable_relationships_schema(
// try and create a new input field
if let Some((name, schema)) = build_model_relationship_schema(
object_type_representation,
object_boolean_expression_data_connector,
target_object_type_representation,
target_model,
relationship,
@ -238,7 +236,6 @@ type InputField = (
// build comparable relationships input fields
fn build_model_relationship_schema(
source_object_type_representation: &ObjectTypeWithRelationships,
source_object_boolean_expression_data_connector: &Option<ObjectBooleanExpressionDataConnector>,
target_object_type_representation: &ObjectTypeWithRelationships,
target_model: &ModelWithPermissions,
relationship: &Relationship,
@ -251,22 +248,10 @@ fn build_model_relationship_schema(
// both the source boolean expression and target_model are backed by a source
// We'll need to find a way of getting this information for BooleanExpressionTypes
// that are uncoupled from their data connector source
if let (Some(source_data_connector), Some(target_source)) = (
&source_object_boolean_expression_data_connector,
&target_model.model.source,
) {
if let Some(target_source) = &target_model.model.source {
let target_model_source =
metadata_resolve::ModelTargetSource::from_model_source(target_source, relationship)?;
// filter expression with relationships is currently only supported for local relationships
if let metadata_resolve::RelationshipExecutionCategory::Local =
metadata_resolve::relationship_execution_category(
&source_data_connector.link,
&target_source.data_connector,
&target_model_source.capabilities,
)
{
if target_source.data_connector.name == source_data_connector.name {
match &target_model.model.filter_expression_type {
None => {}
Some(ModelExpressionType::BooleanExpressionType(_)) => {
@ -306,10 +291,8 @@ fn build_model_relationship_schema(
relationship.field_name.clone(),
None,
types::Annotation::Input(InputAnnotation::BooleanExpression(
BooleanExpressionAnnotation
::BooleanExpressionArgument {
field:
types::ModelFilterArgument::RelationshipField(
BooleanExpressionAnnotation::BooleanExpressionArgument {
field: types::ModelFilterArgument::RelationshipField(
annotation,
),
},
@ -322,15 +305,13 @@ fn build_model_relationship_schema(
None,
gql_schema::DeprecationStatus::NotDeprecated,
),
namespace_annotations
namespace_annotations,
),
)));
}
}
}
}
}
}
Ok(None)
}
@ -409,7 +390,6 @@ fn build_schema_with_object_boolean_expression_type(
input_fields.extend(build_comparable_relationships_schema(
gds,
object_type_representation,
&object_boolean_expression_type.data_connector,
builder,
)?);