Skip to content

Commit

Permalink
intro: Use pairs for relation rendering
Browse files Browse the repository at this point in the history
  • Loading branch information
Julius de Bruijn committed Dec 8, 2022
1 parent a120da3 commit 746bd5a
Show file tree
Hide file tree
Showing 19 changed files with 982 additions and 538 deletions.
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
use crate::{
introspection::introspect,
introspection_helpers::{is_new_migration_table, is_old_migration_table, is_prisma_join_table, is_relay_table},
pair::{EnumPair, ModelPair, Pair},
introspection_map::RelationName,
pair::{EnumPair, ModelPair, Pair, RelationFieldDirection},
warnings, EnumVariantName, IntrospectedName, ModelName, SqlFamilyTrait, SqlIntrospectionResult,
};
use introspection_connector::{IntrospectionContext, IntrospectionResult, Version, Warning};
use psl::{builtin_connectors::*, datamodel_connector::Connector, parser_database::walkers, Configuration};
use psl::{
builtin_connectors::*,
datamodel_connector::Connector,
parser_database::{ast, walkers},
Configuration,
};
use quaint::prelude::SqlFamily;
use sql_schema_describer as sql;
use std::collections::HashMap;
use std::{borrow::Cow, collections::HashMap};

#[derive(Debug, Default)]
pub(crate) struct Warnings {
Expand All @@ -23,6 +29,7 @@ pub(crate) struct Warnings {
pub(crate) reintrospected_id_names: Vec<warnings::Model>,
pub(crate) unsupported_types: Vec<warnings::ModelAndFieldAndType>,
pub(crate) remapped_models: Vec<warnings::Model>,
pub(crate) reintrospected_relations: Vec<warnings::Model>,
}

impl Warnings {
Expand Down Expand Up @@ -104,6 +111,12 @@ impl Warnings {
&mut self.warnings,
);

maybe_warn(
&self.reintrospected_relations,
warnings::warning_relations_added_from_the_previous_data_model,
&mut self.warnings,
);

std::mem::take(&mut self.warnings)
}
}
Expand All @@ -116,7 +129,7 @@ pub(crate) struct InputContext<'a> {
pub(crate) sql_family: SqlFamily,
pub(crate) version: Version,
pub(crate) previous_schema: &'a psl::ValidatedSchema,
pub(crate) introspection_map: &'a crate::introspection_map::IntrospectionMap,
pub(crate) introspection_map: &'a crate::introspection_map::IntrospectionMap<'a>,
}

pub(crate) struct OutputContext<'a> {
Expand Down Expand Up @@ -260,14 +273,134 @@ impl<'a> InputContext<'a> {
// Failing that, potentially sanitize the table name.
.unwrap_or_else(|| ModelName::new_from_sql(self.schema.walk(id).name()))
}

pub(crate) fn forward_inline_relation_field_prisma_name(self, id: sql::ForeignKeyId) -> &'a str {
let existing_relation = self
.existing_inline_relation(id)
.and_then(|relation| relation.as_complete());

match existing_relation {
Some(relation) => relation.referencing_field().name(),
None => &self.inline_relation_name(id).unwrap()[1],
}
}

pub(crate) fn back_inline_relation_field_prisma_name(self, id: sql::ForeignKeyId) -> &'a str {
let existing_relation = self
.existing_inline_relation(id)
.and_then(|relation| relation.as_complete());

match existing_relation {
Some(relation) => relation.referenced_field().name(),
None => &self.inline_relation_name(id).unwrap()[2],
}
}

#[track_caller]
pub(crate) fn forward_m2m_relation_field_prisma_name(self, id: sql::TableId) -> &'a str {
let existing_relation = self.existing_m2m_relation(id);

match existing_relation {
Some(relation) if !relation.is_self_relation() => relation.field_a().name(),
_ => &self.m2m_relation_name(id)[1],
}
}

#[track_caller]
pub(crate) fn back_m2m_relation_field_prisma_name(self, id: sql::TableId) -> &'a str {
let existing_relation = self.existing_m2m_relation(id);

match existing_relation {
Some(relation) if !relation.is_self_relation() => relation.field_b().name(),
_ => &self.m2m_relation_name(id)[2],
}
}

#[track_caller]
pub(crate) fn inline_relation_prisma_name(self, id: sql::ForeignKeyId) -> Cow<'a, str> {
let existing_relation = self
.existing_inline_relation(id)
.and_then(|relation| relation.as_complete());

match existing_relation {
Some(relation) => match relation.referenced_field().relation_name() {
walkers::RelationName::Explicit(name) => Cow::Borrowed(name),
walkers::RelationName::Generated(_) => Cow::Borrowed(""),
},
None => Cow::Borrowed(&self.inline_relation_name(id).unwrap()[0]),
}
}

#[track_caller]
pub(crate) fn m2m_relation_prisma_name(self, id: sql::TableId) -> Cow<'a, str> {
let existing_relation = self.existing_m2m_relation(id);

match existing_relation {
Some(relation) => match relation.relation_name() {
walkers::RelationName::Explicit(name) => Cow::Borrowed(name),
walkers::RelationName::Generated(name) => Cow::Owned(name),
},
None => Cow::Borrowed(&self.m2m_relation_name(id)[0]),
}
}

pub(crate) fn inline_relation_name(self, id: sql::ForeignKeyId) -> Option<&'a RelationName<'a>> {
self.introspection_map.relation_names.inline_relation_name(id)
}

#[track_caller]
pub(crate) fn m2m_relation_name(self, id: sql::TableId) -> &'a RelationName<'a> {
self.introspection_map.relation_names.m2m_relation_name(id)
}

pub(crate) fn table_missing_for_model(self, id: &ast::ModelId) -> bool {
self.introspection_map.missing_tables_for_previous_models.contains(id)
}

pub(crate) fn inline_relations_for_table(
self,
table_id_filter: sql::TableId,
) -> impl Iterator<Item = (RelationFieldDirection, sql::ForeignKeyWalker<'a>)> {
self.introspection_map
.inline_relation_positions
.iter()
.filter(move |(table_id, _, _)| *table_id == table_id_filter)
.filter(move |(_, fk_id, _)| self.inline_relation_name(*fk_id).is_some())
.map(|(_, fk_id, direction)| {
let foreign_key = sql::Walker {
id: *fk_id,
schema: self.schema,
};

(*direction, foreign_key)
})
}

pub(crate) fn m2m_relations_for_table(
self,
table_id_filter: sql::TableId,
) -> impl Iterator<Item = (RelationFieldDirection, sql::ForeignKeyWalker<'a>)> {
self.introspection_map
.m2m_relation_positions
.iter()
.filter(move |(table_id, _, _)| *table_id == table_id_filter)
.map(|(_, fk_id, direction)| {
let next = sql::Walker {
id: *fk_id,
schema: self.schema,
};

(*direction, next)
})
}
}

/// Calculate a data model from a database schema.
pub fn calculate_datamodel(
schema: &sql::SqlSchema,
ctx: &IntrospectionContext,
) -> SqlIntrospectionResult<IntrospectionResult> {
let introspection_map = crate::introspection_map::IntrospectionMap::new(schema, ctx.previous_schema());
let introspection_map = Default::default();

let mut input = InputContext {
version: Version::NonPrisma,
Expand All @@ -279,6 +412,9 @@ pub fn calculate_datamodel(
introspection_map: &introspection_map,
};

let introspection_map = crate::introspection_map::IntrospectionMap::new(input);
input.introspection_map = &introspection_map;

let mut output = OutputContext {
rendered_schema: datamodel_renderer::Datamodel::default(),
target_models: HashMap::default(),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
pub(crate) mod inline_relations;

mod configuration;
mod enums;
mod indexes;
mod m2m_relations;
mod models;
mod postgres;
mod prisma_relation_mode;
mod relation_names;
mod relation_field;
mod scalar_field;

use crate::calculate_datamodel::{InputContext, OutputContext};
Expand All @@ -20,16 +16,7 @@ pub(crate) fn introspect<'a>(
enums::render(input, output);
models::render(input, output);

if input.foreign_keys_enabled() {
let relation_names = relation_names::introspect(input);

inline_relations::render(&relation_names, input, output);
m2m_relations::render(&relation_names, input, output);
} else {
prisma_relation_mode::render(input, output);
}

let rendered = if input.render_config {
let psl_string = if input.render_config {
format!(
"{}\n{}",
configuration::render(input.config, input.schema),
Expand All @@ -39,5 +26,8 @@ pub(crate) fn introspect<'a>(
output.rendered_schema.to_string()
};

Ok((psl::reformat(&rendered, 2).unwrap(), output.rendered_schema.is_empty()))
Ok((
psl::reformat(&psl_string, 2).unwrap(),
output.rendered_schema.is_empty(),
))
}

0 comments on commit 746bd5a

Please sign in to comment.