Skip to content

Commit

Permalink
Fix false positive in ambiguous self-relation validation
Browse files Browse the repository at this point in the history
  • Loading branch information
tomhoule committed Oct 1, 2019
1 parent 87115f5 commit b05e313
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 4 deletions.
4 changes: 2 additions & 2 deletions libs/datamodel/src/dml/validator/validate.rs
Expand Up @@ -90,7 +90,7 @@ impl Validator {

if !is_valid {
return Err(ValidationError::new_model_validation_error(
"Invalid ID field. ID field must be one of: Int @id, String @id @default(cuid()), String @id @default(uuid()).",
"Invalid ID field. ID field must be one of: Int @id, String @id @default(cuid()), String @id @default(uuid()).",
&model.name,
ast_schema.find_field(&model.name, &id_field.name).expect(STATE_ERROR).span));
}
Expand Down Expand Up @@ -156,7 +156,7 @@ impl Validator {
.span,
));
}
} else {
} else if rel_a.to == model.name && rel_b.to == model.name {
// A self relation...
for field_c in model.fields() {
if field_a != field_c && field_b != field_c {
Expand Down
19 changes: 19 additions & 0 deletions libs/datamodel/tests/directives/relations_positive.rs
Expand Up @@ -67,3 +67,22 @@ fn allow_complicated_self_relations() {
user_model.assert_has_field("husband").assert_relation_to("User");
user_model.assert_has_field("wife").assert_relation_to("User");
}

#[test]
fn allow_unambiguous_self_relations_in_presence_of_unrelated_other_relations() {
let dml = r#"
model User {
id Int @id
subscribers Follower[]
son User
mother User
}
model Follower {
id Int @id
following User[]
}
"#;

parse(dml);
}
43 changes: 42 additions & 1 deletion migration-engine/core/tests/datamodel_steps_inferrer_tests.rs
Expand Up @@ -78,7 +78,7 @@ fn infer_UpdateModel() {
r#"
model Post{
id String @id @default(cuid())
@@embedded
}
"#,
Expand Down Expand Up @@ -336,6 +336,47 @@ fn infer_UpdateIndex() {
assert_eq!(steps, expected);
}

#[test]
fn infer_CreateField_on_self_relation() {
let dm1 = parse(
r#"
model User {
id Int @id
}
"#,
);

let dm2 = parse(
r#"
model User {
id Int @id
invitedBy User?
}
"#,
);

let steps = infer(&dm1, &dm2);

let expected = vec![MigrationStep::CreateField(CreateField {
model: "User".into(),
name: "invitedBy".into(),
tpe: FieldType::Relation(RelationInfo {
name: "UserToUser".into(),
on_delete: OnDeleteStrategy::None,
to: "User".into(),
to_fields: vec!["id".to_owned()],
}),
arity: FieldArity::Optional,
db_name: None,
is_created_at: None,
is_updated_at: None,
is_unique: false,
id: None,
default: None,
scalar_list: None,
})];
}

fn infer(dm1: &Datamodel, dm2: &Datamodel) -> Vec<MigrationStep> {
let inferrer = DataModelMigrationStepsInferrerImplWrapper {};
inferrer.infer(&dm1, &dm2)
Expand Down
24 changes: 23 additions & 1 deletion migration-engine/core/tests/migration_tests.rs
Expand Up @@ -1208,7 +1208,7 @@ fn adding_a_scalar_list_for_a_modelwith_id_type_int_must_work() {
strings String[]
enums Status[]
}
enum Status {
OK
ERROR
Expand Down Expand Up @@ -1283,3 +1283,25 @@ fn reserved_sql_key_words_must_work() {
);
});
}

#[test]
fn migrations_with_self_relation_must_be_idempotent() {
// Issue: https://github.com/prisma/prisma2/issues/488
test_each_connector(|sql_family, api| {
let dm = r#"
model User {
id String @default(cuid()) @id
}
"#;

infer_and_apply(api, &dm);

let dm2 = r#"
model User {
id String @default(cuid()) @id
invitedBy User?
}
"#;
let schema_2 = infer_and_apply(api, &dm).sql_schema;
})
}

0 comments on commit b05e313

Please sign in to comment.