Skip to content

Commit

Permalink
break out BooleanExpressionError from Error (#449)
Browse files Browse the repository at this point in the history
<!-- Thank you for submitting this PR! :) -->

## Description

Further breaking up the big error type. Functional no-op.

V3_GIT_ORIGIN_REV_ID: d34acb7fd6421c250c214b133b8a107e03155c70
  • Loading branch information
danieljharvey authored and hasura-bot committed Apr 9, 2024
1 parent 6f8470c commit 66e012f
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 84 deletions.
106 changes: 61 additions & 45 deletions v3/crates/engine/src/metadata/resolved/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,51 +263,6 @@ pub enum Error {
model_name: Qualified<ModelName>,
type_representation: TypeRepresentation,
},
#[error("unknown type used in object boolean expression: {type_name:}")]
UnknownTypeInObjectBooleanExpressionType {
type_name: Qualified<CustomTypeName>,
},
#[error("unsupported type used in object boolean expression: {type_name:}; only object types are supported")]
UnsupportedTypeInObjectBooleanExpressionType {
type_name: Qualified<CustomTypeName>,
},
#[error("unknown data connector {data_connector:} referenced in object boolean expression type {boolean_expression_type:}")]
UnknownDataConnectorInObjectBooleanExpressionType {
data_connector: Qualified<DataConnectorName>,
boolean_expression_type: Qualified<CustomTypeName>,
},
#[error("unknown data connector object type {data_connector_object_type:} (in data connector {data_connector:}) referenced in object boolean expression type {boolean_expression_type:}")]
UnknownDataConnectorTypeInObjectBooleanExpressionType {
data_connector: Qualified<DataConnectorName>,
data_connector_object_type: String,
boolean_expression_type: Qualified<CustomTypeName>,
},
#[error("unknown field '{field_name:}' used in object boolean expression type {boolean_expression_type:}")]
UnknownFieldInObjectBooleanExpressionType {
field_name: FieldName,
boolean_expression_type: Qualified<CustomTypeName>,
},
#[error("the object type '{object_type:}' used in boolean expression type {boolean_expression_type:} does not have a mapping to object {data_connector_object_type:} of data connector {data_connector:}")]
NoDataConnectorTypeMappingForObjectTypeInBooleanExpression {
object_type: Qualified<CustomTypeName>,
boolean_expression_type: Qualified<CustomTypeName>,
data_connector_object_type: String,
data_connector: Qualified<DataConnectorName>,
},
#[error("the following object boolean expression type is defined more than once: {name:}")]
DuplicateObjectBooleanExpressionTypeDefinition { name: Qualified<CustomTypeName> },
#[error("unknown object boolean expression type {name:} is used in model {model:}")]
UnknownBooleanExpressionTypeInModel {
name: Qualified<CustomTypeName>,
model: Qualified<ModelName>,
},
#[error("the boolean expression type {name:} used in model {model:} corresponds to object type {boolean_expression_object_type:} whereas the model's object type is {model_object_type:}")]
BooleanExpressionTypeForInvalidObjectTypeInModel {
name: Qualified<CustomTypeName>,
boolean_expression_object_type: Qualified<CustomTypeName>,
model: Qualified<ModelName>,
model_object_type: Qualified<CustomTypeName>,
},
#[error("a source must be defined for model {model:} in order to use filter expressions")]
CannotUseFilterExpressionsWithoutSource { model: Qualified<ModelName> },
#[error("graphql config must be defined for a filter expression to be used in a {model:}")]
Expand Down Expand Up @@ -582,6 +537,67 @@ pub enum Error {
RelationshipError {
relationship_error: RelationshipError,
},
#[error("{boolean_expression_error:}")]
BooleanExpressionError {
boolean_expression_error: BooleanExpressionError,
},
}

impl From<BooleanExpressionError> for Error {
fn from(val: BooleanExpressionError) -> Self {
Error::BooleanExpressionError {
boolean_expression_error: val,
}
}
}

