Skip to content

Commit

Permalink
Merge pull request #3337 from prisma/fix/re-introspection-referential…
Browse files Browse the repository at this point in the history
…-integrity-16007

fix: re-introspection now preserves 'referentialIntegrity' policy
  • Loading branch information
jkomyno committed Oct 27, 2022
2 parents 5b40874 + 40ecd45 commit 3d0f4a0
Show file tree
Hide file tree
Showing 7 changed files with 1,214 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -108,12 +108,14 @@ impl<'a> Datasource<'a> {
let shadow_database_url = psl_ds.shadow_database_url.as_ref().map(|(url, _)| Env::from(url));
let namespaces: Vec<Text<_>> = psl_ds.namespaces.iter().map(|(ns, _)| Text(ns.as_str())).collect();

let relation_mode = psl_ds.relation_mode.or(psl_ds.referential_integrity);

Self {
name: &psl_ds.name,
provider: Text(&psl_ds.provider),
url: Env::from(&psl_ds.url),
shadow_database_url,
relation_mode: psl_ds.relation_mode,
relation_mode,
documentation: psl_ds.documentation.as_deref().map(Documentation),
custom_properties: Default::default(),
namespaces: Array::from(namespaces),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
mod mssql;
mod mysql;
mod relation_mode;
mod sqlite;
mod vitess;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
mod mssql;
mod mysql;
mod postgres;
mod sqlite;
Original file line number Diff line number Diff line change
@@ -0,0 +1,298 @@
use indoc::indoc;
use introspection_engine_tests::test_api::*;

// referentialIntegrity="prisma" is renamed as relationMode="prisma", and @relations are preserved.
#[test_connector(tags(Mssql))]
async fn referential_integrity_prisma(api: &TestApi) -> TestResult {
let init = indoc! {r#"
CREATE TABLE [dbo].[Foo] (
[id] INT NOT NULL,
[bar_id] INT NOT NULL,
CONSTRAINT [Foo_pkey] PRIMARY KEY CLUSTERED ([id]),
CONSTRAINT [Foo_bar_id_key] UNIQUE NONCLUSTERED ([bar_id])
);
CREATE TABLE [dbo].[Bar] (
[id] INT NOT NULL,
CONSTRAINT [Bar_pkey] PRIMARY KEY CLUSTERED ([id])
);
"#};

api.raw_cmd(&init).await;

let input = indoc! {r#"
generator client {
provider = "prisma-client-js"
previewFeatures = ["referentialIntegrity"]
}
datasource db {
provider = "sqlserver"
url = env("TEST_DATABASE_URL")
referentialIntegrity = "prisma"
}
model Foo {
id Int @id
bar Bar @relation(fields: [bar_id], references: [id])
bar_id Int @unique
}
model Bar {
id Int @id
foo Foo?
}
"#};

let expected = expect![[r#"
generator client {
provider = "prisma-client-js"
previewFeatures = ["referentialIntegrity"]
}
datasource db {
provider = "sqlserver"
url = env("TEST_DATABASE_URL")
relationMode = "prisma"
}
model Foo {
id Int @id
bar Bar @relation(fields: [bar_id], references: [id])
bar_id Int @unique
}
model Bar {
id Int @id
foo Foo?
}
"#]];

let result = api.re_introspect_config(input).await?;
expected.assert_eq(&result);

Ok(())
}

// referentialIntegrity="foreignKeys" is renamed as relationMode="foreignKeys", and @relations are preserved but moved to the bottom.
#[test_connector(tags(Mssql))]
async fn referential_integrity_foreign_keys(api: &TestApi) -> TestResult {
let init = indoc! {r#"
CREATE TABLE [dbo].[Foo] (
[id] INT NOT NULL,
[bar_id] INT NOT NULL,
CONSTRAINT [Foo_pkey] PRIMARY KEY CLUSTERED ([id]),
CONSTRAINT [Foo_bar_id_key] UNIQUE NONCLUSTERED ([bar_id])
);
CREATE TABLE [dbo].[Bar] (
[id] INT NOT NULL,
CONSTRAINT [Bar_pkey] PRIMARY KEY CLUSTERED ([id])
);
ALTER TABLE [dbo].[Foo] ADD CONSTRAINT [Foo_bar_id_fkey] FOREIGN KEY ([bar_id]) REFERENCES [dbo].[Bar]([id]) ON DELETE NO ACTION ON UPDATE CASCADE;
"#};

api.raw_cmd(&init).await;

let input = indoc! {r#"
generator client {
provider = "prisma-client-js"
previewFeatures = ["referentialIntegrity"]
}
datasource db {
provider = "sqlserver"
url = env("TEST_DATABASE_URL")
referentialIntegrity = "foreignKeys"
}
model Foo {
id Int @id
bar Bar @relation(fields: [bar_id], references: [id])
bar_id Int @unique
}
model Bar {
id Int @id
foo Foo?
}
"#};

let expected = expect![[r#"
generator client {
provider = "prisma-client-js"
previewFeatures = ["referentialIntegrity"]
}
datasource db {
provider = "sqlserver"
url = env("TEST_DATABASE_URL")
relationMode = "foreignKeys"
}
model Foo {
id Int @id
bar_id Int @unique
bar Bar @relation(fields: [bar_id], references: [id])
}
model Bar {
id Int @id
foo Foo?
}
"#]];

let result = api.re_introspect_config(input).await?;
expected.assert_eq(&result);

Ok(())
}

// relationMode="prisma" preserves the relation policy ("prisma") as well as @relations.
#[test_connector(tags(Mssql))]
async fn relation_mode_prisma(api: &TestApi) -> TestResult {
let init = indoc! {r#"
CREATE TABLE [dbo].[Foo] (
[id] INT NOT NULL,
[bar_id] INT NOT NULL,
CONSTRAINT [Foo_pkey] PRIMARY KEY CLUSTERED ([id]),
CONSTRAINT [Foo_bar_id_key] UNIQUE NONCLUSTERED ([bar_id])
);
CREATE TABLE [dbo].[Bar] (
[id] INT NOT NULL,
CONSTRAINT [Bar_pkey] PRIMARY KEY CLUSTERED ([id])
);
"#};

api.raw_cmd(&init).await;

let input = indoc! {r#"
generator client {
provider = "prisma-client-js"
previewFeatures = ["referentialIntegrity"]
}
datasource db {
provider = "sqlserver"
url = env("TEST_DATABASE_URL")
relationMode = "prisma"
}
model Foo {
id Int @id
bar Bar @relation(fields: [bar_id], references: [id])
bar_id Int @unique
}
model Bar {
id Int @id
foo Foo?
}
"#};

let expected = expect![[r#"
generator client {
provider = "prisma-client-js"
previewFeatures = ["referentialIntegrity"]
}
datasource db {
provider = "sqlserver"
url = env("TEST_DATABASE_URL")
relationMode = "prisma"
}
model Foo {
id Int @id
bar Bar @relation(fields: [bar_id], references: [id])
bar_id Int @unique
}
model Bar {
id Int @id
foo Foo?
}
"#]];

let result = api.re_introspect_config(input).await?;
expected.assert_eq(&result);

Ok(())
}

// relationMode="foreignKeys" preserves the relation policy ("foreignKeys") as well as @relations, which are moved to the bottom.
#[test_connector(tags(Mssql))]
async fn relation_mode_foreign_keys(api: &TestApi) -> TestResult {
let init = indoc! {r#"
CREATE TABLE [dbo].[Foo] (
[id] INT NOT NULL,
[bar_id] INT NOT NULL,
CONSTRAINT [Foo_pkey] PRIMARY KEY CLUSTERED ([id]),
CONSTRAINT [Foo_bar_id_key] UNIQUE NONCLUSTERED ([bar_id])
);
CREATE TABLE [dbo].[Bar] (
[id] INT NOT NULL,
CONSTRAINT [Bar_pkey] PRIMARY KEY CLUSTERED ([id])
);
ALTER TABLE [dbo].[Foo] ADD CONSTRAINT [Foo_bar_id_fkey] FOREIGN KEY ([bar_id]) REFERENCES [dbo].[Bar]([id]) ON DELETE NO ACTION ON UPDATE CASCADE;
"#};

api.raw_cmd(&init).await;

let input = indoc! {r#"
generator client {
provider = "prisma-client-js"
previewFeatures = ["referentialIntegrity"]
}
datasource db {
provider = "sqlserver"
url = env("TEST_DATABASE_URL")
relationMode = "foreignKeys"
}
model Foo {
id Int @id
bar Bar @relation(fields: [bar_id], references: [id])
bar_id Int @unique
}
model Bar {
id Int @id
foo Foo?
}
"#};

let expected = expect![[r#"
generator client {
provider = "prisma-client-js"
previewFeatures = ["referentialIntegrity"]
}
datasource db {
provider = "sqlserver"
url = env("TEST_DATABASE_URL")
relationMode = "foreignKeys"
}
model Foo {
id Int @id
bar_id Int @unique
bar Bar @relation(fields: [bar_id], references: [id])
}
model Bar {
id Int @id
foo Foo?
}
"#]];

let result = api.re_introspect_config(input).await?;
expected.assert_eq(&result);

Ok(())
}

0 comments on commit 3d0f4a0

Please sign in to comment.