We are extremely excited to launch the first official Beta of Prisma 2.0 today! 🎉 Along with this release, we have also published a new website and an updated Prisma 2.0 documentation. This makes Prisma 2.0 the default for developers who are getting started with Prisma.
Upgrading to the new relation syntax
If you have been using Prisma Migrate before to create your models and their relations, the new relation syntax can seem a bit counterintuitive at first. Here's a quick overview of the most important things to consider when upgrading.
Note that this only covers one-to-one and one-to-many relations. Prisma's implicit many-to-many relations are adjusted by manually adding the @relation
attribute with a single field reference to both sides of the relation (most often this looks as follows: @relation(references: [id])
).
Consider this sample schema from preview025
:
model User {
id Int @id @default(autoincrement())
profile Profile?
posts Post[]
}
model Profile {
id Int @id @default(autoincrement())
user User // backed up by a foreign key called `user` in the DB
}
model Post {
id Int @id @default(autoincrement())
author User // backed up by a foreign key called `author` in the DB
}
Expand for the corresponding SQL
CREATE TABLE "User" (
id integer PRIMARY KEY,
name text NOT NULL DEFAULT ''::text
);
CREATE TABLE "Profile" (
bio text NOT NULL DEFAULT ''::text,
id integer PRIMARY KEY,
user integer NOT NULL,
FOREIGN KEY ("user") REFERENCES "User"(id)
);
CREATE TABLE "Post" (
id integer PRIMARY KEY,
title text NOT NULL
author integer NOT NULL,
FOREIGN KEY ("author") REFERENCES "User"(id)
);
Note that in this case, the foreign keys in the underlying database are located on the Profile
and Post
tables. The User
table does not have any foreign keys (which means the profile
and posts
relation fields on the User
model are virtually maintained by Prisma).
The new syntax requires you to make the foreign key explicit in the Prisma schema (so you need to add another field in addition to the already existing relation field). This new field is your relation scalar field and directly represents the foreign key in the underlying database.
Assume you're now upgrading to 2.0.0-beta.1
:
npm install @prisma/client@2.0.0-beta.1
npm install @prisma/cli@2.0.0-beta.1 --save-dev
Without touching the database, one way to adjust your Prisma schema to adhere to the new syntax would be as follows:
model User {
id Int @id @default(autoincrement())
profile Profile?
}
model Profile {
id Int @id @default(autoincrement())
user User @relation(fields: [userId], references: [id])
+ userId Int @map("user") // relation scalar field (used in the `@relation` attribute above)
}
model Post {
id Int @id @default(autoincrement())
author User @relation(fields: [authorId], references: [id])
+ authorId Int @map("author") // relation scalar field (used in the `@relation` attribute above)
}
In this code, you introduced the userId
and authorId
fields on Profile
and Post
. These fields are your relation scalar fields and represent the foreign key in your database. But because the current foreign keys in the database are called user
and author
and therefore don't map directly to the model fields, you need to annotate the fields with @map
to "map" them to a differently named database column.
You can then re-generate Prisma Client. Note that the prisma2
command has been renamed to prisma
in 2.0.0-beta.1
, so you need to invoke the generate
command as follows:
npx prisma generate
Note that the new relation scalar field is currently read-only in the generated Prisma Client API. To modify the connections in youe database, you can keep using Prisma Client's nested write queries.
Breaking changes
No more Preview releases
With this release the Preview period for Prisma 2.0 ends. This means that releases will not be tagged preview
any more, but with beta
. Today's release is called: 2.0.0-beta.1
.
Restructuring GitHub repositories
Since its initial release, the main repository for Prisma 2.0 has been called prisma2
.
Because Prisma 2.0 is now the default for developers getting started with Prisma, the Prisma repositories have been renamed as follows:
- The
prisma/prisma2
repository has been renamed toprisma/prisma
- The
prisma/prisma
repository has been renamed toprisma/prisma1
Renaming the prisma2
CLI
During the Preview period, the CLI for Prisma 2.0 was invoked using the prisma2
command. With Prisma 2.0 being the default for new developers getting started with Prisma, the command is changed to just prisma
. The exising prisma
command of Prisma 1 is renamed to prisma1
.
Also note that the installation of the npm packages changes:
Prisma version | Old CLI command | New CLI command | Old npm package name | New npm package name |
---|---|---|---|---|
2.0 | prisma2
| prisma
| prisma2
| @prisma/cli
|
1.X | prisma
| prisma1
| prisma
| prisma1
|
New syntax for defining relations
The Beta release introduces a new relation syntax which makes the @relation
attribute required in each relation in the Prisma schema. Note that it often is enough to only declare the attribute only on the side of the relation (the side that stores the foreign key in the underlying database).
Additionally, for one-to-one and one-to-many relations, you need add a relation scalar field to the model which is used in the @relation
attribute. This relation scalar field directly maps to the foreign key in the underlying database. Note that the foreign key is read-only in the Prisma Client API, to modify a relation you can keep using nested write queries as before.
Here's an overview for how relations need to be updated.
One-to-one
During the Preview period, a 1-1-relation could be defined as follows:
model User {
id Int @id @default(autoincrement())
profile Profile
}
model Profile {
id Int @id @default(autoincrement())
user User
}
With the new Beta, you now must determine which side should store the foreign key. You can do so by adding the @relation
attribute with its corresponding relation scalar field to the model:
model User {
id Int @id @default(autoincrement())
profile Profile
}
model Profile {
id Int @id @default(autoincrement())
+ user User @relation(fields: [userId], references: [id])
+ userId Int // relation scalar field (used in the `@relation` attribute above)
}
This Prisma schema is represented as follows in SQL (the foreign key is stored on Profile
):
CREATE TABLE "User" (
id SERIAL PRIMARY KEY
);
CREATE TABLE "Profile" (
id SERIAL PRIMARY KEY,
"userId" INTEGER NOT NULL UNIQUE,
FOREIGN KEY ("userId") REFERENCES "User"(id)
);
One-to-many
During the Preview period, a 1-n-relation could be defined as follows:
model User {
id Int @id @default(autoincrement())
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
author User
}
With the new Beta, you now must add the @relation
attribute and its corresponding relation scalar field to the non-list field of the relation:
model User {
id Int @id @default(autoincrement())
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
+ author User @relation(fields: [authorId], references: [id])
+ authorId Int
}
This Prisma schema is represented as follows in SQL:
CREATE TABLE "User" (
id SERIAL PRIMARY KEY
);
CREATE TABLE "Post" (
id SERIAL PRIMARY KEY,
"authorId" integer NOT NULL,
FOREIGN KEY ("authorId") REFERENCES "User"(id)
);
Many-to-many (implicit)
During the Preview period, a m-n-relation could be defined as follows:
model Post {
id Int @id @default(autoincrement())
categories Category[]
}
model Category {
id Int @id @default(autoincrement())
posts Post[]
}
With the new Beta, you now must add the @relation
attribute to both sides of the relation:
model Post {
id Int @id @default(autoincrement())
+ categories Category[] @relation(references: [id])
}
model Category {
id Int @id @default(autoincrement())
+ posts Post[] @relation(references: [id])
}
Prisma will maintain the relation with the following relation table:
CREATE TABLE "Category" (
id SERIAL PRIMARY KEY
);
CREATE TABLE "Post" (
id SERIAL PRIMARY KEY
);
-- Relation table + indexes -------------------------------------------------------
CREATE TABLE "_CategoryToPost" (
"A" integer NOT NULL REFERENCES "Category"(id),
"B" integer NOT NULL REFERENCES "Post"(id)
);
CREATE UNIQUE INDEX "_CategoryToPost_AB_unique" ON "_CategoryToPost"("A" int4_ops,"B" int4_ops);
CREATE INDEX "_CategoryToPost_B_index" ON "_CategoryToPost"("B" int4_ops);
Why this change was introduced
The changes in the relation syntax were needed to enable more complex relation configurations, e.g. when using multi-field IDs.
Note that we aim to simplify the current syntax in the future again ("take one step backward, to be able to move two steps forward").
The prisma2
npm package is deprecated
The prisma2
npm package is now deprecated, the Prisma 2.0 CLI can now be installed via the @prisma/cli
npm package, e.g.:
npm @prisma/cli --save-dev
npx prisma
To prevent confusions during installation, it now outputs the following when you try to install it:
┌─────────────────────────────────────────────────────────────┐
│ │
│ The package prisma2 has been renamed to @prisma/cli. │
│ │
│ Please uninstall prisma2 from your project or globally. │
│ Then install @prisma/cli to continue using Prisma 2.0: │
│ │
│ # Uninstall old CLI │
│ npm uninstall prisma2 │
│ │
│ # Install new CLI │
│ npm install @prisma/cli --save-dev │
│ │
│ # Invoke via npx │
│ npx prisma --help │
│ │
│ Learn more here: https://pris.ly/preview025 │
│ │
└─────────────────────────────────────────────────────────────┘