mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-15 09:22:43 +03:00
Move TypeMapping and FieldMapping to data_connector_type_mappings
stage (#510)
<!-- Thank you for submitting this PR! :) --> ## Description As everything is taking shape we're finding more loose bits and pieces around, this moves `TypeMappings` and `FieldMappings` into the `data_connector_type_mappings` stage. Functional no-op. V3_GIT_ORIGIN_REV_ID: 2357e47b68d361b373f9fa886683ceb1fcff7cc3
This commit is contained in:
parent
9d25ee2075
commit
d8846328c4
@ -12,7 +12,7 @@ use crate::execute::ir::arguments;
|
||||
use crate::metadata::resolved::subgraph::{
|
||||
Qualified, QualifiedBaseType, QualifiedTypeName, QualifiedTypeReference,
|
||||
};
|
||||
use crate::metadata::resolved::types::TypeMapping;
|
||||
use crate::metadata::resolved::TypeMapping;
|
||||
use crate::schema::types::{
|
||||
Annotation, ArgumentNameAndPath, ArgumentPresets, InputAnnotation, ModelInputAnnotation,
|
||||
};
|
||||
|
@ -87,7 +87,7 @@ pub(crate) fn model_selection_ir<'s>(
|
||||
.type_mappings
|
||||
.get(data_type)
|
||||
.map(|type_mapping| {
|
||||
let resolved::types::TypeMapping::Object { field_mappings, .. } = type_mapping;
|
||||
let resolved::TypeMapping::Object { field_mappings, .. } = type_mapping;
|
||||
field_mappings
|
||||
})
|
||||
.ok_or_else(|| error::InternalEngineError::InternalGeneric {
|
||||
|
@ -51,7 +51,7 @@ pub(crate) struct LocalModelRelationshipInfo<'s> {
|
||||
pub source_type: &'s Qualified<CustomTypeName>,
|
||||
pub source_data_connector: &'s resolved::data_connector::DataConnectorLink,
|
||||
#[serde(serialize_with = "serialize_qualified_btreemap")]
|
||||
pub source_type_mappings: &'s BTreeMap<Qualified<CustomTypeName>, resolved::types::TypeMapping>,
|
||||
pub source_type_mappings: &'s BTreeMap<Qualified<CustomTypeName>, resolved::TypeMapping>,
|
||||
pub target_source: &'s ModelTargetSource,
|
||||
pub target_type: &'s Qualified<CustomTypeName>,
|
||||
pub mappings: &'s Vec<resolved::relationship::RelationshipModelMapping>,
|
||||
@ -62,7 +62,7 @@ pub(crate) struct LocalCommandRelationshipInfo<'s> {
|
||||
pub annotation: &'s CommandRelationshipAnnotation,
|
||||
pub source_data_connector: &'s resolved::data_connector::DataConnectorLink,
|
||||
#[serde(serialize_with = "serialize_qualified_btreemap")]
|
||||
pub source_type_mappings: &'s BTreeMap<Qualified<CustomTypeName>, resolved::types::TypeMapping>,
|
||||
pub source_type_mappings: &'s BTreeMap<Qualified<CustomTypeName>, resolved::TypeMapping>,
|
||||
pub target_source: &'s CommandTargetSource,
|
||||
}
|
||||
|
||||
@ -71,7 +71,7 @@ pub struct RemoteModelRelationshipInfo<'s> {
|
||||
pub annotation: &'s ModelRelationshipAnnotation,
|
||||
/// This contains processed information about the mappings.
|
||||
/// `RelationshipMapping` only contains mapping of field names. This
|
||||
/// contains mapping of field names and `resolved::types::FieldMapping`.
|
||||
/// contains mapping of field names and `resolved::FieldMapping`.
|
||||
/// Also see `build_remote_relationship`.
|
||||
pub join_mapping: Vec<(SourceField, TargetField)>,
|
||||
}
|
||||
@ -82,7 +82,7 @@ pub(crate) struct RemoteCommandRelationshipInfo<'s> {
|
||||
pub join_mapping: Vec<(SourceField, ArgumentName)>,
|
||||
}
|
||||
|
||||
pub type SourceField = (FieldName, resolved::types::FieldMapping);
|
||||
pub type SourceField = (FieldName, resolved::FieldMapping);
|
||||
pub type TargetField = (FieldName, resolved::types::NdcColumnForComparison);
|
||||
|
||||
pub(crate) fn process_model_relationship_definition(
|
||||
@ -216,7 +216,7 @@ pub(crate) fn generate_model_relationship_ir<'s>(
|
||||
field: &Field<'s, GDS>,
|
||||
annotation: &'s ModelRelationshipAnnotation,
|
||||
source_data_connector: &'s resolved::data_connector::DataConnectorLink,
|
||||
type_mappings: &'s BTreeMap<Qualified<CustomTypeName>, resolved::types::TypeMapping>,
|
||||
type_mappings: &'s BTreeMap<Qualified<CustomTypeName>, resolved::TypeMapping>,
|
||||
session_variables: &SessionVariables,
|
||||
usage_counts: &mut UsagesCounts,
|
||||
) -> Result<FieldSelection<'s>, error::Error> {
|
||||
@ -332,7 +332,7 @@ pub(crate) fn generate_command_relationship_ir<'s>(
|
||||
field: &Field<'s, GDS>,
|
||||
annotation: &'s CommandRelationshipAnnotation,
|
||||
source_data_connector: &'s resolved::data_connector::DataConnectorLink,
|
||||
type_mappings: &'s BTreeMap<Qualified<CustomTypeName>, resolved::types::TypeMapping>,
|
||||
type_mappings: &'s BTreeMap<Qualified<CustomTypeName>, resolved::TypeMapping>,
|
||||
session_variables: &SessionVariables,
|
||||
usage_counts: &mut UsagesCounts,
|
||||
) -> Result<FieldSelection<'s>, error::Error> {
|
||||
@ -384,7 +384,7 @@ pub(crate) fn build_local_model_relationship<'s>(
|
||||
field_call: &normalized_ast::FieldCall<'s, GDS>,
|
||||
annotation: &'s ModelRelationshipAnnotation,
|
||||
data_connector: &'s resolved::data_connector::DataConnectorLink,
|
||||
type_mappings: &'s BTreeMap<Qualified<CustomTypeName>, resolved::types::TypeMapping>,
|
||||
type_mappings: &'s BTreeMap<Qualified<CustomTypeName>, resolved::TypeMapping>,
|
||||
target_source: &'s ModelTargetSource,
|
||||
filter_clause: ResolvedFilterExpression<'s>,
|
||||
limit: Option<u32>,
|
||||
@ -430,7 +430,7 @@ pub(crate) fn build_local_command_relationship<'s>(
|
||||
field_call: &normalized_ast::FieldCall<'s, GDS>,
|
||||
annotation: &'s CommandRelationshipAnnotation,
|
||||
data_connector: &'s resolved::data_connector::DataConnectorLink,
|
||||
type_mappings: &'s BTreeMap<Qualified<CustomTypeName>, resolved::types::TypeMapping>,
|
||||
type_mappings: &'s BTreeMap<Qualified<CustomTypeName>, resolved::TypeMapping>,
|
||||
target_source: &'s CommandTargetSource,
|
||||
session_variables: &SessionVariables,
|
||||
) -> Result<FieldSelection<'s>, error::Error> {
|
||||
@ -471,7 +471,7 @@ pub(crate) fn build_remote_relationship<'n, 's>(
|
||||
field: &'n normalized_ast::Field<'s, GDS>,
|
||||
field_call: &'n normalized_ast::FieldCall<'s, GDS>,
|
||||
annotation: &'s ModelRelationshipAnnotation,
|
||||
type_mappings: &'s BTreeMap<Qualified<CustomTypeName>, resolved::types::TypeMapping>,
|
||||
type_mappings: &'s BTreeMap<Qualified<CustomTypeName>, resolved::TypeMapping>,
|
||||
target_source: &'s ModelTargetSource,
|
||||
filter_clause: ResolvedFilterExpression<'s>,
|
||||
limit: Option<u32>,
|
||||
@ -556,7 +556,7 @@ pub(crate) fn build_remote_command_relationship<'n, 's>(
|
||||
field: &'n normalized_ast::Field<'s, GDS>,
|
||||
field_call: &'n normalized_ast::FieldCall<'s, GDS>,
|
||||
annotation: &'s CommandRelationshipAnnotation,
|
||||
type_mappings: &'s BTreeMap<Qualified<CustomTypeName>, resolved::types::TypeMapping>,
|
||||
type_mappings: &'s BTreeMap<Qualified<CustomTypeName>, resolved::TypeMapping>,
|
||||
target_source: &'s CommandTargetSource,
|
||||
session_variables: &SessionVariables,
|
||||
) -> Result<FieldSelection<'s>, error::Error> {
|
||||
@ -606,11 +606,11 @@ pub(crate) fn build_remote_command_relationship<'n, 's>(
|
||||
}
|
||||
|
||||
fn get_field_mapping_of_field_name(
|
||||
type_mappings: &BTreeMap<Qualified<CustomTypeName>, resolved::types::TypeMapping>,
|
||||
type_mappings: &BTreeMap<Qualified<CustomTypeName>, resolved::TypeMapping>,
|
||||
type_name: &Qualified<CustomTypeName>,
|
||||
relationship_name: &RelationshipName,
|
||||
field_name: &FieldName,
|
||||
) -> Result<resolved::types::FieldMapping, error::Error> {
|
||||
) -> Result<resolved::FieldMapping, error::Error> {
|
||||
let type_mapping = type_mappings.get(type_name).ok_or_else(|| {
|
||||
error::InternalDeveloperError::TypeMappingNotFoundForRelationship {
|
||||
type_name: type_name.clone(),
|
||||
@ -618,7 +618,7 @@ fn get_field_mapping_of_field_name(
|
||||
}
|
||||
})?;
|
||||
match type_mapping {
|
||||
resolved::types::TypeMapping::Object { field_mappings, .. } => Ok(field_mappings
|
||||
resolved::TypeMapping::Object { field_mappings, .. } => Ok(field_mappings
|
||||
.get(field_name)
|
||||
.ok_or_else(
|
||||
|| error::InternalDeveloperError::FieldMappingNotFoundForRelationship {
|
||||
|
@ -22,7 +22,6 @@ use crate::metadata::resolved;
|
||||
use crate::metadata::resolved::subgraph::{
|
||||
Qualified, QualifiedBaseType, QualifiedTypeName, QualifiedTypeReference,
|
||||
};
|
||||
use crate::metadata::resolved::types::FieldMapping;
|
||||
use crate::schema::types::TypeKind;
|
||||
use crate::schema::{
|
||||
types::{Annotation, OutputAnnotation, RootFieldAnnotation},
|
||||
@ -108,7 +107,7 @@ pub(crate) struct ResultSelectionSet<'s> {
|
||||
impl<'s> ResultSelectionSet<'s> {
|
||||
/// Takes a 'FieldMapping' and returns the alias, if the field is found in
|
||||
/// existing fields
|
||||
pub(crate) fn contains(&self, other_field: &FieldMapping) -> Option<String> {
|
||||
pub(crate) fn contains(&self, other_field: &resolved::FieldMapping) -> Option<String> {
|
||||
self.fields.iter().find_map(|(alias, field)| match field {
|
||||
FieldSelection::Column { column, .. } => {
|
||||
if *column == other_field.column {
|
||||
@ -124,7 +123,7 @@ impl<'s> ResultSelectionSet<'s> {
|
||||
|
||||
fn build_global_id_fields(
|
||||
global_id_fields: &Vec<FieldName>,
|
||||
field_mappings: &BTreeMap<FieldName, resolved::types::FieldMapping>,
|
||||
field_mappings: &BTreeMap<FieldName, resolved::FieldMapping>,
|
||||
field_alias: &Alias,
|
||||
fields: &mut IndexMap<String, FieldSelection>,
|
||||
) -> Result<(), error::Error> {
|
||||
@ -156,7 +155,7 @@ pub(crate) fn generate_nested_selection<'s>(
|
||||
field_base_type_kind: TypeKind,
|
||||
field: &normalized_ast::Field<'s, GDS>,
|
||||
data_connector: &'s resolved::data_connector::DataConnectorLink,
|
||||
type_mappings: &'s BTreeMap<Qualified<CustomTypeName>, resolved::types::TypeMapping>,
|
||||
type_mappings: &'s BTreeMap<Qualified<CustomTypeName>, resolved::TypeMapping>,
|
||||
session_variables: &SessionVariables,
|
||||
usage_counts: &mut UsagesCounts,
|
||||
) -> Result<Option<NestedSelection<'s>>, error::Error> {
|
||||
@ -179,14 +178,11 @@ pub(crate) fn generate_nested_selection<'s>(
|
||||
QualifiedTypeName::Custom(data_type) => match field_base_type_kind {
|
||||
TypeKind::Scalar => Ok(None),
|
||||
TypeKind::Object => {
|
||||
let resolved::types::TypeMapping::Object { field_mappings, .. } =
|
||||
type_mappings.get(data_type).ok_or(
|
||||
error::InternalEngineError::InternalGeneric {
|
||||
description: format!(
|
||||
"no type mapping found for type {data_type}"
|
||||
),
|
||||
},
|
||||
)?;
|
||||
let resolved::TypeMapping::Object { field_mappings, .. } = type_mappings
|
||||
.get(data_type)
|
||||
.ok_or(error::InternalEngineError::InternalGeneric {
|
||||
description: format!("no type mapping found for type {data_type}"),
|
||||
})?;
|
||||
let nested_selection = generate_selection_set_ir(
|
||||
&field.selection_set,
|
||||
data_connector,
|
||||
@ -210,8 +206,8 @@ pub(crate) fn generate_nested_selection<'s>(
|
||||
pub(crate) fn generate_selection_set_ir<'s>(
|
||||
selection_set: &normalized_ast::SelectionSet<'s, GDS>,
|
||||
data_connector: &'s resolved::data_connector::DataConnectorLink,
|
||||
type_mappings: &'s BTreeMap<Qualified<CustomTypeName>, resolved::types::TypeMapping>,
|
||||
field_mappings: &BTreeMap<FieldName, resolved::types::FieldMapping>,
|
||||
type_mappings: &'s BTreeMap<Qualified<CustomTypeName>, resolved::TypeMapping>,
|
||||
field_mappings: &BTreeMap<FieldName, resolved::FieldMapping>,
|
||||
session_variables: &SessionVariables,
|
||||
usage_counts: &mut UsagesCounts,
|
||||
) -> Result<ResultSelectionSet<'s>, error::Error> {
|
||||
|
@ -13,7 +13,7 @@ use crate::execute::remote_joins::types::{
|
||||
JoinLocations, JoinNode, LocationKind, MonotonicCounter, RemoteJoinType, TargetField,
|
||||
};
|
||||
use crate::execute::remote_joins::types::{Location, RemoteJoin};
|
||||
use crate::metadata::resolved::types::FieldMapping;
|
||||
use crate::metadata::resolved::FieldMapping;
|
||||
|
||||
pub(crate) fn process_nested_selection<'s, 'ir>(
|
||||
nested_selection: &'ir NestedSelection<'s>,
|
||||
|
@ -13,4 +13,5 @@ pub mod subgraph;
|
||||
mod typecheck;
|
||||
pub mod types;
|
||||
|
||||
pub use stages::data_connector_type_mappings::{FieldMapping, TypeMapping};
|
||||
pub use stages::resolve;
|
||||
|
@ -1,4 +1,4 @@
|
||||
use super::stages::data_connector_scalar_types;
|
||||
use super::stages::{data_connector_scalar_types, data_connector_type_mappings};
|
||||
|
||||
use crate::metadata::resolved::data_connector;
|
||||
|
||||
@ -8,8 +8,6 @@ use crate::metadata::resolved::model;
|
||||
use crate::metadata::resolved::stages::graphql_config::GraphqlConfig;
|
||||
use crate::metadata::resolved::subgraph::{Qualified, QualifiedTypeReference};
|
||||
|
||||
use crate::metadata::resolved::types::TypeMapping;
|
||||
|
||||
use lang_graphql::ast::common::{self as ast};
|
||||
use ndc_models;
|
||||
|
||||
@ -52,7 +50,7 @@ pub fn resolve_boolean_expression(
|
||||
where_type_name: ast::TypeName,
|
||||
subgraph: &str,
|
||||
data_connectors: &data_connector_scalar_types::DataConnectorsWithScalars,
|
||||
type_mappings: &TypeMapping,
|
||||
type_mappings: &data_connector_type_mappings::TypeMapping,
|
||||
graphql_config: &GraphqlConfig,
|
||||
) -> Result<BooleanExpression, Error> {
|
||||
let mut scalar_fields = HashMap::new();
|
||||
@ -69,7 +67,7 @@ pub fn resolve_boolean_expression(
|
||||
})?
|
||||
.scalars;
|
||||
|
||||
let TypeMapping::Object { field_mappings, .. } = type_mappings;
|
||||
let data_connector_type_mappings::TypeMapping::Object { field_mappings, .. } = type_mappings;
|
||||
|
||||
let filter_graphql_config = graphql_config
|
||||
.query
|
||||
|
@ -1,4 +1,6 @@
|
||||
use super::stages::{data_connector_scalar_types, scalar_types, type_permissions};
|
||||
use super::stages::{
|
||||
data_connector_scalar_types, data_connector_type_mappings, scalar_types, type_permissions,
|
||||
};
|
||||
use crate::metadata::resolved::argument::get_argument_mappings;
|
||||
use crate::metadata::resolved::data_connector::DataConnectorLink;
|
||||
use crate::metadata::resolved::error::Error;
|
||||
@ -7,10 +9,10 @@ use crate::metadata::resolved::subgraph::{
|
||||
deserialize_qualified_btreemap, mk_qualified_type_reference, serialize_qualified_btreemap,
|
||||
ArgumentInfo, Qualified, QualifiedTypeReference,
|
||||
};
|
||||
use crate::metadata::resolved::types::mk_name;
|
||||
use crate::metadata::resolved::types::{
|
||||
get_type_representation, object_type_exists, unwrap_custom_type_name,
|
||||
};
|
||||
use crate::metadata::resolved::types::{mk_name, TypeMapping};
|
||||
use indexmap::IndexMap;
|
||||
use lang_graphql::ast::common as ast;
|
||||
use open_dds::arguments::ArgumentName;
|
||||
@ -24,7 +26,6 @@ use serde::{Deserialize, Serialize};
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
|
||||
use super::permission::{resolve_value_expression, ValueExpression};
|
||||
use super::stages::data_connector_type_mappings;
|
||||
use super::typecheck;
|
||||
use super::types::{
|
||||
collect_type_mapping_for_source, TypeMappingCollectionError, TypeMappingToCollect,
|
||||
@ -45,7 +46,8 @@ pub struct CommandSource {
|
||||
serialize_with = "serialize_qualified_btreemap",
|
||||
deserialize_with = "deserialize_qualified_btreemap"
|
||||
)]
|
||||
pub type_mappings: BTreeMap<Qualified<CustomTypeName>, TypeMapping>,
|
||||
pub type_mappings:
|
||||
BTreeMap<Qualified<CustomTypeName>, data_connector_type_mappings::TypeMapping>,
|
||||
pub argument_mappings: HashMap<ArgumentName, String>,
|
||||
}
|
||||
|
||||
|
@ -22,8 +22,8 @@ use crate::metadata::resolved::subgraph::{
|
||||
serialize_qualified_btreemap, ArgumentInfo, Qualified, QualifiedBaseType,
|
||||
QualifiedTypeReference,
|
||||
};
|
||||
use crate::metadata::resolved::types::mk_name;
|
||||
use crate::metadata::resolved::types::store_new_graphql_type;
|
||||
use crate::metadata::resolved::types::{mk_name, TypeMapping};
|
||||
use crate::schema::types::output_type::relationship::{
|
||||
ModelTargetSource, PredicateRelationshipAnnotation,
|
||||
};
|
||||
@ -112,7 +112,8 @@ pub struct ModelSource {
|
||||
serialize_with = "serialize_qualified_btreemap",
|
||||
deserialize_with = "deserialize_qualified_btreemap"
|
||||
)]
|
||||
pub type_mappings: BTreeMap<Qualified<CustomTypeName>, TypeMapping>,
|
||||
pub type_mappings:
|
||||
BTreeMap<Qualified<CustomTypeName>, data_connector_type_mappings::TypeMapping>,
|
||||
pub argument_mappings: HashMap<ArgumentName, String>,
|
||||
}
|
||||
|
||||
@ -519,14 +520,14 @@ fn resolve_model_predicate(
|
||||
// TODO: resolve the "in" operator too (ndc_models::BinaryArrayComparisonOperator)
|
||||
if let Some(model_source) = &model.source {
|
||||
// Get field mappings of model data type
|
||||
let TypeMapping::Object { field_mappings, .. } = model_source
|
||||
.type_mappings
|
||||
.get(&model.data_type)
|
||||
.ok_or(Error::TypeMappingRequired {
|
||||
model_name: model.name.clone(),
|
||||
type_name: model.data_type.clone(),
|
||||
data_connector: model_source.data_connector.name.clone(),
|
||||
})?;
|
||||
let data_connector_type_mappings::TypeMapping::Object { field_mappings, .. } =
|
||||
model_source.type_mappings.get(&model.data_type).ok_or(
|
||||
Error::TypeMappingRequired {
|
||||
model_name: model.name.clone(),
|
||||
type_name: model.data_type.clone(),
|
||||
data_connector: model_source.data_connector.name.clone(),
|
||||
},
|
||||
)?;
|
||||
|
||||
// Determine field_mapping for the predicate field
|
||||
let field_mapping = field_mappings.get(field).ok_or_else(|| {
|
||||
@ -584,14 +585,14 @@ fn resolve_model_predicate(
|
||||
permissions::ModelPredicate::FieldIsNull(FieldIsNullPredicate { field }) => {
|
||||
if let Some(model_source) = &model.source {
|
||||
// Get field mappings of model data type
|
||||
let TypeMapping::Object { field_mappings, .. } = model_source
|
||||
.type_mappings
|
||||
.get(&model.data_type)
|
||||
.ok_or(Error::TypeMappingRequired {
|
||||
model_name: model.name.clone(),
|
||||
type_name: model.data_type.clone(),
|
||||
data_connector: model_source.data_connector.name.clone(),
|
||||
})?;
|
||||
let data_connector_type_mappings::TypeMapping::Object { field_mappings, .. } =
|
||||
model_source.type_mappings.get(&model.data_type).ok_or(
|
||||
Error::TypeMappingRequired {
|
||||
model_name: model.name.clone(),
|
||||
type_name: model.data_type.clone(),
|
||||
data_connector: model_source.data_connector.name.clone(),
|
||||
},
|
||||
)?;
|
||||
// Determine field_mapping for the predicate field
|
||||
let field_mapping = field_mappings.get(field).ok_or_else(|| {
|
||||
Error::UnknownFieldInSelectPermissionsDefinition {
|
||||
@ -852,7 +853,7 @@ pub(crate) fn get_ndc_column_for_comparison<F: Fn() -> String>(
|
||||
comparison_location: F,
|
||||
) -> Result<NdcColumnForComparison, Error> {
|
||||
// Get field mappings of model data type
|
||||
let TypeMapping::Object { field_mappings, .. } = model_source
|
||||
let data_connector_type_mappings::TypeMapping::Object { field_mappings, .. } = model_source
|
||||
.type_mappings
|
||||
.get(model_data_type)
|
||||
.ok_or(Error::TypeMappingRequired {
|
||||
@ -1009,14 +1010,16 @@ pub fn resolve_model_graphql_api(
|
||||
)?;
|
||||
order_by_expression_type_name
|
||||
.map(|order_by_type_name| {
|
||||
let TypeMapping::Object { field_mappings, .. } = model_source
|
||||
.type_mappings
|
||||
.get(&model.data_type)
|
||||
.ok_or(Error::TypeMappingRequired {
|
||||
let data_connector_type_mappings::TypeMapping::Object {
|
||||
field_mappings,
|
||||
..
|
||||
} = model_source.type_mappings.get(&model.data_type).ok_or(
|
||||
Error::TypeMappingRequired {
|
||||
model_name: model_name.clone(),
|
||||
type_name: model.data_type.clone(),
|
||||
data_connector: model_source.data_connector.name.clone(),
|
||||
})?;
|
||||
},
|
||||
)?;
|
||||
|
||||
let mut order_by_fields = HashMap::new();
|
||||
for (field_name, field_mapping) in field_mappings.iter() {
|
||||
|
@ -171,7 +171,7 @@ pub fn validate_ndc(
|
||||
NDCValidationError::NoSuchType(collection.collection_type.clone()),
|
||||
)?;
|
||||
|
||||
let super::types::TypeMapping::Object { field_mappings, .. } = model_source
|
||||
let super::TypeMapping::Object { field_mappings, .. } = model_source
|
||||
.type_mappings
|
||||
.get(&model.data_type)
|
||||
.ok_or_else(|| NDCValidationError::UnknownModelTypeMapping {
|
||||
@ -333,7 +333,7 @@ pub fn validate_ndc_command(
|
||||
// Check if the command.output_type is available in schema.object_types
|
||||
Some(command_source_ndc_type) => {
|
||||
// Check if the command.output_type has typeMappings
|
||||
let super::types::TypeMapping::Object { field_mappings, .. } = command_source
|
||||
let super::TypeMapping::Object { field_mappings, .. } = command_source
|
||||
.type_mappings
|
||||
.get(custom_type)
|
||||
.ok_or_else(|| NDCValidationError::UnknownCommandTypeMapping {
|
||||
|
@ -2,15 +2,13 @@ use std::collections::{BTreeMap, HashMap, HashSet};
|
||||
pub mod types;
|
||||
use open_dds::types::CustomTypeName;
|
||||
pub use types::{
|
||||
DataConnectorTypeMappings, DataConnectorTypeMappingsOutput, FieldDefinition,
|
||||
DataConnectorTypeMappings, DataConnectorTypeMappingsOutput, FieldDefinition, FieldMapping,
|
||||
ObjectTypeRepresentation, ResolvedApolloFederationObjectKey,
|
||||
ResolvedObjectApolloFederationConfig,
|
||||
ResolvedObjectApolloFederationConfig, TypeMapping,
|
||||
};
|
||||
|
||||
use crate::metadata::resolved::stages::data_connectors;
|
||||
use crate::metadata::resolved::types::{
|
||||
mk_name, store_new_graphql_type, FieldMapping, TypeMapping,
|
||||
};
|
||||
use crate::metadata::resolved::types::{mk_name, store_new_graphql_type};
|
||||
|
||||
use crate::metadata::resolved::error::{Error, TypeMappingValidationError};
|
||||
use crate::metadata::resolved::subgraph::{mk_qualified_type_reference, Qualified};
|
||||
|
@ -6,12 +6,10 @@ use indexmap::IndexMap;
|
||||
|
||||
use open_dds::types::{CustomTypeName, Deprecated, FieldName};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::collections::{BTreeMap, HashMap, HashSet};
|
||||
|
||||
use open_dds::models::ModelName;
|
||||
|
||||
use crate::metadata::resolved::types::TypeMapping;
|
||||
|
||||
use crate::metadata::resolved::subgraph::Qualified;
|
||||
|
||||
use lang_graphql::ast::common as ast;
|
||||
@ -121,3 +119,17 @@ pub struct ResolvedObjectApolloFederationConfig {
|
||||
pub struct ResolvedApolloFederationObjectKey {
|
||||
pub fields: nonempty::NonEmpty<FieldName>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct FieldMapping {
|
||||
pub column: String,
|
||||
pub column_type: ndc_models::Type,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
|
||||
pub enum TypeMapping {
|
||||
Object {
|
||||
ndc_object_type_name: String,
|
||||
field_mappings: BTreeMap<FieldName, FieldMapping>,
|
||||
},
|
||||
}
|
||||
|
@ -11,7 +11,6 @@ use crate::metadata::resolved::subgraph::{
|
||||
QualifiedTypeReference,
|
||||
};
|
||||
use lang_graphql::ast::common as ast;
|
||||
use ndc_models;
|
||||
use open_dds::data_connector::DataConnectorName;
|
||||
use open_dds::models::EnableAllOrSpecific;
|
||||
use open_dds::types::{self, CustomTypeName, FieldName, ObjectBooleanExpressionTypeV1};
|
||||
@ -27,20 +26,6 @@ pub struct NdcColumnForComparison {
|
||||
pub equal_operator: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct FieldMapping {
|
||||
pub column: String,
|
||||
pub column_type: ndc_models::Type,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
|
||||
pub enum TypeMapping {
|
||||
Object {
|
||||
ndc_object_type_name: String,
|
||||
field_mappings: BTreeMap<FieldName, FieldMapping>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
|
||||
pub struct ObjectBooleanExpressionType {
|
||||
pub name: Qualified<CustomTypeName>,
|
||||
@ -48,7 +33,8 @@ pub struct ObjectBooleanExpressionType {
|
||||
pub data_connector_name: Qualified<DataConnectorName>,
|
||||
pub data_connector_link: data_connector::DataConnectorLink,
|
||||
pub data_connector_object_type: String,
|
||||
pub type_mappings: BTreeMap<Qualified<types::CustomTypeName>, TypeMapping>,
|
||||
pub type_mappings:
|
||||
BTreeMap<Qualified<types::CustomTypeName>, data_connector_type_mappings::TypeMapping>,
|
||||
pub graphql: Option<boolean_expression::BooleanExpression>,
|
||||
}
|
||||
|
||||
@ -80,148 +66,6 @@ pub fn resolve_field(
|
||||
})
|
||||
}
|
||||
|
||||
/*
|
||||
pub fn resolve_object_type(
|
||||
object_type_definition: &ObjectTypeV1,
|
||||
existing_graphql_types: &mut HashSet<ast::TypeName>,
|
||||
qualified_type_name: &Qualified<CustomTypeName>,
|
||||
subgraph: &str,
|
||||
global_id_enabled_types: &mut HashMap<
|
||||
Qualified<CustomTypeName>,
|
||||
Vec<Qualified<open_dds::models::ModelName>>,
|
||||
>,
|
||||
apollo_federation_entity_enabled_types: &mut HashMap<
|
||||
Qualified<CustomTypeName>,
|
||||
Option<Qualified<open_dds::models::ModelName>>,
|
||||
>,
|
||||
) -> Result<data_connector_type_mappings::ObjectTypeRepresentation, Error> {
|
||||
let mut resolved_fields = IndexMap::new();
|
||||
let mut resolved_global_id_fields = Vec::new();
|
||||
|
||||
for field in &object_type_definition.fields {
|
||||
if resolved_fields
|
||||
.insert(field.name.clone(), resolve_field(field, subgraph)?)
|
||||
.is_some()
|
||||
{
|
||||
return Err(Error::DuplicateFieldDefinition {
|
||||
type_name: qualified_type_name.clone(),
|
||||
field_name: field.name.clone(),
|
||||
});
|
||||
}
|
||||
}
|
||||
match &object_type_definition.global_id_fields {
|
||||
Some(global_id_fields) => {
|
||||
if !global_id_fields.is_empty() {
|
||||
// Throw error if the object type has a field called id" and has global fields configured.
|
||||
// Because, when the global id fields are configured, the `id` field will be auto-generated.
|
||||
if resolved_fields.contains_key(&FieldName(identifier!("id"))) {
|
||||
return Err(Error::IdFieldConflictingGlobalId {
|
||||
type_name: qualified_type_name.clone(),
|
||||
});
|
||||
}
|
||||
// To check if global_id_fields are defined in object type but no model has global_id_source set to
|
||||
// true:
|
||||
// - If the object type has globalIdFields configured, add the object type to the
|
||||
// global_id_enabled_types map.
|
||||
global_id_enabled_types.insert(qualified_type_name.clone(), Vec::new());
|
||||
};
|
||||
for global_id_field in global_id_fields {
|
||||
if !resolved_fields.contains_key(global_id_field) {
|
||||
return Err(Error::UnknownFieldInGlobalId {
|
||||
field_name: global_id_field.clone(),
|
||||
type_name: qualified_type_name.clone(),
|
||||
});
|
||||
} else {
|
||||
resolved_global_id_fields.push(global_id_field.clone())
|
||||
}
|
||||
}
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
let (graphql_type_name, graphql_input_type_name, apollo_federation_config) =
|
||||
match object_type_definition.graphql.as_ref() {
|
||||
None => Ok::<_, Error>((None, None, None)),
|
||||
Some(graphql) => {
|
||||
let graphql_type_name = graphql
|
||||
.type_name
|
||||
.as_ref()
|
||||
.map(|type_name| mk_name(type_name.0.as_ref()).map(ast::TypeName))
|
||||
.transpose()?;
|
||||
let graphql_input_type_name = graphql
|
||||
.input_type_name
|
||||
.as_ref()
|
||||
.map(|input_type_name| mk_name(input_type_name.0.as_ref()).map(ast::TypeName))
|
||||
.transpose()?;
|
||||
// To check if apolloFederation.keys are defined in object type but no model has
|
||||
// apollo_federation_entity_source set to true:
|
||||
// - If the object type has apolloFederation.keys configured, add the object type to the
|
||||
// apollo_federation_entity_enabled_types map.
|
||||
let resolved_apollo_federation_config = match &graphql.apollo_federation {
|
||||
None => Ok(None),
|
||||
Some(apollo_federation) => {
|
||||
// Validate that the fields in the apollo federation keys are defined in the object type
|
||||
let mut resolved_keys: Vec<
|
||||
data_connector_type_mappings::ResolvedApolloFederationObjectKey,
|
||||
> = Vec::new();
|
||||
for key in &apollo_federation.keys {
|
||||
let mut resolved_key_fields = Vec::new();
|
||||
for field in &key.fields {
|
||||
if !resolved_fields.contains_key(field) {
|
||||
return Err(Error::UnknownFieldInApolloFederationKey {
|
||||
field_name: field.clone(),
|
||||
object_type: qualified_type_name.clone(),
|
||||
});
|
||||
}
|
||||
resolved_key_fields.push(field.clone());
|
||||
}
|
||||
let resolved_key =
|
||||
match nonempty::NonEmpty::from_vec(resolved_key_fields) {
|
||||
None => {
|
||||
return Err(
|
||||
Error::EmptyFieldsInApolloFederationConfigForObject {
|
||||
object_type: qualified_type_name.clone(),
|
||||
},
|
||||
)
|
||||
}
|
||||
Some(fields) => data_connector_type_mappings::ResolvedApolloFederationObjectKey { fields },
|
||||
};
|
||||
resolved_keys.push(resolved_key);
|
||||
}
|
||||
apollo_federation_entity_enabled_types
|
||||
.insert(qualified_type_name.clone(), None);
|
||||
match nonempty::NonEmpty::from_vec(resolved_keys) {
|
||||
None => Err(Error::EmptyKeysInApolloFederationConfigForObject {
|
||||
object_type: qualified_type_name.clone(),
|
||||
}),
|
||||
Some(keys) => Ok(Some(data_connector_type_mappings
|
||||
::ResolvedObjectApolloFederationConfig { keys })),
|
||||
}
|
||||
}
|
||||
}?;
|
||||
Ok((
|
||||
graphql_type_name,
|
||||
graphql_input_type_name,
|
||||
resolved_apollo_federation_config,
|
||||
))
|
||||
}
|
||||
}?;
|
||||
store_new_graphql_type(existing_graphql_types, graphql_type_name.as_ref())?;
|
||||
store_new_graphql_type(existing_graphql_types, graphql_input_type_name.as_ref())?;
|
||||
|
||||
Ok(data_connector_type_mappings::ObjectTypeRepresentation {
|
||||
fields: resolved_fields,
|
||||
relationships: IndexMap::new(),
|
||||
global_id_fields: resolved_global_id_fields,
|
||||
type_output_permissions: HashMap::new(),
|
||||
type_input_permissions: HashMap::new(),
|
||||
graphql_output_type_name: graphql_type_name,
|
||||
graphql_input_type_name,
|
||||
description: object_type_definition.description.clone(),
|
||||
apollo_federation_config,
|
||||
})
|
||||
}
|
||||
*/
|
||||
|
||||
#[derive(Debug)]
|
||||
/// we do not want to store our types like this, but occasionally it is useful
|
||||
/// for pattern matching
|
||||
@ -534,7 +378,10 @@ pub(crate) fn collect_type_mapping_for_source(
|
||||
data_connector_name: &Qualified<DataConnectorName>,
|
||||
object_types: &HashMap<Qualified<CustomTypeName>, type_permissions::ObjectTypeWithPermissions>,
|
||||
scalar_types: &HashMap<Qualified<CustomTypeName>, scalar_types::ScalarTypeRepresentation>,
|
||||
collected_mappings: &mut BTreeMap<Qualified<CustomTypeName>, TypeMapping>,
|
||||
collected_mappings: &mut BTreeMap<
|
||||
Qualified<CustomTypeName>,
|
||||
data_connector_type_mappings::TypeMapping,
|
||||
>,
|
||||
) -> Result<(), TypeMappingCollectionError> {
|
||||
let type_mapping = data_connector_type_mappings
|
||||
.get(
|
||||
@ -552,7 +399,7 @@ pub(crate) fn collect_type_mapping_for_source(
|
||||
if let Some(inserted_mapping) =
|
||||
collected_mappings.insert(mapping_to_collect.type_name.clone(), type_mapping.clone())
|
||||
{
|
||||
let TypeMapping::Object {
|
||||
let data_connector_type_mappings::TypeMapping::Object {
|
||||
ndc_object_type_name,
|
||||
..
|
||||
} = inserted_mapping;
|
||||
@ -571,7 +418,8 @@ pub(crate) fn collect_type_mapping_for_source(
|
||||
|
||||
match object_types.get(mapping_to_collect.type_name) {
|
||||
Some(object_type_representation) => {
|
||||
let TypeMapping::Object { field_mappings, .. } = type_mapping;
|
||||
let data_connector_type_mappings::TypeMapping::Object { field_mappings, .. } =
|
||||
type_mapping;
|
||||
// For each field in the ObjectType, if that field is using an ObjectType in its type,
|
||||
// resolve the type mappings for that ObjectType too
|
||||
for (field_name, field_definition) in &object_type_representation.object_type.fields {
|
||||
|
@ -3,11 +3,9 @@ use std::collections::{BTreeMap, HashMap};
|
||||
|
||||
use crate::metadata::resolved::model::FilterPermission;
|
||||
use crate::metadata::resolved::permission::resolve_value_expression;
|
||||
use crate::metadata::resolved::stages::type_permissions;
|
||||
use crate::metadata::resolved::stages::{data_connector_type_mappings, type_permissions};
|
||||
use crate::metadata::resolved::subgraph::{Qualified, QualifiedTypeReference};
|
||||
use crate::metadata::resolved::types::{
|
||||
object_type_exists, unwrap_custom_type_name, FieldMapping, TypeMapping,
|
||||
};
|
||||
use crate::metadata::resolved::types::{object_type_exists, unwrap_custom_type_name};
|
||||
use crate::metadata::resolved::{self};
|
||||
use crate::schema::Role;
|
||||
use crate::schema::{self, types};
|
||||
@ -228,7 +226,7 @@ fn build_annotations_from_input_object_type_permissions(
|
||||
type_reference: &QualifiedTypeReference,
|
||||
ndc_argument_name: &Option<String>,
|
||||
object_types: &HashMap<Qualified<CustomTypeName>, type_permissions::ObjectTypeWithPermissions>,
|
||||
type_mappings: &BTreeMap<Qualified<CustomTypeName>, TypeMapping>,
|
||||
type_mappings: &BTreeMap<Qualified<CustomTypeName>, data_connector_type_mappings::TypeMapping>,
|
||||
role_presets_map: &mut HashMap<Role, types::ArgumentPresets>,
|
||||
) -> Result<(), schema::Error> {
|
||||
if let Some(custom_typename) = unwrap_custom_type_name(type_reference) {
|
||||
@ -238,7 +236,7 @@ fn build_annotations_from_input_object_type_permissions(
|
||||
type_mappings
|
||||
.get(&object_type)
|
||||
.map(|type_mapping| match type_mapping {
|
||||
TypeMapping::Object {
|
||||
data_connector_type_mappings::TypeMapping::Object {
|
||||
ndc_object_type_name: _,
|
||||
field_mappings,
|
||||
} => field_mappings,
|
||||
@ -296,7 +294,7 @@ fn build_annotations_from_input_object_type_permissions(
|
||||
/// `Map<("person", ["address", "country"]), ValueExpression(SessionVariable("x-hasura-user-country"))>`
|
||||
fn build_preset_map_from_input_object_type_permission(
|
||||
permission: &type_permissions::TypeInputPermission,
|
||||
field_mappings: Option<&BTreeMap<FieldName, FieldMapping>>,
|
||||
field_mappings: Option<&BTreeMap<FieldName, data_connector_type_mappings::FieldMapping>>,
|
||||
type_reference: &QualifiedTypeReference,
|
||||
field_path: &[String],
|
||||
ndc_argument_name: &Option<String>,
|
||||
|
@ -28,7 +28,7 @@ use crate::{
|
||||
},
|
||||
schema::types::resolved::{
|
||||
subgraph::{deserialize_qualified_btreemap, serialize_qualified_btreemap},
|
||||
types::TypeMapping,
|
||||
TypeMapping,
|
||||
},
|
||||
utils::HashMapWithJsonKey,
|
||||
};
|
||||
|
@ -44,7 +44,7 @@ pub struct FilterRelationshipAnnotation {
|
||||
serialize_with = "serialize_qualified_btreemap",
|
||||
deserialize_with = "deserialize_qualified_btreemap"
|
||||
)]
|
||||
pub source_type_mappings: BTreeMap<Qualified<CustomTypeName>, resolved::types::TypeMapping>,
|
||||
pub source_type_mappings: BTreeMap<Qualified<CustomTypeName>, resolved::TypeMapping>,
|
||||
pub target_source: ModelTargetSource,
|
||||
pub target_type: Qualified<CustomTypeName>,
|
||||
pub target_model_name: Qualified<ModelName>,
|
||||
@ -61,7 +61,7 @@ pub struct OrderByRelationshipAnnotation {
|
||||
serialize_with = "serialize_qualified_btreemap",
|
||||
deserialize_with = "deserialize_qualified_btreemap"
|
||||
)]
|
||||
pub source_type_mappings: BTreeMap<Qualified<CustomTypeName>, resolved::types::TypeMapping>,
|
||||
pub source_type_mappings: BTreeMap<Qualified<CustomTypeName>, resolved::TypeMapping>,
|
||||
pub target_source: ModelTargetSource,
|
||||
pub target_type: Qualified<CustomTypeName>,
|
||||
pub target_model_name: Qualified<ModelName>,
|
||||
@ -78,7 +78,7 @@ pub struct PredicateRelationshipAnnotation {
|
||||
serialize_with = "serialize_qualified_btreemap",
|
||||
deserialize_with = "deserialize_qualified_btreemap"
|
||||
)]
|
||||
pub source_type_mappings: BTreeMap<Qualified<CustomTypeName>, resolved::types::TypeMapping>,
|
||||
pub source_type_mappings: BTreeMap<Qualified<CustomTypeName>, resolved::TypeMapping>,
|
||||
pub target_source: ModelTargetSource,
|
||||
pub target_type: Qualified<CustomTypeName>,
|
||||
pub target_model_name: Qualified<ModelName>,
|
||||
|
Loading…
Reference in New Issue
Block a user