Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

qe: start introducing typed identifiers in relations #3672

Merged
merged 1 commit into from
Feb 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions psl/psl/tests/attributes/relations/relations_new.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,18 @@ fn relation_happy_path() {

let schema = parse(dml);
let user_model = schema.assert_has_model("User");
let post_model = schema.assert_has_model("Post");
user_model
.assert_has_relation_field("posts")
.assert_arity(&dml::FieldArity::List)
.assert_relation_to("Post")
.assert_relation_to(post_model.id)
.assert_relation_base_fields(&[])
.assert_relation_referenced_fields(&[]);

let post_model = schema.assert_has_model("Post");
post_model
.assert_has_relation_field("user")
.assert_arity(&dml::FieldArity::Required)
.assert_relation_to("User")
.assert_relation_to(user_model.id)
.assert_relation_base_fields(&["userId"])
.assert_relation_referenced_fields(&["id"]);
}
Expand Down
42 changes: 25 additions & 17 deletions psl/psl/tests/attributes/relations/relations_positive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@ fn settings_must_be_deteced() {

let schema = parse(dml);

schema
.assert_has_model("Todo")
let todo_model = schema.assert_has_model("Todo");
todo_model
.assert_has_relation_field("parent_todo")
.assert_relation_to("Todo")
.assert_relation_to(todo_model.id)
.assert_relation_referenced_fields(&["id"])
.assert_arity(&dml::FieldArity::Optional);
}
Expand All @@ -68,19 +68,21 @@ fn resolve_relation() {

let schema = parse(dml);
let user_model = schema.assert_has_model("User");
let post_model = schema.assert_has_model("Post");
user_model
.assert_has_scalar_field("firstName")
.assert_base_type(&ScalarType::String);
user_model
.assert_has_relation_field("posts")
.assert_relation_to("Post")
.assert_relation_to(post_model.id)
.assert_arity(&dml::FieldArity::List);

let post_model = schema.assert_has_model("Post");
post_model
.assert_has_scalar_field("text")
.assert_base_type(&ScalarType::String);
post_model.assert_has_relation_field("user").assert_relation_to("User");
post_model
.assert_has_relation_field("user")
.assert_relation_to(user_model.id);
}

#[test]
Expand All @@ -102,10 +104,11 @@ fn resolve_related_field() {

let schema = parse(dml);

let user_model = schema.assert_has_model("User");
let post_model = schema.assert_has_model("Post");
post_model
.assert_has_relation_field("user")
.assert_relation_to("User")
.assert_relation_to(user_model.id)
.assert_relation_referenced_fields(&["firstName"]);
}

Expand All @@ -132,10 +135,11 @@ fn resolve_related_fields() {

let schema = parse(dml);

let user_model = schema.assert_has_model("User");
let post_model = schema.assert_has_model("Post");
post_model
.assert_has_relation_field("user")
.assert_relation_to("User")
.assert_relation_to(user_model.id)
.assert_relation_base_fields(&["authorFirstName", "authorLastName"])
.assert_relation_referenced_fields(&["firstName", "lastName"]);
}
Expand All @@ -162,31 +166,31 @@ fn allow_multiple_relations() {

let schema = parse(dml);
let user_model = schema.assert_has_model("User");
let post_model = schema.assert_has_model("Post");
user_model
.assert_field_count(3)
.assert_has_relation_field("posts")
.assert_relation_to("Post")
.assert_relation_to(post_model.id)
.assert_arity(&dml::FieldArity::List)
.assert_relation_name("PostToUser");
user_model
.assert_has_relation_field("more_posts")
.assert_relation_to("Post")
.assert_relation_to(post_model.id)
.assert_arity(&dml::FieldArity::List)
.assert_relation_name("more_posts");

let post_model = schema.assert_has_model("Post");
post_model
.assert_field_count(6)
.assert_has_scalar_field("text")
.assert_base_type(&ScalarType::String);
post_model
.assert_has_relation_field("user")
.assert_relation_to("User")
.assert_relation_to(user_model.id)
.assert_arity(&dml::FieldArity::Required)
.assert_relation_name("PostToUser");
post_model
.assert_has_relation_field("posting_user")
.assert_relation_to("User")
.assert_relation_to(user_model.id)
.assert_arity(&dml::FieldArity::Required)
.assert_relation_name("more_posts");
}
Expand All @@ -209,14 +213,18 @@ fn allow_complicated_self_relations() {

let schema = parse(dml);
let user_model = schema.assert_has_model("User");
user_model.assert_has_relation_field("son").assert_relation_to("User");
user_model
.assert_has_relation_field("son")
.assert_relation_to(user_model.id);
user_model
.assert_has_relation_field("father")
.assert_relation_to("User");
.assert_relation_to(user_model.id);
user_model
.assert_has_relation_field("husband")
.assert_relation_to("User");
user_model.assert_has_relation_field("wife").assert_relation_to("User");
.assert_relation_to(user_model.id);
user_model
.assert_has_relation_field("wife")
.assert_relation_to(user_model.id);
}

