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

Fix relation_fields validation to accept primary key indexes #4376

Merged
merged 3 commits into from
Mar 19, 2024
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -267,23 +267,27 @@ pub(super) fn validate_missing_relation_indexes(relation_field: RelationFieldWal
// Considers all groups of indexes explicitly declared in the given model.
// An index group can be:
// - a singleton (@unique or @id)
// - an ordered set (@@unique or @@index)
let index_field_groups = model.indexes();

let referencing_fields_appear_in_index = index_field_groups
.map(|index_walker| index_walker.fields().map(|index| index.field_id()))
.any(|index_fields_it| {
let fields_it = referencing_fields_it.clone();
is_leftwise_included_it(fields_it, index_fields_it)
});

if !referencing_fields_appear_in_index {
let ast_field = relation_field.ast_field();
let span = ast_field
.span_for_attribute("relation")
.unwrap_or_else(|| ast_field.span());
ctx.push_warning(DatamodelWarning::new_missing_index_on_emulated_relation(span));
// - an ordered set (@@unique, @@index, or @@id)
for index_walker in model.indexes() {
let index_fields_it = index_walker.fields().map(|col| col.field_id());
let referencing_fields_it = referencing_fields_it.clone();
if is_leftwise_included_it(referencing_fields_it, index_fields_it) {
return;
}
}

if let Some(primary_key_walker) = model.primary_key() {
let primary_key_fields_it = primary_key_walker.fields().map(|col| col.field_id());
if is_leftwise_included_it(referencing_fields_it, primary_key_fields_it) {
return;
}
}

let ast_field = relation_field.ast_field();
let span = ast_field
.span_for_attribute("relation")
.unwrap_or_else(|| ast_field.span());
ctx.push_warning(DatamodelWarning::new_missing_index_on_emulated_relation(span));
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// no relation index validation warning on relationMode = "prisma" when a referenced field is already in @@id.

datasource db {
provider = "mysql"
url = env("TEST_DATABASE_URL")
relationMode = "prisma"
}

model SomeUser {
id Int @id
profile Profile?
}

model Profile {
id Int
user SomeUser? @relation(fields: [id], references: [id])

@@id([id])
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// no relation index validation warning on relationMode = "prisma" when a referenced field is already in @id.

datasource db {
provider = "mysql"
url = env("TEST_DATABASE_URL")
relationMode = "prisma"
}

model SomeUser {
id Int @id
profile Profile?
}

model Profile {
id Int @id
user SomeUser? @relation(fields: [id], references: [id])
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// add missing relation index validation warning on relationMode = "prisma".

datasource db {
provider = "mysql"
url = env("TEST_DATABASE_URL")
relationMode = "prisma"
}

model SomeUser {
idA Int
idB Int
idC Int
posts Post[]

@@id([idA, idB, idC])
}

model Post {
userIdA Int @unique
userIdB Int
userIdC Int @unique
user SomeUser @relation(fields: [userIdA, userIdB, userIdC], references: [idA, idB, idC])

@@id([userIdA, userIdB])
}

// warning: With `relationMode = "prisma"`, no foreign keys are used, so relation fields will not benefit from the index usually created by the relational database under the hood. This can lead to poor performance when querying these fields. We recommend adding an index manually. Learn more at https://pris.ly/d/relation-mode-prisma-indexes" 
// --> schema.prisma:22
//  | 
// 21 |  userIdC Int @unique
// 22 |  user SomeUser @relation(fields: [userIdA, userIdB, userIdC], references: [idA, idB, idC])
//  |