Skip to content

Latest commit

History

History
228 lines (157 loc) 路 10.1 KB

File metadata and controls

228 lines (157 loc) 路 10.1 KB
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.

The issue with index and constraint 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.

Upgrade path for introspection only users

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.

  1. Enable the namedConstraints Preview:

    generator client {
      provider        = "prisma-client-js"
      previewFeatures = ["namedConstraints"]
    }
  2. 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 be User_pk):

    model User {
      id    Int    @id(map: "user_id_primary_key") @default(autoincrement())
      name  String @unique
      posts Post[]
    }

Upgrade paths for Prisma migrate users

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.

Upgrade path 1: I want to maintain my existing constraint and index names

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.

  1. 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])
}
  1. 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")
    }

Upgrade path 2: I want to use Prismas default constraint and index names

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.

  1. 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
     }
  2. 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.

  3. Run the prisma migrate deploy command to apply the migration to your production environment:

    npx prisma deploy
    

Checking whether your environments use identical names

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")
}

Aligning your environments if their constraint or index names differ

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 called migration-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.