#[test]
Expand Down
3 changes: 2 additions & 1 deletion psl/psl/tests/base/array_sugar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ fn should_treat_single_values_as_arrays_of_length_one() {

let schema = parse(dml);

let user_model = schema.assert_has_model("User");
let post_model = schema.assert_has_model("Post");
post_model
.assert_has_relation_field("user")
.assert_relation_to("User")
.assert_relation_to(user_model.id)
.assert_relation_referenced_fields(&["id"]);
}
6 changes: 3 additions & 3 deletions psl/psl/tests/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ pub(crate) use asserts::*;
pub use dml::*;
pub use expect_test::expect;

use psl::{diagnostics::*, Configuration, StringFromEnvVar};
use psl::{diagnostics::*, schema_ast::ast, Configuration, StringFromEnvVar};

pub(crate) fn reformat(input: &str) -> String {
psl::reformat(input, 2).unwrap_or_else(|| input.to_owned())
Expand Down Expand Up @@ -39,7 +39,7 @@ pub(crate) trait CompositeTypeFieldAsserts {

pub(crate) trait RelationFieldAsserts {
fn assert_relation_name(&self, t: &str) -> &Self;
fn assert_relation_to(&self, t: &str) -> &Self;
fn assert_relation_to(&self, t: ast::ModelId) -> &Self;
fn assert_relation_delete_strategy(&self, t: dml::ReferentialAction) -> &Self;
fn assert_relation_update_strategy(&self, t: dml::ReferentialAction) -> &Self;
fn assert_relation_referenced_fields(&self, t: &[&str]) -> &Self;
Expand Down Expand Up @@ -191,7 +191,7 @@ impl RelationFieldAsserts for dml::RelationField {
self
}

fn assert_relation_to(&self, t: &str) -> &Self {
fn assert_relation_to(&self, t: ast::ModelId) -> &Self {
assert_eq!(self.relation_info.referenced_model, t);
self
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,7 @@ impl AsTable for Relation {
}
RelationLinkManifestation::Inline(ref m) => self
.internal_data_model()
.find_model(&m.in_table_of_model_name)
.unwrap()
.find_model_by_id(m.in_table_of_model)
.as_table(ctx),
}
}
Expand Down
31 changes: 6 additions & 25 deletions query-engine/dml/src/datamodel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,8 @@ use crate::composite_type::CompositeType;
use crate::field::RelationField;
use crate::model::Model;
use crate::relation_info::RelationInfo;
use psl_core::schema_ast::ast;

/// Entities in the datamodel can be flagged as `is_commented_out`. This lets the renderer
/// know that introspection encountered unsupported names or features and these are supposed
/// to be rendered as comments. Since the parser will not set these flags when reading a schema
/// string, only introspection and the lowering of the datamodel to the ast care about these flags.
/// The FieldType: Unsupported behaves in the same way.
/// Both of these are never converted into the internal datamodel.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not accurate anymore.

#[derive(Debug, Default)]
pub struct Datamodel {
pub models: Vec<Model>,
Expand All @@ -31,6 +26,10 @@ impl Datamodel {
self.models().find(|model| model.name == name)
}

pub fn find_model_by_id(&self, id: ast::ModelId) -> Option<&Model> {
self.models().find(|m| m.id == id)
}

/// Finds a composite type by name.
pub fn find_composite_type(&self, name: &str) -> Option<&CompositeType> {
self.composite_types().find(|composite| composite.name == name)
Expand All @@ -43,11 +42,6 @@ impl Datamodel {
.find(|model| model.database_name.as_deref() == Some(db_name))
}

/// Finds parent model for a field reference.
pub fn find_model_by_relation_field_ref(&self, field: &RelationField) -> Option<&Model> {
self.find_model(&self.find_related_field_bang(field).1.relation_info.referenced_model)
}

/// Finds a model by name and returns a mutable reference.
pub fn find_model_mut(&mut self, name: &str) -> &mut Model {
self.models
Expand All @@ -56,22 +50,9 @@ impl Datamodel {
.expect("We assume an internally valid datamodel before mutating.")
}

/// Returns (model_name, field_name) for all relation fields pointing to a specific model.
pub fn find_relation_fields_for_model(&mut self, model_name: &str) -> Vec<(String, String)> {
let mut fields = vec![];
for model in self.models() {
for field in model.relation_fields() {
if field.relation_info.referenced_model == model_name {
fields.push((model.name.clone(), field.name.clone()))
}
}
}
fields
}

/// Finds a relation field related to a relation info. Returns a tuple (index_of_relation_field_in_model, relation_field).
pub fn find_related_field_for_info(&self, info: &RelationInfo, exclude: &str) -> Option<(usize, &RelationField)> {
self.find_model(&info.referenced_model)
self.find_model_by_id(info.referenced_model)
.expect("The model referred to by a RelationInfo should always exist.")
.fields
.iter()
Expand Down
20 changes: 0 additions & 20 deletions query-engine/dml/src/field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -331,10 +331,6 @@ impl RelationField {
self.emulates_referential_actions = Some(value);
}

pub fn points_to_model(&self, name: &str) -> bool {
self.relation_info.referenced_model == name
}

pub fn is_required(&self) -> bool {
self.arity.is_required()
}
Expand All @@ -343,14 +339,6 @@ impl RelationField {
self.arity.is_list()
}

pub fn is_singular(&self) -> bool {
!self.is_list()
}

pub fn is_optional(&self) -> bool {
self.arity.is_optional()
}

pub fn default_on_delete_action(&self) -> ReferentialAction {
use ReferentialAction::*;

Expand Down Expand Up @@ -446,14 +434,6 @@ impl ScalarField {
self.arity.is_required()
}

pub fn is_list(&self) -> bool {
self.arity.is_list()
}

pub fn is_singular(&self) -> bool {
!self.is_list()
}

pub fn is_optional(&self) -> bool {
self.arity.is_optional()
}
Expand Down
8 changes: 4 additions & 4 deletions query-engine/dml/src/lift.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ impl<'a> LiftAstToDml<'a> {

let referenced_model = relation.referenced_model();

let relation_info = RelationInfo::new(referenced_model.name());
let relation_info = RelationInfo::new(referenced_model.id);

let forward_field_walker = relation.forward_relation_field().unwrap();
// Construct a relation field in the DML for an existing relation field in the source.
Expand Down Expand Up @@ -181,7 +181,7 @@ impl<'a> LiftAstToDml<'a> {

// Back field
{
let relation_info = RelationInfo::new(relation.referencing_model().name());
let relation_info = RelationInfo::new(relation.referencing_model().id);
let model = schema.find_model_mut(relation.referenced_model().name());

let mut field = if let Some(relation_field) = relation.back_relation_field() {
Expand Down Expand Up @@ -227,7 +227,7 @@ impl<'a> LiftAstToDml<'a> {
for relation_field in [relation.field_a(), relation.field_b()] {
let ast_field = relation_field.ast_field();
let arity = ast_field.arity;
let relation_info = RelationInfo::new(relation_field.related_model().name());
let relation_info = RelationInfo::new(relation_field.related_model().id);
let referential_arity = relation_field.referential_arity();
let mut field = RelationField::new(
relation_field.id,
Expand Down Expand Up @@ -262,7 +262,7 @@ impl<'a> LiftAstToDml<'a> {
for relation_field in [relation.field_a(), relation.field_b()] {
let ast_field = relation_field.ast_field();
let arity = ast_field.arity;
let relation_info = RelationInfo::new(relation_field.related_model().name());
let relation_info = RelationInfo::new(relation_field.related_model().id);
let referential_arity = relation_field.referential_arity();

let mut field = RelationField::new(
Expand Down
8 changes: 4 additions & 4 deletions query-engine/dml/src/relation_info.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use psl_core::parser_database as db;
use psl_core::{parser_database as db, schema_ast::ast};

/// Holds information about a relation field.
#[derive(Debug, PartialEq, Clone)]
pub struct RelationInfo {
/// The target model of the relation.
pub referenced_model: String,
pub referenced_model: ast::ModelId,
/// The fields forming the relation.
pub fields: Vec<String>,
/// The target field of the relation a.k.a. `references`
Expand All @@ -24,9 +24,9 @@ pub struct RelationInfo {
impl RelationInfo {
/// Creates a new relation info for the
/// given target model.
pub fn new(model: &str) -> RelationInfo {
pub fn new(referenced_model: ast::ModelId) -> RelationInfo {
RelationInfo {
referenced_model: String::from(model),
referenced_model,
fields: Vec::new(),
references: Vec::new(),
name: String::new(),
Expand Down
Loading