title | metaTitle | metaDescription |
---|---|---|
Enabling `namedConstraints` |
Enabling the `namedConstraints` preview feature |
How to use the Preview feature `namedConstraints`. |
This page describes manual upgrade steps that you need to perform after upgrading to Prisma 2.29.0 (or newer) if you want to use the namedConstraints
Preview feature.
- I want to maintain my existing constraint and index names
- I want to use Prisma's default constraint and index names
The namedConstraints
preview feature fixes some fundamental problems with the way Prisma handled the naming of constraints and indexes:
The names of compound unique constraints (@@unique
) were passed directly into the client after introspecting a database. This led to problems if these contained characters that resulted in invalid Typescript types.
The Prisma schema did not contain syntax to describe the names of primary keys and foreign keys. This could lead to situations where introspecting an existing database and then replicating it locally based on the introspected schema yielded databases that differed in their constraint names. This results in failing migrations if later on these constraints are manipulated since they are addressed by name.
If you started a development environment based on an initial introspection of a database you should check whether their constraint names match! If the names are out of sync you can now align them by following these steps.
Deprecation warning
From Prisma 3.0.0 onwards, the prisma introspect
command will be deprecated and replaced with the prisma db pull
command.
Use the following guide if you use introspection only.
-
Enable the
namedConstraints
Preview:generator client { provider = "prisma-client-js" previewFeatures = ["namedConstraints"] }
-
Introspect to populate your Prisma schema with any constraint names that do not follow Prisma's naming convention:
npx prisma introspect
For example, in the following model, the
@id
primary key constraint does not follow Prisma's convention (the conventional name would beUser_pk
):model User { id Int @id(map: "user_id_primary_key") @default(autoincrement()) name String @unique posts Post[] }
When enabling the namedConstraints
preview flag, you are changing the behaviour of Prisma migrate.
The default naming convention for constraint and index names will change and you primary and foreign key names will now be part of the schema for databases that support them. Therefore the meaning of your existing schema to Prisma will change.
Before you continue to evolve your schema and your database, you should decided which names for constraints and indexes you want to use on your project from now on.
You can either keep the existing names in your database or you can switch to use the names generated by Prisma's new naming convention. You can pick either of the two options.
If you want to keep your database unchanged and keep the existing names for constraints and indexes you need to pull them into your schema so Prisma is aware of them.
Reasons to keep your existing names might be:
- Naming conventions you have to follow
- Other tooling relying on the names
- Personal preference
To keep existing names, run prisma db pull
against the target environment with the preview flag enabled. This will result in all names that do not match Prisma's naming convention (LINK) for constraint and index names being pulled into your schema as map
arguments on their respective attributes.
- Enable the
namedConstraints
Preview:
generator client {
provider = "prisma-client-js"
previewFeatures = ["namedConstraints"]
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model User {
id Int @id() @default(autoincrement())
name String @unique
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
title String
authorName String @default("Anonymous")
author User? @relation(fields: [authorName], references: [name])
}
-
Introspect your development database to populate the Prisma schema with constraint and index names in your underlying database that do not match Prisma's naming convention:
npx prisma migrate introspect
In this example, the highlighted constraints did not conform to Prisma's default naming convention and now include the
map
attribute field:model User { id Int @id(map: "Custom_Constraint_Name") @default(autoincrement()) name String @unique posts Post[] } model Post { id Int @id @default(autoincrement()) title String authorName String @default("Anonymous") author User? @relation(fields: [authorName], references: [name], map: "Custom_Foreign_Key_Constraint") }
If you want to keep the clean look of your Prisma schema without explicitly spelled out constraint and index names and have no reasons preventing you from renaming their names in the database you can create a migration to update the names.
With the preview flag enabled, run prisma migrate dev
to create a migration updating the constraint names to Prisma's defaults.
Afterwards, do not forget to prisma migrated deploy
against your production environment if you have one to also update the names there. The schema below has no explicit constraint or index names spelled out, so Prisma will infer them.
-
Enable the
namedConstraints
Preview:generator client { provider = "prisma-client-js" previewFeatures = ["namedConstraints"] } model User { name String @id //inferred as User_pkey posts Post[] } model Post { id Int @id @default(autoincrement()) //inferred as Post_pkey authorName String @default("Anonymous") author User? @relation(fields: [authorName], references: [name]) //inferred as Post_authorName_fkey }
-
Run the
prisma migrate dev
command to generate a new migration:npx prisma migrate dev
This migration renames any constraints that do not currently follow Prisma's naming convention.
-
Run the
prisma migrate deploy
command to apply the migration to your production environment:npx prisma deploy
If you have more than one database environment, they could be using different constraint or index names. This can happen when you introspected an existing database with Prisma in the past. Since Prisma did not have support for all constraint names in the Prisma schema, these names were not persisted. When recreating a database from a schema without names present Prisma then either created its own names or left the naming to the database. Both can result in names that differ from the initially introspected database.
In order to detect this, backup your current prisma.schema file and then run prisma db pull
against both environments saving the results to their own files.
Then you can either manually inspect both files or use a diff
tool in your IDE or in the terminal. If you see differences in constraint names, your production and local environments are out of sync and should be aligned.
In the following example, the Post
model has a foreign key constraint with a custom name in production that does not match development:
<TabbedContent tabs={[, ]}>
model Post {
id Int @id @default(autoincrement())
title String
authorName String @default("Anonymous")
author User? @relation(fields: [authorName], references: [name], map: "Custom_Foreign_Key_Constraint")
}
model Post {
id Int @id @default(autoincrement())
title String
authorName String @default("Anonymous")
author User? @relation(fields: [authorName], references: [name], map: "Custom_Production_Name")
}
If the names in your environments differ, the safest option is to align your development environment with the names in your production environment. This way no changes to your production database are needed.
In order to achieve this, enable the preview flag and then:
- Run
prisma db pull
against your production environment to pull in the constraint and index names - Switch to development and run
prisma migrate dev
a new migration calledmigration-to-sync-names
for example - Switch to production, and run
prisma migrate resolve --applied migration-to-sync-names
to mark the migration as applied on production
Your migration history now contains a migration to ensure that the names of any new environments you spin up contain the same names as your production database. And Prisma knows not to apply this migration to production since you already marked it as applied.
Your environments are now in sync and you can proceed to the upgrade paths for migrate users. These let you choose your future naming schema.