#[derive(Debug, Error)]
pub enum BooleanExpressionError {
#[error("unknown type used in object boolean expression: {type_name:}")]
UnknownTypeInObjectBooleanExpressionType {
type_name: Qualified<CustomTypeName>,
},
#[error("unsupported type used in object boolean expression: {type_name:}; only object types are supported")]
UnsupportedTypeInObjectBooleanExpressionType {
type_name: Qualified<CustomTypeName>,
},
#[error("unknown data connector {data_connector:} referenced in object boolean expression type {boolean_expression_type:}")]
UnknownDataConnectorInObjectBooleanExpressionType {
data_connector: Qualified<DataConnectorName>,
boolean_expression_type: Qualified<CustomTypeName>,
},
#[error("unknown data connector object type {data_connector_object_type:} (in data connector {data_connector:}) referenced in object boolean expression type {boolean_expression_type:}")]
UnknownDataConnectorTypeInObjectBooleanExpressionType {
data_connector: Qualified<DataConnectorName>,
data_connector_object_type: String,
boolean_expression_type: Qualified<CustomTypeName>,
},
#[error("unknown field '{field_name:}' used in object boolean expression type {boolean_expression_type:}")]
UnknownFieldInObjectBooleanExpressionType {
field_name: FieldName,
boolean_expression_type: Qualified<CustomTypeName>,
},
#[error("the object type '{object_type:}' used in boolean expression type {boolean_expression_type:} does not have a mapping to object {data_connector_object_type:} of data connector {data_connector:}")]
NoDataConnectorTypeMappingForObjectTypeInBooleanExpression {
object_type: Qualified<CustomTypeName>,
boolean_expression_type: Qualified<CustomTypeName>,
data_connector_object_type: String,
data_connector: Qualified<DataConnectorName>,
},
#[error("the following object boolean expression type is defined more than once: {name:}")]
DuplicateObjectBooleanExpressionTypeDefinition { name: Qualified<CustomTypeName> },
#[error("unknown object boolean expression type {name:} is used in model {model:}")]
UnknownBooleanExpressionTypeInModel {
name: Qualified<CustomTypeName>,
model: Qualified<ModelName>,
},
#[error("the boolean expression type {name:} used in model {model:} corresponds to object type {boolean_expression_object_type:} whereas the model's object type is {model_object_type:}")]
BooleanExpressionTypeForInvalidObjectTypeInModel {
name: Qualified<CustomTypeName>,
boolean_expression_object_type: Qualified<CustomTypeName>,
model: Qualified<ModelName>,
model_object_type: Qualified<CustomTypeName>,
},
}

#[derive(Debug, Error)]
Expand Down
10 changes: 6 additions & 4 deletions v3/crates/engine/src/metadata/resolved/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use crate::metadata::resolved::subgraph::Qualified;

