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

Incorrect migration creates on sql server when index deleted #14051

Closed
ingbond opened this issue Jun 29, 2022 · 6 comments · Fixed by prisma/prisma-engines#3018
Closed

Incorrect migration creates on sql server when index deleted #14051

ingbond opened this issue Jun 29, 2022 · 6 comments · Fixed by prisma/prisma-engines#3018
Assignees
Labels
bug/2-confirmed Bug has been reproduced and confirmed. kind/bug A reported bug. team/schema Issue for team Schema. topic: migrate topic: sql server Microsoft SQL Server
Milestone

Comments

@ingbond
Copy link

ingbond commented Jun 29, 2022

Bug description

Initial prisma model contains unique keys:

model Logbook {    
  categoryId     String?         @db.UniqueIdentifier
  date           DateTime       @db.Date()
  @@unique([date, categoryId], name: "Date_Category_unique_constraint")
}

It creates such sql statement:
-- CreateIndex CREATE UNIQUE NONCLUSTERED INDEX [Logbook_date_categoryId_key] ON [dbo].[Logbook]([date], [categoryId]);
When I delete unique constraint from prisma's schema model

model Logbook {    
  categoryId     String?         @db.UniqueIdentifier
  date           DateTime       @db.Date()
}

it creates migration with such statement:
-- DropIndex ALTER TABLE [dbo].[Logbook] DROP CONSTRAINT [Logbook_date_categoryId_key];
Applying this migration throws an error:
"Database error:
'Logbook_date_categoryId_key' is not a constraint."

How to reproduce

  1. Add unique keys constraint for your model
  2. Apply migration
  3. Delete constraint
  4. Apply migration

Expected behavior

Should call DROP INDEX, not DROP CONSTRAINT;

Prisma information

model Logbook {    
  categoryId     String?         @db.UniqueIdentifier
  date           DateTime       @db.Date()
  @@unique([date, categoryId], name: "Date_Category_unique_constraint")
}

Environment & setup

  • OS: Windows
  • Database: Sql Server
  • Node.js version: 16.15.1

Prisma Version

3.15.1
@ingbond ingbond added the kind/bug A reported bug. label Jun 29, 2022
@ingbond ingbond changed the title Incorrect migration creates on sql server when index changes Incorrect migration creates on sql server when index deleted Jun 29, 2022
@pimeys pimeys added team/schema Issue for team Schema. bug/1-unconfirmed Bug should have enough information for reproduction, but confirmation has not happened yet. topic: migrate topic: sql server Microsoft SQL Server labels Jun 29, 2022
@pimeys pimeys added this to the 4.1.0 milestone Jun 29, 2022
@pimeys
Copy link
Contributor

pimeys commented Jun 29, 2022

I cannot reproduce this. Running with SQL Server 2019.

First datamodel:

datasource db {
  provider = "sqlserver"
  url      = "sqlserver://localhost:1433;database=master;user=SA;password=<YourStrong@Passw0rd>;trustServerCertificate=true"
}

model Logbook {
  id         Int      @id
  categoryId String?  @db.UniqueIdentifier
  date       DateTime @db.Date()

  @@unique([date, categoryId], name: "Date_Category_unique_constraint")
}

This is pushed to the database correctly. Then removing the unique:

datasource db {
  provider = "sqlserver"
  url      = "sqlserver://localhost:1433;database=master;user=SA;password=<YourStrong@Passw0rd>;trustServerCertificate=true"
}

model Logbook {
  id         Int      @id
  categoryId String?  @db.UniqueIdentifier
  date       DateTime @db.Date()
}

This creates a migration:

BEGIN TRY

BEGIN TRAN;

-- DropIndex
ALTER TABLE [dbo].[Logbook] DROP CONSTRAINT [Logbook_date_categoryId_key];

COMMIT TRAN;

END TRY
BEGIN CATCH

