mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-13 19:33:55 +03:00
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:
parent
e8edc5e596
commit
0f245de566
@ -201,49 +201,72 @@ 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)?;
|
||||
relationships.insert(
|
||||
ndc_relationship_name.clone(),
|
||||
LocalModelRelationshipInfo {
|
||||
relationship_name,
|
||||
relationship_type,
|
||||
source_type,
|
||||
source_data_connector: data_connector_link,
|
||||
source_type_mappings: type_mappings,
|
||||
target_source,
|
||||
target_type,
|
||||
mappings,
|
||||
},
|
||||
);
|
||||
// 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(),
|
||||
},
|
||||
)))
|
||||
}
|
||||
|
||||
// This map contains the relationships or the columns of the
|
||||
// relationship that needs to be used for ordering.
|
||||
let filter_object = field.value.as_object()?;
|
||||
metadata_resolve::RelationshipExecutionCategory::Local => {
|
||||
let ndc_relationship_name =
|
||||
NDCRelationshipName::new(source_type, relationship_name)?;
|
||||
|
||||
let mut expressions = Vec::new();
|
||||
relationships.insert(
|
||||
ndc_relationship_name.clone(),
|
||||
LocalModelRelationshipInfo {
|
||||
relationship_name,
|
||||
relationship_type,
|
||||
source_type,
|
||||
source_data_connector: data_connector_link,
|
||||
source_type_mappings: type_mappings,
|
||||
target_source,
|
||||
target_type,
|
||||
mappings,
|
||||
},
|
||||
);
|
||||
|
||||
for field in filter_object.values() {
|
||||
let field_filter_expression = build_filter_expression(
|
||||
field,
|
||||
relationships,
|
||||
&target_source.model.data_connector,
|
||||
&target_source.model.type_mappings,
|
||||
usage_counts,
|
||||
)?;
|
||||
expressions.push(field_filter_expression);
|
||||
// This map contains the relationships or the columns of the
|
||||
// relationship that needs to be used for ordering.
|
||||
let filter_object = field.value.as_object()?;
|
||||
|
||||
let mut expressions = Vec::new();
|
||||
|
||||
for field in filter_object.values() {
|
||||
let field_filter_expression = build_filter_expression(
|
||||
field,
|
||||
relationships,
|
||||
&target_source.model.data_connector,
|
||||
&target_source.model.type_mappings,
|
||||
usage_counts,
|
||||
)?;
|
||||
expressions.push(field_filter_expression);
|
||||
}
|
||||
|
||||
// Using exists clause to build the filter expression for relationship fields.
|
||||
let exists_filter_clause = ndc_models::Expression::And { expressions };
|
||||
let exists_in_relationship = ndc_models::ExistsInCollection::Related {
|
||||
relationship: ndc_relationship_name.0,
|
||||
arguments: BTreeMap::new(),
|
||||
};
|
||||
|
||||
Ok(ndc_models::Expression::Exists {
|
||||
in_collection: exists_in_relationship,
|
||||
predicate: Some(Box::new(exists_filter_clause)),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Using exists clause to build the filter expression for relationship fields.
|
||||
let exists_filter_clause = ndc_models::Expression::And { expressions };
|
||||
let exists_in_relationship = ndc_models::ExistsInCollection::Related {
|
||||
relationship: ndc_relationship_name.0,
|
||||
arguments: BTreeMap::new(),
|
||||
};
|
||||
|
||||
Ok(ndc_models::Expression::Exists {
|
||||
in_collection: exists_in_relationship,
|
||||
predicate: Some(Box::new(exists_filter_clause)),
|
||||
})
|
||||
}
|
||||
other_boolean_annotation => Err(error::InternalEngineError::UnexpectedAnnotation {
|
||||
annotation: schema::Annotation::Input(InputAnnotation::BooleanExpression(
|
||||
|
@ -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,82 +248,66 @@ 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(_)) => {
|
||||
todo!("relationships with BooleanExpressionType")
|
||||
}
|
||||
Some(ModelExpressionType::ObjectBooleanExpressionType(
|
||||
target_model_filter_expression,
|
||||
)) => {
|
||||
// If the relationship target model does not have filterExpressionType do not include
|
||||
// it in the source model filter expression input type.
|
||||
if let Some(ref target_model_filter_expression_graphql) =
|
||||
&target_model_filter_expression.graphql
|
||||
{
|
||||
let annotation = FilterRelationshipAnnotation {
|
||||
source_type: relationship.source.clone(),
|
||||
relationship_name: relationship.name.clone(),
|
||||
target_source: target_model_source.clone(),
|
||||
target_type: target_model.model.data_type.clone(),
|
||||
target_model_name: target_model.model.name.clone(),
|
||||
relationship_type: relationship_type.clone(),
|
||||
mappings: relationship_model_mappings.to_vec(),
|
||||
};
|
||||
match &target_model.model.filter_expression_type {
|
||||
None => {}
|
||||
Some(ModelExpressionType::BooleanExpressionType(_)) => {
|
||||
todo!("relationships with BooleanExpressionType")
|
||||
}
|
||||
Some(ModelExpressionType::ObjectBooleanExpressionType(
|
||||
target_model_filter_expression,
|
||||
)) => {
|
||||
// If the relationship target model does not have filterExpressionType do not include
|
||||
// it in the source model filter expression input type.
|
||||
if let Some(ref target_model_filter_expression_graphql) =
|
||||
&target_model_filter_expression.graphql
|
||||
{
|
||||
let annotation = FilterRelationshipAnnotation {
|
||||
source_type: relationship.source.clone(),
|
||||
relationship_name: relationship.name.clone(),
|
||||
target_source: target_model_source.clone(),
|
||||
target_type: target_model.model.data_type.clone(),
|
||||
target_model_name: target_model.model.name.clone(),
|
||||
relationship_type: relationship_type.clone(),
|
||||
mappings: relationship_model_mappings.to_vec(),
|
||||
};
|
||||
|
||||
let namespace_annotations =
|
||||
permissions::get_model_relationship_namespace_annotations(
|
||||
target_model,
|
||||
source_object_type_representation,
|
||||
target_object_type_representation,
|
||||
relationship_model_mappings,
|
||||
&gds.metadata.object_types,
|
||||
)?;
|
||||
let namespace_annotations =
|
||||
permissions::get_model_relationship_namespace_annotations(
|
||||
target_model,
|
||||
source_object_type_representation,
|
||||
target_object_type_representation,
|
||||
relationship_model_mappings,
|
||||
&gds.metadata.object_types,
|
||||
)?;
|
||||
|
||||
return Ok(Some((
|
||||
relationship.field_name.clone(),
|
||||
builder.conditional_namespaced(
|
||||
gql_schema::InputField::<GDS>::new(
|
||||
relationship.field_name.clone(),
|
||||
None,
|
||||
types::Annotation::Input(InputAnnotation::BooleanExpression(
|
||||
BooleanExpressionAnnotation
|
||||
::BooleanExpressionArgument {
|
||||
field:
|
||||
types::ModelFilterArgument::RelationshipField(
|
||||
annotation,
|
||||
),
|
||||
},
|
||||
)),
|
||||
ast::TypeContainer::named_null(
|
||||
gql_schema::RegisteredTypeName::new(
|
||||
target_model_filter_expression_graphql.type_name.0.clone(),
|
||||
),
|
||||
),
|
||||
None,
|
||||
gql_schema::DeprecationStatus::NotDeprecated,
|
||||
return Ok(Some((
|
||||
relationship.field_name.clone(),
|
||||
builder.conditional_namespaced(
|
||||
gql_schema::InputField::<GDS>::new(
|
||||
relationship.field_name.clone(),
|
||||
None,
|
||||
types::Annotation::Input(InputAnnotation::BooleanExpression(
|
||||
BooleanExpressionAnnotation::BooleanExpressionArgument {
|
||||
field: types::ModelFilterArgument::RelationshipField(
|
||||
annotation,
|
||||
),
|
||||
namespace_annotations
|
||||
},
|
||||
)),
|
||||
ast::TypeContainer::named_null(
|
||||
gql_schema::RegisteredTypeName::new(
|
||||
target_model_filter_expression_graphql.type_name.0.clone(),
|
||||
),
|
||||
)));
|
||||
}
|
||||
}
|
||||
),
|
||||
None,
|
||||
gql_schema::DeprecationStatus::NotDeprecated,
|
||||
),
|
||||
namespace_annotations,
|
||||
),
|
||||
)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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,
|
||||
)?);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user