diff --git a/cSpell.json b/cSpell.json index 1de4ee7a95..47e69a8259 100644 --- a/cSpell.json +++ b/cSpell.json @@ -89,8 +89,9 @@ "libgcc", "libc", "Distroless", + "Nikolas", "Supavisor", - "inshellisense", + "inshellisense" ], "patterns": [ { diff --git a/content/200-concepts/100-components/02-prisma-client/080-null-and-undefined.mdx b/content/200-concepts/100-components/02-prisma-client/080-null-and-undefined.mdx index a6ac332040..832b6444f8 100644 --- a/content/200-concepts/100-components/02-prisma-client/080-null-and-undefined.mdx +++ b/content/200-concepts/100-components/02-prisma-client/080-null-and-undefined.mdx @@ -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). + -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). + + + +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 | + + + + + +## null and undefined 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: + + + + ```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! +}) +``` + + + + + +```json +[ + { + "id": 3, + "name": null, + "email": "sabin@gmail.com" + } +] +``` + + + + + +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: + + + + + +```ts +const users = await prisma.user.findMany({ + where: { + name: undefined, }, -}); +}) +``` -function getEmail() { - const random = Math.floor(Math.random() * 10); + + - 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; -} + + + +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. + + + +**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. + + + +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`. + +## null and undefined 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. + + + +**Note**: `null` is not a valid filter value in a `findUnique` query. + + + +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: + + + + ```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); + - if (random > 5) { - return "ariadne@prisma.io"; // Could be null! + + +```json +[ + { + "id": 3, + "name": null, + "email": "sabin@gmail.com" } +] +``` - return null; -} + + + +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: + + + + + +```ts +const user = await prisma.user.findFirst({ + where: { + name: undefined, + }, +}) +``` + + + + + +```json +[ + { + "id": 1, + "name": "Nikolas", + "email": "nikolas@gmail.com" + } +] ``` -By contrast, the following would ✘ **not work** as the mandatory `email` field cannot be `null`: + + + +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. + +## null and undefined in a GraphQL resolver -
Expand for sample schema +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]) } ``` -
- - - -## Use case: null and undefined 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 { @@ -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) => {