-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Steal ndc-postgres get_schema implementation
- Loading branch information
1 parent
9454f66
commit 92e2421
Showing
6 changed files
with
3,221 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
pub mod configuration; | ||
pub mod connector; | ||
pub mod metrics; | ||
pub mod schema; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,210 @@ | ||
//! Implement the `/schema` endpoint to return the connector's schema. | ||
//! See the Hasura | ||
//! [Native Data Connector Specification](https://hasura.github.io/ndc-spec/specification/schema/index.html) | ||
//! for further details. | ||
use std::collections::BTreeMap; | ||
|
||
use ndc_sdk::connector; | ||
use ndc_sdk::models; | ||
use query_engine_metadata::metadata; | ||
|
||
use super::configuration; | ||
|
||
/// Get the connector's schema. | ||
/// | ||
/// This function implements the [schema endpoint](https://hasura.github.io/ndc-spec/specification/schema/index.html) | ||
/// from the NDC specification. | ||
pub async fn get_schema( | ||
configuration::Configuration { config, .. }: &configuration::Configuration, | ||
) -> Result<models::SchemaResponse, connector::SchemaError> { | ||
let configuration::RawConfiguration { metadata, .. } = config; | ||
let scalar_types: BTreeMap<String, models::ScalarType> = | ||
configuration::occurring_scalar_types(&metadata.tables, &metadata.native_queries) | ||
.iter() | ||
.map(|scalar_type| { | ||
( | ||
scalar_type.0.clone(), | ||
models::ScalarType { | ||
aggregate_functions: metadata | ||
.aggregate_functions | ||
.0 | ||
.get(scalar_type) | ||
.unwrap_or(&BTreeMap::new()) | ||
.iter() | ||
.map(|(function_name, function_definition)| { | ||
( | ||
function_name.clone(), | ||
models::AggregateFunctionDefinition { | ||
result_type: models::Type::Named { | ||
name: function_definition.return_type.0.clone(), | ||
}, | ||
}, | ||
) | ||
}) | ||
.collect(), | ||
comparison_operators: metadata | ||
.comparison_operators | ||
.0 | ||
.get(scalar_type) | ||
.unwrap_or(&BTreeMap::new()) | ||
.iter() | ||
.map(|(op_name, op_def)| { | ||
( | ||
op_name.clone(), | ||
models::ComparisonOperatorDefinition { | ||
argument_type: models::Type::Named { | ||
name: op_def.argument_type.0.clone(), | ||
}, | ||
}, | ||
) | ||
}) | ||
.collect(), | ||
update_operators: BTreeMap::new(), | ||
}, | ||
) | ||
}) | ||
.collect(); | ||
|
||
let tables: Vec<models::CollectionInfo> = metadata | ||
.tables | ||
.0 | ||
.iter() | ||
.map(|(table_name, table)| models::CollectionInfo { | ||
name: table_name.clone(), | ||
description: table.description.clone(), | ||
arguments: BTreeMap::new(), | ||
collection_type: table_name.clone(), | ||
insertable_columns: None, | ||
updatable_columns: None, | ||
deletable: false, | ||
uniqueness_constraints: table | ||
.uniqueness_constraints | ||
.0 | ||
.iter() | ||
.map( | ||
|(constraint_name, metadata::UniquenessConstraint(constraint_columns))| { | ||
( | ||
constraint_name.clone(), | ||
models::UniquenessConstraint { | ||
unique_columns: constraint_columns.iter().cloned().collect(), | ||
}, | ||
) | ||
}, | ||
) | ||
.collect(), | ||
foreign_keys: table | ||
.foreign_relations | ||
.0 | ||
.iter() | ||
.map( | ||
|( | ||
constraint_name, | ||
metadata::ForeignRelation { | ||
foreign_table, | ||
column_mapping, | ||
}, | ||
)| { | ||
( | ||
constraint_name.clone(), | ||
models::ForeignKeyConstraint { | ||
foreign_collection: foreign_table.clone(), | ||
column_mapping: column_mapping.clone(), | ||
}, | ||
) | ||
}, | ||
) | ||
.collect(), | ||
}) | ||
.collect(); | ||
|
||
let native_queries: Vec<models::CollectionInfo> = metadata | ||
.native_queries | ||
.0 | ||
.iter() | ||
.map(|(name, info)| models::CollectionInfo { | ||
name: name.clone(), | ||
description: info.description.clone(), | ||
arguments: info | ||
.arguments | ||
.iter() | ||
.map(|(name, column_info)| { | ||
( | ||
name.clone(), | ||
models::ArgumentInfo { | ||
description: column_info.description.clone(), | ||
argument_type: column_to_type(column_info), | ||
}, | ||
) | ||
}) | ||
.collect(), | ||
collection_type: name.clone(), | ||
insertable_columns: None, | ||
updatable_columns: None, | ||
deletable: false, | ||
uniqueness_constraints: BTreeMap::new(), | ||
foreign_keys: BTreeMap::new(), | ||
}) | ||
.collect(); | ||
|
||
let mut collections = tables; | ||
collections.extend(native_queries); | ||
|
||
let table_types = BTreeMap::from_iter(metadata.tables.0.iter().map(|(table_name, table)| { | ||
let object_type = models::ObjectType { | ||
description: table.description.clone(), | ||
fields: BTreeMap::from_iter(table.columns.values().map(|column| { | ||
( | ||
column.name.clone(), | ||
models::ObjectField { | ||
description: column.description.clone(), | ||
r#type: column_to_type(column), | ||
}, | ||
) | ||
})), | ||
}; | ||
(table_name.clone(), object_type) | ||
})); | ||
|
||
let native_queries_types = | ||
BTreeMap::from_iter(metadata.native_queries.0.iter().map(|(name, info)| { | ||
let object_type = models::ObjectType { | ||
description: info.description.clone(), | ||
fields: BTreeMap::from_iter(info.columns.values().map(|column| { | ||
( | ||
column.name.clone(), | ||
models::ObjectField { | ||
description: column.description.clone(), | ||
r#type: column_to_type(column), | ||
}, | ||
) | ||
})), | ||
}; | ||
(name.clone(), object_type) | ||
})); | ||
|
||
let mut object_types = table_types; | ||
object_types.extend(native_queries_types); | ||
|
||
Ok(models::SchemaResponse { | ||
collections, | ||
procedures: vec![], | ||
functions: vec![], | ||
object_types, | ||
scalar_types, | ||
}) | ||
} | ||
|
||
fn column_to_type(column: &metadata::ColumnInfo) -> models::Type { | ||
match &column.nullable { | ||
metadata::Nullable::NonNullable => models::Type::Named { | ||
name: column.r#type.0.clone(), | ||
}, | ||
metadata::Nullable::Nullable => models::Type::Nullable { | ||
underlying_type: Box::new(models::Type::Named { | ||
name: column.r#type.0.clone(), | ||
}), | ||
}, | ||
} | ||
} | ||
|
Oops, something went wrong.