Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion cSpell.json
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,9 @@
"libgcc",
"libc",
"Distroless",
"Nikolas",
"Supavisor",
"inshellisense",
"inshellisense"
],
"patterns": [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,90 +12,235 @@ Prisma Client differentiates between `null` and `undefined`:
- `null` is a **value**
- `undefined` means **do nothing**

> **Note**: This is particularly important to account for in [a **Prisma with GraphQL context**, where `null` and `undefined` are interchangeable](#use-case-null-and-undefined-in-a-graphql-resolver).
<Admonition type="info">

In the following example, if `emailInput` is `null`, the query sets `email` (a **mandatory** field) to `undefined` - which means ✔ **do not include this in the update**:
This is particularly important to account for in [a **Prisma with GraphQL context**, where `null` and `undefined` are interchangeable](#use-case-null-and-undefined-in-a-graphql-resolver).

</Admonition>

The data below represents a `User` table. This set of data will be used in all of the examples below:

| id | name | email |
| --- | ------- | ----------------- |
| 1 | Nikolas | nikolas@gmail.com |
| 2 | Martin | martin@gmail.com |
| 3 | _empty_ | sabin@gmail.com |
| 4 | Tyler | tyler@gmail.com |

</TopBlock>

<!-- TODO Simple example with `findMany` and `findFirst` that shows how a query with `foo: undefined` (e.g. https://github.com/prisma/prisma/issues/17723) returns everything or any first entry as it is filtered out of the query -->
Comment thread
janpio marked this conversation as resolved.

## <inlinecode>null</inlinecode> and <inlinecode>undefined</inlinecode> in queries that affect _many_ records

This section will cover how `undefined` and `null` values affect the behavior of queries that interact with or create multiple records in a database.

### Null

Consider the following Prisma Client query which searches for all users whose `name` value matches the provided `null` value:

<CodeWithResult outputResultText="query" expanded={true}>

<cmd>

```ts
const update = await prisma.user.update({
const users = await prisma.user.findMany({
where: {
id: 1,
name: null,
},
data: {
name: "Petunia",
| email: emailInput != null ? emailInput : undefined, // If null, don't include in update!
})
```

</cmd>

<cmdResult>

```json
[
{
"id": 3,
"name": null,
"email": "sabin@gmail.com"
}
]
```

</cmdResult>

</CodeWithResult>

Because `null` was provided as the filter for the `name` column, Prisma Client will generate a query that searches for all records in the `User` table whose `name` column is _empty_.

### Undefined

Now consider the scenario where you run the same query with `undefined` as the filter value on the `name` column:

<CodeWithResult outputResultText="query" expanded={true}>

<cmd>

```ts
const users = await prisma.user.findMany({
where: {
name: undefined,
},
});
})
```

function getEmail() {
const random = Math.floor(Math.random() * 10);
</cmd>
<cmdResult>

if (random > 5) {
return "ariadne@prisma.io"; // Could be null!
```json
[
{
"id": 1,
"name": "Nikolas",
"email": "nikolas@gmail.com"
},
{
"id": 2,
"name": "Martin",
"email": "martin@gmail.com"
},
{
"id": 3,
"name": null,
"email": "sabin@gmail.com"
},
{
"id": 4,
"name": "Tyler",
"email": "tyler@gmail.com"
}
]
```

return null;
}
</cmdResult>
</CodeWithResult>

Using `undefined` as a value in a filter essentially tells Prisma Client you have decided _not to define a filter_ for that column.

An equivalent way to write the above query would be:

```ts
const users = await prisma.user.findMany()
```

Setting a field value to `undefined` is the same as not including the `email` field in the `update` query **at all**:
This query will select every row from the `User` table.

<Admonition type="info">

**Note**: Using `undefined` as the value of any key in a Prisma Client query's parameter object will cause Prisma to act as if that key was not provided at all.

</Admonition>

Although this section's examples focused on the `findMany` function, the same concepts apply to any function that can affect multiple records, such as `updateMany` and `deleteMany`.

## <inlinecode>null</inlinecode> and <inlinecode>undefined</inlinecode> in queries that affect _one_ record

This section will cover how `undefined` and `null` values affect the behavior of queries that interact with or create a single record in a database.

<Admonition type="warning">

**Note**: `null` is not a valid filter value in a `findUnique` query.

</Admonition>

The query behavior when using `null` and `undefined` in the filter criteria of a query that affects a single record is very similar to the behaviors described in the previous section.

### Null

Consider the following query where `null` is used to filter the `name` column:

<CodeWithResult outputResultText="query" expanded={true}>

<cmd>

```ts
const update = await prisma.user.update({
const user = await prisma.user.findFirst({
where: {
id: 1,
name: null,
},
data: {
name: "Petunia",
| // No email update here...
},
});
})
```

function getEmail() {
const random = Math.floor(Math.random() * 10);
</cmd>

if (random > 5) {
return "ariadne@prisma.io"; // Could be null!
<cmdResult>

```json
[
{
"id": 3,
"name": null,
"email": "sabin@gmail.com"
}
]
```

return null;
}
</cmdResult>
</CodeWithResult>

Because `null` was used as the filter on the `name` column, Prisma Client will generate a query that searches for the first record in the `User` table whose `name` value is _empty_.

### Undefined

If `undefined` is used as the filter value on the `name` column instead, _the query will act as if no filter criteria was passed to that column at all_.

Consider the query below:

<CodeWithResult outputResultText="query" expanded={true}>

<cmd>

```ts
const user = await prisma.user.findFirst({
where: {
name: undefined,
},
})
```

</cmd>

<cmdResult>

```json
[
{
"id": 1,
"name": "Nikolas",
"email": "nikolas@gmail.com"
}
]
```

By contrast, the following would ✘ **not work** as the mandatory `email` field cannot be `null`:
</cmdResult>
</CodeWithResult>

In this scenario, the query will return the very first record in the database.

Another way to represent the above query is:

```ts
email: isValid(emailInput) ? emailInput : null, // email is a mandatory field!
const user = await prisma.user.findFirst()
```

> **Note**: TypeScript will give you an error in this scenario: `Type 'null' is not assignable to type 'string'. ts(2322)`
Although this section's examples focused on the `findFirst` function, the same concepts apply to any function that affects a single record.

## <inlinecode>null</inlinecode> and <inlinecode>undefined</inlinecode> in a GraphQL resolver

<details><summary>Expand for sample schema</summary>
For this example, consider a database based on the following Prisma schema:

```prisma
model User {
email String @unique
id Int @id @default(autoincrement())
email String @unique
name String?
posts Post[]
}

model Post {
id String @id @default(cuid())
title String
authorId Int?
views Int?
author User? @relation(fields: [authorId], references: [id])
}
```

</details>

</TopBlock>

## Use case: <inlinecode>null</inlinecode> and <inlinecode>undefined</inlinecode> in a GraphQL resolver

In the following example mutation that updates a user, both `authorEmail` and `name` accept `null` - from a GraphQL perspective, this means that fields are **optional**:
In the following GraphQL mutation that updates a user, both `authorEmail` and `name` accept `null`. From a GraphQL perspective, this means that fields are **optional**:

```ts
type Mutation {
Expand All @@ -106,8 +251,8 @@ type Mutation {

However, if you pass `null` values for `authorEmail` or `authorName` on to Prisma, the following will happen:

- If `args.authorEmail` is `null`, the query will **fail** - `email` does not accept `null`
- If `args.authorName` is `null`, Prisma changes the value of `name` to `null` - this is probably not how you want an update to work
- If `args.authorEmail` is `null`, the query will **fail**. `email` does not accept `null`.
- If `args.authorName` is `null`, Prisma changes the value of `name` to `null`. This is probably not how you want an update to work.

```ts
updateUser: (parent, args, ctx: Context) => {
Expand Down