use crate::metadata::resolved::command;
use crate::metadata::resolved::data_connector::DataConnectorContext;
use crate::metadata::resolved::error::Error;
use crate::metadata::resolved::error::{BooleanExpressionError, Error};
use crate::metadata::resolved::model::{
resolve_model, resolve_model_graphql_api, resolve_model_select_permissions,
resolve_model_source, Model,
Expand Down Expand Up @@ -486,9 +486,11 @@ fn resolve_boolean_expression_types(
resolved_boolean_expression.name.clone(),
resolved_boolean_expression,
) {
return Err(Error::DuplicateObjectBooleanExpressionTypeDefinition {
name: existing.name,
});
return Err(Error::from(
BooleanExpressionError::DuplicateObjectBooleanExpressionTypeDefinition {
name: existing.name,
},
));
}
}
Ok(boolean_expression_types)
Expand Down
28 changes: 18 additions & 10 deletions v3/crates/engine/src/metadata/resolved/model.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use crate::metadata::resolved::argument::get_argument_mappings;
use crate::metadata::resolved::data_connector::get_simple_scalar;
use crate::metadata::resolved::data_connector::{DataConnectorContext, DataConnectorLink};
use crate::metadata::resolved::error::{Error, GraphqlConfigError, RelationshipError};
use crate::metadata::resolved::error::{
BooleanExpressionError, Error, GraphqlConfigError, RelationshipError,
};
use crate::metadata::resolved::ndc_validation;
use crate::metadata::resolved::stages::graphql_config::GraphqlConfig;
use crate::metadata::resolved::subgraph::{
Expand Down Expand Up @@ -210,17 +212,23 @@ fn resolve_filter_expression_type(
Qualified::new(subgraph.to_string(), filter_expression_type.clone());
let boolean_expression_type = boolean_expression_types
.get(&boolean_expression_type_name)
.ok_or_else(|| Error::UnknownBooleanExpressionTypeInModel {
name: boolean_expression_type_name.clone(),
model: Qualified::new(subgraph.to_string(), model.name.clone()),
.ok_or_else(|| {
Error::from(
BooleanExpressionError::UnknownBooleanExpressionTypeInModel {
name: boolean_expression_type_name.clone(),
model: Qualified::new(subgraph.to_string(), model.name.clone()),
},
)
})?;
if boolean_expression_type.object_type != *model_data_type {
return Err(Error::BooleanExpressionTypeForInvalidObjectTypeInModel {
name: boolean_expression_type_name.clone(),
boolean_expression_object_type: boolean_expression_type.object_type.clone(),
model: Qualified::new(subgraph.to_string(), model.name.clone()),
model_object_type: model_data_type.clone(),
});
return Err(Error::from(
BooleanExpressionError::BooleanExpressionTypeForInvalidObjectTypeInModel {
name: boolean_expression_type_name.clone(),
boolean_expression_object_type: boolean_expression_type.object_type.clone(),
model: Qualified::new(subgraph.to_string(), model.name.clone()),
model_object_type: model_data_type.clone(),
},
));
}
// This is also checked in resolve_model_graphql_api, but we want to disallow this even
// if the model is not used in the graphql layer.
Expand Down
53 changes: 30 additions & 23 deletions v3/crates/engine/src/metadata/resolved/types.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::metadata::resolved::error::{Error, TypeMappingValidationError};
use crate::metadata::resolved::error::{BooleanExpressionError, Error, TypeMappingValidationError};
use crate::metadata::resolved::relationship::Relationship;
use crate::metadata::resolved::subgraph::{
mk_qualified_type_reference, Qualified, QualifiedBaseType, QualifiedTypeName,
Expand Down Expand Up @@ -504,17 +504,19 @@ pub(crate) fn resolve_object_boolean_expression_type(
object_boolean_expression.object_type.to_owned(),
);
let type_representation = types.get(&qualified_object_type_name).ok_or_else(|| {
Error::UnknownTypeInObjectBooleanExpressionType {
type_name: qualified_object_type_name.clone(),
}
Error::from(
BooleanExpressionError::UnknownTypeInObjectBooleanExpressionType {
type_name: qualified_object_type_name.clone(),
},
)
})?;
match type_representation {
// validate it should only be an object type
TypeRepresentation::ScalarType { .. } => {
Err(Error::UnsupportedTypeInObjectBooleanExpressionType {
TypeRepresentation::ScalarType { .. } => Err(Error::from(
BooleanExpressionError::UnsupportedTypeInObjectBooleanExpressionType {
type_name: qualified_name.clone(),
})
}
},
)),
TypeRepresentation::Object(object_type_representation) => {
let qualified_data_connector_name = Qualified::new(
subgraph.to_string(),
Expand All @@ -524,28 +526,30 @@ pub(crate) fn resolve_object_boolean_expression_type(
// validate data connector name
let data_connector_context = data_connectors
.get(&qualified_data_connector_name)
.ok_or_else(
|| Error::UnknownDataConnectorInObjectBooleanExpressionType {
data_connector: qualified_data_connector_name.clone(),
boolean_expression_type: qualified_name.clone(),
},
)?;
.ok_or_else(|| {
Error::from(
BooleanExpressionError::UnknownDataConnectorInObjectBooleanExpressionType {
data_connector: qualified_data_connector_name.clone(),
boolean_expression_type: qualified_name.clone(),
},
)
})?;

// validate data connector object type
if !data_connector_context
.schema
.object_types
.contains_key(&object_boolean_expression.data_connector_object_type)
{
return Err(
Error::UnknownDataConnectorTypeInObjectBooleanExpressionType {
return Err(Error::from(
BooleanExpressionError::UnknownDataConnectorTypeInObjectBooleanExpressionType {
data_connector: qualified_data_connector_name.clone(),
boolean_expression_type: qualified_name.clone(),
data_connector_object_type: object_boolean_expression
.data_connector_object_type
.clone(),
},
);
));
}

data_connector_type_mappings
Expand All @@ -555,14 +559,14 @@ pub(crate) fn resolve_object_boolean_expression_type(
&object_boolean_expression.data_connector_object_type,
)
.ok_or_else(|| {
Error::NoDataConnectorTypeMappingForObjectTypeInBooleanExpression {
Error::from(BooleanExpressionError::NoDataConnectorTypeMappingForObjectTypeInBooleanExpression {
object_type: qualified_object_type_name.clone(),
boolean_expression_type: qualified_name.clone(),
data_connector_object_type: object_boolean_expression
.data_connector_object_type
.clone(),
data_connector: qualified_data_connector_name.clone(),
}
})
})?;

// validate comparable fields
Expand All @@ -571,10 +575,13 @@ pub(crate) fn resolve_object_boolean_expression_type(
.fields
.contains_key(&comparable_field.field_name)
{
return Err(Error::UnknownFieldInObjectBooleanExpressionType {
field_name: comparable_field.field_name.clone(),
boolean_expression_type: qualified_name.clone(),
});
return Err(
BooleanExpressionError::UnknownFieldInObjectBooleanExpressionType {
field_name: comparable_field.field_name.clone(),
boolean_expression_type: qualified_name.clone(),
}
.into(),
);
}

// As of now, only `"enableAll": true` is allowed for field operators
Expand Down
8 changes: 6 additions & 2 deletions v3/crates/engine/tests/validate_metadata.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::fs;
use std::path::PathBuf;

use engine::metadata::resolved::error::BooleanExpressionError;
use engine::metadata::resolved::error::Error as ResolveError;
use engine::schema::Error as SchemaError;
use engine::schema::GDS;
Expand Down Expand Up @@ -267,7 +268,10 @@ fn test_disallow_filter_expression_with_object_type_mismatch() -> anyhow::Result
matches!(
gds,
Err(SchemaError::ResolveError {
error: ResolveError::BooleanExpressionTypeForInvalidObjectTypeInModel { .. }
error: ResolveError::BooleanExpressionError {
boolean_expression_error:
BooleanExpressionError::BooleanExpressionTypeForInvalidObjectTypeInModel { .. }
}
})
),
"actual: {gds:?}"
Expand Down Expand Up @@ -323,7 +327,7 @@ fn test_disallow_boolean_expression_without_mapping() -> anyhow::Result<()> {
matches!(
gds,
Err(SchemaError::ResolveError {
error: ResolveError::NoDataConnectorTypeMappingForObjectTypeInBooleanExpression { .. }
error: ResolveError::BooleanExpressionError { boolean_expression_error:BooleanExpressionError::NoDataConnectorTypeMappingForObjectTypeInBooleanExpression { .. }}
})
),
"actual: {gds:?}"
Expand Down

0 comments on commit 66e012f

Please sign in to comment.