Skip to content

Commit

Permalink
psl: decouple datasource loader from builtin connectors
Browse files Browse the repository at this point in the history
The connectors still come from crates datamodel-core depends on, but now
they could come from anywhere else.

The next step will be moving builtin connectors to their own crate, stop
depending on them in datamodel-core, then moving datamodel-connector
into datamodel-core, and injecting the builtin connectors from the psl
crate. We will then have reached our goal of a psl-core crate that does
not depend on any connector but takes them as input.
  • Loading branch information
tomhoule committed Sep 14, 2022
1 parent 0769354 commit cf80d03
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 24 deletions.
@@ -1,6 +1,6 @@
use crate::*;
use ::datamodel::datamodel_connector::{constraint_names::ConstraintNames, Connector, EmptyDatamodelConnector};
use ::datamodel::{parser_database as db, common::RelationNames, Datasource};
use ::datamodel::{common::RelationNames, parser_database as db, Datasource};
use schema_ast::string_literal;
use std::fmt::Write;

Expand Down
15 changes: 11 additions & 4 deletions libs/datamodel/core/src/lib.rs
Expand Up @@ -29,6 +29,9 @@ use parser_database::{ast, ParserDatabase, SourceFile};
pub mod builtin_connectors {
pub use mongodb_datamodel_connector::*;
pub use sql_datamodel_connector::*;

pub(crate) type ConnectorRegistry = &'static [&'static dyn datamodel_connector::Connector];
pub(crate) const BUILTIN_CONNECTORS: ConnectorRegistry = &[POSTGRES, MYSQL, SQLITE, MSSQL, COCKROACH, MONGODB];
}

pub struct ValidatedSchema {
Expand Down Expand Up @@ -59,7 +62,7 @@ pub fn parse_schema_parserdb(file: impl Into<SourceFile>) -> Result<ValidatedSch
pub fn validate(file: SourceFile) -> ValidatedSchema {
let mut diagnostics = Diagnostics::new();
let db = ParserDatabase::new(file, &mut diagnostics);
let configuration = validate_configuration(db.ast(), &mut diagnostics);
let configuration = validate_configuration(db.ast(), &mut diagnostics, builtin_connectors::BUILTIN_CONNECTORS);
let datasources = &configuration.datasources;
let out = validate::validate(db, datasources, configuration.preview_features(), diagnostics);

Expand All @@ -76,14 +79,18 @@ pub fn validate(file: SourceFile) -> ValidatedSchema {
pub fn parse_configuration(schema: &str) -> Result<Configuration, diagnostics::Diagnostics> {
let mut diagnostics = Diagnostics::default();
let ast = schema_ast::parse_schema(schema, &mut diagnostics);
let out = validate_configuration(&ast, &mut diagnostics);
let out = validate_configuration(&ast, &mut diagnostics, builtin_connectors::BUILTIN_CONNECTORS);
diagnostics.to_result().map(|_| out)
}

fn validate_configuration(schema_ast: &ast::SchemaAst, diagnostics: &mut Diagnostics) -> Configuration {
fn validate_configuration(
schema_ast: &ast::SchemaAst,
diagnostics: &mut Diagnostics,
connectors: builtin_connectors::ConnectorRegistry,
) -> Configuration {
let generators = GeneratorLoader::load_generators_from_ast(schema_ast, diagnostics);
let preview_features = generators.iter().filter_map(|gen| gen.preview_features).collect();
let datasources = DatasourceLoader.load_datasources_from_ast(schema_ast, preview_features, diagnostics);
let datasources = DatasourceLoader.load_datasources_from_ast(schema_ast, preview_features, diagnostics, connectors);

Configuration {
generators,
Expand Down
33 changes: 14 additions & 19 deletions libs/datamodel/core/src/validate/datasource_loader.rs
Expand Up @@ -7,9 +7,7 @@ use crate::{
};
use datamodel_connector::ReferentialIntegrity;
use enumflags2::BitFlags;
use mongodb_datamodel_connector::*;
use parser_database::{ast::WithDocumentation, coerce, coerce_array, coerce_opt};
use sql_datamodel_connector::*;
use std::{borrow::Cow, collections::HashMap};

const PREVIEW_FEATURES_KEY: &str = "previewFeatures";
Expand All @@ -29,11 +27,12 @@ impl DatasourceLoader {
ast_schema: &ast::SchemaAst,
preview_features: BitFlags<PreviewFeature>,
diagnostics: &mut Diagnostics,
connectors: crate::builtin_connectors::ConnectorRegistry,
) -> Vec<Datasource> {
let mut sources = Vec::new();

for src in ast_schema.sources() {
if let Some(source) = self.lift_datasource(src, preview_features, diagnostics) {
if let Some(source) = self.lift_datasource(src, preview_features, diagnostics, connectors) {
sources.push(source)
}
}
Expand All @@ -56,6 +55,7 @@ impl DatasourceLoader {
ast_source: &ast::SourceConfig,
preview_features: BitFlags<PreviewFeature>,
diagnostics: &mut Diagnostics,
connectors: crate::builtin_connectors::ConnectorRegistry,
) -> Option<Datasource> {
let source_name = &ast_source.name.name;
let mut args: HashMap<_, _> = ast_source
Expand Down Expand Up @@ -134,23 +134,18 @@ impl DatasourceLoader {
let documentation = ast_source.documentation().map(String::from);
let referential_integrity = get_referential_integrity(&args, preview_features, ast_source, diagnostics);

let active_connector: &'static dyn datamodel_connector::Connector = match provider {
p if MYSQL.is_provider(p) => MYSQL,
p if POSTGRES.is_provider(p) => POSTGRES,
p if SQLITE.is_provider(p) => SQLITE,
p if MSSQL.is_provider(p) => MSSQL,
p if MONGODB.is_provider(p) => MONGODB,
p if COCKROACH.is_provider(p) => COCKROACH,

_ => {
diagnostics.push_error(DatamodelError::new_datasource_provider_not_known_error(
provider,
provider_arg.span(),
));
let active_connector: &'static dyn datamodel_connector::Connector =
match connectors.iter().find(|c| c.is_provider(provider)) {
Some(c) => *c,
None => {
diagnostics.push_error(DatamodelError::new_datasource_provider_not_known_error(
provider,
provider_arg.span(),
));

return None;
}
};
return None;
}
};

if let Some(integrity) = referential_integrity {
if !active_connector
Expand Down

0 comments on commit cf80d03

Please sign in to comment.