IF @@TRANCOUNT > 0
BEGIN
    ROLLBACK TRAN;
END;
THROW

END CATCH

Now I can execute this and the constraint is removed.

@pimeys pimeys self-assigned this Jun 29, 2022
@pimeys
Copy link
Contributor

pimeys commented Jun 29, 2022

Ah, found it! So you must first create a table without a unique constraint, then add it and then remove it again. Now it fails.

@pimeys pimeys added bug/2-confirmed Bug has been reproduced and confirmed. and removed bug/1-unconfirmed Bug should have enough information for reproduction, but confirmation has not happened yet. labels Jun 29, 2022
pimeys pushed a commit to prisma/prisma-engines that referenced this issue Jun 29, 2022
Unique constraint and index do not differ in SQL Server today. The
problem is if we create an index and try to drop a constraint, the
drop fails.

Currently if the unique is added when the table is created, we add
constraint. If the table is altered with a unique constraint we create
an index instead. Dropping this does not work.

The PR makes altering the table with an `@unique` to use constraints
instead of an index.

Closes: prisma/prisma#14051
@pimeys
Copy link
Contributor

pimeys commented Jun 29, 2022

I made a fix, this should work with all Prisma cases. Read the details from the PR above.

Now you should manually edit the drop to your migration for it to work. In the future, if you alter a table with @unique, we add a constraint instead of an index. This can then be dropped with DROP CONSTRAINT.

Definitely interesting how SQL Server makes a distinction here, and why you can't drop a unique index with DROP CONSTRAINT.

@pimeys
Copy link
Contributor

pimeys commented Jun 29, 2022

Also it's a bit problematic for existing indices, if coming to a brownfield project with Prisma. We do not make any distinction between unique index or unique constraint...

pimeys pushed a commit to prisma/prisma-engines that referenced this issue Jun 29, 2022
Unique constraint and index do not differ in SQL Server today. The
problem is if we create an index and try to drop a constraint, the
drop fails.

Currently if the unique is added when the table is created, we add
constraint. If the table is altered with a unique constraint we create
an index instead. Dropping this does not work.

The PR makes altering the table with an `@unique` to use constraints
instead of an index.

Closes: prisma/prisma#14051
@pimeys
Copy link
Contributor

pimeys commented Jun 30, 2022

After sleeping one night on this, I decided to detect is it an index or unique, and drop accordingly to fix the brownfield problem. Out in about three weeks in 4.1.0.

pimeys pushed a commit to prisma/prisma-engines that referenced this issue Jun 30, 2022
Unique constraint and index do not differ in SQL Server today. The
problem is if we create an index and try to drop a constraint, the
drop fails.

Currently if the unique is added when the table is created, we add
constraint. If the table is altered with a unique constraint we create
an index instead. Dropping this does not work.

The PR makes altering the table with an `@unique` to use constraints
instead of an index.

Closes: prisma/prisma#14051
@pimeys
Copy link
Contributor

pimeys commented Jun 30, 2022

What can still break is if your development database and production database are not in sync. You drop a constraint in dev, and it fails in production because there it's actually an index. It's kind of not very probable that this happens, but if it gets too common we might need to consider to have the information in the Prisma schema language. E.g. @unique(constraint: true). But I'd prefer not to have that if possible.

yume-chan pushed a commit to yume-chan/prisma-engines that referenced this issue Jul 8, 2022
Unique constraint and index do not differ in SQL Server today. The
problem is if we create an index and try to drop a constraint, the
drop fails.

Currently if the unique is added when the table is created, we add
constraint. If the table is altered with a unique constraint we create
an index instead. Dropping this does not work.

The PR makes altering the table with an `@unique` to use constraints
instead of an index.

Closes: prisma/prisma#14051
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug/2-confirmed Bug has been reproduced and confirmed. kind/bug A reported bug. team/schema Issue for team Schema. topic: migrate topic: sql server Microsoft SQL Server
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants