Today, we are issuing the twenty-fourth [Preview release](https://github.com/prisma/prisma2/blob/master/docs/releases.md#preview): `2.0.0-preview024` (short: `preview024`).
Major improvements
Reduced size of Prisma Client & Azure functions support
This release contains major improvements for Prisma Client. It now [supports Windows Azure functions](https://github.com/prisma/prisma2/issues/1518). In addition to that, the generated Prisma Client code inside your `node_modules` directory [now is a lot smaller](https://github.com/prisma/prisma-client-js/issues/524).
Another improvement is a better [debugging](https://github.com/prisma/prisma2/blob/master/docs/prisma-client-js/api.md#debugging) experience. When setting the `DEBUG` environment variable (e.g. with `export DEBUG="*"`), the [logging output now contains the names of Prisma Client API calls](https://github.com/prisma/prisma-client-js/issues/551).
Use relation fields as ID on a Prisma model
In this release, it's now possible to use relation fields of Prisma models as IDs. In "database-speak", this means that you can now have both a primary key _and_ a foreign key constraint on the same column.
Reference a single-field ID
For example, a `Movie` could always be identified by its `Director`:
prisma
model Movie {
director Director id
title String
}
model Director {
id Int id default(autoincrement())
name String
}
This is what the corresponding SQL (in SQLite dialect) looks like:
sql
CREATE TABLE "Movie" (
"director" INTEGER NOT NULL ,
"title" TEXT NOT NULL DEFAULT '' ,
PRIMARY KEY ("director"),
FOREIGN KEY ("director") REFERENCES "Director"("id")
);
CREATE TABLE "Director" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"name" TEXT NOT NULL DEFAULT ''
);
<details><summary>Expand to view an example for creating `Movie`s and `Director`s in Prisma Client</summary>
Nested write to create `Movie` with `Director`:
ts
// Run inside `async` function
const movie = await prisma.movie.create({
data: {
title: "Hello World",
director: {
create: {
name: "Alice"
}
}
},
})
Nested write to create `Director` with `Movie`:
ts
// Run inside `async` function
const director = await prisma.director.create({
data: {
name: "Bob",
movies: {
create: [{
title: "Hello World"
}]
}
},
})
</details>
Reference a multi-field ID
You can also create a relation to a multi-field ID:
prisma
model Movie {
director Director id map(["firstName", "lastName"])
title String
}
model Director {
firstName String
lastName String
id([firstName, lastName])
}
Note that in this case, the `Movie` table in the underlying database will actually have two physical columns called `firstName` and `lastName`. These are referencing the respective `firstName` and `lastName` column on the `Director` table.
Here is what the above models correspond to in SQL:
sql
CREATE TABLE "Movie" (
"firstName" TEXT NOT NULL ,
"lastName" TEXT NOT NULL ,
"title" TEXT NOT NULL DEFAULT '' ,
PRIMARY KEY ("firstName","lastName"),
FOREIGN KEY ("firstName","lastName") REFERENCES "Director"("firstName","lastName")
);
CREATE TABLE "Director" (
"firstName" TEXT NOT NULL DEFAULT '' ,
"lastName" TEXT NOT NULL DEFAULT '' ,
PRIMARY KEY ("firstName","lastName")
);
In many cases, it might make sense to name the columns on `Movie` differently. For example, they could be called `directorFirstName` and `directorLastName`. This can be achieved via adding the `map` attribute to the field:
prisma
model Movie {
director Director id map(["directorFirstName", "directorLastName"]) relation(references: [firstName, lastName])
title String
}
model Director {
firstName String
lastName String
id([firstName, lastName])
}
Note that in this case you could also omit the `relation` attribute, the result would be the same:
prisma
model Movie {
director Director id map(["directorFirstName", "directorLastName"])
title String
}
model Director {
firstName String
lastName String
id([firstName, lastName])
}
In this case, the field names in `map` on `Movie` get matched with the field names in `id` on `Director`.
Both cases correspond to the following SQL:
sql
CREATE TABLE "Movie" (
"directorFirstName" TEXT NOT NULL ,
"directorLastName" TEXT NOT NULL ,
"title" TEXT NOT NULL DEFAULT '' ,
PRIMARY KEY ("directorFirstName","directorLastName"),
FOREIGN KEY ("directorFirstName","directorLastName") REFERENCES "Director"("firstName","lastName")
);
CREATE TABLE "Director" (
"firstName" TEXT NOT NULL DEFAULT '' ,
"lastName" TEXT NOT NULL DEFAULT '' ,
PRIMARY KEY ("firstName","lastName")
);
<details><summary>Expand to view an example for creating `Movie`s and `Director`s in Prisma Client</summary>
Nested write to create `Movie` with `Director`:
ts
// Run inside `async` function
const movie = await prisma.movie.create({
data: {
title: 'Hello World',
director: {
create: {
firstName: 'Alice',
lastName: 'Allen',
},
},
},
})
Nested write to create `Director` with `Movie`:
ts
// Run inside `async` function
const director = await prisma.director.create({
data: {
firstName: 'Bob',
lastName: 'Nolan',
movies: {
create: [
{
title: 'Hello World',
},
],
},
},
})
</details>
Multi-field ID with a relation field (which targets a model with a single-field ID)
You can also create a multi-field ID on a model that contains a relation field:
prisma
model Movie {
director Director
title String
id([director, title])
}
model Director {
id String id default(cuid())
name String
}
This corresponds to the following SQL:
sql
CREATE TABLE "Movie" (
"director" TEXT NOT NULL ,
"title" TEXT NOT NULL DEFAULT '' ,
PRIMARY KEY ("director","title"),
FOREIGN KEY ("director") REFERENCES "Director"("id")
);
CREATE TABLE "Director" (
"id" TEXT NOT NULL ,
"name" TEXT NOT NULL DEFAULT '' ,
PRIMARY KEY ("id")
);
<details><summary>Expand to view an example for creating `Movie`s and `Director`s in Prisma Client</summary>
Nested write to create `Movie` with `Director`:
ts
// Run inside `async` function
const movie = await prisma.movie.create({
data: {
title: 'Hello World',
director: {
create: {
name: 'Alice',
},
},
},
})
Nested write to create `Director` with `Movie`:
ts
// Run inside `async` function
const director = await prisma.director.create({
data: {
name: 'Bob',
movies: {
create: [
{
title: 'Hello World 2',
},
],
},
},
})
</details>
Multi-field ID with a relation field (which targets a model with a multi-field ID)
You can also define a multi-field ID on a model which contains a relation field that targets a model with a multi-field ID:
prisma
model Movie {
director Director
title String
id([director, title])
}
model Director {
firstName String
lastName String
id([firstName, lastName])
}
This is what the above code translates to in SQL:
sql
CREATE TABLE "Movie" (
"director_firstName" TEXT NOT NULL ,
"director_lastName" TEXT NOT NULL ,
"title" TEXT NOT NULL DEFAULT '' ,
PRIMARY KEY ("director_firstName","director_lastName","title"),
FOREIGN KEY ("director_firstName","director_lastName") REFERENCES "Director"("firstName","lastName")
);
CREATE TABLE "Director" (
"firstName" TEXT NOT NULL DEFAULT '' ,
"lastName" TEXT NOT NULL DEFAULT '' ,
PRIMARY KEY ("firstName","lastName")
);
Similar to the case before, you can also give names to the added columns on `Movie` by using the `map` attributed:
prisma
model Movie {
director Director map(["directorFirstName", "directorLastName"]) relation(references: [firstName, lastName])
title String
id([director, title])
}
model Director {
firstName String
lastName String
id([firstName, lastName])
}
And as before you can also omit the `relation` attribute in this scenario:
prisma
model Movie {
director Director map(["directorFirstName", "directorLastName"])
title String
id([director, title])
}
model Director {
firstName String
lastName String
id([firstName, lastName])
}
In both cases, the models correspond to the following tables:
sql
CREATE TABLE "Movie" (
"directorFirstName" TEXT NOT NULL ,
"directorLastName" TEXT NOT NULL ,
"title" TEXT NOT NULL DEFAULT '' ,
PRIMARY KEY ("directorFirstName","directorLastName","title"),
FOREIGN KEY ("directorFirstName","directorLastName") REFERENCES "Director"("firstName","lastName")
);
CREATE TABLE "Director" (
"firstName" TEXT NOT NULL DEFAULT '' ,
"lastName" TEXT NOT NULL DEFAULT '' ,
PRIMARY KEY ("firstName","lastName")
);
<details><summary>Expand to view an example for creating `Movie`s and `Director`s in Prisma Client</summary>
Nested write to create `Movie` with `Director`:
ts
// Run inside `async` function
const movie = await prisma.movie.create({
data: {
title: 'Hello World',
director: {
create: {
firstName: 'Alice',
lastName: 'Allen',
},
},
},
})
Nested write to create `Director` with `Movie`:
ts
// Run inside `async` function
const director = await prisma.director.create({
data: {
firstName: 'Bob',
lastName: 'Nolan',
movies: {
create: [
{
title: 'Hello World',
},
],
},
},
})
</details>
Breaking changes
`MODELGetSelectPayload` and `MODELGetIncludePayload` have been merged into `MODELGetPayload`. More info [here](https://github.com/prisma/prisma-client-js/issues/564).
Fixes and improvements per Prisma 2 repository
`prisma2`
- [fix(1728) Handle disconnected error for introspection engine](https://github.com/prisma/prisma2/issues/1808)
- [Better handling of introspect crash](https://github.com/prisma/prisma2/issues/1728)
- [[Introspection] Remove type annotation from Postgres default in cases other than Text](https://github.com/prisma/prisma2/issues/1704)
- [Integration tests: SQLite](https://github.com/prisma/prisma2/issues/1603)
- [Integration tests: MySQL](https://github.com/prisma/prisma2/issues/1602)
- [Introspection composite foreign keys pointing to composite primary keys](https://github.com/prisma/prisma2/issues/1599)
- [Prisma doesn't work on Azure windows functions](https://github.com/prisma/prisma2/issues/1518)
- [[Introspection] Postgres `default` include type information](https://github.com/prisma/prisma2/issues/1810)
- [Invalid response data: the query result was required, but an empty Object((Weak)) was returned instead (drupal)](https://github.com/prisma/prisma2/issues/1779)
- [Introspection bug for unique name on MySQL](https://github.com/prisma/prisma2/issues/1774)
- [Integration tests for SQLite and MySQL](https://github.com/prisma/prisma2/issues/1769)
- [Put `prisma/sdk` version in lockstep with `prisma2`](https://github.com/prisma/prisma2/issues/1767)
- [`introspect` for SQLite returns `id` as `String` when it should be `Int`](https://github.com/prisma/prisma2/issues/1764)
- [Update docs about PostgreSQL socket](https://github.com/prisma/prisma2/issues/1756)
- [Document logging options (via `DEBUG` env var)](https://github.com/prisma/prisma2/issues/1697)
- [Kebab-case parameters due to a change in QE/IE/ME](https://github.com/prisma/prisma2/issues/1759)
`migrate`
- [Kebab-case-parameters in ME](https://github.com/prisma/migrate/issues/362)
`prisma-client-js`
- [Reduce size of generated client](https://github.com/prisma/prisma-client-js/issues/524)
- [Print query parameters](https://github.com/prisma/prisma-client-js/issues/504)
- [Nested create broken in latest alpha](https://github.com/prisma/prisma-client-js/issues/480)
- [Query engine generates wrong SQL queries for Hierarchical Data](https://github.com/prisma/prisma-client-js/issues/399)
- [Log all Prisma Client method executions](https://github.com/prisma/prisma-client-js/issues/551)
- [Switching to kebab-case on QE/ME/IE params](https://github.com/prisma/prisma-client-js/issues/542)
- [Change docs about PostgreSQL socket connection](https://github.com/prisma/prisma-client-js/issues/541)
`prisma-engines`
- [Comment out fields with empty names](https://github.com/prisma/prisma-engines/issues/552)
- [Allow Default Values for Enums that look like Booleans](https://github.com/prisma/prisma-engines/issues/551)
- [Postgres Default Values](https://github.com/prisma/prisma-engines/issues/550)
- [Test and fix mapping of mysql and postgres native types](https://github.com/prisma/prisma-engines/issues/538)
- [Start Adding Test Cases for Using a Relation or Parts of it as Primary Key](https://github.com/prisma/prisma-engines/issues/537)
- [Fix prisma-engines567](https://github.com/prisma/prisma-engines/issues/576)
- [Fix unique on composite relation fields](https://github.com/prisma/prisma-engines/issues/573)
- [Better way to query with many compound ids](https://github.com/prisma/prisma-engines/issues/569)
- [ME: Indices to composite foreign keys are impossible to create](https://github.com/prisma/prisma-engines/issues/567)
- [Update README with proper `cargo test` command](https://github.com/prisma/prisma-engines/issues/565)
- [Return a more intelligible error on unexpectedly empty response](https://github.com/prisma/prisma-engines/issues/564)
- [improve nested pagination from O(n log n) to O(n)](https://github.com/prisma/prisma-engines/issues/563)
- [optimize m2m join with in clause](https://github.com/prisma/prisma-engines/issues/562)
- [Index join tables on the B side](https://github.com/prisma/prisma-engines/issues/561)
- [Make foreign key fields cascade on delete by default](https://github.com/prisma/prisma-engines/issues/560)
- [Test and fix Id as part of relation in migration engine](https://github.com/prisma/prisma-engines/issues/559)
- [ME: Many-to-many table indices sub-optimal](https://github.com/prisma/prisma-engines/issues/554)
- [Recognize `int` as Integer on Sqlite](https://github.com/prisma/prisma-engines/issues/553)
- [Unify cli input parsing](https://github.com/prisma/prisma-engines/issues/549)
- [Remove From DMMF](https://github.com/prisma/prisma-engines/issues/547)